Packages
ash_graphql
0.25.3
1.9.4
1.9.3
1.9.2
1.9.1
1.9.0
1.8.5
1.8.4
1.8.3
1.8.2
1.8.1
1.8.0
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.0
1.5.1
1.5.0
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.1
1.2.0
1.1.1
1.1.0
1.0.1
1.0.0
1.0.0-rc.5
1.0.0-rc.4
retired
1.0.0-rc.3
1.0.0-rc.2
1.0.0-rc.1
1.0.0-rc.0
0.28.1
0.28.0
0.27.1
0.27.0
0.26.9
0.26.8
0.26.7
0.26.6
0.26.5
0.26.4
0.26.3
0.26.2
0.26.0
0.25.13
0.25.12
0.25.10
0.25.9
0.25.8
0.25.7
0.25.6
0.25.5
0.25.4
0.25.3
0.25.2
0.25.1
0.25.0
0.24.1
0.24.0
0.23.3
0.23.2
0.23.1
0.23.0
0.22.13
0.22.12
0.22.11
0.22.10
0.22.9
0.22.8
0.22.7
0.22.6
0.22.4
0.22.3
0.22.2
0.22.1
0.22.0
0.21.0
retired
0.20.5
0.20.4
0.20.3
0.20.2
0.20.1
0.20.0-rc.3
0.20.0-rc.2
0.20.0-rc.1
0.20.0-rc.0
0.19.0
0.18.0-rc0
0.17.5
0.17.5-rc0
0.17.4
0.17.2
0.17.1
0.17.0
0.16.28
0.16.27
0.16.26
0.16.25
0.16.24
0.16.23
0.16.22
0.16.21
0.16.20
0.16.18-rc5
0.16.18-rc4
0.16.18-rc3
0.16.18-rc2
0.16.18-rc1
0.16.18-rc0
0.16.17
0.16.16
0.16.15
0.16.14
0.16.13
0.16.12
0.16.11
0.16.10
0.16.9
0.16.8
0.16.7
0.16.6
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.10
0.15.9
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.1
0.14.0
0.13.1
0.13.0
0.12.5
0.12.4
0.12.3
0.12.1
0.12.0
0.10.0
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.0
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.0
0.4.0
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.3
0.1.2
The extension for building GraphQL APIs with Ash
Current section
Files
Jump to
Current section
Files
lib/api/api.ex
defmodule AshGraphql.Api do
@graphql %Spark.Dsl.Section{
name: :graphql,
describe: """
Global configuration for graphql
""",
examples: [
"""
graphql do
authorize? false # To skip authorization for this API
end
"""
],
schema: [
authorize?: [
type: :boolean,
doc: "Whether or not to perform authorization for this API",
default: true
],
tracer: [
type: :atom,
doc:
"A tracer to use to trace execution in the graphql. Will use `config :ash, :tracer` if it is set."
],
root_level_errors?: [
type: :boolean,
default: false,
doc:
"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: [
type: :mfa,
default: {AshGraphql.DefaultErrorHandler, :handle_error, []},
doc: """
Set an MFA to intercept/handle any errors that are generated.
"""
],
show_raised_errors?: [
type: :boolean,
default: false,
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."
],
debug?: [
type: :boolean,
doc: "Whether or not to log (extremely verbose) debug information",
default: false
]
]
}
@sections [@graphql]
@moduledoc """
The entrypoint for adding graphql behavior to an Ash API
<!--- ash-hq-hide-start --> <!--- -->
## DSL Documentation
### Index
#{Spark.Dsl.Extension.doc_index(@sections)}
### Docs
#{Spark.Dsl.Extension.doc(@sections)}
<!--- ash-hq-hide-stop --> <!--- -->
"""
require Ash.Api.Info
use Spark.Dsl.Extension, sections: @sections
@deprecated "See `AshGraphql.Api.Info.authorize?/1`"
defdelegate authorize?(api), to: AshGraphql.Api.Info
@deprecated "See `AshGraphql.Api.Info.root_level_errors?/1`"
defdelegate root_level_errors?(api), to: AshGraphql.Api.Info
@deprecated "See `AshGraphql.Api.Info.show_raised_errors?/1`"
defdelegate show_raised_errors?(api), to: AshGraphql.Api.Info
@deprecated "See `AshGraphql.Api.Info.debug?/1`"
defdelegate debug?(api), to: AshGraphql.Api.Info
@doc false
def queries(api, resources, action_middleware, schema) do
Enum.flat_map(resources, &AshGraphql.Resource.queries(api, &1, action_middleware, schema))
end
@doc false
def mutations(api, resources, action_middleware, schema) do
resources
|> Enum.filter(fn resource ->
AshGraphql.Resource in Spark.extensions(resource)
end)
|> Enum.flat_map(&AshGraphql.Resource.mutations(api, &1, action_middleware, schema))
end
@doc false
def type_definitions(api, resources, schema, env, first?) do
resource_types =
resources
|> Enum.reject(&Ash.Resource.Info.embedded?/1)
|> Enum.flat_map(fn resource ->
if AshGraphql.Resource in Spark.extensions(resource) &&
AshGraphql.Resource.Info.type(resource) do
AshGraphql.Resource.type_definitions(resource, api, schema) ++
AshGraphql.Resource.mutation_types(resource, schema)
else
AshGraphql.Resource.no_graphql_types(resource, schema)
end
end)
if first? do
[
%Absinthe.Blueprint.Schema.InterfaceTypeDefinition{
description: "A relay node",
name: "Node",
fields: [
%Absinthe.Blueprint.Schema.FieldDefinition{
description: "A unique identifier",
identifier: :id,
module: schema,
name: "id",
__reference__: AshGraphql.Resource.ref(env),
type: %Absinthe.Blueprint.TypeReference.NonNull{of_type: :id}
}
],
identifier: :node,
__reference__: AshGraphql.Resource.ref(env),
module: schema
},
%Absinthe.Blueprint.Schema.ObjectTypeDefinition{
description: "A relay page info",
name: "PageInfo",
fields: [
%Absinthe.Blueprint.Schema.FieldDefinition{
description: "When paginating backwards, are there more items?",
identifier: :has_previous_page,
module: schema,
name: "has_previous_page",
__reference__: AshGraphql.Resource.ref(env),
type: %Absinthe.Blueprint.TypeReference.NonNull{of_type: :boolean}
},
%Absinthe.Blueprint.Schema.FieldDefinition{
description: "When paginating forwards, are there more items?",
identifier: :has_next_page,
module: schema,
name: "has_next_page",
__reference__: AshGraphql.Resource.ref(env),
type: %Absinthe.Blueprint.TypeReference.NonNull{of_type: :boolean}
},
%Absinthe.Blueprint.Schema.FieldDefinition{
description: "When paginating backwards, the cursor to continue",
identifier: :start_cursor,
module: schema,
name: "start_cursor",
__reference__: AshGraphql.Resource.ref(env),
type: :string
},
%Absinthe.Blueprint.Schema.FieldDefinition{
description: "When paginating forwards, the cursor to continue",
identifier: :end_cursor,
module: schema,
name: "end_cursor",
__reference__: AshGraphql.Resource.ref(env),
type: :string
}
# 'count' field is not compatible with keyset pagination
],
identifier: :page_info,
module: schema,
__reference__: AshGraphql.Resource.ref(env)
}
] ++ resource_types
else
resource_types
end
end
def global_type_definitions(schema, env) do
[mutation_error(schema, env), sort_order(schema, env)]
end
defp sort_order(schema, env) do
%Absinthe.Blueprint.Schema.EnumTypeDefinition{
module: schema,
name: "SortOrder",
values: [
%Absinthe.Blueprint.Schema.EnumValueDefinition{
module: schema,
identifier: :desc,
__reference__: AshGraphql.Resource.ref(env),
name: "DESC",
value: :desc
},
%Absinthe.Blueprint.Schema.EnumValueDefinition{
module: schema,
identifier: :asc,
__reference__: AshGraphql.Resource.ref(env),
name: "ASC",
value: :asc
}
],
identifier: :sort_order,
__reference__: AshGraphql.Resource.ref(env)
}
end
defp mutation_error(schema, env) do
%Absinthe.Blueprint.Schema.ObjectTypeDefinition{
description: "An error generated by a failed mutation",
fields: error_fields(schema, env),
identifier: :mutation_error,
module: schema,
name: "MutationError",
__reference__: AshGraphql.Resource.ref(env)
}
end
defp error_fields(schema, env) do
[
%Absinthe.Blueprint.Schema.FieldDefinition{
description: "The human readable error message",
identifier: :message,
module: schema,
__reference__: AshGraphql.Resource.ref(env),
name: "message",
type: :string
},
%Absinthe.Blueprint.Schema.FieldDefinition{
description: "A shorter error message, with vars not replaced",
identifier: :short_message,
module: schema,
__reference__: AshGraphql.Resource.ref(env),
name: "short_message",
type: :string
},
%Absinthe.Blueprint.Schema.FieldDefinition{
description: "Replacements for the short message",
identifier: :vars,
module: schema,
__reference__: AshGraphql.Resource.ref(env),
name: "vars",
type: :json
},
%Absinthe.Blueprint.Schema.FieldDefinition{
description: "An error code for the given error",
identifier: :code,
module: schema,
__reference__: AshGraphql.Resource.ref(env),
name: "code",
type: :string
},
%Absinthe.Blueprint.Schema.FieldDefinition{
description: "The field or fields that produced the error",
identifier: :fields,
module: schema,
__reference__: AshGraphql.Resource.ref(env),
name: "fields",
type: %Absinthe.Blueprint.TypeReference.List{
of_type: :string
}
}
]
end
end