Skip to content

Commit

Permalink
Import directive definitions from custom prototype (#92)
Browse files Browse the repository at this point in the history
Using a custom prototype with the skip_prototype option would fail the
federated schema composition because absinthe will not add required
directive and type definitions from the prototype. This changes the way we
use a custom prototype; instead of providing a skip_prototype boolean and
a module attribute for the prototype, we provide the prototype_schema
option when we `use Absinthe.Federation.Schema`. This way, the definitions
are imported as necessary.

This change also unlocks the @composeDirective support in the
federation_compatibility checks.

The breaking change from 0.4.2 will be added to the changelog.
  • Loading branch information
kzlsakal authored Feb 23, 2024
1 parent 57e281e commit 8c60cf2
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 24 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,7 @@ If you are already using a schema prototype
```elixir
defmodule MyApp.MySchema do
use Absinthe.Schema
+ use Absinthe.Federation.Schema, skip_prototype: true

@prototype_schema MyApp.MySchemaPrototype
+ use Absinthe.Federation.Schema, prototype_schema: MyApp.MySchemaPrototype

query do
...
Expand Down
25 changes: 20 additions & 5 deletions federation_compatibility/lib/products_web/schema.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
defmodule ProductsWeb.Schema do
use Absinthe.Schema
use Absinthe.Federation.Schema

defmodule Product do
defstruct [:id, :sku, :package, :variation]
end
Expand All @@ -26,9 +23,24 @@ defmodule ProductsWeb.Schema do
defstruct [:email, :name, :total_products_created, :years_of_employment]
end

defmodule Prototype do
use Absinthe.Schema.Prototype
use Absinthe.Federation.Schema.Prototype.FederatedDirectives

directive :custom do
on :object
end
end

use Absinthe.Schema
use Absinthe.Federation.Schema, prototype_schema: Prototype

extend schema do
directive :composeDirective, name: "@custom"
directive :link, url: "https://divvypay.com/test/v2.4", import: ["@custom"]

directive :link,
url: "https://specs.apollo.dev/federation/v2.0",
url: "https://specs.apollo.dev/federation/v2.1",
import: [
"@extends",
"@external",
Expand All @@ -38,7 +50,8 @@ defmodule ProductsWeb.Schema do
"@provides",
"@requires",
"@shareable",
"@tag"
"@tag",
"@composeDirective"
]
end

Expand All @@ -56,6 +69,8 @@ defmodule ProductsWeb.Schema do
"""
object :product do
key_fields(["id", "sku package", "sku variation { id }"])
directive :custom

field :id, non_null(:id)
field :sku, :string
field :package, :string
Expand Down
25 changes: 22 additions & 3 deletions lib/absinthe/federation/schema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ defmodule Absinthe.Federation.Schema do
end
"""

alias Absinthe.Federation.Schema.Prototype, as: FederationPrototype
alias Absinthe.Phase.Schema.TypeImports
alias Absinthe.Pipeline

Expand All @@ -22,14 +23,32 @@ defmodule Absinthe.Federation.Schema do
end

defp do_using(opts) do
has_custom_prototype? = Keyword.has_key?(opts, :prototype_schema)
prototype_schema = if has_custom_prototype?, do: opts[:prototype_schema], else: FederationPrototype

quote do
@pipeline_modifier unquote(__MODULE__)
use Absinthe.Federation.Notation

unless unquote(opts[:skip_prototype]) do
@prototype_schema Absinthe.Federation.Schema.Prototype
if Keyword.has_key?(unquote(opts), :skip_prototype) do
raise ArgumentError,
":skip_prototype option is no longer supported. \n" <>
"Please provide your custom prototype module with the :prototype_schema option instead. \n" <>
"Example: `use Absinthe.Federation.Schema, prototype_schema: MySchema.Prototype`"
end

if unquote(has_custom_prototype?) do
@prototype_schema unquote(prototype_schema)

import_types unquote(prototype_schema),
except: unquote(Map.keys(FederationPrototype.__absinthe_types__()))

import_directives unquote(prototype_schema),
except: unquote(Map.keys(FederationPrototype.__absinthe_directives__()))
else
@prototype_schema FederationPrototype
end

use Absinthe.Federation.Notation
import_types Absinthe.Federation.Types
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
defmodule Absinthe.Federation.Schema.Prototype.FederatedDirectives do
@moduledoc false

use Absinthe.Schema.Notation

defmacro __using__(_) do
quote do
@desc """
Expand Down
15 changes: 10 additions & 5 deletions test/absinthe/federation/notation_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,13 @@ defmodule Absinthe.Federation.NotationTest do
end

directive :other do
on :schema
on :object
end
end

defmodule MultipleComposeDirectivesSchema do
use Absinthe.Schema
use Absinthe.Federation.Schema, skip_prototype: true

@prototype_schema ComposePrototype
use Absinthe.Federation.Schema, prototype_schema: ComposePrototype

extend schema do
directive :link, url: "https://specs.apollo.dev/federation/v2.1", import: ["@composeDirective"]
Expand All @@ -149,13 +147,20 @@ defmodule Absinthe.Federation.NotationTest do
end

query do
field :hello, :string
field :hello, :user
end

object :user do
directive :other
field :name, :string
end
end

sdl = Absinthe.Schema.to_sdl(MultipleComposeDirectivesSchema)

assert sdl =~ ~s{schema @composeDirective(name: "@other") @composeDirective(name: "@custom")}
assert sdl =~ ~s{directive @custom on SCHEMA}
assert sdl =~ ~s{directive @other on OBJECT}
end
end
end
11 changes: 5 additions & 6 deletions test/absinthe/federation/schema_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,18 @@ defmodule Absinthe.Federation.SchemaTest do
use Absinthe.Schema.Prototype
use Absinthe.Federation.Schema.Prototype.FederatedDirectives

directive :my_directive do
directive :custom do
on [:schema]
end
end

defmodule CustomPrototypeSchema do
use Absinthe.Schema
use Absinthe.Federation.Schema, skip_prototype: true

@prototype_schema CustomPrototype
use Absinthe.Federation.Schema, prototype_schema: CustomPrototype

extend schema do
directive :link, url: "https://specs.apollo.dev/federation/v2.0", import: ["@tag"]
directive :myDirective
directive :custom
end

query do
Expand All @@ -91,7 +89,8 @@ defmodule Absinthe.Federation.SchemaTest do
test "it includes federation and custom directions" do
sdl = Absinthe.Federation.to_federated_sdl(CustomPrototypeSchema)

assert sdl =~ "schema @myDirective @link"
assert sdl =~ "schema @custom @link"
assert sdl =~ "directive @custom on SCHEMA"
end
end
end

0 comments on commit 8c60cf2

Please sign in to comment.