
schema
  @link(url: "https://specs.apollo.dev/link/v1.0")
  @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION)
  @link(url: "https://specs.apollo.dev/requiresScopes/v0.1", for: SECURITY)
{
  query: Query
  mutation: Mutation
}
directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA

directive @join__field(graph: join__Graph!, requires: join__FieldSet, provides: join__FieldSet, type: String, external: Boolean) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION

directive @join__type(graph: join__Graph!, key: join__FieldSet) repeatable on OBJECT | INTERFACE

directive @join__owner(graph: join__Graph!) on OBJECT | INTERFACE

directive @join__graph(name: String!, url: String!) on ENUM_VALUE

directive @join__implements(graph: join__Graph!, interface: String!) repeatable on OBJECT | INTERFACE

directive @join__unionMember(graph: join__Graph!, member: String!) repeatable on UNION

directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE

directive @tag(name: String!) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION

directive @inaccessible on OBJECT | FIELD_DEFINITION | INTERFACE | UNION

scalar link__Import

enum link__Purpose {
    """
    `SECURITY` features provide metadata necessary to securely resolve fields.
    """
    SECURITY
  
    """
    `EXECUTION` features provide metadata necessary for operation execution.
    """
    EXECUTION
  }

scalar join__FieldSet

scalar federation__Scope

directive @requiresScopes(scopes: [[federation__Scope!]!]!) on OBJECT | FIELD_DEFINITION | INTERFACE | SCALAR | ENUM


enum join__Graph {
  ACCOUNTS @join__graph(name: "accounts", url: "https://accounts.demo.starstuff.dev")
  INVENTORY @join__graph(name: "inventory", url: "https://inventory.demo.starstuff.dev")
  PRODUCTS @join__graph(name: "products", url: "https://products.demo.starstuff.dev")
  REVIEWS @join__graph(name: "reviews", url: "https://reviews.demo.starstuff.dev")
}
type Mutation
  @join__type(graph: PRODUCTS)
  @join__type(graph: REVIEWS)
{
  createProduct(name: String, upc: ID!): Product @join__field(graph: PRODUCTS)
  createReview(body: String, id: ID!, upc: ID!): Review @join__field(graph: REVIEWS)
}

type Product
  @join__type(graph: PRODUCTS, key: "upc")
  @join__type(graph: INVENTORY, key: "upc")
  @join__type(graph: REVIEWS, key: "upc")
{
  inStock: Boolean @join__field(graph: INVENTORY) @tag(name: "private") @inaccessible
  name: String @join__field(graph: PRODUCTS)
  price: Int @join__field(graph: PRODUCTS)
  reviews: [Review] @join__field(graph: REVIEWS)
  reviewsForAuthor(authorID: ID!): [Review] @join__field(graph: REVIEWS)
  upc: String! @join__field(graph: PRODUCTS) @join__field(graph: INVENTORY, external: true) @join__field(graph: REVIEWS, external: true)
  weight: Int @join__field(graph: PRODUCTS)
}

type Query
  @join__type(graph: ACCOUNTS)
  @join__type(graph: PRODUCTS) {
  me: User @join__field(graph: ACCOUNTS) @requiresScopes(scopes: [["profile"]])
  topProducts(first: Int = 5): [Product] @join__field(graph: PRODUCTS)
}

type Review
  @join__owner(graph: REVIEWS)
  @join__type(graph: REVIEWS, key: "id")
{
  author: User @join__field(graph: REVIEWS)
  body: String @join__field(graph: REVIEWS)
  id: ID!
  product: Product @join__field(graph: REVIEWS)
}

type User
  @join__owner(graph: ACCOUNTS)
  @join__type(graph: ACCOUNTS, key: "id")
  @join__type(graph: REVIEWS, key: "id")
  @requiresScopes(scopes: [["read:user"]])
{
  id: ID!
  name: String @join__field(graph: ACCOUNTS) @requiresScopes(scopes: [["read:name"]])
  reviews: [Review] @join__field(graph: REVIEWS)
  username: String @join__field(graph: ACCOUNTS)
}
