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...
Define schema
Define schema
Use only classes and decorators to define your GraphQL schema. No need to define types in SDL and no need to create interfaces for them!
This way you will have only one source of truth, so say goodbye to all field type mismatches, typos and annoying refactoring.
@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.
Gold Sponsors π
Please ask your company to support this open source project by becoming a gold sponsor and getting a premium technical support from our core contributors.
Silver Sponsors π₯
Bronze Sponsors π₯
Members πͺ
GitHub Sponsors π
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!