Skip to content

Commit c8ff6e3

Browse files
committed
Use absinthe directive macros instead of meta
1 parent a8c828d commit c8ff6e3

File tree

11 files changed

+149
-160
lines changed

11 files changed

+149
-160
lines changed

README.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ defmodule MyApp.MySchema do
5252
+ use Absinthe.Federation.Schema
5353

5454
query do
55-
+ extends()
55+
+ directive :extends
5656

5757
field :review, :review do
5858
arg(:id, non_null(:id))
@@ -62,12 +62,10 @@ defmodule MyApp.MySchema do
6262
end
6363

6464
object :product do
65-
+ key_fields("upc")
66-
+ extends()
65+
+ directive :key, fields: "upc"
66+
+ directive :extends
6767

68-
field :upc, non_null(:string) do
69-
+ external()
70-
end
68+
+ field :upc, non_null(:string), directives: [:external]
7169

7270
field(:reviews, list_of(:review)) do
7371
resolve(&ReviewResolver.get_reviews_for_product/3)

lib/absinthe/federation/notation.ex

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,18 @@ defmodule Absinthe.Federation.Notation do
4242
id: ID!
4343
}
4444
"""
45-
defmacro key_fields(fields) when is_binary(fields) or is_list(fields) do
45+
@deprecated "Use absinthe built in directive/2 macro"
46+
defmacro key_fields(fieldset) when is_binary(fieldset) do
4647
quote do
47-
meta :key_fields, unquote(fields)
48+
directive :key, fields: unquote(fieldset)
49+
end
50+
end
51+
52+
defmacro key_fields(fields) when is_list(fields) do
53+
for fieldset <- fields do
54+
quote do
55+
directive :key, fields: unquote(fieldset)
56+
end
4857
end
4958
end
5059

@@ -75,9 +84,10 @@ defmodule Absinthe.Federation.Notation do
7584
This type extension in the Reviews service extends the User type from the Users service.
7685
It extends it for the purpose of adding a new field called reviews, which returns a list of `Review`s.
7786
"""
87+
@deprecated "Use absinthe built in directive/2 macro"
7888
defmacro external() do
7989
quote do
80-
meta :external, true
90+
directive :external
8191
end
8292
end
8393

@@ -117,9 +127,10 @@ defmodule Absinthe.Federation.Notation do
117127
to know the `email` of the `User` from the Users service in order to look up the `reviews`.
118128
This means the `reviews` field / resolver requires the `email` field from the base `User` type.
119129
"""
120-
defmacro requires_fields(fields) when is_binary(fields) do
130+
@deprecated "Use absinthe built in directive/2 macro"
131+
defmacro requires_fields(fieldset) when is_binary(fieldset) do
121132
quote do
122-
meta :requires_fields, unquote(fields)
133+
directive :requires, fields: unquote(fieldset)
123134
end
124135
end
125136

@@ -164,9 +175,10 @@ defmodule Absinthe.Federation.Notation do
164175
can provide it when going from review to product. `Product.name` is an external field
165176
on an external type which is why the local type extension of `Product` and annotation of `name` is required.
166177
"""
167-
defmacro provides_fields(fields) when is_binary(fields) do
178+
@deprecated "Use absinthe built in directive/2 macro"
179+
defmacro provides_fields(fieldset) when is_binary(fieldset) do
168180
quote do
169-
meta :provides_fields, unquote(fields)
181+
directive :provides, fields: unquote(fieldset)
170182
end
171183
end
172184

