GraphQL
GraphQL
Define your whole schema, including types, interfaces, enums, unions and subscriptions
TypeScript
TypeScript
Create the schema, types and resolvers only with TypeScript, using classes and decorators!
Advanced features
Advanced features
Use features like automatic validation, authorization guards, dependency injection and plenty more...
@ObjectType()
class Recipe {
@Field()
title: string;
@Field({ nullable: true })
description?: string;
@Field(type => [Rate])
ratings: Rate[];
@Field(type => Float, { nullable: true })
get averageRating() {
const sum = this.ratings.reduce((a, b) => a + b, 0);
return sum / this.ratings.length;
}
}
@Resolver(of => Recipe)
export class RecipeResolver {
constructor(
private readonly recipeRepository: Repository<Recipe>,
private readonly rateRepository: Repository<Rate>,
) {}
@Query(returns => Recipe)
async recipe(@Arg("recipeId") recipeId: string) {
return this.recipeRepository.findOneById(recipeId);
}
@Mutation(returns => Recipe)
async addRecipe(@Arg("recipe") recipeInput: RecipeInput) {
const newRecipe = this.recipeRepository.create(recipeInput);
return this.recipeRepository.save(newRecipe);
}
@FieldResolver()
ratings(@Root() recipe: Recipe) {
return this.rateRepository.find({ recipeId: recipe.id });
}
}
Create resolvers
Create resolvers
Implement queries and mutations as normal class methods! Dependency injection support and decorators abstraction provides great separation of business logic from the underlying transport layer.
That gives you really easy testability, so you can just provide mocks of dependencies to prevent side effects and unit test your resolvers like a simple services which methods only take some parameters and return results.
Easy validation
Easy validation
Forget about manual inputs and arguments validation! No need to create custom scalars to limit the length of a string or the range of an int.
Just use decorators from class-validator library and declare the requirements of the inputs. It couldn't be easier!
@InputType()
export class RecipeInput {
@Field()
@MaxLength(30)
title: string;
@Field({ nullable: true })
@Length(30, 255)
description?: string;
@Field(type => [String])
@MaxArraySize(25)
ingredients: string[];
}
@Entity()
@ObjectType()
export class Rate {
@PrimaryGeneratedColumn()
readonly id: number;
@Field(type => Int)
@Column({ type: "int" })
value: number;
@Field(type => User)
@ManyToOne(type => User)
user: Promise<User>;
@Field()
@CreateDateColumn()
date: Date;
@ManyToOne(type => Recipe)
recipe: Promise<Recipe>;
}
Interoperable
Interoperable
Although TypeGraphQL is data-layer library agnostic, it integrates well with other decorator-based libraries, like TypeORM, sequelize-typescript or Typegoose.
This allows you to define both the GraphQL type and the entity in a single class - no need to jump between multiple files to add or rename
some properties.
Community supported
Community supported
TypeGraphQL is an MIT-licensed open source project. It doesn't have a large company that sits behind - its ongoing development is possible only thanks to the support by the community.
If you fell in love with TypeGraphQL, please consider supporting our efforts and help it grow, especially if you are using it commercially - just to ensure that the project which your product relies on is actively maintained and improved.
Want more?
That was only a tip of the iceberg. Interested?Give it a try and experiment with TypeGraphQL! It will reduce your codebase size by a half or more!