There are many advantages to GraphQL but predictability is one of the best.
Send a GraphQL query to your API and get exactly what you need, nothing more and nothing less. GraphQL queries always return predictable results.
Apollo is one of the most popular libraries to build a GraphQL API today. It works well with Node and React. We will be using it. We will also use TypeGraphQL to define our schema with TypeScript classes.
From now, we are building our app. So let's remove the migration until we need it. We'll keep one for reference.
sequelize.sync({ force: true }) will automatically create the required tables for you.
Don't forget to change it to force: false when you got live.
001_example.ts
import{QueryInterface}from"sequelize";module.exports={ // change the database schemaasyncup(query:QueryInterface){ // add migration here}, // revert in case it goes wrongasyncdown(query:QueryInterface){ // revert}};
Move from models to entities
The vast majority of GraphQL queries and mutations are to interact with the database.
To avoid repeating ourselves, we will define your models and GraphQL schema with the same files.
Rename models to entities to reflect the semantic of our files.
Change sequelize.ts import path import * as models from "./entities";.
Build the GraphQL Schema
Install dependencies
Following the TypeGraphQL documentation, we have to import reflect-metadata before we use/import type-graphql or our resolvers.
Update Link.tsto add ObjectType and Field.
Create a resolver in a new folder GraphQL inrouters as well as resolvers to keep things tidy.
For now, we're just going to return a hardcoded array of Links
// ...
import { setLinkEntity } from "../containers";
// ...
class Link extends Model<Link> {
// ...
}
setLinkEntity(Link);
export { Link };
PaginatedResponse.ts
import { ClassType, ObjectType, Field, Int } from "type-graphql";
export function PaginatedResponse<TItem>(TItemClass: ClassType<TItem>) {
// `isAbstract` decorator option is mandatory to prevent registering in schema
@ObjectType({ isAbstract: true })
abstract class PaginatedResponseClass {
// here we use the runtime argument
@Field(type => [TItemClass])
// and here the generic type
items: TItem[];
@Field(type => Int)
total: number;
@Field(type => Boolean)
hasMore: Boolean;
}
return PaginatedResponseClass;
}