@@ -188,9 +200,10 @@ defmodule Absinthe.Federation.Notation do
188200
id: ID!
189201
}
190202
"""
203+
@deprecated "Use absinthe built in directive/2 macro"
191204
defmacro extends() do
192205
quote do
193-
meta :extends, true
206+
directive :extends
194207
end
195208
end
196209
end

lib/absinthe/federation/schema.ex

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ defmodule Absinthe.Federation.Schema do
3737
def pipeline(pipeline) do
3838
Pipeline.insert_after(pipeline, TypeImports, [
3939
__MODULE__.Phase.AddFederatedTypes,
40-
__MODULE__.Phase.AddFederatedDirectives,
4140
__MODULE__.Phase.Validation.KeyFieldsMustExist,
4241
__MODULE__.Phase.Validation.KeyFieldsMustBeValidWhenExtends
4342
])

lib/absinthe/federation/schema/phase/add_federated_directives.ex

Lines changed: 0 additions & 86 deletions
This file was deleted.

lib/absinthe/federation/schema/phase/validation/key_fields_must_exist.ex

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,15 @@ defmodule Absinthe.Federation.Schema.Phase.Validation.KeyFieldsMustExist do
2727
object
2828

2929
true ->
30-
key_fields = get_in(object.__private__, [:meta, :key_fields])
30+
key_fields = object.directives
31+
|> Enum.filter(fn %{name: name} -> name == "key" end)
32+
|> Enum.map(fn
33+
%{arguments: [%{input_value: %{content: %{value: fieldset}}}]} -> fieldset
34+
%{arguments: [%{value: fieldset}]} -> fieldset
35+
end)
36+
# IO.inspect(object.directives, label: "object.directives")
37+
# IO.inspect(key_fields, label: "key_fields")
38+
3139
validate_key_fields(key_fields, object, adapter)
3240
end
3341
end
@@ -82,7 +90,7 @@ defmodule Absinthe.Federation.Schema.Phase.Validation.KeyFieldsMustExist do
8290
end
8391

8492
defp is_defining_or_extending?(object) do
85-
not is_nil(get_in(object.__private__, [:meta, :key_fields]))
93+
Enum.find_value(object.directives, false, fn %{name: name} -> name == "key" end)
8694
end
8795

8896
defp in?(key, fields, adapter) do

lib/absinthe/federation/schema/prototype.ex

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,25 @@ defmodule Absinthe.Federation.Schema.Prototype do
1414
parse &{:ok, &1}
1515
end
1616

17+
enum :link_purpose, name: "link__Purpose" do
18+
value :security
19+
value :execution
20+
end
21+
22+
scalar :link_import, name: "link__Import" do
23+
serialize & &1
24+
parse &{:ok, &1}
25+
end
26+
1727
@desc """
1828
The `@key` directive is used to indicate a combination of fields that can be used
1929
to uniquely identify and fetch an object or interface.
2030
"""
2131
directive :key do
2232
arg :fields, non_null(:_field_set)
33+
arg :resolvable, :boolean, default_value: true
34+
35+
repeatable true
2336
on [:object, :interface]
2437
end
2538

@@ -53,4 +66,57 @@ defmodule Absinthe.Federation.Schema.Prototype do
5366
directive :extends do
5467
on [:object, :interface]
5568
end
69+
70+
@desc """
71+
Indicates that an object type's field is allowed to be resolved by multiple subgraphs
72+
(by default, each field can be resolved by only one subgraph).
73+
"""
74+
directive :shareable do
75+
on [:field_definition, :object]
76+
end
77+
78+
@desc """
79+
Indicates that a field or type should be omitted from the gateway's API schema,
80+
even if it's also defined in other subgraphs.
81+
"""
82+
directive :inaccessible do
83+
on [:field_definition, :object, :interface, :union]
84+
end
85+
86+
@desc """
87+
Indicates that a field is now resolved by this subgraph
88+
instead of another subgraph where it's also defined.
89+
"""
90+
directive :override do
91+
arg :from, non_null(:string)
92+
on [:field_definition]
93+
end
94+
95+
@desc """
96+
The @link directive links definitions within the document to external schemas.
97+
98+
External schemas are identified by their url,
99+
which optionally ends with a name and version with the following format:
100+
{NAME}/v{MAJOR}.{MINOR}
101+
102+
The presence of a @link directive makes a document a core schema.
103+
104+
The for argument describes the purpose of a @link.
105+
Currently accepted values are SECURITY or EXECUTION.
106+
Core schema-aware servers such as Apollo Router and Gateway will refuse to operate on schemas that contain @links to unsupported specs which are for: SECURITY or for: EXECUTION.
107+
108+
By default, @linked definitions will be namespaced,
109+
i.e., @federation__requires.
110+
The as argument lets you pick the name for this namespace:
111+
"""
112+
directive :link do
113+
arg :url, :string
114+
arg :as, :string
115+
arg :for, :link_purpose
116+
arg :import, :link_import
117+
118+
repeatable true
119+
120+
on [:schema]
121+
end
56122
end

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ defmodule Absinthe.Federation.MixProject do
6262

6363
defp deps do
6464
[
65-
{:absinthe, "~> 1.6.5 or ~> 1.7.0"},
65+
{:absinthe, path: "../../absinthe-graphql/absinthe"},
6666
{:dataloader, "~> 1.0.9"},
6767

6868
# Dev

mix.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
%{
2-
"absinthe": {:hex, :absinthe, "1.6.6", "d4b3d87c868264edf47fbf9c152155f31e8d26c370607f5fe92f6e106d190b74", [:mix], [{:dataloader, "~> 1.0.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0 or ~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a03e18478b19bdf81ed1eef9b0853edf4496a080c2048ed17993dc945a90bedc"},
3-
"dataloader": {:hex, :dataloader, "1.0.9", "8fb981e327fa692f741ab283ed93790203a6f6d412800f0f4f1531372e1dbf15", [:mix], [{:ecto, ">= 3.4.3 and < 4.0.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6f8b7566c8dda46f53bdb336fd02f03f00bf58aeb6cc0f139ccdfd6f99d265a7"},
2+
"absinthe": {:git, "https://github.com/absinthe-graphql/absinthe.git", "453fd12c0bbfd938c43a9251a320cfae96dafe16", [branch: "master"]},
3+
"dataloader": {:hex, :dataloader, "1.0.10", "a42f07641b1a0572e0b21a2a5ae1be11da486a6790f3d0d14512d96ff3e3bbe9", [:mix], [{:ecto, ">= 3.4.3 and < 4.0.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:telemetry, "~> 1.0 or ~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "54cd70cec09addf4b2ace14cc186a283a149fd4d3ec5475b155951bf33cd963f"},
44
"dialyxir": {:hex, :dialyxir, "1.0.0", "6a1fa629f7881a9f5aaf3a78f094b2a51a0357c843871b8bc98824e7342d00a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "aeb06588145fac14ca08d8061a142d52753dbc2cf7f0d00fc1013f53f8654654"},
55
"earmark_parser": {:hex, :earmark_parser, "1.4.16", "607709303e1d4e3e02f1444df0c821529af1c03b8578dfc81bb9cf64553d02b9", [:mix], [], "hexpm", "69fcf696168f5a274dd012e3e305027010658b2d1630cef68421d6baaeaccead"},
66
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
77
"ex_doc": {:hex, :ex_doc, "0.25.3", "3edf6a0d70a39d2eafde030b8895501b1c93692effcbd21347296c18e47618ce", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "9ebebc2169ec732a38e9e779fd0418c9189b3ca93f4a676c961be6c1527913f5"},
88
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
99
"makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"},
1010
"makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"},
11-
"nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"},
12-
"telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"},
11+
"nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"},
12+
"telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"},
1313
}
Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,54 @@
11
defmodule Absinthe.Federation.NotationTest do
22
use Absinthe.Federation.Case, async: true
33

4-
describe "macro schema" do
5-
defmodule MacroSchema do
6-
use Absinthe.Schema
7-
use Absinthe.Federation.Schema
4+
defmodule FederatedMacroSchema do
5+
use Absinthe.Schema
6+
use Absinthe.Federation.Schema
87

9-
query do
10-
field :me, :user
11-
end
8+
query do
9+
field :me, :user
10+
end
1211

13-
object :user do
14-
key_fields("id")
15-
extends()
12+
object :user do
13+
key_fields("id")
14+
extends()
1615

17-
field :id, non_null(:id) do
18-
external()
19-
end
16+
field :id, non_null(:id) do
17+
external()
2018
end
2119
end
20+
end
2221

23-
test "can use federation macros" do
24-
sdl = Absinthe.Schema.to_sdl(MacroSchema)
25-
assert sdl =~ "type User @extends @key(fields: \"id\")"
26-
assert sdl =~ "id: ID! @external"
22+
test "can use federation macros" do
23+
sdl = Absinthe.Schema.to_sdl(FederatedMacroSchema)
24+
assert sdl =~ "type User @extends @key(fields: \"id\")"
25+
assert sdl =~ "id: ID! @external"
26+
end
27+
28+
defmodule AbsintheMacroSchema do
29+
use Absinthe.Schema
30+
use Absinthe.Federation.Schema
31+
32+
query do
33+
field :me, :user
2734
end
35+
36+
object :user do
37+
directive :key, fields: "id"
38+
directive :extends
39+
40+
field :id, non_null(:id) do
41+
directive :external
42+
end
43+
44+
field :name, :string, directives: [:provides]
45+
end
46+
end
47+
48+
test "can use absinthe directive macros" do
49+
sdl = Absinthe.Schema.to_sdl(AbsintheMacroSchema)
50+
assert sdl =~ "type User @extends @key(fields: \"id\")"
51+
assert sdl =~ "id: ID! @external"
52+
assert sdl =~ "name: String @provides"
2853
end
2954
end

0 commit comments

Comments
 (0)