-
Notifications
You must be signed in to change notification settings - Fork 527
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Build SDL version of Things test schema * Use Absinthe.Case consistently * Start work on schema directives * Extensible SDL directives * Expand schema directives * Add resolvers to SDL schema * Support no-op directives * Add directive placement for schema declarations * Work on hydrate rename * Fix callback * Typos! * Formatting * Update travis
- Loading branch information
Showing
112 changed files
with
994 additions
and
384 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
defmodule Absinthe.Blueprint.Schema.SchemaDeclaration do | ||
@moduledoc false | ||
|
||
alias Absinthe.Blueprint | ||
|
||
defstruct description: nil, | ||
module: nil, | ||
field_definitions: [], | ||
directives: [], | ||
source_location: nil, | ||
# Added by phases | ||
flags: %{}, | ||
errors: [], | ||
__reference__: nil, | ||
__private__: [] | ||
|
||
@type t :: %__MODULE__{ | ||
description: nil | String.t(), | ||
module: nil | module(), | ||
directives: [Blueprint.Directive.t()], | ||
field_definitions: [Blueprint.Schema.FieldDefinition.t()], | ||
source_location: nil | Blueprint.SourceLocation.t(), | ||
# Added by phases | ||
flags: Blueprint.flags_t(), | ||
errors: [Absinthe.Phase.Error.t()] | ||
} | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
defmodule Absinthe.Language.SchemaDeclaration do | ||
@moduledoc false | ||
|
||
alias Absinthe.{Blueprint, Language} | ||
|
||
defstruct description: nil, | ||
directives: [], | ||
fields: [], | ||
loc: %{line: nil} | ||
|
||
@type t :: %__MODULE__{ | ||
description: nil | String.t(), | ||
directives: [Language.Directive.t()], | ||
fields: [Language.FieldDefinition.t()], | ||
loc: Language.loc_t() | ||
} | ||
|
||
defimpl Blueprint.Draft do | ||
def convert(node, doc) do | ||
%Blueprint.Schema.SchemaDeclaration{ | ||
description: node.description, | ||
field_definitions: Absinthe.Blueprint.Draft.convert(node.fields, doc), | ||
directives: Absinthe.Blueprint.Draft.convert(node.directives, doc), | ||
source_location: source_location(node) | ||
} | ||
end | ||
|
||
defp source_location(%{loc: nil}), do: nil | ||
defp source_location(%{loc: loc}), do: Blueprint.SourceLocation.at(loc) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
defmodule Absinthe.Phase.Schema.ApplyDeclaration do | ||
@moduledoc false | ||
|
||
use Absinthe.Phase | ||
alias Absinthe.Blueprint | ||
|
||
@type operation :: :query | :mutation | :subscription | ||
|
||
@type root_mappings :: %{operation() => Blueprint.TypeReference.Name.t()} | ||
|
||
def run(blueprint, _opts) do | ||
blueprint = process(blueprint) | ||
{:ok, blueprint} | ||
end | ||
|
||
# Apply schema declaration to each schema definition | ||
@spec process(blueprint :: Blueprint.t()) :: Blueprint.t() | ||
defp process(blueprint = %Blueprint{}) do | ||
%{ | ||
blueprint | ||
| schema_definitions: Enum.map(blueprint.schema_definitions, &process_schema_definition/1) | ||
} | ||
end | ||
|
||
# Strip the schema declaration out of the schema's type definitions and apply it | ||
@spec process_schema_definition(schema_definition :: Blueprint.Schema.SchemaDefinition.t()) :: | ||
Blueprint.Schema.SchemaDefinition.t() | ||
defp process_schema_definition(schema_definition) do | ||
{declarations, type_defs} = | ||
Enum.split_with( | ||
schema_definition.type_definitions, | ||
&match?(%Blueprint.Schema.SchemaDeclaration{}, &1) | ||
) | ||
|
||
# Remove declaration | ||
schema_definition = %{schema_definition | type_definitions: type_defs} | ||
|
||
case declarations do | ||
[declaration] -> | ||
root_mappings = | ||
declaration | ||
|> extract_root_mappings | ||
|
||
%{ | ||
schema_definition | ||
| type_definitions: | ||
Enum.map(schema_definition.type_definitions, &maybe_mark_root(&1, root_mappings)) | ||
} | ||
|
||
[] -> | ||
schema_definition | ||
|
||
[_first | extra_declarations] -> | ||
extra_declarations | ||
|> Enum.reduce(schema_definition, fn declaration, acc -> | ||
acc | ||
|> put_error(error(declaration)) | ||
end) | ||
end | ||
end | ||
|
||
# Generate an error for extraneous schema declarations | ||
@spec error(declaration :: Blueprint.Schema.SchemaDeclaration.t()) :: Absinthe.Phase.Error.t() | ||
defp error(declaration) do | ||
%Absinthe.Phase.Error{ | ||
message: | ||
"More than one schema declaration found. Only one instance of `schema' should be present in SDL.", | ||
locations: [declaration.__reference__.location], | ||
phase: __MODULE__ | ||
} | ||
end | ||
|
||
# Extract the declared root type names | ||
@spec extract_root_mappings(declaration :: Blueprint.Schema.SchemaDeclaration.t()) :: | ||
root_mappings() | ||
defp extract_root_mappings(declaration) do | ||
for field_def <- declaration.field_definitions, | ||
field_def.identifier in ~w(query mutation subscription)a, | ||
into: %{} do | ||
{field_def.identifier, field_def.type} | ||
end | ||
end | ||
|
||
# If the type definition is declared as a root type, set the identifier appropriately | ||
@spec maybe_mark_root(type_def :: Blueprint.Schema.node_t(), root_mappings :: root_mappings()) :: | ||
Blueprint.Schema.node_t() | ||
defp maybe_mark_root(%Blueprint.Schema.ObjectTypeDefinition{} = type_def, root_mappings) do | ||
case operation_root_identifier(type_def, root_mappings) do | ||
nil -> | ||
type_def | ||
|
||
identifier -> | ||
%{type_def | identifier: identifier} | ||
end | ||
end | ||
|
||
defp maybe_mark_root(type_def, _root_mappings), do: type_def | ||
|
||
# Determine which, if any, root identifier should be applied to an object type definitiona | ||
@spec operation_root_identifier( | ||
type_def :: Blueprint.Schema.ObjectTypeDefinition.t(), | ||
root_mappings :: root_mappings() | ||
) :: nil | operation() | ||
defp operation_root_identifier(type_def, root_mappings) do | ||
match_name = type_def.name | ||
|
||
Enum.find_value(root_mappings, fn | ||
{ident, %{name: ^match_name}} -> | ||
ident | ||
|
||
_ -> | ||
false | ||
end) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
defmodule Absinthe.Phase.Schema.AttachDirectives do | ||
@moduledoc false | ||
|
||
# Expand all directives in the document. | ||
# | ||
# Note that no validation occurs in this phase. | ||
|
||
use Absinthe.Phase | ||
alias Absinthe.Blueprint | ||
|
||
@spec run(Blueprint.t(), Keyword.t()) :: {:ok, Blueprint.t()} | ||
def run(input, _options \\ []) do | ||
node = Blueprint.prewalk(input, &handle_node(&1, input.schema)) | ||
{:ok, node} | ||
end | ||
|
||
@spec handle_node(node :: Blueprint.Directive.t(), schema :: Absinthe.Schema.t()) :: | ||
Blueprint.Directive.t() | ||
defp handle_node(%Blueprint.Directive{} = node, schema) do | ||
schema_node = Enum.find(available_directives(schema), &(&1.name == node.name)) | ||
%{node | schema_node: schema_node} | ||
end | ||
|
||
@spec handle_node(node :: Blueprint.node_t(), schema :: Absinthe.Schema.t()) :: | ||
Blueprint.node_t() | ||
defp handle_node(node, _schema) do | ||
node | ||
end | ||
|
||
defp available_directives(schema) do | ||
schema.sdl_directives(builtins()) | ||
end | ||
|
||
def builtins do | ||
[ | ||
%Absinthe.Type.Directive{ | ||
name: "deprecated", | ||
locations: [:field_definition, :input_field_definition, :argument_definition], | ||
expand: &expand_deprecate/2 | ||
} | ||
] | ||
end | ||
|
||
@doc """ | ||
Add a deprecation (with an optional reason) to a node. | ||
""" | ||
@spec expand_deprecate( | ||
arguments :: %{optional(:reason) => String.t()}, | ||
node :: Blueprint.node_t() | ||
) :: Blueprint.node_t() | ||
def expand_deprecate(arguments, node) do | ||
%{node | deprecation: %Absinthe.Type.Deprecation{reason: arguments[:reason]}} | ||
end | ||
end |
Oops, something went wrong.