### Install Ash Graphql using Igniter Source: https://hexdocs.pm/ash_graphql/getting-started-with-graphql This command installs the ash_graphql dependency using the Igniter tool, which is the recommended installation method. ```bash mix igniter.install ash_graphql ``` -------------------------------- ### GraphQL Query Configuration Example Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-resource This example shows how to define specific queries for an Ash resource within the GraphQL schema. It includes examples for fetching a single post by ID (`get`), retrieving a current user (`read_one`), and listing multiple posts (`list`). ```elixir queries do get :get_post, :read read_one :current_user, :current_user list :list_posts, :read end ``` -------------------------------- ### Install Ash Authentication Phoenix with Igniter Source: https://hexdocs.pm/ash_graphql/authorize-with-graphql This command uses the 'igniter' tool to install both the 'ash_authentication' and 'ash_authentication_phoenix' Elixir packages. This is the first step in setting up user authentication with Ash. ```bash # installs ash_authentication & ash_authentication_phoenix mix igniter.install ash_authentication_phoenix ``` -------------------------------- ### Example of list Query in Ash GraphQL Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-resource Examples of using the 'list' query, including a standard list and a paginated list using Relay. ```elixir list :list_posts, :read ``` ```elixir list :list_posts_paginated, :read, relay?: true ``` -------------------------------- ### Example of read_one Query in Ash GraphQL Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-resource An example demonstrating how to use the 'read_one' query to fetch the current user's data. ```elixir read_one :current_user, :current_user ``` -------------------------------- ### GraphQL Resource Configuration Example Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-resource This example demonstrates how to configure a GraphQL schema for an Ash resource, specifying available queries and mutations. It utilizes the `graphql` DSL within an Ash resource definition. ```elixir graphql do type :post queries do get :get_post, :read list :list_posts, :read end mutations do create :create_post, :create update :update_post, :update destroy :destroy_post, :destroy end end ``` -------------------------------- ### Subscription DSL (beta) Setup Source: https://hexdocs.pm/ash_graphql/use-subscriptions-with-graphql Details on enabling and configuring the beta Subscription DSL, including adding AshGraphql.Subscription.Endpoint and AshGraphql.Subscription.Batcher to your supervision tree, and adding an empty subscription block to your schema. ```APIDOC ## Subscription DSL (beta) The Subscription DSL is currently in beta. To use it, you must first enable subscriptions in your configuration. ### Enabling Subscriptions Add the following to your `config/config.exs`: ```elixir config :ash_graphql, :subscriptions, true ``` ### Endpoint and Batcher Setup Follow the Absinthe setup guide, but use `AshGraphql.Subscription.Endpoint` instead of `Absinthe.Pheonix.Endpoint`. By default, subscriptions resolve synchronously. For improved performance with many subscribers, consider adding `AshGraphql.Subscription.Batcher` to your supervision tree: ```elixir defmodule MyAppWeb.Supervisor do use Supervisor @impl true def start(_type, _args) do children = [ # ... other children {Absinthe.Subscription, MyAppWeb.Endpoint}, AshGraphql.Subscription.Batcher ] # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_one, name: MyAppWeb.Supervisor] Supervisor.start_link(children, opts) end end ``` ### Schema Module Configuration Add an empty subscription block to your schema module: ```elixir defmodule MyAppWeb.Schema do ... subscription do end end ``` ``` -------------------------------- ### GraphQL 'get' Query Definition Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-resource This snippet illustrates the basic syntax for defining a `get` query in GraphQL for an Ash resource. The `get` query is used to fetch a single record by its primary key. ```elixir get :get_post, :read ``` -------------------------------- ### Using AshAuthentication with AshGraphql Source: https://hexdocs.pm/ash_graphql/authorize-with-graphql Instructions on installing AshAuthentication and configuring the router pipeline to integrate with AshGraphql for user authentication. ```APIDOC ## Using AshAuthentication To install `AshAuthentication` and `AshAuthenticationPhoenix`: ```bash mix igniter.install ash_authentication_phoenix ``` Ensure your router pipeline includes the necessary plugs for GraphQL, especially if you've already set up `AshGraphql`: ```elixir pipeline :graphql do plug :load_from_bearer plug :set_actor, :user plug AshGraphql.Plug end ``` ``` -------------------------------- ### Ash Graphql Subscription DSL - Basic Setup Source: https://hexdocs.pm/ash_graphql/use-subscriptions-with-graphql Defines an empty subscription block in an Absinthe schema module, preparing it to use the Ash Graphql Subscription DSL. This is a necessary step after enabling subscriptions in the configuration. ```elixir defmodule MyAppWeb.Schema do ... subscription do end end ``` -------------------------------- ### Using Subscriptions with Absinthe Source: https://hexdocs.pm/ash_graphql/use-subscriptions-with-graphql This section details how to implement subscriptions using Absinthe directly and the `AshGraphql.Subscription.query_for_subscription/3` function, with an example for a single record subscription. ```APIDOC ## Using Subscriptions with Absinthe You can implement subscriptions directly with Absinthe. The `AshGraphql.Subscription.query_for_subscription/3` function can be used to facilitate this. Below is an example demonstrating how to set up a subscription for a single record, which can be extended to support lists of records. ### Example Schema Configuration ```elixir # in your absinthe schema file subscription do field :field, :type_name do config(fn _args, %{context: %{current_user: %{id: user_id}}} -> {:ok, topic: user_id, context_id: "user/#{user_id}"} _args, _context -> {:error, :unauthorized} end) resolve(fn args, _, resolution -> # loads all the data you need AshGraphql.Subscription.query_for_subscription( YourResource, YourDomain, resolution ) |> Ash.Query.filter(id == ^args.id) |> Ash.read(actor: resolution.context.current_user) end) end end ``` ``` -------------------------------- ### Define GraphQL Mutations for Ash Resource Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-domain Example of how to define create, update, and destroy mutations for an Ash resource using the `mutations` DSL. This DSL allows for mapping resource actions to specific GraphQL mutation names. ```elixir mutations do create Post, :create_post, :create update Post, :update_post, :update destroy Post, :destroy_post, :destroy end ``` -------------------------------- ### AshGraphql Generic Action Returning Scalar Source: https://hexdocs.pm/ash_graphql/generic-actions This example demonstrates a generic action in AshGraphql that returns a simple scalar value (a string). It defines a 'say_hello' query and a corresponding action that takes a 'to' argument and returns a greeting string. No external dependencies are required for this basic scalar action. ```elixir graphql do queries do action :say_hello, :say_hello end end actions do action :say_hello, :string do argument :to, :string, allow_nil?: false run fn input, _ -> {:ok, "Hello, #{input.arguments.to}"} end end end ``` -------------------------------- ### Configure Ash GraphQL Tracer Source: https://hexdocs.pm/ash_graphql/monitoring Configures a custom tracer for Ash GraphQL operations within a domain. If not explicitly set, it falls back to the global tracer configuration. ```elixir graphql do trace MyApp.Tracer end ``` -------------------------------- ### AshGraphql Query: Get Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-resource Configures a query to fetch a single record by its primary key. ```APIDOC ## AshGraphql.Resource.Queries.get ### Description A query to fetch a record by primary key. ### Method Not Applicable (Configuration DSL) ### Endpoint Not Applicable (Configuration DSL) ### Parameters #### Syntax `get name, action` #### Example ```elixir get :get_post, :read ``` ``` -------------------------------- ### Configure GraphQL Query (Get by Primary Key) Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-domain Configure a specific query to fetch a record by its primary key. This involves specifying the resource, the desired query name, and the Ash action to execute. Options allow for customization of identity lookup, nilability, and metadata handling. ```elixir get :get_post, :read ``` -------------------------------- ### GraphQL Query and Response for Fetching Single Ticket Source: https://hexdocs.pm/ash_graphql/graphql-generation Illustrates the GraphQL query for fetching a single ticket by its ID and the corresponding JSON response structure. This example demonstrates how to request specific fields and how the server might return the data. ```graphql query ($id: ID!) { getTicket(id: $id) { id subject } } ``` ```json { "data": { "getTicket": { "id": "", "subject": "" } } } ``` -------------------------------- ### Load Fields on Existing Records with load_fields Source: https://hexdocs.pm/ash_graphql/custom-queries-and-mutations This example shows how to use `AshGraphql.load_fields/3` to load data on existing records within a custom GraphQL query. It first retrieves a post using `Ash.get/2` and then applies `AshGraphql.load_fields/3` to load the necessary data based on the GraphQL resolution context. This is useful when you already have the resource in memory and need to prepare it for GraphQL. ```elixir query do field :custom_get_post, :post do arg(:id, non_null(:id)) resolve(fn %{id: post_id}, resolution -> with {:ok, post} when not is_nil(post) <- Ash.get(MyApp.Blog.Post, post_id) do AshGraphql.load_fields(post, MyApp.Blog.Post, resolution) end |> AshGraphql.handle_errors(MyApp.Blog.Post, resolution) end) end end ``` -------------------------------- ### Absinthe Schema Subscription Configuration Source: https://hexdocs.pm/ash_graphql/use-subscriptions-with-graphql Configures a subscription field in an Absinthe schema to listen for changes on a specific Ash resource. It defines the subscription topic and context_id for authorization and uses Ash.read to fetch data based on subscription arguments and the current user's context. This example is for a single record subscription. ```elixir subscription do field :field, :type_name do config(fn _args, %{context: %{current_user: %{id: user_id}}} ) -> {:ok, topic: user_id, context_id: "user/#{user_id}"} _args, _context -> {:error, :unauthorized} end) resolve(fn args, _, resolution -> # loads all the data you need AshGraphql.Subscription.query_for_subscription( YourResource, YourDomain, resolution ) |> Ash.Query.filter(id == ^args.id) |> Ash.read(actor: resolution.context.current_user) end) end end ``` -------------------------------- ### AshGraphql Generic Action Returning List of Records Source: https://hexdocs.pm/ash_graphql/generic-actions This example illustrates a generic action in AshGraphql that returns a list of records. It defines a 'random_ten' query and a corresponding action that fetches records using Ash.read and returns a random subset of ten. Ensure the relevant module is imported or available for Ash.read to function correctly. ```elixir graphql do type :post queries do action :random_ten, :random_ten end end actions do action :random_ten, {:array, :struct} do constraints items: [instance_of: __MODULE__] run fn input, context -> # This is just an example, not an efficient way to get # ten random records with {:ok, records} <- Ash.read(__MODULE__) do {:ok, Enum.take_random(records, 10)} end end end end ``` -------------------------------- ### Resource Level GraphQL Configuration Source: https://hexdocs.pm/ash_graphql/getting-started-with-graphql Define GraphQL queries and mutations directly on the Ash Resource. This is an alternative to domain-level configuration. ```APIDOC ## GraphQL Resource Configuration ### Description Defines GraphQL queries and mutations directly on the Ash Resource. This allows for resource-specific GraphQL interfaces. ### Method N/A (Configuration) ### Endpoint N/A (Configuration) ### Parameters N/A ### Request Example N/A ### Response N/A ### Configuration Example ```elixir defmodule Helpdesk.Support.Ticket do use Ash.Resource, extensions: [ AshGraphql.Resource ] graphql do type :ticket queries do get :get_ticket, :read read_one :most_important_ticket, :most_important list :list_tickets, :read end mutations do create :create_ticket, :create update :update_ticket, :update destroy :destroy_ticket, :destroy end end ... end ``` ``` -------------------------------- ### Mutations Configuration Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-domain Configure which mutations (create, update, destroy actions) should be exposed for a resource. ```APIDOC ## Mutations Configuration API ### Description This section describes how to define mutations for a resource in Ash Graphql. You can expose create, update, and destroy actions as GraphQL mutations. ### Method DSL Configuration ### Endpoint N/A (DSL Configuration) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```elixir mutations do create Post, :create_post, :create update Post, :update_post, :update destroy Post, :destroy_post, :destroy end ``` ### Response #### Success Response (200) N/A (DSL Configuration) #### Response Example N/A (DSL Configuration) ``` -------------------------------- ### AshGraphql Queries Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-resource Configuration for exposing read actions (queries) for a resource in GraphQL. ```APIDOC ## AshGraphql.Resource.Queries ### Description Queries (read actions) to expose for the resource. ### Nested DSLs * get * read_one * list * action ### Examples ```elixir queries do get :get_post, :read read_one :current_user, :current_user list :list_posts, :read end ``` ``` -------------------------------- ### Configure UTC Datetime Type in AshGraphql Source: https://hexdocs.pm/ash_graphql/upgrade This snippet shows how to configure the UTC datetime type to `:naive_datetime` for backwards compatibility in AshGraphql. It replaces the older configuration key. ```elixir config :ash_graphql, :utc_datetime_type, :naive_datetime ``` -------------------------------- ### Domain Level GraphQL Configuration Source: https://hexdocs.pm/ash_graphql/getting-started-with-graphql Define GraphQL queries and mutations for a resource within the Ash Domain. This approach centralizes interface definition. ```APIDOC ## GraphQL Domain Configuration ### Description Defines GraphQL queries and mutations at the domain level, providing a centralized interface for interacting with resources. ### Method N/A (Configuration) ### Endpoint N/A (Configuration) ### Parameters N/A ### Request Example N/A ### Response N/A ### Configuration Example ```elixir defmodule Helpdesk.Support do use Ash.Domain, extensions: [ AshGraphql.Domain ] graphql do queries do # Creates a 'get_ticket' field using the 'read' action for single ticket fetch get Helpdesk.Support.Ticket, :get_ticket, :read # Creates a 'most_important_ticket' field using the 'most_important' read action read_one Helpdesk.Support.Ticket, :most_important_ticket, :most_important # Creates a 'list_tickets' field using the 'read' action for fetching multiple tickets 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 end ``` ``` -------------------------------- ### Configure Ignored Managed Relationship Source: https://hexdocs.pm/ash_graphql/upgrade This Elixir snippet configures a managed relationship for the `:create` action on `:comments` within AshGraphql, explicitly ignoring the automatic type generation for this relationship. ```elixir managed_relationships do managed_relationship :create, :comments, ignore?: true end ``` -------------------------------- ### GraphQL Queries - Action Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-domain This endpoint allows executing a generic action on a specified resource. ```APIDOC ## action resource, name, action ### Description Runs a generic action. ### Method GET (GraphQL Query) ### Endpoint /graphql ### Parameters #### Query Parameters - **resource** (module) - Required - The resource that the action is defined on. - **name** (atom) - Optional - The name to use for the query. Defaults to `:get`. - **action** (atom) - Required - The action to use for the query. #### Options - **allow_nil?** (boolean) - Optional - Whether or not the action can return nil. Defaults to `true`. - **type_name** (atom) - Optional - Override the type name returned by this query. Must be set if the read action has `metadata` that is not hidden via the `show_metadata` key. - **description** (String.t) - Optional - The query description that gets shown in the Graphql schema. If not provided, the action description will be used. - **metadata_names** (keyword) - Optional - Name overrides for metadata fields on the read action. Defaults to `[]`. - **metadata_types** (keyword) - Optional - Type overrides for metadata fields on the read action. Defaults to `[]`. - **show_metadata** (list(atom)) - Optional - The metadata attributes to show. Defaults to all. - **as_mutation?** (boolean) - Optional - Places the query in the `mutations` key instead. Defaults to `false`. - **relay_id_translations** (keyword) - Optional - A keyword list indicating arguments or attributes that have to be translated from global Relay IDs to internal IDs. Defaults to `[]`. - **hide_inputs** (list(atom)) - Optional - A list of inputs to hide from the mutation. Defaults to `[]`. - **complexity** ({module, list(any)}) - Optional - An {module, function} that will be called with the arguments and complexity value of the child fields query. Defaults to `{AshGraphql.Graphql.Resolver, :query_complexity}`. - **modify_resolution** (mfa) - Optional - An MFA that will be called with the resolution, the query, and the result of the action as the first three arguments. - **meta** (keyword) - Optional - A keyword list of metadata for the query. Defaults to `[]`. ### Request Example ```json { "query": "query { check_status_action: action(resource: MyApp.Resources.MyResource, name: :check_status, action: :check_status) { status } }" } ``` ### Response #### Success Response (200) - **data** (object) - The result of the action. #### Response Example ```json { "data": { "check_status_action": { "status": "ok" } } } ``` ``` -------------------------------- ### Connect Ash Graphql Schema with Phoenix Router Source: https://hexdocs.pm/ash_graphql/getting-started-with-graphql This Elixir code demonstrates how to integrate Ash Graphql into a Phoenix router. It sets up a pipeline for GraphQL requests and defines routes for the playground and the main GraphQL endpoint. ```elixir pipeline :graphql do plug AshGraphql.Plug end scope "/gql" do pipe_through [:graphql] forward "/playground", Absinthe.Plug.GraphiQL, schema: Module.concat(["Helpdesk.GraphqlSchema"]), interface: :playground forward "/", Absinthe.Plug, schema: Module.concat(["Helpdesk.GraphqlSchema"]) end ``` -------------------------------- ### GraphQL Queries (Resource.Query) Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-resource Defines how to expose resource actions as GraphQL queries. This section details the available options for customizing query behavior, including pagination, type naming, and metadata handling. ```APIDOC ## GraphQL Queries (Resource.Query) ### Description Defines how to expose resource actions as GraphQL queries. This section details the available options for customizing query behavior, including pagination, type naming, and metadata handling. ### Method N/A (GraphQL Schema Definition) ### Endpoint N/A (GraphQL Endpoint) ### Parameters #### Query Options - **relay?** (boolean) - Optional - If true, the graphql queries/resolvers for this resource will be built to honor the relay specification. - **paginate_with** (:keyset | :offset | nil) - Optional - Determines the pagination strategy to use. Defaults to `:keyset`. - **type_name** (atom) - Optional - Overrides the type name returned by this query. Must be set if the read action has `metadata` that is not hidden via the `show_metadata` key. - **description** (String.t) - Optional - The query description that gets shown in the Graphql schema. - **metadata_names** (keyword) - Optional - Name overrides for metadata fields on the read action. - **metadata_types** (keyword) - Optional - Type overrides for metadata fields on the read action. - **show_metadata** (list(atom)) - Optional - The metadata attributes to show. Defaults to all. - **as_mutation?** (boolean) - Optional - Places the query in the `mutations` key instead. - **relay_id_translations** (keyword) - Optional - A keyword list indicating arguments or attributes that have to be translated from global Relay IDs to internal IDs. - **hide_inputs** (list(atom)) - Optional - A list of inputs to hide from the mutation. - **complexity** ({module, list(any)}) - Optional - An MFA that will be called with the arguments and complexity value of the child fields query. It should return the complexity of this query. - **modify_resolution** (mfa) - Optional - An MFA that will be called with the resolution, the query, and the result of the action. - **meta** (keyword) - Optional - A keyword list of metadata for the query. ### Request Example ```graphql query { # Example query for a resource action user(id: "123") { name email } } ``` ### Response #### Success Response (200) - **data** (map) - The result of the GraphQL query. #### Response Example ```json { "data": { "user": { "name": "John Doe", "email": "john.doe@example.com" } } } ``` ``` -------------------------------- ### Define GraphQL Resource Queries & Mutations - Elixir Source: https://hexdocs.pm/ash_graphql/getting-started-with-graphql Defines GraphQL queries and mutations directly on the Ash resource. This method allows for localized configuration of API operations tied to a specific resource. It maps actions like `:read`, `:create`, `:update`, and `:destroy` to GraphQL fields within the resource's definition. ```elixir defmodule Helpdesk.Support.Ticket do use Ash.Resource, ..., extensions: [ AshGraphql.Resource ] graphql do type :ticket queries do get :get_ticket, :read read_one :most_important_ticket, :most_important list :list_tickets, :read end mutations do create :create_ticket, :create update :update_ticket, :update destroy :destroy_ticket, :destroy end end ... end ``` -------------------------------- ### Define Enum Type for Graphql Attributes Source: https://hexdocs.pm/ash_graphql/upgrade This Elixir code defines a custom `Ash.Type.Enum` for a `post_status` attribute. This is necessary in AshGraphql 1.0 to explicitly define enum types for GraphQL, replacing automatic generation. ```elixir defmodule MyApp.PostStatus do use Ash.Type.Enum, values: [:active, :archived] def graphql_type(_), do: :post_status def graphql_input_type(_), do: :post_status end attribute :post_status, MyApp.PostStatus ``` -------------------------------- ### AshGraphql Resource Configuration Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-resource Configuration for exposing an Ash resource in a GraphQL schema. ```APIDOC ## AshGraphql.Resource Configuration ### Description This Ash resource extension adds configuration for exposing a resource in a graphql. ### Method Not Applicable (Configuration Block) ### Endpoint Not Applicable (Configuration Block) ### Parameters #### Options - **type** (atom) - The type to use for this entity in the graphql schema. If the resource doesn't have a type, it also needs to have `generate_object? false` and can only expose generic action queries. - **derive_filter?** (boolean) - Defaults to `true`. Set to false to disable the automatic generation of a filter input for read actions. - **derive_sort?** (boolean) - Defaults to `true`. Set to false to disable the automatic generation of a sort input for read actions. - **encode_primary_key?** (boolean) - Defaults to `true`. For resources with composite primary keys, or primary keys not called `:id`, this will cause the id to be encoded as a single `id` attribute, both in the representation of the resource and in get requests. - **relationships** (list(atom)) - A list of relationships to include on the created type. Defaults to all public relationships where the destination defines a graphql type. - **paginate_relationship_with** (keyword) - Defaults to `[]`. A keyword list indicating which kind of pagination should be used for each `has_many` and `many_to_many` relationships, e.g. `related_things: :keyset, other_related_things: :offset`. Valid pagination values are `nil`, `:none`, `:offset`, `:keyset` and `:relay`. - **field_names** (keyword) - A keyword list of name overrides for attributes. - **hide_fields** (list(atom)) - A list of attributes to hide from the domain. - **show_fields** (list(atom)) - A list of attributes to show in the domain. If not specified includes all (excluding `hide_fiels`). - **argument_names** (keyword) - A nested keyword list of action names, to argument name remappings. i.e `create: [arg_name: :new_name]`. - **keyset_field** (atom) - If set, the keyset will be displayed on all read actions in this field. It will be `nil` unless at least one of the read actions on a resource uses keyset pagination or it is the result of a mutation. - **attribute_types** (keyword) - A keyword list of type overrides for attributes. The type overrides should refer to types available in the graphql (absinthe) schema. `list_of/1` and `non_null/1` helpers can be used. - **attribute_input_types** (keyword) - A keyword list of input type overrides for attributes. The type overrides should refer to types available in the graphql (absinthe) schema. `list_of/1` and `non_null/1` helpers can be used. - **argument_input_types** (keyword) - A keyword list of actions and their input type overrides for arguments. The type overrides should refer to types available in the graphql (absinthe) schema. `list_of/1` and `non_null/1` helpers can be used. - **primary_key_delimiter** (String.t) - Defaults to `"~"`. If a composite primary key exists, this can be set to determine delimiter used in the `id` field value. - **depth_limit** (integer) - A simple way to prevent massive queries. - **complexity** ({module, list(any)}) - An {module, function} that will be called with the arguments and complexity value of the child fields query. It should return the complexity of this query. - **generate_object?** (boolean) - Defaults to `true`. Whether or not to create the GraphQL object, this allows you to manually create the GraphQL object. - **filterable_fields** (list(atom)) - A list of fields that are allowed to be filtered on. Defaults to all filterable fields for which a GraphQL type can be created. - **sortable_fields** (list(atom)) - A list of fields that are allowed to be sorted on. Defaults to all sortable fields for which a GraphQL type can be created. - **nullable_fields** (atom | list(atom)) - Mark fields as nullable even if they are required. This is useful when using field policies. See the authorization guide for more. - **error_handler** (mfa) - Set an MFA to intercept/handle any errors that are generated. ### Request Example ```elixir graphql do type :post queries do get :get_post, :read list :list_posts, :read end mutations do create :create_post, :create update :update_post, :update destroy :destroy_post, :destroy end end ``` ### Response #### Success Response (200) Not Applicable (Configuration Block) #### Response Example Not Applicable (Configuration Block) ``` -------------------------------- ### Update Absinthe Schema to Use Domains Source: https://hexdocs.pm/ash_graphql/upgrade This Elixir code demonstrates updating an Absinthe schema file to use `Ash.Domain` instead of `Ash.Api` in Ash 3.0. It shows how to declare the domains and use them with `use AshGraphql`. ```elixir @domains [MyApp.Domain1, MyApp.Domain2] use AshGraphql, domains: @domains ``` -------------------------------- ### Define GraphQL Domain Queries & Mutations - Elixir Source: https://hexdocs.pm/ash_graphql/getting-started-with-graphql Defines GraphQL queries and mutations directly on the Ash domain. This approach centralizes the interface definition, making it easier to manage your API's operations. It maps specific actions (like `:read`, `:create`, `:update`, `:destroy`) to GraphQL fields. ```elixir defmodule Helpdesk.Support do use Ash.Domain, extensions: [ AshGraphql.Domain ] ... graphql do queries do # create a field called `get_ticket` that uses the `read` read action to fetch a single ticke get Helpdesk.Support.Ticket, :get_ticket, :read # create a field called `most_important_ticket` that uses the `most_important` read action to fetch a single record read_one Helpdesk.Support.Ticket, :most_important_ticket, :most_important # create a field called `list_tickets` that uses the `read` read action to fetch a list of tickets 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 end ``` -------------------------------- ### Remove Deprecated Ash UTC Datetime Config Source: https://hexdocs.pm/ash_graphql/upgrade This snippet demonstrates removing the old configuration for UTC datetime type, which is no longer used in AshGraphql 1.0. The old configuration was `config :ash, :utc_datetime_type, :datetime`. ```elixir config :ash, :utc_datetime_type, :datetime ``` -------------------------------- ### AshGraphql Domain Configuration Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-domain Configure global settings for AshGraphql at the domain level. ```APIDOC ## graphql Domain level configuration for GraphQL ### Options - `authorize?` (boolean) - Required/Optional - Whether or not to perform authorization for this domain. Defaults to `true`. - `tracer` (atom) - Required/Optional - A tracer to use to trace execution in the graphql. Will use `config :ash, :tracer` if it is set. - `root_level_errors?` (boolean) - Required/Optional - By default, mutation errors are shown in their result object's errors key, but this setting places those errors in the top level errors list. Defaults to `false`. - `error_handler` (mfa) - Required/Optional - Set an MFA to intercept/handle any errors that are generated. Defaults to `{AshGraphql.DefaultErrorHandler, :handle_error, []}`. - `show_raised_errors?` (boolean) - Required/Optional - For security purposes, if an error is _raised_ then Ash simply shows a generic error. If you want to show those errors, set this to true. Defaults to `false`. ### Example ```elixir graphql do authorize? false # To skip authorization for this domain end ``` ``` -------------------------------- ### Add Ash Graphql Dependency to Mix Project Source: https://hexdocs.pm/ash_graphql/getting-started-with-graphql This Elixir code snippet shows how to add the ash_graphql dependency to your project's `deps` function in your `mix.exs` file. ```elixir def deps() [ ... {:ash_graphql, "~> 1.8.3"} ] end ``` -------------------------------- ### Define NewType for Graphql Union Types Source: https://hexdocs.pm/ash_graphql/upgrade This Elixir code defines a custom `Ash.Type.NewType` for a union type attribute `scale`. This approach is required in AshGraphql 1.0 for union types, replacing automatic generation and providing explicit type definitions. ```elixir defmodule MyApp.Scale do use Ash.Type.NewType, subtype_of: :union, constraints: [ types: [ whole: [ type: :integer ], fractional: [ type: :decimal ] ] ] def graphql_type(_), do: :scale def graphql_input_type(_), do: :scale end attribute :scale, MyApp.Scale ``` -------------------------------- ### GraphQL Queries - List Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-domain This endpoint allows fetching a list of records from a specified resource using various options for pagination and data shaping. ```APIDOC ## list resource, name, action ### Description A query to fetch a list of records. ### Method GET (GraphQL Query) ### Endpoint /graphql ### Parameters #### Query Parameters - **resource** (module) - Required - The resource that the action is defined on. - **name** (atom) - Optional - The name to use for the query. Defaults to `:get`. - **action** (atom) - Required - The action to use for the query. #### Options - **relay?** (boolean) - Optional - If true, the graphql queries/resolvers for this resource will be built to honor the relay specification. Defaults to `false`. - **paginate_with** (:keyset | :offset | nil) - Optional - Determine the pagination strategy to use, if multiple are available. Defaults to `:keyset`. - **type_name** (atom) - Optional - Override the type name returned by this query. Must be set if the read action has `metadata` that is not hidden via the `show_metadata` key. - **description** (String.t) - Optional - The query description that gets shown in the Graphql schema. If not provided, the action description will be used. - **metadata_names** (keyword) - Optional - Name overrides for metadata fields on the read action. Defaults to `[]`. - **metadata_types** (keyword) - Optional - Type overrides for metadata fields on the read action. Defaults to `[]`. - **show_metadata** (list(atom)) - Optional - The metadata attributes to show. Defaults to all. - **as_mutation?** (boolean) - Optional - Places the query in the `mutations` key instead. Defaults to `false`. - **relay_id_translations** (keyword) - Optional - A keyword list indicating arguments or attributes that have to be translated from global Relay IDs to internal IDs. Defaults to `[]`. - **hide_inputs** (list(atom)) - Optional - A list of inputs to hide from the mutation. Defaults to `[]`. - **complexity** ({module, list(any)}) - Optional - An {module, function} that will be called with the arguments and complexity value of the child fields query. Defaults to `{AshGraphql.Graphql.Resolver, :query_complexity}`. - **modify_resolution** (mfa) - Optional - An MFA that will be called with the resolution, the query, and the result of the action as the first three arguments. - **meta** (keyword) - Optional - A keyword list of metadata for the query. Defaults to `[]`. ### Request Example ```json { "query": "query { list_posts { id name } }" } ``` ### Response #### Success Response (200) - **data** (object) - The result of the query. #### Response Example ```json { "data": { "list_posts": [ { "id": "1", "name": "Example Post" } ] } } ``` ``` -------------------------------- ### Define Enum Type for GraphQL in Ash Source: https://hexdocs.pm/ash_graphql/use-enums-with-graphql This example shows how to define an `Ash.Type.Enum` that can be used in GraphQL attributes and arguments. It includes defining the `graphql_type/0` function to specify the GraphQL type name, optionally remapping values with `graphql_rename_value/1`, and providing descriptions for enum values using `graphql_describe_enum_value/1`. ```elixir defmodule AshPostgres.Test.Types.Status do @moduledoc false use Ash.Type.Enum, values: [:open, :closed] def graphql_type(_), do: :ticket_status # Optionally, remap the names used in GraphQL, for instance if you have a value like `:"10"` # that value is not compatible with GraphQL def graphql_rename_value(value), do: value # You can also provide descriptions for the enum values, which will be exposed in the GraphQL # schema. # Remember to have a fallback clause that returns nil if you don't provide descriptions for all # values. def graphql_describe_enum_value(:open), do: "The post is open" def graphql_describe_enum_value(_), do: nil end ``` -------------------------------- ### AshGraphql.Resource.Transformers.Subscription: before?/1 Function Source: https://hexdocs.pm/ash_graphql/AshGraphql.Resource.Transformers The `before?/1` function is a callback implementation for `Spark.Dsl.Transformer.before?/1`. It is used to determine if a transformer should be applied before another specific transformer. This provides control over the sequence of transformer applications in Ash GraphQL. ```elixir def before?(other_transformer) do # Implementation to check if this transformer runs before another end ``` -------------------------------- ### Resource Actions Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-domain Defines specific actions for a resource that can be exposed via GraphQL. ```APIDOC ## POST /graphql (action) ### Description Runs a specific action on a resource, exposing it as a GraphQL mutation or query. ### Method POST ### Endpoint /graphql ### Parameters #### Query Parameters - **query** (String) - Required - The GraphQL query string. - **variables** (JSON) - Optional - Variables for the query. #### Request Body (Not applicable for standard GraphQL POST requests, typically sent via query string) ### Request Example ```json { "query": "query ($id: ID!) { user(id: $id) { name } }", "variables": { "id": "1" } } ``` ### Response #### Success Response (200) - **data** (Object) - Contains the result of the action. - **errors** (Array) - Contains any errors encountered during the action. #### Response Example ```json { "data": { "user": { "name": "John Doe" } } } ``` ### Arguments - **resource** (module) - Required - The resource that the action is defined on. - **name** (atom) - Optional - The name to use for the query. Defaults to `:get`. - **action** (atom) - Required - The action to use for the query. ### Options - **description** (String.t) - Optional - The description that gets shown in the Graphql schema. - **hide_inputs** (list(atom)) - Optional - Inputs to hide in the mutation/query. - **error_location** (:in_result | :top_level) - Optional - If the result should have an `errors` and a `result` key, or if errors should be shown in the top level errors key. Defaults to `:top_level`. - **modify_resolution** (mfa) - Optional - An MFA that will be called with the resolution, the query, and the result of the action. - **relay_id_translations** (keyword) - Optional - A keyword list indicating arguments or attributes that have to be translated from global Relay IDs to internal IDs. - **meta** (keyword) - Optional - A keyword list of metadata for the action. - **args** (list(atom)) - Optional - A list of action attributes or arguments that should get their own arguments in the mutation instead of being passed in an input object. ``` -------------------------------- ### Connect Ash Graphql Schema with Plug Router Source: https://hexdocs.pm/ash_graphql/getting-started-with-graphql This Elixir code shows how to connect Ash Graphql to a standalone Plug router. It forwards requests to Absinthe.Plug for the main GraphQL endpoint and Absinthe.Plug.GraphiQL for the playground. ```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 ] ``` -------------------------------- ### Ash Graphql Subscription DSL - Resource Creation Source: https://hexdocs.pm/ash_graphql/use-subscriptions-with-graphql Defines a subscription for resource creation using the Ash Graphql Subscription DSL. This subscription listens for `:create` action types on a specific resource and is enabled by the `AshGraphql.Resource` extension. ```elixir defmodule MyApp.Resource do use Ash.Resource, data_layer: Ash.DataLayer.Ets, extensions: [AshGraphql.Resource] graphql do subscriptions do subscribe :resource_created do action_types :create end end end end ``` -------------------------------- ### Nested DSLs for Mutations Source: https://hexdocs.pm/ash_graphql/dsl-ashgraphql-resource Details the nested DSLs available for defining create, update, and destroy mutations. ```APIDOC ## Nested DSLs for Mutations ### Description Details the nested DSLs available for defining create, update, and destroy mutations. ### Method N/A (GraphQL Schema Definition) ### Endpoint N/A (GraphQL Endpoint) ### Parameters #### Nested DSLs - **create** - Defines a mutation for creating a record. - **Arguments**: - `name` (atom) - Required - The name to use for the mutation. Defaults to `:get`. - `action` (atom) - Required - The action to use for the mutation. - **update** - Defines a mutation for updating a record. - **Arguments**: - `name` (atom) - Required - The name to use for the mutation. Defaults to `:get`. - `action` (atom) - Required - The action to use for the mutation. - **destroy** - Defines a mutation for destroying a record. - **Arguments**: - `name` (atom) - Required - The name to use for the mutation. Defaults to `:get`. - `action` (atom) - Required - The action to use for the mutation. ### Request Example ```graphql mutations do create :create_post, :create update :update_post, :update destroy :destroy_post, :destroy end ``` ### Response (See GraphQL Mutations section for general response structure) #### Response Example ```json { "data": { "create_post": { "post": { "id": "post-456", "title": "New Post" } } } } ``` ``` -------------------------------- ### Defining Subscriptions with the DSL Source: https://hexdocs.pm/ash_graphql/use-subscriptions-with-graphql Demonstrates how to define subscriptions on a resource using the Subscription DSL, specifying action types and custom deduplication logic. ```APIDOC ### Defining Subscriptions Once the setup is complete, you can define subscriptions on your resources or domains. #### Resource Subscription Example ```elixir defmodule MyApp.Resource do use Ash.Resource, data_layer: Ash.DataLayer.Ets, extensions: [AshGraphql.Resource] graphql do subscriptions do subscribe :resource_created do action_types :create end end end end ``` For more details, refer to the DSL documentation for resources and domains. #### Deduplication Customization Absinthe deduplicates subscriptions based on `context_id` by default. You can customize this by providing an `actor` function within the `subscriptions` block. This function allows you to return a more generic actor, consolidating subscriptions from multiple users. ```elixir defmodule MyApp.Resource do use Ash.Resource, data_layer: Ash.DataLayer.Ets, extensions: [AshGraphql.Resource] graphql do subscriptions do subscribe :resource_created do action_types :create actor fn actor -> if check_actor(actor) do %{id: "your generic actor", ...} # Return a more generic actor else actor # Return the original actor if no customization needed end end end end end end ``` ```