Skip to content
This repository was archived by the owner on Jul 25, 2024. It is now read-only.
This repository was archived by the owner on Jul 25, 2024. It is now read-only.

Schema DSL #15

Closed
Closed
@1player

Description

@1player

I've been lurking in this repo for a while and I've tried to come up with some kind of DSL to describe a schema at a high level. Has anybody already given some thought about this?

I've tried to replicate the Star Wars example from the reference graphql repository from Facebook (https://github.com/graphql/graphql-js/tree/master/src/__tests__), this is what I've come up with:

defmodule Character do
  use GraphQL.ObjectInterface

  field :id, null: false
  field :name
  field :friends, type: List.of(Character)
  field :appearsIn, type: List.of(Episode)
end

defmodule Human do
  use GraphQL.Object, deriving: Character

  field :homePlanet
end

defmodule Droid do
  use GraphQL.Object, deriving: Character

  field :primaryFunction
end

defmodule Schema do
  use GraphQL.Schema

  field :hero, type: Character do
    argument :episode, description: "foo"

    resolve %{episode: episode} do
      getHero(episode)
    end

    resolve do
      getHero(1000)
    end
  end

  field :human, type: Human do
    argument :id, description: "id of the human", null: false

    resolve %{id: id} do
      getHuman(id)
    end
  end

  field :droid, type: Droid do
    argument :id, description: "id of the droid", null: false

    resolve %{id: id} do
      getDroid(id)
    end
  end



  @humans [ 
    "1000": %Human{
      id: "1000",
      name: "Luke Skywalker",
      friends: ["1002", "1003", "2000", "2001"],
      appearsIn: [4, 5, 6],
      homePlanet: "Tatooine",
    },
    "1001": %Human{
      id: "1001",
      name: "Darth Vader",
      friends: [ "1004" ],
      appearsIn: [ 4, 5, 6 ],
      homePlanet: "Tatooine",
    },
    [ ... ]
  ]

  @droids [ ... ]

  defp getHero(5), do: @humans["1000"]
  defp getHero(_), do: @droids["2001"]

  defp getHuman(id), do: @humans[id]

  defp getDroid(id), do: @droids[id]
end

The Schema module defines the schema with its field. Each field has some arguments and one or more resolve functions, depending on whether some arguments are nullable.
Fields and arguments accept a "type" option, and nullability is expressed with a "null: false" option.

Interfaces are defined by using GraphQL.ObjectInterface, with a similar DSL to define the fields, while objects deriving the interface specify doing so when "using" GraphQL.Object (see Human and Droid).

Modules importing GraphQL.Object behave very similarly to structs, and inherit all the fields defined in the parent interface, if any.

That's just a proof of concept but I'd like to hear some comments and if there's any idea somebody's written down for a DSL.

Disclaimer: I'm quite new with Elixir, there surely are syntax errors in the POC code above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions