Skip to content

Define and build GraphQL Schemas using typed classes

License

Notifications You must be signed in to change notification settings

kdby-io/graphql-typescript

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

graphql-typescript npm npm CircleCI token Coveralls github dependencies Status

Define and build GraphQL Schemas using typed classes

import { Type, Field, Nullable, Mutation, String, Boolean, Int, makeSchema } from 'graphql-typescript'

@Type class Query {
  @Field(() => Box) box: Box
}

class UnboxArguments {
  @Field(() => [String]) tools: string[]
}

@Type class Box {
  @Field(() => Size)
  size: Size

  @Nullable
  @Field(() => String)
  content: string

  @Mutation(() => Boolean)
  unbox(box: BoxModel, args: UnboxArguments, context: any) { ... }
}

@Type class Size {
  @Field(() => Int) height: number
  @Field(() => Int) width: number
  @Field(() => Int) length: number
}


const schema = makeSchema(Query, {
  types: [Size, Box]
})
type Query {
  box: Box!
}

type Mutation {
  unbox(tools: [String]!): Boolean!
}

type Box {
  size: Size!
  content: String
}

type Size {
  height: Int!
  width: Int!
  length: Int!
}

Prerequisites

Set decorator flags in your tsconfig.json

"experimentalDecorators": true,
"emitDecoratorMetadata": true

Installing

npm install -S graphql
npm install -S graphql-typescript

Type Definition

@Type

Adding @Type to a class definition defines GraphQL object type.

@Type class Character {
  @Field(() => String) name: string
  @Field(() => [Episode]) appearsIn: Episode[]
}
type Character {
  name: String!
  appearsIn: [Episode]!
}

@Field

Adding @Field to properties or methods of a @Type decorated class defines what fields it has.

@Type
class Hello {
  @Field(() => String)
  a: string

  @Field(() => [String])
  b: string[]

  @Field(() => String)
  c(_:any, _args: any, context: any) { ... }
}
type Hello {
  a: String!
  b: [String]!
  c: String!
}

@Mutation

Adding @Mutation to methods of a @Type decorated class defines a mutation. No matter which class it is in, it will come under mutation type.

class Argument {
  @Field(() => [Int]) world: number[]
}

@Type
class Hello {
  @Mutation(() => String)
  a(_: any, _args: any, context: any) { ... }

  @Mutation(() => [String])
  b(_: any, _args: any, context: any) { ... }

  @Mutation(() => String)
  c(_: any, args: Argument, context: any) { ... }
}
type Mutation {
  ...
  a: String!
  b: [String]!
  c(world: [Int]!): String!
}

@Nullable

All fields and mutations are Non-null type by default. Adding `@Nullable to fields or mutations properties make it nullable.

@Type
class Hello {
  @Nullable
  @Field(() => String)
  hello: string
}
type Hello {
  hello: String
}

@Input

Adding @Input to a class definition defines a input type An input class can only have @Field properties.

@Input class AddCharacterInput {
  @Field(() => String) name: string
  @Field(() => Int) age: number
}
input AddCharacterInput {
  name: String!
  age: Int!
}

Scalar types

To use GraphQL default scalar types, import it from 'graphql-typescript'

import { String, Boolean, Int, Float, ID } from 'graphql-typescript'

Arguments

All fields of GraphQL objects type can have arguments. Methods with @Field or @Mutation get request query arguments from second parameter. It needs to define a argument class. Because a purpose of this class is only typing arguments, there is no class decorator and it can have only @Field properties.

class UnboxArguments {
  @Field(() => [String]) tools: string[]
}

@Type class Box {
  @Mutation(() => Boolean) unbox(box: BoxModel, args: UnboxArguments) { ... }
}
type Mutation{
  unbox(tools: [String]!): Boolean
}

To use input type in argument, do like below.

@Input class UnboxInput {
  @Field(() => [String]) tools: string[]
}
class UnboxArguments {
  @Field(() => UnboxInput) inputs: UnboxInput
}

@Type class Box {
  @Mutation(() => Boolean) unbox(box: BoxModel, args: UnboxArguments) { ... }
}
input UnboxInput {
  tools: [String]!
}

type Mutation{
  unbox(inputs: UnboxInput!): Boolean
}

Generating GraphQL Schema

import { makeSchema } from 'graphql-typescript'
import { Query } from './Query'
import { Box } from './Box'
import { Character } from './Character'

const schema = makeSchema(Query, {
  models: [ Box, Character ]
})

makeSchema

makeSchema(rootType, {
  types: [ ... ]
})
  • rootType: A root type of schema
  • types: Rest of types except a root type