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!
}
Set decorator flags in your tsconfig.json
"experimentalDecorators": true,
"emitDecoratorMetadata": true
npm install -S graphql
npm install -S graphql-typescript
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]!
}
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!
}
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!
}
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
}
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!
}
To use GraphQL default scalar types, import it from 'graphql-typescript'
import { String, Boolean, Int, Float, ID } from 'graphql-typescript'
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
}
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(rootType, {
types: [ ... ]
})
rootType
: A root type of schematypes
: Rest of types except a root type