improvement!: port AshGraphql to Ash 3.0 (#123)

Step 1: update Ash

Step 2: mass rename Api to Domain

Step 3: Ash.Query.expr -> Ash.Expr.expr

Also change ref interpolation

Step 4: remove all warnings

Step 5: remove registries from tests

Step 6: fix filter

Step 7: private? -> !public?

Step 8: Ash.Calculation -> Ash.Resource.Calculation

Step 9: use depend_on_resources/1 -> resources/1

Step 10: add Domain to all resources

Step 11: use Ash module for all actions

Step 12: add public? true all around

Step 13: remove verbose? from options passed during Domain calls

Step 14: add simple_sat

Step 15: Ash.ErrorKind is no more, so remove code from errors

Step 16: sprinkle default_accept :* around tests

Step 17: replace Ash.Changeset.new/2 with Ash.Changeset.for_*

Step 18: calculation fixups

- Context is now a struct and arguments go under the arguments key
- Function based calculations receive a list of records
- Add a select to query-based loads
- select -> load

Step 19: pass the correct name to pass the policy in tests

Step 20: Ash.Query.new/2 is no more

Step 21: add AshGraphql.Resource.embedded? utility function

Use that instead of Ash.Type.embedded_type?(resource_or_type) since resources
are not types anymore

Step 22: handle struct + instance_of: Resource in unions

Resources are not type anymore so they need to be passed this way in unions

Step 23: ensure we only check GraphQL actions for pagination

All reads are now paginated by default, so this triggered a compilation error

Step 24: swap arguments for sort on calculations

Step 25: remove unused debug? option
This commit is contained in:
Riccardo Binetti 2024-04-01 20:03:06 +02:00 committed by GitHub
parent 9f0ed5ed7e
commit 513c1ac68f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
88 changed files with 1036 additions and 869 deletions

View file

@ -10,7 +10,6 @@ spark_locals_without_parens = [
auto?: 1, auto?: 1,
create: 2, create: 2,
create: 3, create: 3,
debug?: 1,
depth_limit: 1, depth_limit: 1,
derive_filter?: 1, derive_filter?: 1,
derive_sort?: 1, derive_sort?: 1,

View file

@ -2,8 +2,8 @@ import Config
config :ash, :utc_datetime_type, :datetime config :ash, :utc_datetime_type, :datetime
config :ash, :disable_async?, true config :ash, :disable_async?, true
config :ash, :validate_api_resource_inclusion?, false config :ash, :validate_domain_resource_inclusion?, false
config :ash, :validate_api_config_inclusion?, false config :ash, :validate_domain_config_inclusion?, false
config :ash_graphql, :default_managed_relationship_type_name_template, :action_name config :ash_graphql, :default_managed_relationship_type_name_template, :action_name
config :ash_graphql, :allow_non_null_mutation_arguments?, true config :ash_graphql, :allow_non_null_mutation_arguments?, true

View file

@ -1,9 +1,9 @@
<!-- <!--
This file was generated by Spark. Do not edit it by hand. This file was generated by Spark. Do not edit it by hand.
--> -->
# DSL: AshGraphql.Api # DSL: AshGraphql.Domain
The entrypoint for adding graphql behavior to an Ash API The entrypoint for adding graphql behavior to an Ash domain
## graphql ## graphql
@ -15,7 +15,7 @@ Global configuration for graphql
### Examples ### Examples
``` ```
graphql do graphql do
authorize? false # To skip authorization for this API authorize? false # To skip authorization for this domain
end end
``` ```
@ -27,12 +27,11 @@ end
| Name | Type | Default | Docs | | Name | Type | Default | Docs |
|------|------|---------|------| |------|------|---------|------|
| [`authorize?`](#graphql-authorize?){: #graphql-authorize? } | `boolean` | `true` | Whether or not to perform authorization for this API | | [`authorize?`](#graphql-authorize?){: #graphql-authorize? } | `boolean` | `true` | Whether or not to perform authorization for this domain |
| [`tracer`](#graphql-tracer){: #graphql-tracer } | `atom` | | A tracer to use to trace execution in the graphql. Will use `config :ash, :tracer` if it is set. | | [`tracer`](#graphql-tracer){: #graphql-tracer } | `atom` | | A tracer to use to trace execution in the graphql. Will use `config :ash, :tracer` if it is set. |
| [`root_level_errors?`](#graphql-root_level_errors?){: #graphql-root_level_errors? } | `boolean` | `false` | 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 | | [`root_level_errors?`](#graphql-root_level_errors?){: #graphql-root_level_errors? } | `boolean` | `false` | 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 |
| [`error_handler`](#graphql-error_handler){: #graphql-error_handler } | `mfa` | `{AshGraphql.DefaultErrorHandler, :handle_error, []}` | Set an MFA to intercept/handle any errors that are generated. | | [`error_handler`](#graphql-error_handler){: #graphql-error_handler } | `mfa` | `{AshGraphql.DefaultErrorHandler, :handle_error, []}` | Set an MFA to intercept/handle any errors that are generated. |
| [`show_raised_errors?`](#graphql-show_raised_errors?){: #graphql-show_raised_errors? } | `boolean` | `false` | 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. | | [`show_raised_errors?`](#graphql-show_raised_errors?){: #graphql-show_raised_errors? } | `boolean` | `false` | 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. |
| [`debug?`](#graphql-debug?){: #graphql-debug? } | `boolean` | `false` | Whether or not to log (extremely verbose) debug information |

View file

@ -57,8 +57,8 @@ end
| [`encode_primary_key?`](#graphql-encode_primary_key?){: #graphql-encode_primary_key? } | `boolean` | `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 | | [`encode_primary_key?`](#graphql-encode_primary_key?){: #graphql-encode_primary_key? } | `boolean` | `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`](#graphql-relationships){: #graphql-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. | | [`relationships`](#graphql-relationships){: #graphql-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. |
| [`field_names`](#graphql-field_names){: #graphql-field_names } | `keyword` | | A keyword list of name overrides for attributes. | | [`field_names`](#graphql-field_names){: #graphql-field_names } | `keyword` | | A keyword list of name overrides for attributes. |
| [`hide_fields`](#graphql-hide_fields){: #graphql-hide_fields } | `list(atom)` | | A list of attributes to hide from the api | | [`hide_fields`](#graphql-hide_fields){: #graphql-hide_fields } | `list(atom)` | | A list of attributes to hide from the domain |
| [`show_fields`](#graphql-show_fields){: #graphql-show_fields } | `list(atom)` | | A list of attributes to show in the api. If not specified includes all (excluding `hide_fiels`). | | [`show_fields`](#graphql-show_fields){: #graphql-show_fields } | `list(atom)` | | A list of attributes to show in the domain. If not specified includes all (excluding `hide_fiels`). |
| [`argument_names`](#graphql-argument_names){: #graphql-argument_names } | `keyword` | | A nested keyword list of action names, to argument name remappings. i.e `create: [arg_name: :new_name]` | | [`argument_names`](#graphql-argument_names){: #graphql-argument_names } | `keyword` | | A nested keyword list of action names, to argument name remappings. i.e `create: [arg_name: :new_name]` |
| [`keyset_field`](#graphql-keyset_field){: #graphql-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 | | [`keyset_field`](#graphql-keyset_field){: #graphql-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`](#graphql-attribute_types){: #graphql-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_types`](#graphql-attribute_types){: #graphql-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. |
@ -322,7 +322,7 @@ create :create_post, :create
| Name | Type | Default | Docs | | Name | Type | Default | Docs |
|------|------|---------|------| |------|------|---------|------|
| [`upsert?`](#graphql-mutations-create-upsert?){: #graphql-mutations-create-upsert? } | `boolean` | `false` | Whether or not to use the `upsert?: true` option when calling `YourApi.create/2`. | | [`upsert?`](#graphql-mutations-create-upsert?){: #graphql-mutations-create-upsert? } | `boolean` | `false` | Whether or not to use the `upsert?: true` option when calling `YourDomain.create/2`. |
| [`upsert_identity`](#graphql-mutations-create-upsert_identity){: #graphql-mutations-create-upsert_identity } | `atom` | `false` | Which identity to use for the upsert | | [`upsert_identity`](#graphql-mutations-create-upsert_identity){: #graphql-mutations-create-upsert_identity } | `atom` | `false` | Which identity to use for the upsert |
| [`modify_resolution`](#graphql-mutations-create-modify_resolution){: #graphql-mutations-create-modify_resolution } | `mfa` | | An MFA that will be called with the resolution, the query, and the result of the action as the first three arguments. See the [the guide](/documentation/topics/modifying-the-resolution.html) for more. | | [`modify_resolution`](#graphql-mutations-create-modify_resolution){: #graphql-mutations-create-modify_resolution } | `mfa` | | An MFA that will be called with the resolution, the query, and the result of the action as the first three arguments. See the [the guide](/documentation/topics/modifying-the-resolution.html) for more. |
| [`hide_inputs`](#graphql-mutations-create-hide_inputs){: #graphql-mutations-create-hide_inputs } | `list(atom)` | `[]` | A list of inputs to hide from the mutation. | | [`hide_inputs`](#graphql-mutations-create-hide_inputs){: #graphql-mutations-create-hide_inputs } | `list(atom)` | `[]` | A list of inputs to hide from the mutation. |

View file

@ -6,7 +6,7 @@ AshGraphql uses three special keys in the `absinthe` context:
* `:tenant` - a tenant when using [multitenancy](https://ash-hq.org/docs/guides/ash/latest/topics/multitenancy.md). * `: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` * `: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 api is set to true. To disable authorization for a given API in graphql, use: By default, `authorize?` in the domain is set to true. To disable authorization for a given domain in graphql, use:
```elixir ```elixir
graphql do graphql do

View file

@ -1,6 +1,6 @@
# Handling Errors # Handling Errors
There are various options that can be set on the Api module to determine how errors behave and/or are shown in the GraphQL. There are various options that can be set on the Domain module to determine how errors behave and/or are shown in the GraphQL.
## Showing raised errors ## Showing raised errors
@ -12,9 +12,9 @@ graphql do
end end
# or it can be done in config # or it can be done in config
# make sure you've set `otp_app` in your api, i.e use Ash.Api, otp_app: :my_app # make sure you've set `otp_app` in your domain, i.e use Ash.Domain, otp_app: :my_app
config :my_app, YourApi, [ config :my_app, YourDomain, [
graphql: [ graphql: [
show_raised_errors?: true show_raised_errors?: true
] ]

View file

@ -18,11 +18,11 @@ subscription do
# loads all the data you need # loads all the data you need
AshGraphql.Subscription.query_for_subscription( AshGraphql.Subscription.query_for_subscription(
YourResource, YourResource,
YourAPi, YourDomain,
resolution resolution
) )
|> Ash.Query.filter(id == ^args.id) |> Ash.Query.filter(id == ^args.id)
|> YourAPi.read(actor: resolution.context.current_user) |> Ash.read(actor: resolution.context.current_user)
end) end)
end end
end end

View file

@ -9,11 +9,13 @@ defmodule MyApp.Armor do
types: [ types: [
plate: [ plate: [
# This is an embedded resource, with its own fields # This is an embedded resource, with its own fields
type: MyApp.Armor.Plate type: :struct,
constraints: [MyApp.Armor.Plate]
], ],
chain_mail: [ chain_mail: [
# And so is this # And so is this
type: MyApp.Armor.ChainMail type: :struct,
constraints: [instance_of: MyApp.Armor.ChainMail]
], ],
custom: [ custom: [
type: :string type: :string

View file

@ -247,11 +247,11 @@ mutation($input: CreateTicketInput!) {
- Validation errors are wrapped in a list of error objects under `errors`, also specified in the query. - Validation errors are wrapped in a list of error objects under `errors`, also specified in the query.
AshGraphql does this by default instead of exposing errors in GraphQL's standard `errors` array. AshGraphql does this by default instead of exposing errors in GraphQL's standard `errors` array.
This behavior can be changed by setting `root_level_errors? true` in the `graphql` section This behavior can be changed by setting `root_level_errors? true` in the `graphql` section
of your Ash API module: of your Ash domain module:
```elixir ```elixir
defmodule Helpdesk.Support do defmodule Helpdesk.Support do
use Ash.Api, extensions: [AshGraphql.Api] use Ash.Domain, extensions: [AshGraphql.Domain]
graphql do graphql do
root_level_errors? true root_level_errors? true
@ -302,4 +302,4 @@ If you haven't already, please turn on the documentation tag for AshGraphql. Tag
at the top of the left navigation menu, under "Including Libraries:". at the top of the left navigation menu, under "Including Libraries:".
- [Getting Started With GraphQL](/documentation/tutorials/getting-started-with-graphql.md) - [Getting Started With GraphQL](/documentation/tutorials/getting-started-with-graphql.md)
- `AshGraphql.Api` - `AshGraphql.Domain`

View file

@ -2,7 +2,7 @@
Please read [the Ash monitoring guide](https://hexdocs.pm/ash/monitoring.html) for more information. Here we simply cover the additional traces & telemetry events that we publish from this extension. Please read [the Ash monitoring guide](https://hexdocs.pm/ash/monitoring.html) for more information. Here we simply cover the additional traces & telemetry events that we publish from this extension.
A tracer can be configured in the api. It will fallback to the global tracer configuration `config :ash, :tracer, Tracer` A tracer can be configured in the domain. It will fallback to the global tracer configuration `config :ash, :tracer, Tracer`
```elixir ```elixir
graphql do graphql do
@ -18,13 +18,13 @@ Each graphql resolver, and batch resolution of the underlying data loader, will
AshGraphql emits the following telemetry events, suffixed with `:start` and `:stop`. Start events have `system_time` measurements, and stop events have `system_time` and `duration` measurements. All times will be in the native time unit. AshGraphql emits the following telemetry events, suffixed with `:start` and `:stop`. Start events have `system_time` measurements, and stop events have `system_time` and `duration` measurements. All times will be in the native time unit.
- `[:ash, <api_short_name>, :gql_mutation]` - The execution of a mutation. Use `resource_short_name` and `mutation` (or `action`) metadata to break down measurements. - `[:ash, <domain_short_name>, :gql_mutation]` - The execution of a mutation. Use `resource_short_name` and `mutation` (or `action`) metadata to break down measurements.
- `[:ash, <api_short_name>, :gql_query]` - The execution of a mutation. Use `resource_short_name` and `query` (or `action`) metadata to break down measurements. - `[:ash, <domain_short_name>, :gql_query]` - The execution of a mutation. Use `resource_short_name` and `query` (or `action`) metadata to break down measurements.
- `[:ash, <api_short_name>, :gql_relationship]` - The resolution of a relationship. Use `resource_short_name` and `relationship` metadata to break down measurements. - `[:ash, <domain_short_name>, :gql_relationship]` - The resolution of a relationship. Use `resource_short_name` and `relationship` metadata to break down measurements.
- `[:ash, <api_short_name>, :gql_calculation]` - The resolution of a calculation. Use `resource_short_name` and `calculation` metadata to break down measurements. - `[:ash, <domain_short_name>, :gql_calculation]` - The resolution of a calculation. Use `resource_short_name` and `calculation` metadata to break down measurements.
- `[:ash, <api_short_name>, :gql_relationship_batch]` - The resolution of a batch of relationships by the data loader. Use `resource_short_name` and `relationship` metadata to break down measurements. - `[:ash, <domain_short_name>, :gql_relationship_batch]` - The resolution of a batch of relationships by the data loader. Use `resource_short_name` and `relationship` metadata to break down measurements.
- `[:ash, <api_short_name>, :gql_calculation_batch]` - The resolution of a batch of calculations by the data loader. Use `resource_short_name` and `calculation` metadata to break down measurements. - `[:ash, <domain_short_name>, :gql_calculation_batch]` - The resolution of a batch of calculations by the data loader. Use `resource_short_name` and `calculation` metadata to break down measurements.

View file

@ -2,7 +2,7 @@
## Get familiar with Ash resources ## Get familiar with Ash resources
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/apis. 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.
## Bring in the ash_graphql dependency ## Bring in the ash_graphql dependency
@ -26,18 +26,18 @@ config :ash_graphql, :allow_non_null_mutation_arguments?, true
This won't be necessary after the next major release, where this new configuration will be the default. This won't be necessary after the next major release, where this new configuration will be the default.
## Add the API Extension ## Add the domain Extension
Add the following to your API module. If you don't have one, be sure to start with the [Ash Getting Started Guide](https://hexdocs.pm/ash/get-started.html). Add the following to your domain module. If you don't have one, be sure to start with the [Ash Getting Started Guide](https://hexdocs.pm/ash/get-started.html).
```elixir ```elixir
defmodule Helpdesk.Support do defmodule Helpdesk.Support do
use Ash.Api, extensions: [ use Ash.Domain, extensions: [
AshGraphql.Api AshGraphql.Domain
] ]
graphql do graphql do
authorize? false # Defaults to `true`, use this to disable authorization for the entire API (you probably only want this while prototyping) authorize? false # Defaults to `true`, use this to disable authorization for the entire domain (you probably only want this while prototyping)
end end
... ...
@ -94,9 +94,9 @@ in `lib/helpdesk/schema.ex`
defmodule Helpdesk.Schema do defmodule Helpdesk.Schema do
use Absinthe.Schema use Absinthe.Schema
@apis [Helpdesk.Support] @domains [Helpdesk.Support]
use AshGraphql, apis: @apis use AshGraphql, domains: @domains
# The query and mutation blocks is where you can add custom absinthe code # The query and mutation blocks is where you can add custom absinthe code
query do query do

View file

@ -1,44 +0,0 @@
defmodule AshGraphql.Api.Info do
@moduledoc "Introspection helpers for AshGraphql.Api"
alias Spark.Dsl.Extension
@doc "Wether or not to run authorization on this api"
def authorize?(api) do
Extension.get_opt(api, [:graphql], :authorize?, true)
end
@doc "The tracer to use for the given schema"
def tracer(api) do
api
|> Extension.get_opt([:graphql], :tracer, nil, true)
|> List.wrap()
|> Enum.concat(List.wrap(Application.get_env(:ash, :tracer)))
end
@doc "Wether or not to surface errors to the root of the response"
def root_level_errors?(api) do
Extension.get_opt(api, [:graphql], :root_level_errors?, false, true)
end
@doc "An error handler for errors produced by api"
def error_handler(api) do
Extension.get_opt(
api,
[:graphql],
:error_handler,
{AshGraphql.DefaultErrorHandler, :handle_error, []},
true
)
end
@doc "Wether or not to render raised errors in the graphql response"
def show_raised_errors?(api) do
Extension.get_opt(api, [:graphql], :show_raised_errors?, false, true)
end
@doc "Wether or not to pass debug? down to internal execution"
def debug?(api) do
Extension.get_opt(api, [:graphql], :debug?, false)
end
end

View file

@ -33,14 +33,14 @@ defmodule AshGraphql do
defmacro __using__(opts) do defmacro __using__(opts) do
quote bind_quoted: [ quote bind_quoted: [
apis: opts[:apis], domains: opts[:domains],
api: opts[:api], domain: opts[:domain],
action_middleware: opts[:action_middleware] || [], action_middleware: opts[:action_middleware] || [],
define_relay_types?: Keyword.get(opts, :define_relay_types?, true), define_relay_types?: Keyword.get(opts, :define_relay_types?, true),
relay_ids?: Keyword.get(opts, :relay_ids?, false) relay_ids?: Keyword.get(opts, :relay_ids?, false)
], ],
generated: true do generated: true do
require Ash.Api.Info require Ash.Domain.Info
import Absinthe.Schema, import Absinthe.Schema,
except: [ except: [
@ -52,34 +52,34 @@ defmodule AshGraphql do
mutation: 1 mutation: 1
] ]
apis = domains =
api domain
|> List.wrap() |> List.wrap()
|> Kernel.++(List.wrap(apis)) |> Kernel.++(List.wrap(domains))
apis = domains =
apis domains
|> Enum.map(fn |> Enum.map(fn
{api, registry} -> {domain, registry} ->
IO.warn(""" IO.warn("""
It is no longer required to list the registry along with an API when using `AshGraphql` It is no longer required to list the registry along with a domain when using `AshGraphql`
use AshGraphql, apis: [{My.App.Api, My.App.Registry}] use AshGraphql, domains: [{My.App.Domain, My.App.Registry}]
Can now be stated simply as Can now be stated simply as
use AshGraphql, apis: [My.App.Api] use AshGraphql, domains: [My.App.Domain]
""") """)
api domain
api -> domain ->
api domain
end) end)
|> Enum.map(fn api -> {api, Ash.Api.Info.depend_on_resources(api), false} end) |> Enum.map(fn domain -> {domain, Ash.Domain.Info.resources(domain), false} end)
|> List.update_at(0, fn {api, resources, _} -> {api, resources, true} end) |> List.update_at(0, fn {domain, resources, _} -> {domain, resources, true} end)
@ash_resources Enum.flat_map(apis, &elem(&1, 1)) @ash_resources Enum.flat_map(domains, &elem(&1, 1))
ash_resources = @ash_resources ash_resources = @ash_resources
schema = __MODULE__ schema = __MODULE__
@ -119,8 +119,8 @@ defmodule AshGraphql do
end) end)
end end
for {api, resources, first?} <- apis do for {domain, resources, first?} <- domains do
defmodule Module.concat(api, AshTypes) do defmodule Module.concat(domain, AshTypes) do
@moduledoc false @moduledoc false
alias Absinthe.{Blueprint, Phase, Pipeline} alias Absinthe.{Blueprint, Phase, Pipeline}
@ -134,12 +134,12 @@ defmodule AshGraphql do
@dialyzer {:nowarn_function, {:run, 2}} @dialyzer {:nowarn_function, {:run, 2}}
def run(blueprint, _opts) do def run(blueprint, _opts) do
api = unquote(api) domain = unquote(domain)
action_middleware = unquote(action_middleware) action_middleware = unquote(action_middleware)
api_queries = domain_queries =
AshGraphql.Api.queries( AshGraphql.Domain.queries(
api, domain,
unquote(resources), unquote(resources),
action_middleware, action_middleware,
__MODULE__, __MODULE__,
@ -148,21 +148,21 @@ defmodule AshGraphql do
relay_queries = relay_queries =
if unquote(first?) and unquote(define_relay_types?) and unquote(relay_ids?) do if unquote(first?) and unquote(define_relay_types?) and unquote(relay_ids?) do
apis_with_resources = unquote(Enum.map(apis, &{elem(&1, 0), elem(&1, 1)})) domains_with_resources = unquote(Enum.map(domains, &{elem(&1, 0), elem(&1, 1)}))
AshGraphql.relay_queries(apis_with_resources, unquote(schema), __ENV__) AshGraphql.relay_queries(domains_with_resources, unquote(schema), __ENV__)
else else
[] []
end end
blueprint_with_queries = blueprint_with_queries =
(relay_queries ++ api_queries) (relay_queries ++ domain_queries)
|> Enum.reduce(blueprint, fn query, blueprint -> |> Enum.reduce(blueprint, fn query, blueprint ->
Absinthe.Blueprint.add_field(blueprint, "RootQueryType", query) Absinthe.Blueprint.add_field(blueprint, "RootQueryType", query)
end) end)
blueprint_with_mutations = blueprint_with_mutations =
api domain
|> AshGraphql.Api.mutations( |> AshGraphql.Domain.mutations(
unquote(resources), unquote(resources),
action_middleware, action_middleware,
__MODULE__, __MODULE__,
@ -174,7 +174,7 @@ defmodule AshGraphql do
type_definitions = type_definitions =
if unquote(first?) do if unquote(first?) do
apis = unquote(Enum.map(apis, &elem(&1, 0))) domains = unquote(Enum.map(domains, &elem(&1, 0)))
embedded_types = embedded_types =
AshGraphql.get_embedded_types( AshGraphql.get_embedded_types(
@ -190,9 +190,9 @@ defmodule AshGraphql do
AshGraphql.global_unions(unquote(ash_resources), unquote(schema), __ENV__) AshGraphql.global_unions(unquote(ash_resources), unquote(schema), __ENV__)
Enum.uniq_by( Enum.uniq_by(
AshGraphql.Api.global_type_definitions(unquote(schema), __ENV__) ++ AshGraphql.Domain.global_type_definitions(unquote(schema), __ENV__) ++
AshGraphql.Api.type_definitions( AshGraphql.Domain.type_definitions(
api, domain,
unquote(resources), unquote(resources),
unquote(schema), unquote(schema),
__ENV__, __ENV__,
@ -206,8 +206,8 @@ defmodule AshGraphql do
& &1.identifier & &1.identifier
) )
else else
AshGraphql.Api.type_definitions( AshGraphql.Domain.type_definitions(
api, domain,
unquote(resources), unquote(resources),
unquote(schema), unquote(schema),
__ENV__, __ENV__,
@ -235,7 +235,7 @@ defmodule AshGraphql do
import_types(AshGraphql.Types.JSONString) import_types(AshGraphql.Types.JSONString)
end end
@pipeline_modifier Module.concat(api, AshTypes) @pipeline_modifier Module.concat(domain, AshTypes)
end end
end end
end end
@ -386,16 +386,16 @@ defmodule AshGraphql do
end end
end end
def relay_queries(apis_with_resources, schema, env) do def relay_queries(domains_with_resources, schema, env) do
type_to_api_and_resource_map = type_to_domain_and_resource_map =
apis_with_resources domains_with_resources
|> Enum.flat_map(fn {api, resources} -> |> Enum.flat_map(fn {domain, resources} ->
resources resources
|> Enum.flat_map(fn resource -> |> Enum.flat_map(fn resource ->
type = AshGraphql.Resource.Info.type(resource) type = AshGraphql.Resource.Info.type(resource)
if type do if type do
[{type, {api, resource}}] [{type, {domain, resource}}]
else else
[] []
end end
@ -419,7 +419,7 @@ defmodule AshGraphql do
} }
], ],
middleware: [ middleware: [
{{AshGraphql.Graphql.Resolver, :resolve_node}, type_to_api_and_resource_map} {{AshGraphql.Graphql.Resolver, :resolve_node}, type_to_domain_and_resource_map}
], ],
complexity: {AshGraphql.Graphql.Resolver, :query_complexity}, complexity: {AshGraphql.Graphql.Resolver, :query_complexity},
module: schema, module: schema,
@ -458,7 +458,7 @@ defmodule AshGraphql do
defp nested_attrs(type, constraints, already_checked) do defp nested_attrs(type, constraints, already_checked) do
cond do cond do
Ash.Type.embedded_type?(type) -> AshGraphql.Resource.embedded?(type) ->
type type
|> unwrap_type() |> unwrap_type()
|> all_attributes_and_arguments(already_checked, true, true) |> all_attributes_and_arguments(already_checked, true, true)
@ -625,7 +625,7 @@ defmodule AshGraphql do
attribute.constraints[:types] attribute.constraints[:types]
|> Kernel.||([]) |> Kernel.||([])
|> Enum.flat_map(fn {name, config} -> |> Enum.flat_map(fn {name, config} ->
if Ash.Type.embedded_type?(config[:type]) do if AshGraphql.Resource.embedded?(config[:type]) do
[ [
{source_resource, {source_resource,
%{ %{
@ -641,7 +641,7 @@ defmodule AshGraphql do
end) end)
other -> other ->
if Ash.Type.embedded_type?(other) do if AshGraphql.Resource.embedded?(other) do
[{source_resource, attribute}] [{source_resource, attribute}]
else else
[] []
@ -661,7 +661,7 @@ defmodule AshGraphql do
[ [
AshGraphql.Resource.type_definition( AshGraphql.Resource.type_definition(
embedded_type, embedded_type,
Module.concat(embedded_type, ShadowApi), Module.concat(embedded_type, ShadowDomain),
schema, schema,
relay_ids? relay_ids?
), ),
@ -732,7 +732,7 @@ defmodule AshGraphql do
defp get_nested_embedded_types(embedded_type) do defp get_nested_embedded_types(embedded_type) do
embedded_type embedded_type
|> Ash.Resource.Info.public_attributes() |> Ash.Resource.Info.public_attributes()
|> Enum.filter(&Ash.Type.embedded_type?(&1.type)) |> Enum.filter(&AshGraphql.Resource.embedded?(&1.type))
|> Enum.map(fn attribute -> |> Enum.map(fn attribute ->
{attribute, unwrap_type(attribute.type)} {attribute, unwrap_type(attribute.type)}
end) end)
@ -742,7 +742,7 @@ defmodule AshGraphql do
end end
@deprecated "add_context is no longer necessary" @deprecated "add_context is no longer necessary"
def add_context(ctx, _apis, _options \\ []) do def add_context(ctx, _domains, _options \\ []) do
ctx ctx
end end
end end

View file

@ -1,4 +1,4 @@
defmodule AshGraphql.Api do defmodule AshGraphql.Domain do
@graphql %Spark.Dsl.Section{ @graphql %Spark.Dsl.Section{
name: :graphql, name: :graphql,
describe: """ describe: """
@ -7,14 +7,14 @@ defmodule AshGraphql.Api do
examples: [ examples: [
""" """
graphql do graphql do
authorize? false # To skip authorization for this API authorize? false # To skip authorization for this domain
end end
""" """
], ],
schema: [ schema: [
authorize?: [ authorize?: [
type: :boolean, type: :boolean,
doc: "Whether or not to perform authorization for this API", doc: "Whether or not to perform authorization for this domain",
default: true default: true
], ],
tracer: [ tracer: [
@ -40,11 +40,6 @@ defmodule AshGraphql.Api do
default: false, default: false,
doc: doc:
"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." "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."
],
debug?: [
type: :boolean,
doc: "Whether or not to log (extremely verbose) debug information",
default: false
] ]
] ]
} }
@ -52,52 +47,49 @@ defmodule AshGraphql.Api do
@sections [@graphql] @sections [@graphql]
@moduledoc """ @moduledoc """
The entrypoint for adding graphql behavior to an Ash API The entrypoint for adding graphql behavior to an Ash domain
""" """
require Ash.Api.Info require Ash.Domain.Info
use Spark.Dsl.Extension, sections: @sections use Spark.Dsl.Extension, sections: @sections
@deprecated "See `AshGraphql.Api.Info.authorize?/1`" @deprecated "See `AshGraphql.Domain.Info.authorize?/1`"
defdelegate authorize?(api), to: AshGraphql.Api.Info defdelegate authorize?(domain), to: AshGraphql.Domain.Info
@deprecated "See `AshGraphql.Api.Info.root_level_errors?/1`" @deprecated "See `AshGraphql.Domain.Info.root_level_errors?/1`"
defdelegate root_level_errors?(api), to: AshGraphql.Api.Info defdelegate root_level_errors?(domain), to: AshGraphql.Domain.Info
@deprecated "See `AshGraphql.Api.Info.show_raised_errors?/1`" @deprecated "See `AshGraphql.Domain.Info.show_raised_errors?/1`"
defdelegate show_raised_errors?(api), to: AshGraphql.Api.Info defdelegate show_raised_errors?(domain), to: AshGraphql.Domain.Info
@deprecated "See `AshGraphql.Api.Info.debug?/1`"
defdelegate debug?(api), to: AshGraphql.Api.Info
@doc false @doc false
def queries(api, resources, action_middleware, schema, relay_ids?) do def queries(domain, resources, action_middleware, schema, relay_ids?) do
Enum.flat_map( Enum.flat_map(
resources, resources,
&AshGraphql.Resource.queries(api, &1, action_middleware, schema, relay_ids?) &AshGraphql.Resource.queries(domain, &1, action_middleware, schema, relay_ids?)
) )
end end
@doc false @doc false
def mutations(api, resources, action_middleware, schema, relay_ids?) do def mutations(domain, resources, action_middleware, schema, relay_ids?) do
resources resources
|> Enum.filter(fn resource -> |> Enum.filter(fn resource ->
AshGraphql.Resource in Spark.extensions(resource) AshGraphql.Resource in Spark.extensions(resource)
end) end)
|> Enum.flat_map( |> Enum.flat_map(
&AshGraphql.Resource.mutations(api, &1, action_middleware, schema, relay_ids?) &AshGraphql.Resource.mutations(domain, &1, action_middleware, schema, relay_ids?)
) )
end end
@doc false @doc false
def type_definitions(api, resources, schema, env, first?, define_relay_types?, relay_ids?) do def type_definitions(domain, resources, schema, env, first?, define_relay_types?, relay_ids?) do
resource_types = resource_types =
resources resources
|> Enum.reject(&Ash.Resource.Info.embedded?/1) |> Enum.reject(&Ash.Resource.Info.embedded?/1)
|> Enum.flat_map(fn resource -> |> Enum.flat_map(fn resource ->
if AshGraphql.Resource in Spark.extensions(resource) do if AshGraphql.Resource in Spark.extensions(resource) do
AshGraphql.Resource.type_definitions(resource, api, schema, relay_ids?) ++ AshGraphql.Resource.type_definitions(resource, domain, schema, relay_ids?) ++
AshGraphql.Resource.mutation_types(resource, schema) AshGraphql.Resource.mutation_types(resource, schema)
else else
AshGraphql.Resource.no_graphql_types(resource, schema) AshGraphql.Resource.no_graphql_types(resource, schema)

39
lib/domain/info.ex Normal file
View file

@ -0,0 +1,39 @@
defmodule AshGraphql.Domain.Info do
@moduledoc "Introspection helpers for AshGraphql.Domain"
alias Spark.Dsl.Extension
@doc "Wether or not to run authorization on this domain"
def authorize?(domain) do
Extension.get_opt(domain, [:graphql], :authorize?, true)
end
@doc "The tracer to use for the given schema"
def tracer(domain) do
domain
|> Extension.get_opt([:graphql], :tracer, nil, true)
|> List.wrap()
|> Enum.concat(List.wrap(Application.get_env(:ash, :tracer)))
end
@doc "Wether or not to surface errors to the root of the response"
def root_level_errors?(domain) do
Extension.get_opt(domain, [:graphql], :root_level_errors?, false, true)
end
@doc "An error handler for errors produced by domain"
def error_handler(domain) do
Extension.get_opt(
domain,
[:graphql],
:error_handler,
{AshGraphql.DefaultErrorHandler, :handle_error, []},
true
)
end
@doc "Wether or not to render raised errors in the graphql response"
def show_raised_errors?(domain) do
Extension.get_opt(domain, [:graphql], :show_raised_errors?, false, true)
end
end

View file

@ -8,7 +8,6 @@ defimpl AshGraphql.Error, for: Ash.Error.Changes.InvalidChanges do
message: error.message, message: error.message,
short_message: error.message, short_message: error.message,
vars: Map.new(error.vars), vars: Map.new(error.vars),
code: Ash.ErrorKind.code(error),
fields: List.wrap(error.fields) fields: List.wrap(error.fields)
} }
end end
@ -20,7 +19,6 @@ defimpl AshGraphql.Error, for: Ash.Error.Query.InvalidQuery do
message: error.message, message: error.message,
short_message: error.message, short_message: error.message,
vars: Map.new(error.vars), vars: Map.new(error.vars),
code: Ash.ErrorKind.code(error),
fields: [error.field] fields: [error.field]
} }
end end
@ -32,7 +30,6 @@ defimpl AshGraphql.Error, for: Ash.Error.Page.InvalidKeyset do
message: "Invalid value provided as a keyset for %{key}: %{value}", message: "Invalid value provided as a keyset for %{key}: %{value}",
short_message: "invalid keyset", short_message: "invalid keyset",
vars: Map.merge(Map.new(error.vars), %{value: inspect(error.value), key: error.key}), vars: Map.merge(Map.new(error.vars), %{value: inspect(error.value), key: error.key}),
code: Ash.ErrorKind.code(error),
fields: List.wrap(Map.get(error, :key)) fields: List.wrap(Map.get(error, :key))
} }
end end
@ -44,7 +41,6 @@ defimpl AshGraphql.Error, for: Ash.Error.Changes.InvalidAttribute do
message: error.message, message: error.message,
short_message: error.message, short_message: error.message,
vars: Map.new(error.vars), vars: Map.new(error.vars),
code: Ash.ErrorKind.code(error),
fields: [error.field] fields: [error.field]
} }
end end
@ -54,7 +50,6 @@ defimpl AshGraphql.Error, for: Ash.Error.Changes.InvalidArgument do
def to_error(error) do def to_error(error) do
%{ %{
message: error.message, message: error.message,
code: Ash.ErrorKind.code(error),
short_message: error.message, short_message: error.message,
vars: Map.new(error.vars), vars: Map.new(error.vars),
fields: [error.field] fields: [error.field]
@ -66,7 +61,6 @@ defimpl AshGraphql.Error, for: Ash.Error.Query.InvalidArgument do
def to_error(error) do def to_error(error) do
%{ %{
message: error.message, message: error.message,
code: Ash.ErrorKind.code(error),
short_message: error.message, short_message: error.message,
vars: Map.new(error.vars), vars: Map.new(error.vars),
fields: [error.field] fields: [error.field]
@ -79,7 +73,6 @@ defimpl AshGraphql.Error, for: Ash.Error.Changes.Required do
%{ %{
message: "is required", message: "is required",
short_message: "is required", short_message: "is required",
code: Ash.ErrorKind.code(error),
vars: error.vars, vars: error.vars,
fields: [error.field] fields: [error.field]
} }
@ -92,8 +85,7 @@ defimpl AshGraphql.Error, for: Ash.Error.Query.NotFound do
message: "could not be found", message: "could not be found",
short_message: "could not be found", short_message: "could not be found",
fields: Map.keys(error.primary_key || %{}), fields: Map.keys(error.primary_key || %{}),
vars: error.vars, vars: error.vars
code: Ash.ErrorKind.code(error)
} }
end end
end end
@ -104,7 +96,6 @@ defimpl AshGraphql.Error, for: Ash.Error.Query.Required do
message: "is required", message: "is required",
short_message: "is required", short_message: "is required",
vars: error.vars, vars: error.vars,
code: Ash.ErrorKind.code(error),
fields: [error.field] fields: [error.field]
} }
end end
@ -148,8 +139,7 @@ defimpl AshGraphql.Error, for: Ash.Error.Invalid.InvalidPrimaryKey do
message: "invalid primary key provided", message: "invalid primary key provided",
short_message: "invalid primary key provided", short_message: "invalid primary key provided",
fields: [], fields: [],
vars: Map.new(error.vars), vars: Map.new(error.vars)
code: Ash.ErrorKind.code(error)
} }
end end
end end

View file

@ -1,6 +0,0 @@
defmodule AshGraphql.Graphql.ApiMiddleware do
@moduledoc false
def set_api(resolution, api) do
Map.update!(resolution, :context, &Map.put(&1, :api, api))
end
end

View file

@ -0,0 +1,6 @@
defmodule AshGraphql.Graphql.DomainMiddleware do
@moduledoc false
def set_domain(resolution, domain) do
Map.update!(resolution, :context, &Map.put(&1, :domain, domain))
end
end

View file

@ -7,14 +7,14 @@ defmodule AshGraphql.Errors do
@doc """ @doc """
Transform an error or list of errors into the response for graphql. Transform an error or list of errors into the response for graphql.
""" """
def to_errors(errors, context, api) do def to_errors(errors, context, domain) do
errors errors
|> AshGraphql.Graphql.Resolver.unwrap_errors() |> AshGraphql.Graphql.Resolver.unwrap_errors()
|> Enum.map(fn error -> |> Enum.map(fn error ->
if AshGraphql.Error.impl_for(error) do if AshGraphql.Error.impl_for(error) do
error = AshGraphql.Error.to_error(error) error = AshGraphql.Error.to_error(error)
case AshGraphql.Api.Info.error_handler(api) do case AshGraphql.Domain.Info.error_handler(domain) do
nil -> nil ->
error error

File diff suppressed because it is too large Load diff

View file

@ -94,12 +94,12 @@ defmodule AshGraphql.Resource.Info do
Extension.get_opt(resource, [:graphql], :field_names, []) Extension.get_opt(resource, [:graphql], :field_names, [])
end end
@doc "Fields to hide from the graphql api" @doc "Fields to hide from the graphql domain"
def hide_fields(resource) do def hide_fields(resource) do
Extension.get_opt(resource, [:graphql], :hide_fields, []) Extension.get_opt(resource, [:graphql], :hide_fields, [])
end end
@doc "Fields to show in the graphql api" @doc "Fields to show in the graphql domain"
def show_fields(resource) do def show_fields(resource) do
Extension.get_opt(resource, [:graphql], :show_fields, nil) Extension.get_opt(resource, [:graphql], :show_fields, nil)
end end

View file

@ -27,7 +27,7 @@ defmodule AshGraphql.Resource.Mutation do
upsert?: [ upsert?: [
type: :boolean, type: :boolean,
default: false, default: false,
doc: "Whether or not to use the `upsert?: true` option when calling `YourApi.create/2`." doc: "Whether or not to use the `upsert?: true` option when calling `YourDomain.create/2`."
], ],
upsert_identity: [ upsert_identity: [
type: :atom, type: :atom,

View file

@ -89,7 +89,7 @@ defmodule AshGraphql.Resource.Query do
""" """
] ]
] ]
|> Spark.OptionsHelpers.merge_schemas(@query_schema, "Shared Query Options") |> Spark.Options.merge(@query_schema, "Shared Query Options")
@read_one_schema [ @read_one_schema [
allow_nil?: [ allow_nil?: [
@ -98,7 +98,7 @@ defmodule AshGraphql.Resource.Query do
doc: "Whether or not the action can return nil." doc: "Whether or not the action can return nil."
] ]
] ]
|> Spark.OptionsHelpers.merge_schemas(@query_schema, "Shared Query Options") |> Spark.Options.merge(@query_schema, "Shared Query Options")
@list_schema [ @list_schema [
relay?: [ relay?: [
@ -116,7 +116,7 @@ defmodule AshGraphql.Resource.Query do
""" """
] ]
] ]
|> Spark.OptionsHelpers.merge_schemas(@query_schema, "Shared Query Options") |> Spark.Options.merge(@query_schema, "Shared Query Options")
def get_schema, do: @get_schema def get_schema, do: @get_schema
def read_one_schema, do: @read_one_schema def read_one_schema, do: @read_one_schema

View file

@ -316,12 +316,12 @@ defmodule AshGraphql.Resource do
], ],
hide_fields: [ hide_fields: [
type: {:list, :atom}, type: {:list, :atom},
doc: "A list of attributes to hide from the api" doc: "A list of attributes to hide from the domain"
], ],
show_fields: [ show_fields: [
type: {:list, :atom}, type: {:list, :atom},
doc: doc:
"A list of attributes to show in the api. If not specified includes all (excluding `hide_fiels`)." "A list of attributes to show in the domain. If not specified includes all (excluding `hide_fiels`)."
], ],
argument_names: [ argument_names: [
type: :keyword_list, type: :keyword_list,
@ -498,7 +498,7 @@ defmodule AshGraphql.Resource do
end end
@doc false @doc false
def queries(api, resource, action_middleware, schema, relay_ids?, as_mutations? \\ false) do def queries(domain, resource, action_middleware, schema, relay_ids?, as_mutations? \\ false) do
resource resource
|> queries() |> queries()
|> Enum.filter(&(Map.get(&1, :as_mutation?, false) == as_mutations?)) |> Enum.filter(&(Map.get(&1, :as_mutation?, false) == as_mutations?))
@ -513,10 +513,10 @@ defmodule AshGraphql.Resource do
identifier: name, identifier: name,
middleware: middleware:
action_middleware ++ action_middleware ++
api_middleware(api) ++ domain_middleware(domain) ++
id_translation_middleware(query.relay_id_translations, relay_ids?) ++ id_translation_middleware(query.relay_id_translations, relay_ids?) ++
[ [
{{AshGraphql.Graphql.Resolver, :resolve}, {api, resource, query, false}} {{AshGraphql.Graphql.Resolver, :resolve}, {domain, resource, query, false}}
], ],
complexity: {AshGraphql.Graphql.Resolver, :query_complexity}, complexity: {AshGraphql.Graphql.Resolver, :query_complexity},
module: schema, module: schema,
@ -554,10 +554,10 @@ defmodule AshGraphql.Resource do
identifier: query.name, identifier: query.name,
middleware: middleware:
action_middleware ++ action_middleware ++
api_middleware(api) ++ domain_middleware(domain) ++
id_translation_middleware(query.relay_id_translations, relay_ids?) ++ id_translation_middleware(query.relay_id_translations, relay_ids?) ++
[ [
{{AshGraphql.Graphql.Resolver, :resolve}, {api, resource, query, relay_ids?}} {{AshGraphql.Graphql.Resolver, :resolve}, {domain, resource, query, relay_ids?}}
], ],
complexity: {AshGraphql.Graphql.Resolver, :query_complexity}, complexity: {AshGraphql.Graphql.Resolver, :query_complexity},
module: schema, module: schema,
@ -571,7 +571,7 @@ defmodule AshGraphql.Resource do
# sobelow_skip ["DOS.StringToAtom"] # sobelow_skip ["DOS.StringToAtom"]
@doc false @doc false
def mutations(api, resource, action_middleware, schema, relay_ids?) do def mutations(domain, resource, action_middleware, schema, relay_ids?) do
resource resource
|> mutations() |> mutations()
|> Enum.map(fn |> Enum.map(fn
@ -602,10 +602,10 @@ defmodule AshGraphql.Resource do
identifier: name, identifier: name,
middleware: middleware:
action_middleware ++ action_middleware ++
api_middleware(api) ++ domain_middleware(domain) ++
id_translation_middleware(query.relay_id_translations, relay_ids?) ++ id_translation_middleware(query.relay_id_translations, relay_ids?) ++
[ [
{{AshGraphql.Graphql.Resolver, :resolve}, {api, resource, query, true}} {{AshGraphql.Graphql.Resolver, :resolve}, {domain, resource, query, true}}
], ],
complexity: {AshGraphql.Graphql.Resolver, :query_complexity}, complexity: {AshGraphql.Graphql.Resolver, :query_complexity},
module: schema, module: schema,
@ -621,22 +621,31 @@ defmodule AshGraphql.Resource do
raise "No such action #{mutation.action} for #{inspect(resource)}" raise "No such action #{mutation.action} for #{inspect(resource)}"
if action.soft? do if action.soft? do
update_mutation(resource, schema, mutation, schema, action_middleware, api, relay_ids?) update_mutation(
resource,
schema,
mutation,
schema,
action_middleware,
domain,
relay_ids?
)
else else
%Absinthe.Blueprint.Schema.FieldDefinition{ %Absinthe.Blueprint.Schema.FieldDefinition{
arguments: mutation_args(mutation, resource, schema), arguments: mutation_args(mutation, resource, schema),
identifier: mutation.name, identifier: mutation.name,
middleware: middleware:
action_middleware ++ action_middleware ++
api_middleware(api) ++ domain_middleware(domain) ++
id_translation_middleware(mutation.relay_id_translations, relay_ids?) ++ id_translation_middleware(mutation.relay_id_translations, relay_ids?) ++
[ [
{{AshGraphql.Graphql.Resolver, :mutate}, {api, resource, mutation, relay_ids?}} {{AshGraphql.Graphql.Resolver, :mutate},
{domain, resource, mutation, relay_ids?}}
], ],
module: schema, module: schema,
name: to_string(mutation.name), name: to_string(mutation.name),
description: Ash.Resource.Info.action(resource, mutation.action).description, description: Ash.Resource.Info.action(resource, mutation.action).description,
type: mutation_result_type(mutation.name, api), type: mutation_result_type(mutation.name, domain),
__reference__: ref(__ENV__) __reference__: ref(__ENV__)
} }
end end
@ -674,26 +683,26 @@ defmodule AshGraphql.Resource do
identifier: mutation.name, identifier: mutation.name,
middleware: middleware:
action_middleware ++ action_middleware ++
api_middleware(api) ++ domain_middleware(domain) ++
id_translation_middleware(mutation.relay_id_translations, relay_ids?) ++ id_translation_middleware(mutation.relay_id_translations, relay_ids?) ++
[ [
{{AshGraphql.Graphql.Resolver, :mutate}, {api, resource, mutation, relay_ids?}} {{AshGraphql.Graphql.Resolver, :mutate}, {domain, resource, mutation, relay_ids?}}
], ],
module: schema, module: schema,
name: to_string(mutation.name), name: to_string(mutation.name),
description: Ash.Resource.Info.action(resource, mutation.action).description, description: Ash.Resource.Info.action(resource, mutation.action).description,
type: mutation_result_type(mutation.name, api), type: mutation_result_type(mutation.name, domain),
__reference__: ref(__ENV__) __reference__: ref(__ENV__)
} }
mutation -> mutation ->
update_mutation(resource, schema, mutation, schema, action_middleware, api, relay_ids?) update_mutation(resource, schema, mutation, schema, action_middleware, domain, relay_ids?)
end) end)
|> Enum.concat(queries(api, resource, action_middleware, schema, relay_ids?, true)) |> Enum.concat(queries(domain, resource, action_middleware, schema, relay_ids?, true))
end end
# sobelow_skip ["DOS.StringToAtom"] # sobelow_skip ["DOS.StringToAtom"]
defp update_mutation(resource, schema, mutation, schema, action_middleware, api, relay_ids?) do defp update_mutation(resource, schema, mutation, schema, action_middleware, domain, relay_ids?) do
action = action =
Ash.Resource.Info.action(resource, mutation.action) || Ash.Resource.Info.action(resource, mutation.action) ||
raise "No such action #{mutation.action} for #{inspect(resource)}" raise "No such action #{mutation.action} for #{inspect(resource)}"
@ -728,23 +737,23 @@ defmodule AshGraphql.Resource do
identifier: mutation.name, identifier: mutation.name,
middleware: middleware:
action_middleware ++ action_middleware ++
api_middleware(api) ++ domain_middleware(domain) ++
id_translation_middleware(mutation.relay_id_translations, relay_ids?) ++ id_translation_middleware(mutation.relay_id_translations, relay_ids?) ++
[ [
{{AshGraphql.Graphql.Resolver, :mutate}, {api, resource, mutation, relay_ids?}} {{AshGraphql.Graphql.Resolver, :mutate}, {domain, resource, mutation, relay_ids?}}
], ],
module: schema, module: schema,
name: to_string(mutation.name), name: to_string(mutation.name),
description: Ash.Resource.Info.action(resource, mutation.action).description, description: Ash.Resource.Info.action(resource, mutation.action).description,
type: mutation_result_type(mutation.name, api), type: mutation_result_type(mutation.name, domain),
__reference__: ref(__ENV__) __reference__: ref(__ENV__)
} }
end end
# sobelow_skip ["DOS.StringToAtom"] # sobelow_skip ["DOS.StringToAtom"]
defp mutation_result_type(mutation_name, api) do defp mutation_result_type(mutation_name, domain) do
type = String.to_atom("#{mutation_name}_result") type = String.to_atom("#{mutation_name}_result")
root_level_errors? = AshGraphql.Api.Info.root_level_errors?(api) root_level_errors? = AshGraphql.Domain.Info.root_level_errors?(domain)
maybe_wrap_non_null(type, not root_level_errors?) maybe_wrap_non_null(type, not root_level_errors?)
end end
@ -827,7 +836,7 @@ defmodule AshGraphql.Resource do
end end
read_action.arguments read_action.arguments
|> Enum.reject(& &1.private?) |> Enum.filter(& &1.public?)
|> Enum.map(fn argument -> |> Enum.map(fn argument ->
type = type =
argument.type argument.type
@ -959,8 +968,8 @@ defmodule AshGraphql.Resource do
[] []
end end
defp api_middleware(api) do defp domain_middleware(domain) do
[{{AshGraphql.Graphql.ApiMiddleware, :set_api}, api}] [{{AshGraphql.Graphql.DomainMiddleware, :set_domain}, domain}]
end end
# sobelow_skip ["DOS.StringToAtom"] # sobelow_skip ["DOS.StringToAtom"]
@ -1113,7 +1122,7 @@ defmodule AshGraphql.Resource do
argument_fields = argument_fields =
action.arguments action.arguments
|> Enum.reject(& &1.private?) |> Enum.filter(& &1.public?)
|> Enum.map(fn argument -> |> Enum.map(fn argument ->
name = argument_names[action.name][argument.name] || argument.name name = argument_names[action.name][argument.name] || argument.name
@ -1180,7 +1189,7 @@ defmodule AshGraphql.Resource do
of_type: of_type:
maybe_wrap_non_null( maybe_wrap_non_null(
wrap_arrays(arg_type, type, constraints[:items] || []), wrap_arrays(arg_type, type, constraints[:items] || []),
!constraints[:nil_items?] || Ash.Type.embedded_type?(type) !constraints[:nil_items?] || embedded?(type)
) )
} }
end end
@ -1388,7 +1397,7 @@ defmodule AshGraphql.Resource do
defp generic_action_args(action, resource, schema) do defp generic_action_args(action, resource, schema) do
action.arguments action.arguments
|> Enum.reject(& &1.private?) |> Enum.filter(& &1.public?)
|> Enum.map(fn argument -> |> Enum.map(fn argument ->
type = type =
argument.type argument.type
@ -1546,7 +1555,7 @@ defmodule AshGraphql.Resource do
defp read_args(resource, action, schema, hide_inputs) do defp read_args(resource, action, schema, hide_inputs) do
action.arguments action.arguments
|> Enum.reject(&(&1.private? || &1.name in hide_inputs)) |> Enum.filter(&(&1.public? && &1.name not in hide_inputs))
|> Enum.map(fn argument -> |> Enum.map(fn argument ->
type = type =
argument.type argument.type
@ -1689,10 +1698,10 @@ defmodule AshGraphql.Resource do
end end
@doc false @doc false
def type_definitions(resource, api, schema, relay_ids?) do def type_definitions(resource, domain, schema, relay_ids?) do
List.wrap(calculation_input(resource, schema)) ++ List.wrap(calculation_input(resource, schema)) ++
List.wrap(type_definition(resource, api, schema, relay_ids?)) ++ List.wrap(type_definition(resource, domain, schema, relay_ids?)) ++
List.wrap(query_type_definitions(resource, api, schema, relay_ids?)) ++ List.wrap(query_type_definitions(resource, domain, schema, relay_ids?)) ++
List.wrap(sort_input(resource, schema)) ++ List.wrap(sort_input(resource, schema)) ++
List.wrap(filter_input(resource, schema)) ++ List.wrap(filter_input(resource, schema)) ++
filter_field_types(resource, schema) ++ filter_field_types(resource, schema) ++
@ -1759,13 +1768,13 @@ defmodule AshGraphql.Resource do
Enum.reduce(defaults, Ash.Changeset.manage_relationship_schema(), fn {key, value}, Enum.reduce(defaults, Ash.Changeset.manage_relationship_schema(), fn {key, value},
manage_opts -> manage_opts ->
Spark.OptionsHelpers.set_default!(manage_opts, key, value) Spark.Options.Helpers.set_default!(manage_opts, key, value)
end) end)
else else
Ash.Changeset.manage_relationship_schema() Ash.Changeset.manage_relationship_schema()
end end
manage_opts = Spark.OptionsHelpers.validate!(opts[:opts], manage_opts_schema) manage_opts = Spark.Options.validate!(opts[:opts], manage_opts_schema)
fields = manage_fields(manage_opts, managed_relationship, relationship, schema) fields = manage_fields(manage_opts, managed_relationship, relationship, schema)
@ -2288,7 +2297,7 @@ defmodule AshGraphql.Resource do
{type, attribute_or_aggregate} {type, attribute_or_aggregate}
end end
if Ash.Type.embedded_type?(type) do if embedded?(type) do
[] []
else else
attribute_or_aggregate = constraints_to_item_constraints(type, attribute_or_aggregate) attribute_or_aggregate = constraints_to_item_constraints(type, attribute_or_aggregate)
@ -2375,7 +2384,7 @@ defmodule AshGraphql.Resource do
attribute attribute
| constraints: [ | constraints: [
items: constraints, items: constraints,
nil_items?: allow_nil? || Ash.Type.embedded_type?(attribute.type) nil_items?: allow_nil? || embedded?(attribute.type)
] ]
} }
end end
@ -2432,7 +2441,7 @@ defmodule AshGraphql.Resource do
true true
calc -> calc ->
Ash.Type.embedded_type?(calc.type) || Enum.empty?(calc.arguments) embedded?(calc.type) || Enum.empty?(calc.arguments)
end) end)
field_names = AshGraphql.Resource.Info.field_names(resource) field_names = AshGraphql.Resource.Info.field_names(resource)
@ -2670,7 +2679,7 @@ defmodule AshGraphql.Resource do
defp filterable?(%{type: Ash.Type.Union}, _), do: false defp filterable?(%{type: Ash.Type.Union}, _), do: false
defp filterable?(%Ash.Resource.Calculation{type: type, calculation: {module, _opts}}, _) do defp filterable?(%Ash.Resource.Calculation{type: type, calculation: {module, _opts}}, _) do
!Ash.Type.embedded_type?(type) && function_exported?(module, :expression, 2) !embedded?(type) && function_exported?(module, :expression, 2)
end end
defp filterable?(%{type: type} = attribute, resource) do defp filterable?(%{type: type} = attribute, resource) do
@ -2684,7 +2693,7 @@ defmodule AshGraphql.Resource do
resource resource
) )
else else
!Ash.Type.embedded_type?(type) !embedded?(type)
end end
end end
@ -3171,8 +3180,13 @@ defmodule AshGraphql.Resource do
{name, {name,
field_type( field_type(
config[:type], config[:type],
%{attribute | name: nested_union_type_name(attribute, name)}, %{
resource attribute
| name: nested_union_type_name(attribute, name),
constraints: config[:constraints]
},
resource,
false
)} )}
end) end)
@ -3519,8 +3533,9 @@ defmodule AshGraphql.Resource do
paginatable? = paginatable? =
resource resource
|> Ash.Resource.Info.actions() |> queries()
|> Enum.any?(fn action -> |> Enum.any?(fn query ->
action = Ash.Resource.Info.action(resource, query.action)
action.type == :read && action.pagination action.type == :read && action.pagination
end) end)
@ -3581,7 +3596,7 @@ defmodule AshGraphql.Resource do
type.identifier == :node type.identifier == :node
end end
def query_type_definitions(resource, api, schema, relay_ids?) do def query_type_definitions(resource, domain, schema, relay_ids?) do
resource_type = AshGraphql.Resource.Info.type(resource) resource_type = AshGraphql.Resource.Info.type(resource)
resource resource
@ -3602,7 +3617,7 @@ defmodule AshGraphql.Resource do
%Absinthe.Blueprint.Schema.ObjectTypeDefinition{ %Absinthe.Blueprint.Schema.ObjectTypeDefinition{
description: Ash.Resource.Info.description(resource), description: Ash.Resource.Info.description(resource),
interfaces: interfaces, interfaces: interfaces,
fields: fields(resource, api, schema, relay_ids?, query), fields: fields(resource, domain, schema, relay_ids?, query),
identifier: query.type_name, identifier: query.type_name,
module: schema, module: schema,
name: Macro.camelize(to_string(query.type_name)), name: Macro.camelize(to_string(query.type_name)),
@ -3611,7 +3626,7 @@ defmodule AshGraphql.Resource do
end) end)
end end
def type_definition(resource, api, schema, relay_ids?) do def type_definition(resource, domain, schema, relay_ids?) do
actual_resource = Ash.Type.NewType.subtype_of(resource) actual_resource = Ash.Type.NewType.subtype_of(resource)
if generate_object?(resource) do if generate_object?(resource) do
@ -3652,7 +3667,7 @@ defmodule AshGraphql.Resource do
%Absinthe.Blueprint.Schema.ObjectTypeDefinition{ %Absinthe.Blueprint.Schema.ObjectTypeDefinition{
description: Ash.Resource.Info.description(resource), description: Ash.Resource.Info.description(resource),
interfaces: interfaces, interfaces: interfaces,
fields: fields(resource, api, schema, relay_ids?), fields: fields(resource, domain, schema, relay_ids?),
identifier: type, identifier: type,
module: schema, module: schema,
name: Macro.camelize(to_string(type)), name: Macro.camelize(to_string(type)),
@ -3661,12 +3676,12 @@ defmodule AshGraphql.Resource do
end end
end end
defp fields(resource, api, schema, relay_ids?, query \\ nil) do defp fields(resource, domain, schema, relay_ids?, query \\ nil) do
attributes(resource, api, schema, relay_ids?) ++ attributes(resource, domain, schema, relay_ids?) ++
metadata(query, resource, schema) ++ metadata(query, resource, schema) ++
relationships(resource, api, schema) ++ relationships(resource, domain, schema) ++
aggregates(resource, api, schema) ++ aggregates(resource, domain, schema) ++
calculations(resource, api, schema) ++ calculations(resource, domain, schema) ++
keyset(resource, schema) keyset(resource, schema)
end end
@ -3725,7 +3740,7 @@ defmodule AshGraphql.Resource do
end end
end end
defp attributes(resource, api, schema, relay_ids?) do defp attributes(resource, domain, schema, relay_ids?) do
attribute_names = AshGraphql.Resource.Info.field_names(resource) attribute_names = AshGraphql.Resource.Info.field_names(resource)
attributes = attributes =
@ -3759,7 +3774,7 @@ defmodule AshGraphql.Resource do
attribute.name, attribute.name,
attribute.type, attribute.type,
attribute.constraints, attribute.constraints,
api domain
), ),
name: to_string(name), name: to_string(name),
type: field_type, type: field_type,
@ -3780,9 +3795,7 @@ defmodule AshGraphql.Resource do
[field] -> [field] ->
attribute = Ash.Resource.Info.attribute(resource, field) attribute = Ash.Resource.Info.attribute(resource, field)
if attribute.private? do if attribute.public? do
[]
else
[ [
%Absinthe.Blueprint.Schema.FieldDefinition{ %Absinthe.Blueprint.Schema.FieldDefinition{
description: attribute.description, description: attribute.description,
@ -3796,6 +3809,8 @@ defmodule AshGraphql.Resource do
__reference__: ref(__ENV__) __reference__: ref(__ENV__)
} }
] ]
else
[]
end end
fields -> fields ->
@ -3861,7 +3876,7 @@ defmodule AshGraphql.Resource do
defp argument_required?(_), do: true defp argument_required?(_), do: true
# sobelow_skip ["DOS.StringToAtom"] # sobelow_skip ["DOS.StringToAtom"]
defp relationships(resource, api, schema) do defp relationships(resource, domain, schema) do
field_names = AshGraphql.Resource.Info.field_names(resource) field_names = AshGraphql.Resource.Info.field_names(resource)
relationships = AshGraphql.Resource.Info.relationships(resource) relationships = AshGraphql.Resource.Info.relationships(resource)
@ -3897,7 +3912,7 @@ defmodule AshGraphql.Resource do
description: relationship.description, description: relationship.description,
arguments: args(:one_related, relationship.destination, read_action, schema), arguments: args(:one_related, relationship.destination, read_action, schema),
middleware: [ middleware: [
{{AshGraphql.Graphql.Resolver, :resolve_assoc}, {api, relationship}} {{AshGraphql.Graphql.Resolver, :resolve_assoc}, {domain, relationship}}
], ],
type: type, type: type,
__reference__: ref(__ENV__) __reference__: ref(__ENV__)
@ -3930,7 +3945,7 @@ defmodule AshGraphql.Resource do
description: relationship.description, description: relationship.description,
complexity: {AshGraphql.Graphql.Resolver, :query_complexity}, complexity: {AshGraphql.Graphql.Resolver, :query_complexity},
middleware: [ middleware: [
{{AshGraphql.Graphql.Resolver, :resolve_assoc}, {api, relationship}} {{AshGraphql.Graphql.Resolver, :resolve_assoc}, {domain, relationship}}
], ],
arguments: args(:list_related, relationship.destination, read_action, schema), arguments: args(:list_related, relationship.destination, read_action, schema),
type: query_type, type: query_type,
@ -3939,7 +3954,7 @@ defmodule AshGraphql.Resource do
end) end)
end end
defp aggregates(resource, api, schema) do defp aggregates(resource, domain, schema) do
field_names = AshGraphql.Resource.Info.field_names(resource) field_names = AshGraphql.Resource.Info.field_names(resource)
resource resource
@ -3991,7 +4006,7 @@ defmodule AshGraphql.Resource do
identifier: aggregate.name, identifier: aggregate.name,
module: schema, module: schema,
middleware: middleware:
middleware_for_field(resource, aggregate, aggregate.name, agg_type, constraints, api), middleware_for_field(resource, aggregate, aggregate.name, agg_type, constraints, domain),
name: to_string(name), name: to_string(name),
description: aggregate.description, description: aggregate.description,
type: type, type: type,
@ -4000,11 +4015,11 @@ defmodule AshGraphql.Resource do
end) end)
end end
defp middleware_for_field(resource, field, name, {:array, type}, constraints, api) do defp middleware_for_field(resource, field, name, {:array, type}, constraints, domain) do
middleware_for_field(resource, field, name, type, constraints, api) middleware_for_field(resource, field, name, type, constraints, domain)
end end
defp middleware_for_field(resource, field, name, type, constraints, api) do defp middleware_for_field(resource, field, name, type, constraints, domain) do
if Ash.Type.NewType.new_type?(type) && if Ash.Type.NewType.new_type?(type) &&
Ash.Type.NewType.subtype_of(type) == Ash.Type.Union && Ash.Type.NewType.subtype_of(type) == Ash.Type.Union &&
function_exported?(type, :graphql_unnested_unions, 1) do function_exported?(type, :graphql_unnested_unions, 1) do
@ -4012,16 +4027,16 @@ defmodule AshGraphql.Resource do
[ [
{{AshGraphql.Graphql.Resolver, :resolve_union}, {{AshGraphql.Graphql.Resolver, :resolve_union},
{name, type, field, resource, unnested_types, api}} {name, type, field, resource, unnested_types, domain}}
] ]
else else
[ [
{{AshGraphql.Graphql.Resolver, :resolve_attribute}, {name, type, constraints, api}} {{AshGraphql.Graphql.Resolver, :resolve_attribute}, {name, type, constraints, domain}}
] ]
end end
end end
defp calculations(resource, api, schema) do defp calculations(resource, domain, schema) do
field_names = AshGraphql.Resource.Info.field_names(resource) field_names = AshGraphql.Resource.Info.field_names(resource)
resource resource
@ -4039,7 +4054,7 @@ defmodule AshGraphql.Resource do
arguments: arguments, arguments: arguments,
complexity: 2, complexity: 2,
middleware: [ middleware: [
{{AshGraphql.Graphql.Resolver, :resolve_calculation}, {api, resource, calculation}} {{AshGraphql.Graphql.Resolver, :resolve_calculation}, {domain, resource, calculation}}
], ],
name: to_string(name), name: to_string(name),
description: calculation.description, description: calculation.description,
@ -4144,9 +4159,7 @@ defmodule AshGraphql.Resource do
field_type = field_type =
type type
|> do_field_type(new_attribute, resource, input?) |> do_field_type(new_attribute, resource, input?)
|> maybe_wrap_non_null( |> maybe_wrap_non_null(!attribute.constraints[:nil_items?] || embedded?(attribute.type))
!attribute.constraints[:nil_items?] || Ash.Type.embedded_type?(attribute.type)
)
%Absinthe.Blueprint.TypeReference.List{ %Absinthe.Blueprint.TypeReference.List{
of_type: field_type of_type: field_type
@ -4166,7 +4179,7 @@ defmodule AshGraphql.Resource do
if Ash.Type.builtin?(type) do if Ash.Type.builtin?(type) do
get_specific_field_type(type, attribute, resource, input?) get_specific_field_type(type, attribute, resource, input?)
else else
if Spark.Dsl.is?(type, Ash.Resource) && !Ash.Type.embedded_type?(type) do if Ash.Resource.Info.resource?(type) && !Ash.Resource.Info.embedded?(type) do
if input? do if input? do
Application.get_env(:ash_graphql, :json_type) || :json_string Application.get_env(:ash_graphql, :json_type) || :json_string
else else
@ -4410,4 +4423,16 @@ defmodule AshGraphql.Resource do
|> AshGraphql.Resource.Info.queries() |> AshGraphql.Resource.Info.queries()
|> Enum.find(&(&1.type == :get and (&1.identity == nil or &1.identity == false))) |> Enum.find(&(&1.type == :get and (&1.identity == nil or &1.identity == false)))
end end
def embedded?({:array, resource_or_type}) do
embedded?(resource_or_type)
end
def embedded?(resource_or_type) do
if Ash.Resource.Info.resource?(resource_or_type) do
Ash.Resource.Info.embedded?(resource_or_type)
else
Ash.Type.embedded_type?(resource_or_type)
end
end
end end

View file

@ -8,18 +8,17 @@ defmodule AshGraphql.Subscription do
@doc """ @doc """
Produce a query that will load the correct data for a subscription. Produce a query that will load the correct data for a subscription.
""" """
def query_for_subscription(query, api, %{context: context} = resolution) do def query_for_subscription(query, domain, %{context: context} = resolution) do
query = Ash.Query.to_query(query)
query query
|> Ash.Query.new()
|> Ash.Query.set_tenant(Map.get(context, :tenant)) |> Ash.Query.set_tenant(Map.get(context, :tenant))
|> Ash.Query.set_context(get_context(context)) |> Ash.Query.set_context(get_context(context))
|> AshGraphql.Graphql.Resolver.select_fields(query.resource, resolution, nil) |> AshGraphql.Graphql.Resolver.select_fields(query.resource, resolution, nil)
|> AshGraphql.Graphql.Resolver.load_fields( |> AshGraphql.Graphql.Resolver.load_fields(
[ [
api: api, domain: domain,
tenant: Map.get(context, :tenant), tenant: Map.get(context, :tenant),
authorize?: AshGraphql.Api.Info.authorize?(api), authorize?: AshGraphql.Domain.Info.authorize?(domain),
actor: Map.get(context, :actor) actor: Map.get(context, :actor)
], ],
query.resource, query.resource,

View file

@ -1,30 +1,30 @@
defmodule AshGraphql.TraceHelpers do defmodule AshGraphql.TraceHelpers do
@moduledoc false @moduledoc false
defmacro trace(api, resource, type, name, metadata, do: body) do defmacro trace(domain, resource, type, name, metadata, do: body) do
quote do quote do
require Ash.Tracer require Ash.Tracer
api = unquote(api) domain = unquote(domain)
resource = unquote(resource) resource = unquote(resource)
type = unquote(type) type = unquote(type)
name = unquote(name) name = unquote(name)
metadata = unquote(metadata) metadata = unquote(metadata)
Ash.Tracer.span type, Ash.Tracer.span type,
AshGraphql.TraceHelpers.span_name(api, resource, type, name), AshGraphql.TraceHelpers.span_name(domain, resource, type, name),
AshGraphql.Api.Info.tracer(api) do AshGraphql.Domain.Info.tracer(domain) do
Ash.Tracer.set_metadata(AshGraphql.Api.Info.tracer(api), type, metadata) Ash.Tracer.set_metadata(AshGraphql.Domain.Info.tracer(domain), type, metadata)
Ash.Tracer.telemetry_span [:ash, Ash.Api.Info.short_name(api), type], metadata do Ash.Tracer.telemetry_span [:ash, Ash.Domain.Info.short_name(domain), type], metadata do
unquote(body) unquote(body)
end end
end end
end end
end end
def span_name(api, resource, type, name) def span_name(domain, resource, type, name)
when is_atom(api) and is_atom(resource) and is_atom(type) and when is_atom(domain) and is_atom(resource) and is_atom(type) and
(is_atom(name) or is_binary(name)) do (is_atom(name) or is_binary(name)) do
Ash.Api.Info.span_name(api, resource, "#{type}.#{name}") Ash.Domain.Info.span_name(domain, resource, "#{type}.#{name}")
end end
end end

18
mix.exs
View file

@ -71,7 +71,7 @@ defmodule AshGraphql.MixProject do
"documentation/topics/graphql-generation.md", "documentation/topics/graphql-generation.md",
"documentation/topics/modifying-the-resolution.md", "documentation/topics/modifying-the-resolution.md",
"documentation/topics/relay.md", "documentation/topics/relay.md",
"documentation/dsls/DSL:-AshGraphql.Api.md", "documentation/dsls/DSL:-AshGraphql.Domain.md",
"documentation/dsls/DSL:-AshGraphql.Resource.md" "documentation/dsls/DSL:-AshGraphql.Resource.md"
], ],
groups_for_extras: [ groups_for_extras: [
@ -86,9 +86,9 @@ defmodule AshGraphql.MixProject do
], ],
Introspection: [ Introspection: [
AshGraphql.Resource.Info, AshGraphql.Resource.Info,
AshGraphql.Api.Info, AshGraphql.Domain.Info,
AshGraphql.Resource, AshGraphql.Resource,
AshGraphql.Api, AshGraphql.Domain,
AshGraphql.Resource.Action, AshGraphql.Resource.Action,
AshGraphql.Resource.ManagedRelationship, AshGraphql.Resource.ManagedRelationship,
AshGraphql.Resource.Mutation, AshGraphql.Resource.Mutation,
@ -136,7 +136,7 @@ defmodule AshGraphql.MixProject do
# Run "mix help deps" to learn about dependencies. # Run "mix help deps" to learn about dependencies.
defp deps do defp deps do
[ [
{:ash, ash_version("~> 2.17")}, {:ash, ash_version("~> 3.0-dev")},
{:absinthe_plug, "~> 1.4"}, {:absinthe_plug, "~> 1.4"},
{:absinthe, "~> 1.7"}, {:absinthe, "~> 1.7"},
{:jason, "~> 1.2"}, {:jason, "~> 1.2"},
@ -147,7 +147,8 @@ defmodule AshGraphql.MixProject do
{:sobelow, ">= 0.0.0", only: [:dev, :test], runtime: false}, {:sobelow, ">= 0.0.0", only: [:dev, :test], runtime: false},
{:git_ops, "~> 2.5", only: [:dev, :test]}, {:git_ops, "~> 2.5", only: [:dev, :test]},
{:excoveralls, "~> 0.13", only: [:dev, :test]}, {:excoveralls, "~> 0.13", only: [:dev, :test]},
{:mix_test_watch, "~> 1.0", only: :dev, runtime: false} {:mix_test_watch, "~> 1.0", only: :dev, runtime: false},
{:simple_sat, ">= 0.0.0", only: :test}
] ]
end end
@ -170,10 +171,11 @@ defmodule AshGraphql.MixProject do
"spark.replace_doc_links", "spark.replace_doc_links",
"spark.cheat_sheets_in_search" "spark.cheat_sheets_in_search"
], ],
"spark.formatter": "spark.formatter --extensions AshGraphql.Resource,AshGraphql.Api", "spark.formatter": "spark.formatter --extensions AshGraphql.Resource,AshGraphql.Domain",
"spark.cheat_sheets_in_search": "spark.cheat_sheets_in_search":
"spark.cheat_sheets_in_search --extensions AshGraphql.Resource,AshGraphql.Api", "spark.cheat_sheets_in_search --extensions AshGraphql.Resource,AshGraphql.Domain",
"spark.cheat_sheets": "spark.cheat_sheets --extensions AshGraphql.Resource,AshGraphql.Api" "spark.cheat_sheets":
"spark.cheat_sheets --extensions AshGraphql.Resource,AshGraphql.Domain"
] ]
end end
end end

View file

@ -1,16 +1,14 @@
%{ %{
"absinthe": {:hex, :absinthe, "1.7.5", "a15054f05738e766f7cc7fd352887dfd5e61cec371fb4741cca37c3359ff74ac", [:mix], [{:dataloader, "~> 1.0.0 or ~> 2.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 1.2.2 or ~> 1.3.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:opentelemetry_process_propagator, "~> 0.2.1", [hex: :opentelemetry_process_propagator, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "22a9a38adca26294ad0ee91226168f5d215b401efd770b8a1b8fd9c9b21ec316"}, "absinthe": {:hex, :absinthe, "1.7.5", "a15054f05738e766f7cc7fd352887dfd5e61cec371fb4741cca37c3359ff74ac", [:mix], [{:dataloader, "~> 1.0.0 or ~> 2.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 1.2.2 or ~> 1.3.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:opentelemetry_process_propagator, "~> 0.2.1", [hex: :opentelemetry_process_propagator, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "22a9a38adca26294ad0ee91226168f5d215b401efd770b8a1b8fd9c9b21ec316"},
"absinthe_plug": {:hex, :absinthe_plug, "1.5.8", "38d230641ba9dca8f72f1fed2dfc8abd53b3907d1996363da32434ab6ee5d6ab", [:mix], [{:absinthe, "~> 1.5", [hex: :absinthe, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bbb04176647b735828861e7b2705465e53e2cf54ccf5a73ddd1ebd855f996e5a"}, "absinthe_plug": {:hex, :absinthe_plug, "1.5.8", "38d230641ba9dca8f72f1fed2dfc8abd53b3907d1996363da32434ab6ee5d6ab", [:mix], [{:absinthe, "~> 1.5", [hex: :absinthe, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bbb04176647b735828861e7b2705465e53e2cf54ccf5a73ddd1ebd855f996e5a"},
"ash": {:hex, :ash, "2.21.1", "4b098f68ba0bb20b49216f4771b885c88f72446ea98ad97eb3ea5a2b3543770b", [:mix], [{:comparable, "~> 1.0", [hex: :comparable, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: false]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, "~> 0.6", [hex: :reactor, repo: "hexpm", optional: false]}, {:spark, ">= 1.1.55 and < 2.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:stream_data, "~> 0.6", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "8890215fe59c85325af302ca307e2d103d555383f7d20b4da98bde79ec6dd76c"}, "ash": {:hex, :ash, "3.0.0-rc.4", "b8142d27a4541d44d2400f5a127d87cc88a54928945f302210b779fcbaf8fc41", [:mix], [{:comparable, "~> 1.0", [hex: :comparable, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, "~> 0.8", [hex: :reactor, repo: "hexpm", optional: false]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:spark, ">= 2.1.7 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:stream_data, "~> 0.6", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "518a8948e3973efe5df432825db58eaf03cf3f0cd6445e98479aa398ebaedfdf"},
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
"comparable": {:hex, :comparable, "1.0.0", "bb669e91cedd14ae9937053e5bcbc3c52bb2f22422611f43b6e38367d94a495f", [:mix], [{:typable, "~> 0.1", [hex: :typable, repo: "hexpm", optional: false]}], "hexpm", "277c11eeb1cd726e7cd41c6c199e7e52fa16ee6830b45ad4cdc62e51f62eb60c"}, "comparable": {:hex, :comparable, "1.0.0", "bb669e91cedd14ae9937053e5bcbc3c52bb2f22422611f43b6e38367d94a495f", [:mix], [{:typable, "~> 0.1", [hex: :typable, repo: "hexpm", optional: false]}], "hexpm", "277c11eeb1cd726e7cd41c6c199e7e52fa16ee6830b45ad4cdc62e51f62eb60c"},
"credo": {:hex, :credo, "1.7.4", "68ca5cf89071511c12fd9919eb84e388d231121988f6932756596195ccf7fd35", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "9cf776d062c78bbe0f0de1ecaee183f18f2c3ec591326107989b054b7dddefc2"}, "credo": {:hex, :credo, "1.7.4", "68ca5cf89071511c12fd9919eb84e388d231121988f6932756596195ccf7fd35", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "9cf776d062c78bbe0f0de1ecaee183f18f2c3ec591326107989b054b7dddefc2"},
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
"dialyxir": {:hex, :dialyxir, "1.4.1", "a22ed1e7bd3a3e3f197b68d806ef66acb61ee8f57b3ac85fc5d57354c5482a93", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "84b795d6d7796297cca5a3118444b80c7d94f7ce247d49886e7c291e1ae49801"}, "dialyxir": {:hex, :dialyxir, "1.4.1", "a22ed1e7bd3a3e3f197b68d806ef66acb61ee8f57b3ac85fc5d57354c5482a93", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "84b795d6d7796297cca5a3118444b80c7d94f7ce247d49886e7c291e1ae49801"},
"earmark": {:hex, :earmark, "1.4.46", "8c7287bd3137e99d26ae4643e5b7ef2129a260e3dcf41f251750cb4563c8fb81", [:mix], [], "hexpm", "798d86db3d79964e759ddc0c077d5eb254968ed426399fbf5a62de2b5ff8910a"},
"earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"},
"ecto": {:hex, :ecto, "3.11.2", "e1d26be989db350a633667c5cda9c3d115ae779b66da567c68c80cfb26a8c9ee", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c38bca2c6f8d8023f2145326cc8a80100c3ffe4dcbd9842ff867f7fc6156c65"}, "ecto": {:hex, :ecto, "3.11.2", "e1d26be989db350a633667c5cda9c3d115ae779b66da567c68c80cfb26a8c9ee", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c38bca2c6f8d8023f2145326cc8a80100c3ffe4dcbd9842ff867f7fc6156c65"},
"elixir_make": {:hex, :elixir_make, "0.8.3", "d38d7ee1578d722d89b4d452a3e36bcfdc644c618f0d063b874661876e708683", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "5c99a18571a756d4af7a4d89ca75c28ac899e6103af6f223982f09ce44942cc9"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"ets": {:hex, :ets, "0.9.0", "79c6a6c205436780486f72d84230c6cba2f8a9920456750ddd1e47389107d5fd", [:mix], [], "hexpm", "2861fdfb04bcaeff370f1a5904eec864f0a56dcfebe5921ea9aadf2a481c822b"}, "ets": {:hex, :ets, "0.9.0", "79c6a6c205436780486f72d84230c6cba2f8a9920456750ddd1e47389107d5fd", [:mix], [], "hexpm", "2861fdfb04bcaeff370f1a5904eec864f0a56dcfebe5921ea9aadf2a481c822b"},
"ex_check": {:hex, :ex_check, "0.15.0", "074b94c02de11c37bba1ca82ae5cc4926e6ccee862e57a485b6ba60fca2d8dc1", [:mix], [], "hexpm", "33848031a0c7e4209c3b4369ce154019788b5219956220c35ca5474299fb6a0e"}, "ex_check": {:hex, :ex_check, "0.15.0", "074b94c02de11c37bba1ca82ae5cc4926e6ccee862e57a485b6ba60fca2d8dc1", [:mix], [], "hexpm", "33848031a0c7e4209c3b4369ce154019788b5219956220c35ca5474299fb6a0e"},
@ -26,15 +24,15 @@
"makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"}, "makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"},
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"}, "mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
"mix_test_watch": {:hex, :mix_test_watch, "1.1.1", "eee6fc570d77ad6851c7bc08de420a47fd1e449ef5ccfa6a77ef68b72e7e51ad", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "f82262b54dee533467021723892e15c3267349849f1f737526523ecba4e6baae"}, "mix_test_watch": {:hex, :mix_test_watch, "1.1.1", "eee6fc570d77ad6851c7bc08de420a47fd1e449ef5ccfa6a77ef68b72e7e51ad", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "f82262b54dee533467021723892e15c3267349849f1f737526523ecba4e6baae"},
"nimble_options": {:hex, :nimble_options, "1.1.0", "3b31a57ede9cb1502071fade751ab0c7b8dbe75a9a4c2b5bbb0943a690b63172", [:mix], [], "hexpm", "8bbbb3941af3ca9acc7835f5655ea062111c9c27bcac53e004460dfd19008a99"},
"nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"}, "nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"},
"picosat_elixir": {:hex, :picosat_elixir, "0.2.3", "bf326d0f179fbb3b706bb2c15fbc367dacfa2517157d090fdfc32edae004c597", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "f76c9db2dec9d2561ffaa9be35f65403d53e984e8cd99c832383b7ab78c16c66"},
"plug": {:hex, :plug, "1.15.3", "712976f504418f6dff0a3e554c40d705a9bcf89a7ccef92fc6a5ef8f16a30a97", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cc4365a3c010a56af402e0809208873d113e9c38c401cabd88027ef4f5c01fd2"}, "plug": {:hex, :plug, "1.15.3", "712976f504418f6dff0a3e554c40d705a9bcf89a7ccef92fc6a5ef8f16a30a97", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cc4365a3c010a56af402e0809208873d113e9c38c401cabd88027ef4f5c01fd2"},
"plug_crypto": {:hex, :plug_crypto, "2.0.0", "77515cc10af06645abbfb5e6ad7a3e9714f805ae118fa1a70205f80d2d70fe73", [:mix], [], "hexpm", "53695bae57cc4e54566d993eb01074e4d894b65a3766f1c43e2c61a1b0f45ea9"}, "plug_crypto": {:hex, :plug_crypto, "2.0.0", "77515cc10af06645abbfb5e6ad7a3e9714f805ae118fa1a70205f80d2d70fe73", [:mix], [], "hexpm", "53695bae57cc4e54566d993eb01074e4d894b65a3766f1c43e2c61a1b0f45ea9"},
"reactor": {:hex, :reactor, "0.7.0", "fb76d23d95829b28ac9b9d654620c43c890c6a32ea26ac13086c48540b34e8c5", [:mix], [{:libgraph, "~> 0.16", [hex: :libgraph, repo: "hexpm", optional: false]}, {:spark, "~> 1.0", [hex: :spark, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4310da820d753aafd7dc4ee8cc687b84565dd6d9536e38806ee211da792178fd"}, "reactor": {:hex, :reactor, "0.8.1", "1aec71d16083901277727c8162f6dd0f07e80f5ca98911b6ef4f2c95e6e62758", [:mix], [{:libgraph, "~> 0.16", [hex: :libgraph, repo: "hexpm", optional: false]}, {:spark, "~> 2.0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ae3936d97a3e4a316744f70c77b85345b08b70da334024c26e6b5eb8ede1246b"},
"simple_sat": {:hex, :simple_sat, "0.1.1", "68a5ebe6f6d5956bd806e4881c495692c14580a2f1a4420488985abd0fba2119", [:mix], [], "hexpm", "63571218f92ff029838df7645eb8f0c38df8ed60d2d14578412a8d142a94471e"},
"sobelow": {:hex, :sobelow, "0.13.0", "218afe9075904793f5c64b8837cc356e493d88fddde126a463839351870b8d1e", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cd6e9026b85fc35d7529da14f95e85a078d9dd1907a9097b3ba6ac7ebbe34a0d"}, "sobelow": {:hex, :sobelow, "0.13.0", "218afe9075904793f5c64b8837cc356e493d88fddde126a463839351870b8d1e", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cd6e9026b85fc35d7529da14f95e85a078d9dd1907a9097b3ba6ac7ebbe34a0d"},
"sourceror": {:hex, :sourceror, "1.0.2", "c5e86fdc14881f797749d1fe5df017ca66727a8146e7ee3e736605a3df78f3e6", [:mix], [], "hexpm", "832335e87d0913658f129d58b2a7dc0490ddd4487b02de6d85bca0169ec2bd79"}, "sourceror": {:hex, :sourceror, "1.0.2", "c5e86fdc14881f797749d1fe5df017ca66727a8146e7ee3e736605a3df78f3e6", [:mix], [], "hexpm", "832335e87d0913658f129d58b2a7dc0490ddd4487b02de6d85bca0169ec2bd79"},
"spark": {:hex, :spark, "1.1.55", "d20c3f899b23d841add29edc912ffab4463d3bb801bc73448738631389291d2e", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.5 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.0", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "bbc15a4223d8e610c81ceca825d5d0bae3738d1c4ac4dbb1061749966776c3f1"}, "spark": {:hex, :spark, "2.1.11", "8093149dfd583b5ce2c06e1fea1faaf4125b50e4703138b2cbefb78c8f4aa07f", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.0", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "1877d92ab993b860e9d828bfd72d50367c0d3a53dd84f4de5d221baf66ae8723"},
"splode": {:hex, :splode, "0.2.1", "020079ec06c9e00f8b6586852e781b5e07aee6ba588f3f45dd993831c87b0511", [:mix], [], "hexpm", "d232a933666061fe1f659d9906042fa94b9b393bb1129a4fde6fa680033b2611"},
"stream_data": {:hex, :stream_data, "0.6.0", "e87a9a79d7ec23d10ff83eb025141ef4915eeb09d4491f79e52f2562b73e5f47", [:mix], [], "hexpm", "b92b5031b650ca480ced047578f1d57ea6dd563f5b57464ad274718c9c29501c"}, "stream_data": {:hex, :stream_data, "0.6.0", "e87a9a79d7ec23d10ff83eb025141ef4915eeb09d4491f79e52f2562b73e5f47", [:mix], [], "hexpm", "b92b5031b650ca480ced047578f1d57ea6dd563f5b57464ad274718c9c29501c"},
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
"typable": {:hex, :typable, "0.3.0", "0431e121d124cd26f312123e313d2689b9a5322b15add65d424c07779eaa3ca1", [:mix], [], "hexpm", "880a0797752da1a4c508ac48f94711e04c86156f498065a83d160eef945858f8"}, "typable": {:hex, :typable, "0.3.0", "0431e121d124cd26f312123e313d2689b9a5322b15add65d424c07779eaa3ca1", [:mix], [], "hexpm", "880a0797752da1a4c508ac48f94711e04c86156f498065a83d160eef945858f8"},

View file

@ -13,7 +13,7 @@ defmodule AliasTest do
post = post =
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foo", published: true, score: 9.8) |> Ash.Changeset.for_create(:create, text: "foo", published: true, score: 9.8)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -39,7 +39,7 @@ defmodule AliasTest do
post = post =
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foo", published: true, score: 9.8) |> Ash.Changeset.for_create(:create, text: "foo", published: true, score: 9.8)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -70,7 +70,7 @@ defmodule AliasTest do
published: true, published: true,
score: 9.8 score: 9.8
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -103,7 +103,7 @@ defmodule AliasTest do
published: true, published: true,
score: 9.8 score: 9.8
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -144,7 +144,7 @@ defmodule AliasTest do
published: true, published: true,
score: 9.8 score: 9.8
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -179,7 +179,7 @@ defmodule AliasTest do
published: true, published: true,
score: 9.8 score: 9.8
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -209,8 +209,8 @@ defmodule AliasTest do
test "relationship alias works correctly" do test "relationship alias works correctly" do
author = author =
AshGraphql.Test.User AshGraphql.Test.User
|> Ash.Changeset.for_create(:create, name: "test") |> Ash.Changeset.for_create(:create, name: "My Name")
|> AshGraphql.Test.Api.create!() |> Ash.create!()
post = post =
AshGraphql.Test.Post AshGraphql.Test.Post
@ -220,7 +220,7 @@ defmodule AliasTest do
score: 9.8, score: 9.8,
author_id: author.id author_id: author.id
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """

View file

@ -3,7 +3,7 @@ defmodule AshGraphql.AttributeTest do
setup do setup do
on_exit(fn -> on_exit(fn ->
Application.delete_env(:ash_graphql, AshGraphql.Test.Api) Application.delete_env(:ash_graphql, AshGraphql.Test.Domain)
try do try do
AshGraphql.TestHelpers.stop_ets() AshGraphql.TestHelpers.stop_ets()

View file

@ -3,7 +3,7 @@ defmodule AshGraphql.CreateTest do
setup do setup do
on_exit(fn -> on_exit(fn ->
Application.delete_env(:ash_graphql, AshGraphql.Test.Api) Application.delete_env(:ash_graphql, AshGraphql.Test.Domain)
AshGraphql.TestHelpers.stop_ets() AshGraphql.TestHelpers.stop_ets()
end) end)
@ -304,7 +304,7 @@ defmodule AshGraphql.CreateTest do
simpleCreatePost(input: $input) { simpleCreatePost(input: $input) {
result{ result{
text1 text1
integerAsStringInApi integerAsStringInDomain
} }
errors{ errors{
message message
@ -313,7 +313,7 @@ defmodule AshGraphql.CreateTest do
} }
""" """
|> Absinthe.run(AshGraphql.Test.Schema, |> Absinthe.run(AshGraphql.Test.Schema,
variables: %{"input" => %{"text1" => "foo", "integerAsStringInApi" => "1"}} variables: %{"input" => %{"text1" => "foo", "integerAsStringInDomain" => "1"}}
) )
assert {:ok, result} = resp assert {:ok, result} = resp
@ -324,7 +324,7 @@ defmodule AshGraphql.CreateTest do
data: %{ data: %{
"simpleCreatePost" => %{ "simpleCreatePost" => %{
"result" => %{ "result" => %{
"integerAsStringInApi" => "1" "integerAsStringInDomain" => "1"
} }
} }
} }
@ -332,7 +332,10 @@ defmodule AshGraphql.CreateTest do
end end
test "a create can load a calculation on a related belongs_to record" do test "a create can load a calculation on a related belongs_to record" do
author = AshGraphql.Test.Api.create!(Ash.Changeset.new(AshGraphql.Test.User, name: "bob")) author =
AshGraphql.Test.User
|> Ash.Changeset.for_create(:create, name: "My Name")
|> Ash.create!()
resp = resp =
""" """
@ -365,7 +368,7 @@ defmodule AshGraphql.CreateTest do
"result" => %{ "result" => %{
"fullText" => "foobar", "fullText" => "foobar",
"author" => %{ "author" => %{
"nameTwice" => "bob bob" "nameTwice" => "My Name My Name"
} }
} }
} }
@ -487,8 +490,8 @@ defmodule AshGraphql.CreateTest do
test "an upsert works" do test "an upsert works" do
post = post =
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.new(text: "foobar") |> Ash.Changeset.for_create(:create, text: "foobar")
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -560,7 +563,7 @@ defmodule AshGraphql.CreateTest do
end end
test "errors can be intercepted" do test "errors can be intercepted" do
Application.put_env(:ash_graphql, AshGraphql.Test.Api, Application.put_env(:ash_graphql, AshGraphql.Test.Domain,
graphql: [ graphql: [
error_handler: {ErrorHandler, :handle_error, []} error_handler: {ErrorHandler, :handle_error, []}
] ]
@ -600,7 +603,7 @@ defmodule AshGraphql.CreateTest do
end end
test "root level error" do test "root level error" do
Application.put_env(:ash_graphql, AshGraphql.Test.Api, Application.put_env(:ash_graphql, AshGraphql.Test.Domain,
graphql: [show_raised_errors?: true, root_level_errors?: true] graphql: [show_raised_errors?: true, root_level_errors?: true]
) )

View file

@ -17,20 +17,20 @@ defmodule AshGraphql.CustpmPaginateTest do
test "channel record with direct union message records are fetched" do test "channel record with direct union message records are fetched" do
channel = channel =
AshGraphql.Test.Channel AshGraphql.Test.Channel
|> Ash.Changeset.new(%{}) |> Ash.Changeset.for_create(:create, %{})
|> AshGraphql.Test.Api.create!() |> Ash.create!()
text_message = text_message =
AshGraphql.Test.TextMessage AshGraphql.Test.TextMessage
|> Ash.Changeset.for_create(:create, text: "test text message") |> Ash.Changeset.for_create(:create, text: "test text message")
|> Ash.Changeset.manage_relationship(:channel, channel, type: :append_and_remove) |> Ash.Changeset.manage_relationship(:channel, channel, type: :append_and_remove)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
image_message = image_message =
AshGraphql.Test.ImageMessage AshGraphql.Test.ImageMessage
|> Ash.Changeset.for_create(:create, text: "test image message") |> Ash.Changeset.for_create(:create, text: "test image message")
|> Ash.Changeset.manage_relationship(:channel, channel, type: :append_and_remove) |> Ash.Changeset.manage_relationship(:channel, channel, type: :append_and_remove)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -88,20 +88,20 @@ defmodule AshGraphql.CustpmPaginateTest do
test "channel record with page of channel messages record is fetched" do test "channel record with page of channel messages record is fetched" do
channel = channel =
AshGraphql.Test.Channel AshGraphql.Test.Channel
|> Ash.Changeset.new(%{}) |> Ash.Changeset.for_create(:create, %{})
|> AshGraphql.Test.Api.create!() |> Ash.create!()
text_message = text_message =
AshGraphql.Test.TextMessage AshGraphql.Test.TextMessage
|> Ash.Changeset.for_create(:create, text: "test text message") |> Ash.Changeset.for_create(:create, text: "test text message")
|> Ash.Changeset.manage_relationship(:channel, channel, type: :append_and_remove) |> Ash.Changeset.manage_relationship(:channel, channel, type: :append_and_remove)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
image_message = image_message =
AshGraphql.Test.ImageMessage AshGraphql.Test.ImageMessage
|> Ash.Changeset.for_create(:create, text: "test image message") |> Ash.Changeset.for_create(:create, text: "test image message")
|> Ash.Changeset.manage_relationship(:channel, channel, type: :append_and_remove) |> Ash.Changeset.manage_relationship(:channel, channel, type: :append_and_remove)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """

View file

@ -3,14 +3,17 @@ defmodule AshGraphql.DestroyTest do
setup do setup do
on_exit(fn -> on_exit(fn ->
Application.delete_env(:ash_graphql, AshGraphql.Test.Api) Application.delete_env(:ash_graphql, AshGraphql.Test.Domain)
AshGraphql.TestHelpers.stop_ets() AshGraphql.TestHelpers.stop_ets()
end) end)
end end
test "a destroy works" do test "a destroy works" do
post = AshGraphql.Test.Api.create!(Ash.Changeset.new(AshGraphql.Test.Post, text: "foobar")) post =
AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foobar")
|> Ash.create!()
resp = resp =
""" """
@ -38,7 +41,10 @@ defmodule AshGraphql.DestroyTest do
end end
test "a soft destroy works" do test "a soft destroy works" do
post = AshGraphql.Test.Api.create!(Ash.Changeset.new(AshGraphql.Test.Post, text: "foobar")) post =
AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foobar")
|> Ash.create!()
resp = resp =
""" """
@ -66,9 +72,9 @@ defmodule AshGraphql.DestroyTest do
end end
test "a destroy with a configured read action and no identity works" do test "a destroy with a configured read action and no identity works" do
AshGraphql.Test.Api.create!( AshGraphql.Test.Post
Ash.Changeset.new(AshGraphql.Test.Post, text: "foobar", best: true) |> Ash.Changeset.for_create(:create, text: "foobar", best: true)
) |> Ash.create!()
resp = resp =
""" """
@ -92,7 +98,10 @@ defmodule AshGraphql.DestroyTest do
end end
test "a destroy with an error" do test "a destroy with an error" do
post = AshGraphql.Test.Api.create!(Ash.Changeset.new(AshGraphql.Test.Post, text: "foobar")) post =
AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foobar", best: true)
|> Ash.create!()
resp = resp =
""" """
@ -154,11 +163,14 @@ defmodule AshGraphql.DestroyTest do
end end
test "root level error on destroy" do test "root level error on destroy" do
Application.put_env(:ash_graphql, AshGraphql.Test.Api, Application.put_env(:ash_graphql, AshGraphql.Test.Domain,
graphql: [show_raised_errors?: true, root_level_errors?: true] graphql: [show_raised_errors?: true, root_level_errors?: true]
) )
post = AshGraphql.Test.Api.create!(Ash.Changeset.new(AshGraphql.Test.Post, text: "foobar")) post =
AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foobar", best: true)
|> Ash.create!()
resp = resp =
""" """

View file

@ -3,7 +3,7 @@ defmodule AshGraphql.EnumTest do
setup do setup do
on_exit(fn -> on_exit(fn ->
Application.delete_env(:ash_graphql, AshGraphql.Test.Api) Application.delete_env(:ash_graphql, AshGraphql.Test.Domain)
AshGraphql.TestHelpers.stop_ets() AshGraphql.TestHelpers.stop_ets()
end) end)

View file

@ -4,7 +4,7 @@ defmodule AshGraphql.ErrorsTest do
setup do setup do
on_exit(fn -> on_exit(fn ->
Application.delete_env(:ash_graphql, AshGraphql.Test.Api) Application.delete_env(:ash_graphql, AshGraphql.Test.Domain)
Application.delete_env(:ash_graphql, :policies) Application.delete_env(:ash_graphql, :policies)
AshGraphql.TestHelpers.stop_ets() AshGraphql.TestHelpers.stop_ets()
@ -74,7 +74,9 @@ defmodule AshGraphql.ErrorsTest do
end end
test "raised errors can be configured to be shown" do test "raised errors can be configured to be shown" do
Application.put_env(:ash_graphql, AshGraphql.Test.Api, graphql: [show_raised_errors?: true]) Application.put_env(:ash_graphql, AshGraphql.Test.Domain,
graphql: [show_raised_errors?: true]
)
resp = resp =
""" """
@ -109,7 +111,7 @@ defmodule AshGraphql.ErrorsTest do
end end
test "showing raised errors alongside root errors shows raised errors in the root" do test "showing raised errors alongside root errors shows raised errors in the root" do
Application.put_env(:ash_graphql, AshGraphql.Test.RootLevelErrorsApi, Application.put_env(:ash_graphql, AshGraphql.Test.RootLevelErrorsDomain,
graphql: [show_raised_errors?: true] graphql: [show_raised_errors?: true]
) )
@ -157,7 +159,7 @@ defmodule AshGraphql.ErrorsTest do
[name: "My Tag4"], [name: "My Tag4"],
tenant: tenant tenant: tenant
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -188,7 +190,7 @@ defmodule AshGraphql.ErrorsTest do
[name: "My Tag2"], [name: "My Tag2"],
tenant: tenant tenant: tenant
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -219,7 +221,7 @@ defmodule AshGraphql.ErrorsTest do
[name: "My Tag3"], [name: "My Tag3"],
tenant: tenant tenant: tenant
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
post = post =
AshGraphql.Test.Post AshGraphql.Test.Post
@ -230,7 +232,7 @@ defmodule AshGraphql.ErrorsTest do
on_no_match: {:create, :create_action}, on_no_match: {:create, :create_action},
on_lookup: :relate on_lookup: :relate
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -266,7 +268,7 @@ defmodule AshGraphql.ErrorsTest do
|> Ash.Changeset.for_create(:create, |> Ash.Changeset.for_create(:create,
name: "My Name" name: "My Name"
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -315,7 +317,7 @@ defmodule AshGraphql.ErrorsTest do
|> Ash.Changeset.for_create(:create, |> Ash.Changeset.for_create(:create,
name: "My Name" name: "My Name"
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """

View file

@ -3,7 +3,7 @@ defmodule AshGraphql.GenericActionsTest do
setup do setup do
on_exit(fn -> on_exit(fn ->
Application.delete_env(:ash_graphql, AshGraphql.Test.Api) Application.delete_env(:ash_graphql, AshGraphql.Test.Domain)
AshGraphql.TestHelpers.stop_ets() AshGraphql.TestHelpers.stop_ets()
end) end)
@ -55,7 +55,10 @@ defmodule AshGraphql.GenericActionsTest do
end end
test "generic action mutations can be run" do test "generic action mutations can be run" do
post = AshGraphql.Test.Api.create!(Ash.Changeset.new(AshGraphql.Test.Post, text: "foobar")) post =
AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foobar", best: true)
|> Ash.create!()
resp = resp =
""" """
@ -79,7 +82,10 @@ defmodule AshGraphql.GenericActionsTest do
end end
test "generic action mutations can be run with input" do test "generic action mutations can be run with input" do
post = AshGraphql.Test.Api.create!(Ash.Changeset.new(AshGraphql.Test.Post, text: "foobar")) post =
AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foobar", best: true)
|> Ash.create!()
resp = resp =
""" """

View file

@ -17,13 +17,13 @@ defmodule AshGraphql.PaginateTest do
post = post =
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: text, published: true) |> Ash.Changeset.for_create(:create, text: text, published: true)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
for text <- letters do for text <- letters do
AshGraphql.Test.Comment AshGraphql.Test.Comment
|> Ash.Changeset.for_create(:create, text: text) |> Ash.Changeset.for_create(:create, text: text)
|> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
end end
end end
@ -77,13 +77,13 @@ defmodule AshGraphql.PaginateTest do
post = post =
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: text, published: true) |> Ash.Changeset.for_create(:create, text: text, published: true)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
for text <- letters do for text <- letters do
AshGraphql.Test.Comment AshGraphql.Test.Comment
|> Ash.Changeset.for_create(:create, text: text) |> Ash.Changeset.for_create(:create, text: text)
|> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
end end
end end

View file

@ -25,8 +25,8 @@ defmodule AshGraphql.PlugTest do
test "when the actor is set, the current user returns the correct value" do test "when the actor is set, the current user returns the correct value" do
user = user =
AshGraphql.Test.User AshGraphql.Test.User
|> Ash.Changeset.for_create(:create, %{name: "Marty McFly"}) |> Ash.Changeset.for_create(:create, %{name: "My Name"})
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -67,7 +67,7 @@ defmodule AshGraphql.PlugTest do
tag = tag =
AshGraphql.Test.MultitenantTag AshGraphql.Test.MultitenantTag
|> Ash.Changeset.for_create(:create, [name: "1985"], tenant: tenant) |> Ash.Changeset.for_create(:create, [name: "1985"], tenant: tenant)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """

View file

@ -12,11 +12,11 @@ defmodule AshGraphql.ReadTest do
test "float fields works correctly" do test "float fields works correctly" do
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foo", published: true, score: 9.8) |> Ash.Changeset.for_create(:create, text: "foo", published: true, score: 9.8)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "bar", published: true, score: 9.85) |> Ash.Changeset.for_create(:create, text: "bar", published: true, score: 9.85)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -41,11 +41,11 @@ defmodule AshGraphql.ReadTest do
test "union fields works correctly" do test "union fields works correctly" do
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foo", published: true, simple_union: 10) |> Ash.Changeset.for_create(:create, text: "foo", published: true, simple_union: 10)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "bar", published: true, simple_union: "foo") |> Ash.Changeset.for_create(:create, text: "bar", published: true, simple_union: "foo")
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -83,7 +83,7 @@ defmodule AshGraphql.ReadTest do
|> Ash.Changeset.for_create(:create, |> Ash.Changeset.for_create(:create,
name: "My Name" name: "My Name"
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -107,7 +107,7 @@ defmodule AshGraphql.ReadTest do
|> Ash.Changeset.for_create(:create, |> Ash.Changeset.for_create(:create,
name: "My Name" name: "My Name"
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -131,8 +131,8 @@ defmodule AshGraphql.ReadTest do
test "loading relationships with fragment works" do test "loading relationships with fragment works" do
user = user =
AshGraphql.Test.User AshGraphql.Test.User
|> Ash.Changeset.for_create(:create, %{name: "fred"}) |> Ash.Changeset.for_create(:create, %{name: "My Name"})
|> AshGraphql.Test.Api.create!() |> Ash.create!()
post = post =
AshGraphql.Test.Post AshGraphql.Test.Post
@ -144,7 +144,7 @@ defmodule AshGraphql.ReadTest do
published: true published: true
} }
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
post post
|> Ash.Changeset.for_update( |> Ash.Changeset.for_update(
@ -153,7 +153,7 @@ defmodule AshGraphql.ReadTest do
comments: [%{text: "comment", author_id: user.id}] comments: [%{text: "comment", author_id: user.id}]
} }
) )
|> AshGraphql.Test.Api.update!() |> Ash.update!()
resp = resp =
""" """
@ -186,7 +186,7 @@ defmodule AshGraphql.ReadTest do
%{ %{
"comments" => [ "comments" => [
%{ %{
"author" => %{"name" => "fred"} "author" => %{"name" => "My Name"}
} }
] ]
} }
@ -198,11 +198,11 @@ defmodule AshGraphql.ReadTest do
test "a read with arguments works" do test "a read with arguments works" do
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foo", published: true) |> Ash.Changeset.for_create(:create, text: "foo", published: true)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "bar", published: false) |> Ash.Changeset.for_create(:create, text: "bar", published: false)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -228,17 +228,17 @@ defmodule AshGraphql.ReadTest do
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, |> Ash.Changeset.for_create(:create,
text: "foo", text: "foo",
integer_as_string_in_api: 1, integer_as_string_in_domain: 1,
published: true published: true
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
query PostLibrary { query PostLibrary {
postLibrary { postLibrary {
text text
integerAsStringInApi integerAsStringInDomain
} }
} }
""" """
@ -247,19 +247,19 @@ defmodule AshGraphql.ReadTest do
assert {:ok, result} = resp assert {:ok, result} = resp
refute Map.has_key?(result, :errors) refute Map.has_key?(result, :errors)
assert %{data: %{"postLibrary" => [%{"integerAsStringInApi" => "1"}]}} = result assert %{data: %{"postLibrary" => [%{"integerAsStringInDomain" => "1"}]}} = result
end end
test "reading relationships works, without selecting the id field" do test "reading relationships works, without selecting the id field" do
post = post =
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foo", published: true) |> Ash.Changeset.for_create(:create, text: "foo", published: true)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
AshGraphql.Test.Comment AshGraphql.Test.Comment
|> Ash.Changeset.for_create(:create, %{text: "stuff"}) |> Ash.Changeset.for_create(:create, %{text: "stuff"})
|> Ash.Changeset.force_change_attribute(:post_id, post.id) |> Ash.Changeset.force_change_attribute(:post_id, post.id)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -290,12 +290,12 @@ defmodule AshGraphql.ReadTest do
post = post =
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foo", published: true) |> Ash.Changeset.for_create(:create, text: "foo", published: true)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
AshGraphql.Test.Comment AshGraphql.Test.Comment
|> Ash.Changeset.for_create(:create, %{text: "stuff"}) |> Ash.Changeset.for_create(:create, %{text: "stuff"})
|> Ash.Changeset.force_change_attribute(:post_id, post.id) |> Ash.Changeset.force_change_attribute(:post_id, post.id)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -332,13 +332,13 @@ defmodule AshGraphql.ReadTest do
post = post =
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foo", published: true) |> Ash.Changeset.for_create(:create, text: "foo", published: true)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
for _ <- 0..1 do for _ <- 0..1 do
AshGraphql.Test.Comment AshGraphql.Test.Comment
|> Ash.Changeset.for_create(:create, %{text: "stuff"}) |> Ash.Changeset.for_create(:create, %{text: "stuff"})
|> Ash.Changeset.force_change_attribute(:post_id, post.id) |> Ash.Changeset.force_change_attribute(:post_id, post.id)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
end end
resp = resp =
@ -424,7 +424,7 @@ defmodule AshGraphql.ReadTest do
test "a read with a loaded field works" do test "a read with a loaded field works" do
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "bar", published: true) |> Ash.Changeset.for_create(:create, text: "bar", published: true)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -452,7 +452,7 @@ defmodule AshGraphql.ReadTest do
test "the same calculation can be loaded twice with different arguments via aliases" do test "the same calculation can be loaded twice with different arguments via aliases" do
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "bar", text1: "1", text2: "2", published: true) |> Ash.Changeset.for_create(:create, text: "bar", text1: "1", text2: "2", published: true)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -475,11 +475,11 @@ defmodule AshGraphql.ReadTest do
test "the same calculation can be sorted on twice with different arguments via aliases" do test "the same calculation can be sorted on twice with different arguments via aliases" do
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "bar", text1: "1", text2: "2", published: true) |> Ash.Changeset.for_create(:create, text: "bar", text1: "1", text2: "2", published: true)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "bar", text1: "1", text2: "2", published: true) |> Ash.Changeset.for_create(:create, text: "bar", text1: "1", text2: "2", published: true)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -507,7 +507,7 @@ defmodule AshGraphql.ReadTest do
record = record =
AshGraphql.Test.NonIdPrimaryKey AshGraphql.Test.NonIdPrimaryKey
|> Ash.Changeset.for_create(:create, %{}) |> Ash.Changeset.for_create(:create, %{})
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -535,7 +535,7 @@ defmodule AshGraphql.ReadTest do
record = record =
AshGraphql.Test.CompositePrimaryKeyNotEncoded AshGraphql.Test.CompositePrimaryKeyNotEncoded
|> Ash.Changeset.for_create(:create, %{}) |> Ash.Changeset.for_create(:create, %{})
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -570,7 +570,7 @@ defmodule AshGraphql.ReadTest do
record = record =
AshGraphql.Test.CompositePrimaryKey AshGraphql.Test.CompositePrimaryKey
|> Ash.Changeset.for_create(:create, %{}) |> Ash.Changeset.for_create(:create, %{})
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -601,17 +601,17 @@ defmodule AshGraphql.ReadTest do
published: true, published: true,
score: 9.8 score: 9.8
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
post = post =
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foo", published: true) |> Ash.Changeset.for_create(:create, text: "foo", published: true)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
AshGraphql.Test.Comment AshGraphql.Test.Comment
|> Ash.Changeset.for_create(:create, %{text: "stuff"}) |> Ash.Changeset.for_create(:create, %{text: "stuff"})
|> Ash.Changeset.force_change_attribute(:post_id, post.id) |> Ash.Changeset.force_change_attribute(:post_id, post.id)
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -638,7 +638,7 @@ defmodule AshGraphql.ReadTest do
published: true, published: true,
foo: %{foo: "foo", bar: "bar"} foo: %{foo: "foo", bar: "bar"}
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -682,7 +682,7 @@ defmodule AshGraphql.ReadTest do
|> Ash.Changeset.for_create(:create, |> Ash.Changeset.for_create(:create,
name: "My Name" name: "My Name"
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
doc = """ doc = """
query CurrentUser { query CurrentUser {
@ -712,7 +712,7 @@ defmodule AshGraphql.ReadTest do
[name: "My Tag1"], [name: "My Tag1"],
tenant: tenant tenant: tenant
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
doc = """ doc = """
query MultitenantTag($id: ID!) { query MultitenantTag($id: ID!) {
@ -746,7 +746,7 @@ defmodule AshGraphql.ReadTest do
[name: "My Tag"], [name: "My Tag"],
tenant: tenant tenant: tenant
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
post = post =
AshGraphql.Test.Post AshGraphql.Test.Post
@ -757,7 +757,7 @@ defmodule AshGraphql.ReadTest do
on_no_match: {:create, :create_action}, on_no_match: {:create, :create_action},
on_lookup: :relate on_lookup: :relate
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
doc = """ doc = """
query MultitenantPostTag($id: ID!) { query MultitenantPostTag($id: ID!) {
@ -798,7 +798,7 @@ defmodule AshGraphql.ReadTest do
:create, :create,
name: "My Tag" name: "My Tag"
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
post_1 = post_1 =
AshGraphql.Test.Post AshGraphql.Test.Post
@ -809,7 +809,7 @@ defmodule AshGraphql.ReadTest do
on_no_match: {:create, :create_action}, on_no_match: {:create, :create_action},
on_lookup: :relate on_lookup: :relate
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "bar", published: true) |> Ash.Changeset.for_create(:create, text: "bar", published: true)
@ -819,7 +819,7 @@ defmodule AshGraphql.ReadTest do
on_no_match: {:create, :create_action}, on_no_match: {:create, :create_action},
on_lookup: :relate on_lookup: :relate
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
doc = """ doc = """
query ($id: ID!) { query ($id: ID!) {
@ -847,8 +847,11 @@ defmodule AshGraphql.ReadTest do
describe "loading through types" do describe "loading through types" do
test "loading through an embed works" do test "loading through an embed works" do
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.new(embed_foo: %{type: "foo", foo: "fred"}, published: true) |> Ash.Changeset.for_create(:create,
|> AshGraphql.Test.Api.create!() embed_foo: %{foo: "fred"},
published: true
)
|> Ash.create!()
resp = resp =
""" """
@ -881,12 +884,20 @@ defmodule AshGraphql.ReadTest do
test "loading through a union works" do test "loading through a union works" do
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.new(text: "a", embed_union: %{type: :foo, foo: "fred"}, published: true) |> Ash.Changeset.for_create(:create,
|> AshGraphql.Test.Api.create!() text: "a",
embed_union: %{type: :foo, foo: "fred"},
published: true
)
|> Ash.create!()
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.new(text: "b", embed_union: %{type: :bar, bar: "george"}, published: true) |> Ash.Changeset.for_create(:create,
|> AshGraphql.Test.Api.create!() text: "b",
embed_union: %{type: :bar, bar: "george"},
published: true
)
|> Ash.create!()
resp = resp =
""" """
@ -937,20 +948,20 @@ defmodule AshGraphql.ReadTest do
test "loading through an unnested union works" do test "loading through an unnested union works" do
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.new( |> Ash.Changeset.for_create(:create,
text: "a", text: "a",
embed_union_unnested: %{type: :foo, foo: "fred"}, embed_union_unnested: %{type: :foo, foo: "fred"},
published: true published: true
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.new( |> Ash.Changeset.for_create(:create,
text: "b", text: "b",
embed_union_unnested: %{type: :bar, bar: "george"}, embed_union_unnested: %{type: :bar, bar: "george"},
published: true published: true
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -993,20 +1004,20 @@ defmodule AshGraphql.ReadTest do
test "loading through a list of unnested union with aliases works" do test "loading through a list of unnested union with aliases works" do
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.new( |> Ash.Changeset.for_create(:create,
text: "a", text: "a",
embed_union_new_type_list: [%{type: :foo, foo: "fred"}], embed_union_new_type_list: [%{type: :foo, foo: "fred"}],
published: true published: true
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.new( |> Ash.Changeset.for_create(:create,
text: "b", text: "b",
embed_union_new_type_list: [%{type: :bar, bar: "george"}], embed_union_new_type_list: [%{type: :bar, bar: "george"}],
published: true published: true
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -1055,20 +1066,20 @@ defmodule AshGraphql.ReadTest do
test "loading through an unnested union with aliases works" do test "loading through an unnested union with aliases works" do
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.new( |> Ash.Changeset.for_create(:create,
text: "a", text: "a",
embed_union_unnested: %{type: :foo, foo: "fred"}, embed_union_unnested: %{type: :foo, foo: "fred"},
published: true published: true
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.new( |> Ash.Changeset.for_create(:create,
text: "b", text: "b",
embed_union_unnested: %{type: :bar, bar: "george"}, embed_union_unnested: %{type: :bar, bar: "george"},
published: true published: true
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -1117,19 +1128,19 @@ defmodule AshGraphql.ReadTest do
test "loading through an unnested union with aliases works when one is nil" do test "loading through an unnested union with aliases works when one is nil" do
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.new( |> Ash.Changeset.for_create(:create,
text: "a", text: "a",
embed_union_unnested: %{type: :foo, foo: "fred"}, embed_union_unnested: %{type: :foo, foo: "fred"},
published: true published: true
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Changeset.new( |> Ash.Changeset.for_create(:create,
text: "b", text: "b",
published: true published: true
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
resp = resp =
""" """
@ -1180,12 +1191,12 @@ defmodule AshGraphql.ReadTest do
user1 = user1 =
AshGraphql.Test.User AshGraphql.Test.User
|> Ash.Changeset.for_create(:create, %{name: "fred"}) |> Ash.Changeset.for_create(:create, %{name: "fred"})
|> AshGraphql.Test.Api.create!() |> Ash.create!(authorize?: false)
user2 = user2 =
AshGraphql.Test.User AshGraphql.Test.User
|> Ash.Changeset.for_create(:create, %{name: "barney"}) |> Ash.Changeset.for_create(:create, %{name: "barney"})
|> AshGraphql.Test.Api.create!() |> Ash.create!(authorize?: false)
post1 = post1 =
AshGraphql.Test.Post AshGraphql.Test.Post
@ -1197,7 +1208,7 @@ defmodule AshGraphql.ReadTest do
published: true published: true
} }
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
post1 = post1 =
post1 post1
@ -1208,7 +1219,7 @@ defmodule AshGraphql.ReadTest do
sponsored_comments: [%{text: "sponsored"}] sponsored_comments: [%{text: "sponsored"}]
} }
) )
|> AshGraphql.Test.Api.update!() |> Ash.update!()
resp = resp =
""" """
@ -1253,8 +1264,8 @@ defmodule AshGraphql.ReadTest do
test "loading relationships through an unnested union with aliases works" do test "loading relationships through an unnested union with aliases works" do
user = user =
AshGraphql.Test.User AshGraphql.Test.User
|> Ash.Changeset.for_create(:create, %{name: "fred"}) |> Ash.Changeset.for_create(:create, %{name: "My Name"})
|> AshGraphql.Test.Api.create!() |> Ash.create!()
post = post =
AshGraphql.Test.Post AshGraphql.Test.Post
@ -1266,7 +1277,7 @@ defmodule AshGraphql.ReadTest do
published: true published: true
} }
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
post = post =
post post
@ -1277,7 +1288,7 @@ defmodule AshGraphql.ReadTest do
sponsored_comments: [%{text: "sponsored"}] sponsored_comments: [%{text: "sponsored"}]
} }
) )
|> AshGraphql.Test.Api.update!() |> Ash.update!()
resp = resp =
""" """
@ -1340,12 +1351,12 @@ defmodule AshGraphql.ReadTest do
%{ %{
"__typename" => "SponsoredComment", "__typename" => "SponsoredComment",
"text" => "sponsored", "text" => "sponsored",
"p" => %{"id" => ^post_id, "user" => %{"name" => "fred"}} "p" => %{"id" => ^post_id, "user" => %{"name" => "My Name"}}
}, },
%{ %{
"__typename" => "Comment", "__typename" => "Comment",
"text" => "comment", "text" => "comment",
"author" => %{"name" => "fred"} "author" => %{"name" => "My Name"}
} }
], ],
"bar" => [ "bar" => [
@ -1357,7 +1368,7 @@ defmodule AshGraphql.ReadTest do
%{ %{
"__typename" => "Comment", "__typename" => "Comment",
"text" => "comment", "text" => "comment",
"author" => %{"name" => "fred"} "author" => %{"name" => "My Name"}
} }
] ]
} }

View file

@ -1,7 +1,7 @@
defmodule AshGraphql.RelayIdsTest do defmodule AshGraphql.RelayIdsTest do
use ExUnit.Case, async: false use ExUnit.Case, async: false
alias AshGraphql.Test.RelayIds.{Api, Post, ResourceWithNoPrimaryKeyGet, Schema, User} alias AshGraphql.Test.RelayIds.{Post, ResourceWithNoPrimaryKeyGet, Schema, User}
setup do setup do
on_exit(fn -> on_exit(fn ->
@ -14,7 +14,7 @@ defmodule AshGraphql.RelayIdsTest do
user = user =
User User
|> Ash.Changeset.for_create(:create, %{name: "fred"}) |> Ash.Changeset.for_create(:create, %{name: "fred"})
|> Api.create!() |> Ash.create!()
post = post =
Post Post
@ -22,11 +22,10 @@ defmodule AshGraphql.RelayIdsTest do
:create, :create,
%{ %{
author_id: user.id, author_id: user.id,
text: "foo", text: "foo"
published: true
} }
) )
|> Api.create!() |> Ash.create!()
user_relay_id = AshGraphql.Resource.encode_relay_id(user) user_relay_id = AshGraphql.Resource.encode_relay_id(user)
post_relay_id = AshGraphql.Resource.encode_relay_id(post) post_relay_id = AshGraphql.Resource.encode_relay_id(post)
@ -79,14 +78,14 @@ defmodule AshGraphql.RelayIdsTest do
) )
assert {:ok, result} = resp assert {:ok, result} = resp
assert [%{code: "invalid_primary_key"}] = result[:errors] assert [%{message: "invalid primary key provided"}] = result[:errors]
end end
test "returns error on ID for wrong resource" do test "returns error on ID for wrong resource" do
user = user =
User User
|> Ash.Changeset.for_create(:create, %{name: "fred"}) |> Ash.Changeset.for_create(:create, %{name: "fred"})
|> Api.create!() |> Ash.create!()
user_relay_id = AshGraphql.Resource.encode_relay_id(user) user_relay_id = AshGraphql.Resource.encode_relay_id(user)
@ -105,7 +104,7 @@ defmodule AshGraphql.RelayIdsTest do
) )
assert {:ok, result} = resp assert {:ok, result} = resp
assert [%{code: "invalid_primary_key"}] = result[:errors] assert [%{message: "invalid primary key provided"}] = result[:errors]
end end
end end
@ -114,7 +113,7 @@ defmodule AshGraphql.RelayIdsTest do
user = user =
User User
|> Ash.Changeset.for_create(:create, %{name: "fred"}) |> Ash.Changeset.for_create(:create, %{name: "fred"})
|> Api.create!() |> Ash.create!()
post = post =
Post Post
@ -122,11 +121,10 @@ defmodule AshGraphql.RelayIdsTest do
:create, :create,
%{ %{
author_id: user.id, author_id: user.id,
text: "foo", text: "foo"
published: true
} }
) )
|> Api.create!() |> Ash.create!()
user_relay_id = AshGraphql.Resource.encode_relay_id(user) user_relay_id = AshGraphql.Resource.encode_relay_id(user)
post_relay_id = AshGraphql.Resource.encode_relay_id(post) post_relay_id = AshGraphql.Resource.encode_relay_id(post)
@ -195,7 +193,7 @@ defmodule AshGraphql.RelayIdsTest do
resource = resource =
ResourceWithNoPrimaryKeyGet ResourceWithNoPrimaryKeyGet
|> Ash.Changeset.for_create(:create, %{name: "foo"}) |> Ash.Changeset.for_create(:create, %{name: "foo"})
|> Api.create!() |> Ash.create!()
document = document =
""" """
@ -231,7 +229,7 @@ defmodule AshGraphql.RelayIdsTest do
user = user =
User User
|> Ash.Changeset.for_create(:create, %{name: "Fred"}) |> Ash.Changeset.for_create(:create, %{name: "Fred"})
|> Api.create!() |> Ash.create!()
user_id = user.id user_id = user.id
user_type = AshGraphql.Resource.Info.type(User) user_type = AshGraphql.Resource.Info.type(User)
@ -263,7 +261,7 @@ defmodule AshGraphql.RelayIdsTest do
author_id = author_id =
User User
|> Ash.Changeset.for_create(:create, %{name: "Fred"}) |> Ash.Changeset.for_create(:create, %{name: "Fred"})
|> Api.create!() |> Ash.create!()
|> AshGraphql.Resource.encode_relay_id() |> AshGraphql.Resource.encode_relay_id()
resp = resp =
@ -313,13 +311,13 @@ defmodule AshGraphql.RelayIdsTest do
author_id = author_id =
User User
|> Ash.Changeset.for_create(:create, %{name: "Fred"}) |> Ash.Changeset.for_create(:create, %{name: "Fred"})
|> Api.create!() |> Ash.create!()
|> AshGraphql.Resource.encode_relay_id() |> AshGraphql.Resource.encode_relay_id()
post_id = post_id =
Post Post
|> Ash.Changeset.for_create(:create, %{text: "foo"}) |> Ash.Changeset.for_create(:create, %{text: "foo"})
|> Api.create!() |> Ash.create!()
|> AshGraphql.Resource.encode_relay_id() |> AshGraphql.Resource.encode_relay_id()
resp = resp =
@ -368,14 +366,14 @@ defmodule AshGraphql.RelayIdsTest do
author_id = author_id =
User User
|> Ash.Changeset.for_create(:create, %{name: "Fred"}) |> Ash.Changeset.for_create(:create, %{name: "Fred"})
|> Api.create!() |> Ash.create!()
|> AshGraphql.Resource.encode_relay_id() |> AshGraphql.Resource.encode_relay_id()
post_ids = post_ids =
Enum.map(1..5, fn i -> Enum.map(1..5, fn i ->
Post Post
|> Ash.Changeset.for_create(:create, %{text: "foo #{i}"}) |> Ash.Changeset.for_create(:create, %{text: "foo #{i}"})
|> Api.create!() |> Ash.create!()
|> AshGraphql.Resource.encode_relay_id() |> AshGraphql.Resource.encode_relay_id()
end) end)
@ -425,14 +423,14 @@ defmodule AshGraphql.RelayIdsTest do
author_id = author_id =
User User
|> Ash.Changeset.for_create(:create, %{name: "Fred"}) |> Ash.Changeset.for_create(:create, %{name: "Fred"})
|> Api.create!() |> Ash.create!()
|> AshGraphql.Resource.encode_relay_id() |> AshGraphql.Resource.encode_relay_id()
post_ids = post_ids =
Enum.map(1..5, fn i -> Enum.map(1..5, fn i ->
Post Post
|> Ash.Changeset.for_create(:create, %{text: "foo #{i}"}) |> Ash.Changeset.for_create(:create, %{text: "foo #{i}"})
|> Api.create!() |> Ash.create!()
|> AshGraphql.Resource.encode_relay_id() |> AshGraphql.Resource.encode_relay_id()
end) end)
@ -484,7 +482,7 @@ defmodule AshGraphql.RelayIdsTest do
author_id = author_id =
User User
|> Ash.Changeset.for_create(:create, %{name: "Fred"}) |> Ash.Changeset.for_create(:create, %{name: "Fred"})
|> Api.create!() |> Ash.create!()
|> AshGraphql.Resource.encode_relay_id() |> AshGraphql.Resource.encode_relay_id()
post_ids = [author_id] post_ids = [author_id]

View file

@ -20,7 +20,7 @@ defmodule AshGraphql.RelayTest do
:create, :create,
name: name name: name
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
for text <- letters do for text <- letters do
AshGraphql.Test.Post AshGraphql.Test.Post
@ -31,7 +31,7 @@ defmodule AshGraphql.RelayTest do
on_no_match: :error, on_no_match: :error,
on_lookup: :relate_and_update on_lookup: :relate_and_update
) )
|> AshGraphql.Test.Api.create!() |> Ash.create!()
end end
end end
@ -796,7 +796,6 @@ defmodule AshGraphql.RelayTest do
%{ %{
locations: [%{column: 3, line: 2}], locations: [%{column: 3, line: 2}],
message: "Invalid value provided as a keyset for after: \"abc\"", message: "Invalid value provided as a keyset for after: \"abc\"",
code: "invalid_keyset",
short_message: "invalid keyset", short_message: "invalid keyset",
path: ["getRelayTags"] path: ["getRelayTags"]
} }
@ -833,7 +832,6 @@ defmodule AshGraphql.RelayTest do
%{ %{
locations: [%{column: 3, line: 2}], locations: [%{column: 3, line: 2}],
message: "Invalid value provided as a keyset for before: \"abc\"", message: "Invalid value provided as a keyset for before: \"abc\"",
code: "invalid_keyset",
short_message: "invalid keyset", short_message: "invalid keyset",
path: ["getRelayTags"] path: ["getRelayTags"]
} }

View file

@ -1,13 +0,0 @@
defmodule AshGraphql.Test.Api do
@moduledoc false
use Ash.Api,
extensions: [
AshGraphql.Api
],
otp_app: :ash_graphql
resources do
registry(AshGraphql.Test.Registry)
end
end

34
test/support/domain.ex Normal file
View file

@ -0,0 +1,34 @@
defmodule AshGraphql.Test.Domain do
@moduledoc false
use Ash.Domain,
extensions: [
AshGraphql.Domain
],
otp_app: :ash_graphql
resources do
resource(AshGraphql.Test.Comment)
resource(AshGraphql.Test.CompositePrimaryKey)
resource(AshGraphql.Test.CompositePrimaryKeyNotEncoded)
resource(AshGraphql.Test.DoubleRelRecursive)
resource(AshGraphql.Test.DoubleRelToRecursiveParentOfEmbed)
resource(AshGraphql.Test.MapTypes)
resource(AshGraphql.Test.MultitenantPostTag)
resource(AshGraphql.Test.MultitenantTag)
resource(AshGraphql.Test.NoGraphql)
resource(AshGraphql.Test.NoObject)
resource(AshGraphql.Test.NonIdPrimaryKey)
resource(AshGraphql.Test.Post)
resource(AshGraphql.Test.PostTag)
resource(AshGraphql.Test.RelayPostTag)
resource(AshGraphql.Test.RelayTag)
resource(AshGraphql.Test.SponsoredComment)
resource(AshGraphql.Test.Tag)
resource(AshGraphql.Test.User)
resource(AshGraphql.Test.Channel)
resource(AshGraphql.Test.Message)
resource(AshGraphql.Test.TextMessage)
resource(AshGraphql.Test.ImageMessage)
end
end

View file

@ -1,6 +1,7 @@
defmodule Foo do defmodule Foo do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: :embedded, data_layer: :embedded,
extensions: [ extensions: [
AshGraphql.Resource AshGraphql.Resource
@ -12,24 +13,27 @@ defmodule Foo do
attributes do attributes do
attribute :type, :atom do attribute :type, :atom do
public?(true)
constraints(one_of: [:foo]) constraints(one_of: [:foo])
writable?(false) writable?(false)
end end
attribute :foo, :string do attribute :foo, :string do
public?(true)
allow_nil? false allow_nil? false
end end
end end
calculations do calculations do
calculate(:always_true, :boolean, expr(true)) calculate(:always_true, :boolean, expr(true), public?: true)
calculate(:always_nil, :boolean, expr(nil)) calculate(:always_nil, :boolean, expr(nil), public?: true)
end end
end end
defmodule Bar do defmodule Bar do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: :embedded, data_layer: :embedded,
extensions: [ extensions: [
AshGraphql.Resource AshGraphql.Resource
@ -41,17 +45,19 @@ defmodule Bar do
attributes do attributes do
attribute :type, :atom do attribute :type, :atom do
public?(true)
constraints(one_of: [:foo]) constraints(one_of: [:foo])
writable?(false) writable?(false)
end end
attribute :bar, :string do attribute :bar, :string do
public?(true)
allow_nil? false allow_nil? false
end end
end end
calculations do calculations do
calculate(:always_true, :boolean, expr(true)) calculate(:always_true, :boolean, expr(true), public?: true)
calculate(:always_false, :boolean, expr(false)) calculate(:always_false, :boolean, expr(false), public?: true)
end end
end end

View file

@ -1,29 +0,0 @@
defmodule AshGraphql.Test.Registry do
@moduledoc false
use Ash.Registry
entries do
entry(AshGraphql.Test.Comment)
entry(AshGraphql.Test.CompositePrimaryKey)
entry(AshGraphql.Test.CompositePrimaryKeyNotEncoded)
entry(AshGraphql.Test.DoubleRelRecursive)
entry(AshGraphql.Test.DoubleRelToRecursiveParentOfEmbed)
entry(AshGraphql.Test.MapTypes)
entry(AshGraphql.Test.MultitenantPostTag)
entry(AshGraphql.Test.MultitenantTag)
entry(AshGraphql.Test.NoGraphql)
entry(AshGraphql.Test.NoObject)
entry(AshGraphql.Test.NonIdPrimaryKey)
entry(AshGraphql.Test.Post)
entry(AshGraphql.Test.PostTag)
entry(AshGraphql.Test.RelayPostTag)
entry(AshGraphql.Test.RelayTag)
entry(AshGraphql.Test.SponsoredComment)
entry(AshGraphql.Test.Tag)
entry(AshGraphql.Test.User)
entry(AshGraphql.Test.Channel)
entry(AshGraphql.Test.Message)
entry(AshGraphql.Test.TextMessage)
entry(AshGraphql.Test.ImageMessage)
end
end

View file

@ -1,13 +0,0 @@
defmodule AshGraphql.Test.RelayIds.Api do
@moduledoc false
use Ash.Api,
extensions: [
AshGraphql.Api
],
otp_app: :ash_graphql
resources do
registry(AshGraphql.Test.RelayIds.Registry)
end
end

View file

@ -0,0 +1,15 @@
defmodule AshGraphql.Test.RelayIds.Domain do
@moduledoc false
use Ash.Domain,
extensions: [
AshGraphql.Domain
],
otp_app: :ash_graphql
resources do
resource(AshGraphql.Test.RelayIds.Post)
resource(AshGraphql.Test.RelayIds.ResourceWithNoPrimaryKeyGet)
resource(AshGraphql.Test.RelayIds.User)
end
end

View file

@ -1,10 +0,0 @@
defmodule AshGraphql.Test.RelayIds.Registry do
@moduledoc false
use Ash.Registry
entries do
entry(AshGraphql.Test.RelayIds.Post)
entry(AshGraphql.Test.RelayIds.ResourceWithNoPrimaryKeyGet)
entry(AshGraphql.Test.RelayIds.User)
end
end

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.RelayIds.Post do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.RelayIds.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -24,6 +25,7 @@ defmodule AshGraphql.Test.RelayIds.Post do
end end
actions do actions do
default_accept(:*)
defaults([:update, :read, :destroy]) defaults([:update, :read, :destroy])
create :create do create :create do
@ -42,11 +44,12 @@ defmodule AshGraphql.Test.RelayIds.Post do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
attribute(:text, :string) attribute(:text, :string, public?: true)
end end
relationships do relationships do
belongs_to(:author, AshGraphql.Test.RelayIds.User) do belongs_to(:author, AshGraphql.Test.RelayIds.User) do
public?(true)
attribute_writable?(true) attribute_writable?(true)
end end
end end

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.RelayIds.ResourceWithNoPrimaryKeyGet do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.RelayIds.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -18,6 +19,7 @@ defmodule AshGraphql.Test.RelayIds.ResourceWithNoPrimaryKeyGet do
end end
actions do actions do
default_accept(:*)
defaults([:create, :update, :destroy, :read]) defaults([:create, :update, :destroy, :read])
read(:get_by_name, get_by: :name) read(:get_by_name, get_by: :name)
@ -25,14 +27,17 @@ defmodule AshGraphql.Test.RelayIds.ResourceWithNoPrimaryKeyGet do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
attribute(:name, :string, allow_nil?: false) attribute(:name, :string, allow_nil?: false, public?: true)
end end
identities do identities do
identity(:name, [:name], pre_check_with: AshGraphql.Test.RelayIds.Api) identity(:name, [:name], pre_check_with: AshGraphql.Test.RelayIds.Domain)
end end
relationships do relationships do
has_many(:posts, AshGraphql.Test.RelayIds.Post, destination_attribute: :author_id) has_many(:posts, AshGraphql.Test.RelayIds.Post,
destination_attribute: :author_id,
public?: true
)
end end
end end

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.RelayIds.User do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.RelayIds.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -19,6 +20,7 @@ defmodule AshGraphql.Test.RelayIds.User do
end end
actions do actions do
default_accept(:*)
defaults([:create, :update, :destroy, :read]) defaults([:create, :update, :destroy, :read])
update :assign_posts do update :assign_posts do
@ -30,10 +32,13 @@ defmodule AshGraphql.Test.RelayIds.User do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
attribute(:name, :string) attribute(:name, :string, public?: true)
end end
relationships do relationships do
has_many(:posts, AshGraphql.Test.RelayIds.Post, destination_attribute: :author_id) has_many(:posts, AshGraphql.Test.RelayIds.Post,
destination_attribute: :author_id,
public?: true
)
end end
end end

View file

@ -3,9 +3,9 @@ defmodule AshGraphql.Test.RelayIds.Schema do
use Absinthe.Schema use Absinthe.Schema
@apis [AshGraphql.Test.RelayIds.Api] @domains [AshGraphql.Test.RelayIds.Domain]
use AshGraphql, apis: @apis, relay_ids?: true use AshGraphql, domains: @domains, relay_ids?: true
query do query do
end end

View file

@ -1,20 +1,24 @@
defmodule AshGraphql.Test.PageOfChannelMessagesCalculation do defmodule AshGraphql.Test.PageOfChannelMessagesCalculation do
@moduledoc false @moduledoc false
use Ash.Calculation use Ash.Resource.Calculation
def load(_, _, context) do def load(_, _, context) do
limit = context[:limit] || 100 limit = context.arguments.limit || 100
offset = context[:offset] || 0 offset = context.arguments.offset || 0
[ [
:channel_message_count, :channel_message_count,
messages: AshGraphql.Test.Message |> Ash.Query.limit(limit) |> Ash.Query.offset(offset) messages:
AshGraphql.Test.Message
|> Ash.Query.limit(limit)
|> Ash.Query.offset(offset)
|> Ash.Query.select([:type, :text])
] ]
end end
def calculate([post], _, context) do def calculate([post], _, context) do
limit = context[:limit] || 100 limit = context.arguments.limit || 100
offset = context[:offset] || 0 offset = context.arguments.offset || 0
{:ok, {:ok,
[ [

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.Channel do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -16,6 +17,8 @@ defmodule AshGraphql.Test.Channel do
end end
actions do actions do
default_accept(:*)
create :create do create :create do
primary?(true) primary?(true)
end end
@ -30,30 +33,32 @@ defmodule AshGraphql.Test.Channel do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
create_timestamp(:created_at, private?: false) create_timestamp(:created_at, public?: true)
end end
calculations do calculations do
calculate( calculate(
:direct_channel_messages, :direct_channel_messages,
{:array, AshGraphql.Test.MessageUnion}, {:array, AshGraphql.Test.MessageUnion},
fn record, fn records, _ ->
%{ records = Ash.load!(records, :messages)
api: api
} ->
record = api.load!(record, :messages)
{:ok, {:ok,
Enum.map(records, fn record ->
record.messages record.messages
|> Enum.map( |> Enum.map(
&%Ash.Union{type: AshGraphql.Test.MessageUnion.struct_to_name(&1), value: &1} &%Ash.Union{type: AshGraphql.Test.MessageUnion.struct_to_name(&1), value: &1}
)} )
end end)}
end,
public?: true
) )
calculate :indirect_channel_messages, calculate :indirect_channel_messages,
AshGraphql.Test.PageOfChannelMessages, AshGraphql.Test.PageOfChannelMessages,
AshGraphql.Test.PageOfChannelMessagesCalculation do AshGraphql.Test.PageOfChannelMessagesCalculation do
public?(true)
argument :offset, :integer do argument :offset, :integer do
default(0) default(0)
end end
@ -65,10 +70,10 @@ defmodule AshGraphql.Test.Channel do
end end
aggregates do aggregates do
count(:channel_message_count, :messages) count(:channel_message_count, :messages, public?: true)
end end
relationships do relationships do
has_many(:messages, AshGraphql.Test.Message) has_many(:messages, AshGraphql.Test.Message, public?: true)
end end
end end

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.ImageMessage do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -18,6 +19,7 @@ defmodule AshGraphql.Test.ImageMessage do
end end
actions do actions do
default_accept(:*)
defaults([:read, :update, :destroy]) defaults([:read, :update, :destroy])
create :create do create :create do
@ -28,12 +30,16 @@ defmodule AshGraphql.Test.ImageMessage do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
attribute(:text, :string) attribute(:text, :string, public?: true)
attribute(:type, :atom, default: :image, constraints: [one_of: [:text, :image]]) attribute(:type, :atom,
default: :image,
constraints: [one_of: [:text, :image]],
public?: true
)
end end
relationships do relationships do
belongs_to(:channel, AshGraphql.Test.Channel) belongs_to(:channel, AshGraphql.Test.Channel, public?: true)
end end
end end

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.Message do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets data_layer: Ash.DataLayer.Ets
# extensions: [AshGraphql.Resource] # extensions: [AshGraphql.Resource]
@ -11,6 +12,7 @@ defmodule AshGraphql.Test.Message do
end end
actions do actions do
default_accept(:*)
defaults([:read, :update, :destroy]) defaults([:read, :update, :destroy])
create :create do create :create do
@ -21,13 +23,13 @@ defmodule AshGraphql.Test.Message do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
attribute(:text, :string) attribute(:text, :string, public?: true)
attribute(:type, :atom, default: :text, constraints: [one_of: [:text, :image]]) attribute(:type, :atom, default: :text, constraints: [one_of: [:text, :image]], public?: true)
end end
relationships do relationships do
belongs_to(:channel, AshGraphql.Test.Channel) belongs_to(:channel, AshGraphql.Test.Channel, public?: true)
end end
# graphql do # graphql do

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.TextMessage do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -18,6 +19,7 @@ defmodule AshGraphql.Test.TextMessage do
end end
actions do actions do
default_accept(:*)
defaults([:read, :update, :destroy]) defaults([:read, :update, :destroy])
create :create do create :create do
@ -28,12 +30,12 @@ defmodule AshGraphql.Test.TextMessage do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
attribute(:text, :string) attribute(:text, :string, public?: true)
attribute(:type, :atom, default: :text, constraints: [one_of: [:text, :image]]) attribute(:type, :atom, default: :text, constraints: [one_of: [:text, :image]], public?: true)
end end
relationships do relationships do
belongs_to(:channel, AshGraphql.Test.Channel) belongs_to(:channel, AshGraphql.Test.Channel, public?: true)
end end
end end

View file

@ -3,12 +3,14 @@ defmodule AshGraphql.Test.MessageUnion do
@types [ @types [
text: [ text: [
type: AshGraphql.Test.TextMessage, type: :struct,
constraints: [instance_of: AshGraphql.Test.TextMessage],
tag: :type, tag: :type,
tag_value: :text_message tag_value: :text_message
], ],
image: [ image: [
type: AshGraphql.Test.ImageMessage, type: :struct,
constraints: [instance_of: AshGraphql.Test.ImageMessage],
tag: :type, tag: :type,
tag_value: :image_message tag_value: :image_message
] ]

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.Comment do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -19,6 +20,7 @@ defmodule AshGraphql.Test.Comment do
end end
actions do actions do
default_accept(:*)
defaults([:create, :update, :destroy]) defaults([:create, :update, :destroy])
read :read do read :read do
@ -32,9 +34,10 @@ defmodule AshGraphql.Test.Comment do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
attribute(:text, :string) attribute(:text, :string, public?: true)
attribute :type, :atom do attribute :type, :atom do
public?(true)
writable?(false) writable?(false)
default(:comment) default(:comment)
constraints(one_of: [:comment, :reply]) constraints(one_of: [:comment, :reply])
@ -47,14 +50,16 @@ defmodule AshGraphql.Test.Comment do
calculate( calculate(
:timestamp, :timestamp,
:utc_datetime_usec, :utc_datetime_usec,
expr(created_at) expr(created_at),
public?: true
) )
end end
relationships do relationships do
belongs_to(:post, AshGraphql.Test.Post) belongs_to(:post, AshGraphql.Test.Post, public?: true)
belongs_to :author, AshGraphql.Test.User do belongs_to :author, AshGraphql.Test.User do
public?(true)
attribute_writable?(true) attribute_writable?(true)
end end
end end

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.CompositePrimaryKey do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.CompositePrimaryKeyNotEncoded do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.DoubleRelEmbed do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: :embedded, data_layer: :embedded,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -10,6 +11,6 @@ defmodule AshGraphql.Test.DoubleRelEmbed do
end end
attributes do attributes do
attribute(:recursive, :string, default: "No, not I, but me dad be!") attribute(:recursive, :string, default: "No, not I, but me dad be!", public?: true)
end end
end end

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.DoubleRelRecursive do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -12,12 +13,13 @@ defmodule AshGraphql.Test.DoubleRelRecursive do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
attribute(:type, DoubleRelType, allow_nil?: true) attribute(:type, DoubleRelType, allow_nil?: true, public?: true)
attribute(:this, :string, allow_nil?: true) attribute(:this, :string, allow_nil?: true, public?: true)
attribute(:or_that, DoubleRelEmbed, allow_nil?: true) attribute(:or_that, DoubleRelEmbed, allow_nil?: true, public?: true)
end end
actions do actions do
default_accept(:*)
defaults([:create, :read, :update, :destroy]) defaults([:create, :read, :update, :destroy])
end end
@ -27,6 +29,7 @@ defmodule AshGraphql.Test.DoubleRelRecursive do
relationships do relationships do
belongs_to :double_rel, DoubleRelToRecursiveParentOfEmbed do belongs_to :double_rel, DoubleRelToRecursiveParentOfEmbed do
public?(true)
source_attribute(:double_rel_id) source_attribute(:double_rel_id)
allow_nil?(false) allow_nil?(false)
end end
@ -34,15 +37,17 @@ defmodule AshGraphql.Test.DoubleRelRecursive do
belongs_to :myself, DoubleRelRecursive do belongs_to :myself, DoubleRelRecursive do
source_attribute(:recursive_id) source_attribute(:recursive_id)
allow_nil?(false) allow_nil?(false)
private?(true) public?(true)
end end
has_many :first_rel, DoubleRelRecursive do has_many :first_rel, DoubleRelRecursive do
public?(true)
destination_attribute(:recursive_id) destination_attribute(:recursive_id)
filter(expr(type == :first)) filter(expr(type == :first))
end end
has_many :second_rel, DoubleRelRecursive do has_many :second_rel, DoubleRelRecursive do
public?(true)
destination_attribute(:recursive_id) destination_attribute(:recursive_id)
filter(expr(type == :second)) filter(expr(type == :second))
end end

View file

@ -2,12 +2,14 @@ defmodule AshGraphql.Test.DoubleRelToRecursiveParentOfEmbed do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
alias AshGraphql.Test.DoubleRelRecursive alias AshGraphql.Test.DoubleRelRecursive
actions do actions do
default_accept(:*)
defaults([:read, :create, :update, :destroy]) defaults([:read, :create, :update, :destroy])
end end

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.Embed do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: :embedded, data_layer: :embedded,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -10,6 +11,6 @@ defmodule AshGraphql.Test.Embed do
end end
attributes do attributes do
attribute(:nested_embed, AshGraphql.Test.NestedEmbed) attribute(:nested_embed, AshGraphql.Test.NestedEmbed, public?: true)
end end
end end

View file

@ -1,6 +1,7 @@
defmodule AshGraphql.Test.MapTypes do defmodule AshGraphql.Test.MapTypes do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -24,15 +25,19 @@ defmodule AshGraphql.Test.MapTypes do
) )
allow_nil? false allow_nil? false
public?(true)
end end
attribute(:json_map, :map) attribute(:json_map, :map, public?: true)
attribute :values, AshGraphql.Test.ConstrainedMap do attribute :values, AshGraphql.Test.ConstrainedMap do
public?(true)
end end
end end
actions do actions do
default_accept(:*)
defaults([:create, :read, :update, :destroy]) defaults([:create, :read, :update, :destroy])
update :inline do update :inline do

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.MultitenantPostTag do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets data_layer: Ash.DataLayer.Ets
actions do actions do

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.MultitenantTag do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -24,6 +25,7 @@ defmodule AshGraphql.Test.MultitenantTag do
end end
actions do actions do
default_accept(:*)
defaults([:read, :update, :destroy]) defaults([:read, :update, :destroy])
create :create do create :create do
@ -34,18 +36,19 @@ defmodule AshGraphql.Test.MultitenantTag do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
attribute(:name, :string) attribute(:name, :string, public?: true)
end end
identities do identities do
identity(:name, [:name], pre_check_with: AshGraphql.Test.Api) identity(:name, [:name], pre_check_with: AshGraphql.Test.Domain)
end end
relationships do relationships do
many_to_many(:posts, AshGraphql.Test.Post, many_to_many(:posts, AshGraphql.Test.Post,
through: AshGraphql.Test.MultitenantPostTag, through: AshGraphql.Test.MultitenantPostTag,
source_attribute_on_join_resource: :tag_id, source_attribute_on_join_resource: :tag_id,
destination_attribute_on_join_resource: :post_id destination_attribute_on_join_resource: :post_id,
public?: true
) )
end end
end end

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.NestedEmbed do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: :embedded, data_layer: :embedded,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -10,7 +11,7 @@ defmodule AshGraphql.Test.NestedEmbed do
end end
attributes do attributes do
attribute(:name, :string) attribute(:name, :string, public?: true)
attribute(:enum, AshGraphql.Test.NestedEnum) attribute(:enum, AshGraphql.Test.NestedEnum, public?: true)
end end
end end

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.NoGraphql do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets data_layer: Ash.DataLayer.Ets
attributes do attributes do

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.NoObject do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -26,6 +27,6 @@ defmodule AshGraphql.Test.NoObject do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
attribute(:name, :string) attribute(:name, :string, public?: true)
end end
end end

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.NonIdPrimaryKey do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]

View file

@ -36,7 +36,7 @@ end
defmodule FullTextCalculation do defmodule FullTextCalculation do
@moduledoc false @moduledoc false
use Ash.Calculation use Ash.Resource.Calculation
def calculate(posts, _, _) do def calculate(posts, _, _) do
Enum.map(posts, fn post -> Enum.map(posts, fn post ->
@ -44,7 +44,7 @@ defmodule FullTextCalculation do
end) end)
end end
def select(_, _, _), do: [:text1, :text2] def load(_, _, _), do: [:text1, :text2]
end end
defmodule AfterActionRaiseResourceError do defmodule AfterActionRaiseResourceError do
@ -63,8 +63,8 @@ defmodule RelatedPosts do
use Ash.Resource.ManualRelationship use Ash.Resource.ManualRelationship
require Ash.Query require Ash.Query
def load(posts, _opts, %{api: api}) do def load(posts, _opts, %{domain: domain}) do
posts = api.load!(posts, :tags) posts = domain.load!(posts, :tags)
{ {
:ok, :ok,
@ -78,7 +78,7 @@ defmodule RelatedPosts do
AshGraphql.Test.Post AshGraphql.Test.Post
|> Ash.Query.filter(tags.id in ^tag_ids) |> Ash.Query.filter(tags.id in ^tag_ids)
|> Ash.Query.filter(id != ^post.id) |> Ash.Query.filter(id != ^post.id)
|> api.read!() |> Ash.read!()
{post.id, other_posts} {post.id, other_posts}
end) end)
@ -93,6 +93,7 @@ defmodule AshGraphql.Test.Post do
alias AshGraphql.Test.SponsoredComment alias AshGraphql.Test.SponsoredComment
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
authorizers: [Ash.Policy.Authorizer], authorizers: [Ash.Policy.Authorizer],
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -112,8 +113,8 @@ defmodule AshGraphql.Test.Post do
graphql do graphql do
type :post type :post
attribute_types integer_as_string_in_api: :string attribute_types integer_as_string_in_domain: :string
attribute_input_types integer_as_string_in_api: :string attribute_input_types integer_as_string_in_domain: :string
field_names text_1_and_2: :text1_and2 field_names text_1_and_2: :text1_and2
keyset_field :keyset keyset_field :keyset
@ -172,6 +173,8 @@ defmodule AshGraphql.Test.Post do
end end
actions do actions do
default_accept(:*)
create :create do create :create do
primary?(true) primary?(true)
metadata(:foo, :string) metadata(:foo, :string)
@ -206,7 +209,7 @@ defmodule AshGraphql.Test.Post do
__MODULE__ __MODULE__
end end
input.api.count(query) input.domain.count(query)
end) end)
end end
@ -218,7 +221,7 @@ defmodule AshGraphql.Test.Post do
run(fn input, _ -> run(fn input, _ ->
__MODULE__ __MODULE__
|> Ash.Query.limit(1) |> Ash.Query.limit(1)
|> input.api.read_one() |> input.domain.read_one()
end) end)
end end
@ -324,20 +327,24 @@ defmodule AshGraphql.Test.Post do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
attribute(:text, :string) attribute(:text, :string, public?: true)
attribute(:published, :boolean, default: false) attribute(:published, :boolean, default: false, public?: true)
attribute(:foo, AshGraphql.Test.Foo) attribute(:foo, AshGraphql.Test.Foo, public?: true)
attribute(:status, AshGraphql.Test.Status) attribute(:status, AshGraphql.Test.Status, public?: true)
attribute(:status_enum, AshGraphql.Test.StatusEnum) attribute(:status_enum, AshGraphql.Test.StatusEnum, public?: true)
attribute(:enum_with_ash_graphql_description, AshGraphql.Test.EnumWithAshGraphqlDescription)
attribute(:enum_with_ash_description, AshGraphql.Test.EnumWithAshDescription) attribute(:enum_with_ash_graphql_description, AshGraphql.Test.EnumWithAshGraphqlDescription,
attribute(:best, :boolean) public?: true
attribute(:score, :float) )
attribute(:integer_as_string_in_api, :integer)
attribute(:embed, AshGraphql.Test.Embed) attribute(:enum_with_ash_description, AshGraphql.Test.EnumWithAshDescription, public?: true)
attribute(:text1, :string) attribute(:best, :boolean, public?: true)
attribute(:text2, :string) attribute(:score, :float, public?: true)
attribute(:visibility, :atom, constraints: [one_of: [:public, :private]]) attribute(:integer_as_string_in_domain, :integer, public?: true)
attribute(:embed, AshGraphql.Test.Embed, public?: true)
attribute(:text1, :string, public?: true)
attribute(:text2, :string, public?: true)
attribute(:visibility, :atom, constraints: [one_of: [:public, :private]], public?: true)
attribute(:simple_union, :union, attribute(:simple_union, :union,
constraints: [ constraints: [
@ -349,10 +356,11 @@ defmodule AshGraphql.Test.Post do
type: :string type: :string
] ]
] ]
] ],
public?: true
) )
attribute(:embed_foo, Foo) attribute(:embed_foo, Foo, public?: true)
attribute(:embed_union, :union, attribute(:embed_union, :union,
constraints: [ constraints: [
@ -368,90 +376,110 @@ defmodule AshGraphql.Test.Post do
tag_value: :bar tag_value: :bar
] ]
] ]
] ],
public?: true
) )
attribute(:embed_union_new_type_list, {:array, AshGraphql.Types.EmbedUnionNewTypeUnnested}) attribute(:embed_union_new_type_list, {:array, AshGraphql.Types.EmbedUnionNewTypeUnnested},
attribute(:embed_union_new_type, AshGraphql.Types.EmbedUnionNewType) public?: true
attribute(:embed_union_unnested, AshGraphql.Types.EmbedUnionNewTypeUnnested) )
attribute(:enum_new_type, AshGraphql.Types.EnumNewType)
attribute(:string_new_type, AshGraphql.Types.StringNewType) attribute(:embed_union_new_type, AshGraphql.Types.EmbedUnionNewType, public?: true)
attribute(:embed_union_unnested, AshGraphql.Types.EmbedUnionNewTypeUnnested, public?: true)
attribute(:enum_new_type, AshGraphql.Types.EnumNewType, public?: true)
attribute(:string_new_type, AshGraphql.Types.StringNewType, public?: true)
attribute :required_string, :string do attribute :required_string, :string do
allow_nil? false allow_nil? false
default("test") default("test")
public?(true)
end end
create_timestamp(:created_at, private?: false) create_timestamp(:created_at, public?: true)
end end
calculations do calculations do
calculate(:static_calculation, :string, AshGraphql.Test.StaticCalculation) calculate(:static_calculation, :string, AshGraphql.Test.StaticCalculation, public?: true)
calculate(:full_text, :string, FullTextCalculation) calculate(:full_text, :string, FullTextCalculation, public?: true)
calculate(:text_1_and_2, :string, expr(text1 <> ^arg(:separator) <> text2)) do calculate(:text_1_and_2, :string, expr(text1 <> ^arg(:separator) <> text2)) do
public?(true)
argument :separator, :string do argument :separator, :string do
allow_nil? false allow_nil? false
default(" ") default(" ")
end end
end end
calculate(:post_comments, {:array, UnionRelation}, fn record, _ -> calculate(
:post_comments,
{:array, UnionRelation},
fn records, _ ->
# This is very inefficient, do not copy this pattern into your own app!!! # This is very inefficient, do not copy this pattern into your own app!!!
values = values =
Enum.map(records, fn record ->
[ [
SponsoredComment |> AshGraphql.Test.Api.read!(), SponsoredComment |> Ash.read!(),
Comment |> AshGraphql.Test.Api.read!() Comment |> Ash.read!()
] ]
|> List.flatten() |> List.flatten()
|> Stream.filter(&(&1.post_id == record.id)) |> Stream.filter(&(&1.post_id == record.id))
|> Enum.map(&%Ash.Union{type: UnionRelation.struct_to_name(&1), value: &1}) |> Enum.map(&%Ash.Union{type: UnionRelation.struct_to_name(&1), value: &1})
end)
{:ok, values} {:ok, values}
end) end,
public?: true
)
end end
aggregates do aggregates do
count(:comment_count, :comments) count(:comment_count, :comments, public?: true)
max(:latest_comment_at, [:comments], :timestamp) max(:latest_comment_at, [:comments], :timestamp, public?: true)
first :latest_comment_type, [:comments], :type do first :latest_comment_type, [:comments], :type do
public?(true)
sort(timestamp: :desc) sort(timestamp: :desc)
end end
end end
relationships do relationships do
belongs_to(:author, AshGraphql.Test.User) do belongs_to(:author, AshGraphql.Test.User) do
public?(true)
attribute_writable?(true) attribute_writable?(true)
end end
has_many(:comments, AshGraphql.Test.Comment) has_many(:comments, AshGraphql.Test.Comment, public?: true)
has_many(:sponsored_comments, AshGraphql.Test.SponsoredComment) has_many(:sponsored_comments, AshGraphql.Test.SponsoredComment, public?: true)
has_many(:paginated_comments, AshGraphql.Test.Comment, read_action: :paginated) has_many(:paginated_comments, AshGraphql.Test.Comment, read_action: :paginated, public?: true)
many_to_many(:tags, AshGraphql.Test.Tag, many_to_many(:tags, AshGraphql.Test.Tag,
through: AshGraphql.Test.PostTag, through: AshGraphql.Test.PostTag,
source_attribute_on_join_resource: :post_id, source_attribute_on_join_resource: :post_id,
destination_attribute_on_join_resource: :tag_id destination_attribute_on_join_resource: :tag_id,
public?: true
) )
many_to_many(:multitenant_tags, AshGraphql.Test.MultitenantTag, many_to_many(:multitenant_tags, AshGraphql.Test.MultitenantTag,
through: AshGraphql.Test.MultitenantPostTag, through: AshGraphql.Test.MultitenantPostTag,
source_attribute_on_join_resource: :post_id, source_attribute_on_join_resource: :post_id,
destination_attribute_on_join_resource: :tag_id destination_attribute_on_join_resource: :tag_id,
public?: true
) )
many_to_many(:relay_tags, AshGraphql.Test.RelayTag, many_to_many(:relay_tags, AshGraphql.Test.RelayTag,
through: AshGraphql.Test.RelayPostTag, through: AshGraphql.Test.RelayPostTag,
source_attribute_on_join_resource: :post_id, source_attribute_on_join_resource: :post_id,
destination_attribute_on_join_resource: :tag_id destination_attribute_on_join_resource: :tag_id,
public?: true
) )
has_many :related_posts, AshGraphql.Test.Post do has_many :related_posts, AshGraphql.Test.Post do
public?(true)
manual(RelatedPosts) manual(RelatedPosts)
no_attributes?(true) no_attributes?(true)
end end
has_one(:no_graphql, AshGraphql.Test.NoGraphql) has_one(:no_graphql, AshGraphql.Test.NoGraphql, public?: true)
end end
end end

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.PostTag do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets data_layer: Ash.DataLayer.Ets
actions do actions do

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.RelayPostTag do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets data_layer: Ash.DataLayer.Ets
actions do actions do

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.RelayTag do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -20,6 +21,7 @@ defmodule AshGraphql.Test.RelayTag do
end end
actions do actions do
default_accept(:*)
defaults([:create, :update, :destroy, :read]) defaults([:create, :update, :destroy, :read])
read :read_paginated do read :read_paginated do
@ -30,11 +32,11 @@ defmodule AshGraphql.Test.RelayTag do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
attribute(:name, :string) attribute(:name, :string, public?: true)
end end
identities do identities do
identity(:name, [:name], pre_check_with: AshGraphql.Test.Api) identity(:name, [:name], pre_check_with: AshGraphql.Test.Domain)
end end
relationships do relationships do

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.SponsoredComment do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -18,6 +19,7 @@ defmodule AshGraphql.Test.SponsoredComment do
end end
actions do actions do
default_accept(:*)
defaults([:create, :update, :destroy]) defaults([:create, :update, :destroy])
read :read do read :read do
@ -31,15 +33,16 @@ defmodule AshGraphql.Test.SponsoredComment do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
attribute(:text, :string) attribute(:text, :string, public?: true)
attribute :type, :atom do attribute :type, :atom do
public?(true)
writable?(false) writable?(false)
default(:sponsored) default(:sponsored)
end end
end end
relationships do relationships do
belongs_to(:post, AshGraphql.Test.Post) belongs_to(:post, AshGraphql.Test.Post, public?: true)
end end
end end

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.Tag do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -20,6 +21,7 @@ defmodule AshGraphql.Test.Tag do
end end
actions do actions do
default_accept(:*)
defaults([:read, :update, :destroy]) defaults([:read, :update, :destroy])
create :create do create :create do
@ -30,11 +32,11 @@ defmodule AshGraphql.Test.Tag do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
attribute(:name, :string) attribute(:name, :string, public?: true)
end end
identities do identities do
identity(:name, [:name], pre_check_with: AshGraphql.Test.Api) identity(:name, [:name], pre_check_with: AshGraphql.Test.Domain)
end end
relationships do relationships do

View file

@ -2,6 +2,7 @@ defmodule AshGraphql.Test.User do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshGraphql.Test.Domain,
data_layer: Ash.DataLayer.Ets, data_layer: Ash.DataLayer.Ets,
authorizers: [Ash.Policy.Authorizer], authorizers: [Ash.Policy.Authorizer],
extensions: [AshGraphql.Resource] extensions: [AshGraphql.Resource]
@ -25,12 +26,14 @@ defmodule AshGraphql.Test.User do
end end
actions do actions do
default_accept(:*)
defaults([:create, :update, :destroy, :read]) defaults([:create, :update, :destroy, :read])
create(:create_policies) create(:create_policies)
read :current_user do read :current_user do
filter(id: actor(:id)) filter(expr(id == ^actor(:id)))
end end
read :current_user_with_metadata do read :current_user_with_metadata do
@ -50,20 +53,21 @@ defmodule AshGraphql.Test.User do
attributes do attributes do
uuid_primary_key(:id) uuid_primary_key(:id)
attribute(:name, :string) attribute(:name, :string, public?: true)
attribute(:secret, :string) do attribute(:secret, :string) do
public?(true)
allow_nil? false allow_nil? false
default("super secret") default("super secret")
end end
end end
relationships do relationships do
has_many(:posts, AshGraphql.Test.Post, destination_attribute: :author_id) has_many(:posts, AshGraphql.Test.Post, destination_attribute: :author_id, public?: true)
end end
calculations do calculations do
calculate(:name_twice, :string, expr(name <> " " <> name)) calculate(:name_twice, :string, expr(name <> " " <> name), public?: true)
end end
policies do policies do

View file

@ -1,17 +0,0 @@
defmodule AshGraphql.Test.RootLevelErrorsApi do
@moduledoc false
use Ash.Api,
extensions: [
AshGraphql.Api
],
otp_app: :ash_graphql
graphql do
root_level_errors? true
end
resources do
registry(AshGraphql.Test.Registry)
end
end

View file

@ -0,0 +1,38 @@
defmodule AshGraphql.Test.RootLevelErrorsDomain do
@moduledoc false
use Ash.Domain,
extensions: [
AshGraphql.Domain
],
otp_app: :ash_graphql
graphql do
root_level_errors? true
end
resources do
resource(AshGraphql.Test.Comment)
resource(AshGraphql.Test.CompositePrimaryKey)
resource(AshGraphql.Test.CompositePrimaryKeyNotEncoded)
resource(AshGraphql.Test.DoubleRelRecursive)
resource(AshGraphql.Test.DoubleRelToRecursiveParentOfEmbed)
resource(AshGraphql.Test.MapTypes)
resource(AshGraphql.Test.MultitenantPostTag)
resource(AshGraphql.Test.MultitenantTag)
resource(AshGraphql.Test.NoGraphql)
resource(AshGraphql.Test.NoObject)
resource(AshGraphql.Test.NonIdPrimaryKey)
resource(AshGraphql.Test.Post)
resource(AshGraphql.Test.PostTag)
resource(AshGraphql.Test.RelayPostTag)
resource(AshGraphql.Test.RelayTag)
resource(AshGraphql.Test.SponsoredComment)
resource(AshGraphql.Test.Tag)
resource(AshGraphql.Test.User)
resource(AshGraphql.Test.Channel)
resource(AshGraphql.Test.Message)
resource(AshGraphql.Test.TextMessage)
resource(AshGraphql.Test.ImageMessage)
end
end

View file

@ -3,9 +3,9 @@ defmodule AshGraphql.Test.RootLevelErrorsSchema do
use Absinthe.Schema use Absinthe.Schema
@apis [AshGraphql.Test.RootLevelErrorsApi] @domains [AshGraphql.Test.RootLevelErrorsDomain]
use AshGraphql, apis: @apis use AshGraphql, domains: @domains
query do query do
end end

View file

@ -3,9 +3,9 @@ defmodule AshGraphql.Test.Schema do
use Absinthe.Schema use Absinthe.Schema
@apis [AshGraphql.Test.Api] @domains [AshGraphql.Test.Domain]
use AshGraphql, apis: @apis use AshGraphql, domains: @domains
query do query do
end end

View file

@ -1,6 +1,6 @@
defmodule AshGraphql.Test.StaticCalculation do defmodule AshGraphql.Test.StaticCalculation do
@moduledoc false @moduledoc false
use Ash.Calculation, type: :string use Ash.Resource.Calculation, type: :string
def calculate(records, _, _) do def calculate(records, _, _) do
Enum.map(records, fn _ -> "static" end) Enum.map(records, fn _ -> "static" end)

View file

@ -3,7 +3,7 @@ defmodule AshGraphql.TestHelpers do
require Logger require Logger
def stop_ets do def stop_ets do
for resource <- Ash.Registry.Info.entries(AshGraphql.Test.Registry) do for resource <- Ash.Domain.Info.resources(AshGraphql.Test.Domain) do
try do try do
Ash.DataLayer.Ets.stop(resource) Ash.DataLayer.Ets.stop(resource)
rescue rescue

View file

@ -4,18 +4,22 @@ defmodule UnionRelation do
@types [ @types [
comment: [ comment: [
type: Comment, type: :struct,
constraints: [instance_of: Comment],
tag: :type, tag: :type,
tag_value: :comment tag_value: :comment
], ],
sponsored_comment: [ sponsored_comment: [
type: SponsoredComment, type: :struct,
constraints: [instance_of: SponsoredComment],
tag: :type, tag: :type,
tag_value: :sponsored tag_value: :sponsored
] ]
] ]
@structs_to_names Keyword.new(@types, fn {key, value} -> {value[:type], key} end) @structs_to_names Keyword.new(@types, fn {key, value} ->
{value[:constraints][:instance_of], key}
end)
use Ash.Type.NewType, use Ash.Type.NewType,
subtype_of: :union, subtype_of: :union,

View file

@ -1,3 +1,3 @@
ExUnit.start() ExUnit.start()
Code.ensure_compiled(AshGraphql.Test.Api) Code.ensure_compiled(AshGraphql.Test.Domain)

View file

@ -3,7 +3,7 @@ defmodule AshGraphql.UpdateTest do
setup do setup do
on_exit(fn -> on_exit(fn ->
Application.delete_env(:ash_graphql, AshGraphql.Test.Api) Application.delete_env(:ash_graphql, AshGraphql.Test.Domain)
try do try do
AshGraphql.TestHelpers.stop_ets() AshGraphql.TestHelpers.stop_ets()
@ -15,7 +15,10 @@ defmodule AshGraphql.UpdateTest do
end end
test "an update works" do test "an update works" do
post = AshGraphql.Test.Api.create!(Ash.Changeset.new(AshGraphql.Test.Post, text: "foobar")) post =
AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foobar")
|> Ash.create!()
resp = resp =
""" """
@ -137,9 +140,9 @@ defmodule AshGraphql.UpdateTest do
test "an update with a configured read action and no identity works" do test "an update with a configured read action and no identity works" do
post = post =
AshGraphql.Test.Api.create!( AshGraphql.Test.Post
Ash.Changeset.new(AshGraphql.Test.Post, text: "foobar", best: true) |> Ash.Changeset.for_create(:create, text: "foobar", best: true)
) |> Ash.create!()
resp = resp =
""" """
@ -169,9 +172,9 @@ defmodule AshGraphql.UpdateTest do
end end
test "an update with a configured read action and no identity works with an argument the same name as an attribute" do test "an update with a configured read action and no identity works with an argument the same name as an attribute" do
AshGraphql.Test.Api.create!( AshGraphql.Test.Post
Ash.Changeset.new(AshGraphql.Test.Post, text: "foobar", best: true) |> Ash.Changeset.for_create(:create, text: "foobar", best: true)
) |> Ash.create!()
resp = resp =
""" """
@ -203,9 +206,9 @@ defmodule AshGraphql.UpdateTest do
test "arguments are threaded properly" do test "arguments are threaded properly" do
post = post =
AshGraphql.Test.Api.create!( AshGraphql.Test.Post
Ash.Changeset.new(AshGraphql.Test.Post, text: "foobar", best: true) |> Ash.Changeset.for_create(:create, text: "foobar", best: true)
) |> Ash.create!()
resp = resp =
""" """
@ -242,14 +245,14 @@ defmodule AshGraphql.UpdateTest do
end end
test "root level error" do test "root level error" do
Application.put_env(:ash_graphql, AshGraphql.Test.Api, Application.put_env(:ash_graphql, AshGraphql.Test.Domain,
graphql: [show_raised_errors?: true, root_level_errors?: true] graphql: [show_raised_errors?: true, root_level_errors?: true]
) )
post = post =
AshGraphql.Test.Api.create!( AshGraphql.Test.Post
Ash.Changeset.new(AshGraphql.Test.Post, text: "foobar", best: true) |> Ash.Changeset.for_create(:create, text: "foobar", best: true)
) |> Ash.create!()
resp = resp =
""" """
@ -282,7 +285,10 @@ defmodule AshGraphql.UpdateTest do
end end
test "referencing a hidden input is not allowed" do test "referencing a hidden input is not allowed" do
post = AshGraphql.Test.Api.create!(Ash.Changeset.new(AshGraphql.Test.Post, text: "foobar")) post =
AshGraphql.Test.Post
|> Ash.Changeset.for_create(:create, text: "foobar")
|> Ash.create!()
resp = resp =
""" """