CLOSE
← Back to Articles
Simple GraphQL Example with TypeScript, TypeORM, and TypeGraphQL
GraphQLJune 25, 2024
Entity Definition
First, let's define our Task
entity using TypeORM and TypeGraphQL.
import { Field, ID, ObjectType } from "type-graphql";
import {
BaseEntity,
Column,
CreateDateColumn,
Entity,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from "typeorm";
@Entity()
@ObjectType()
export class Task extends BaseEntity {
@PrimaryGeneratedColumn()
@Field(() => ID)
id: number;
@CreateDateColumn()
@Field(() => String)
created: Date;
@UpdateDateColumn()
@Field(() => String)
updated: Date;
@Column()
@Field(() => String)
title: string;
@Column()
@Field(() => Boolean)
isComplete: boolean;
}
Entity Definition
Next, let's define our TaskResolver to handle GraphQL queries and mutations.
// src/resolvers/task.ts
import { Arg, Int, Query, Resolver, Mutation } from "type-graphql";
import { Task } from "../entities/task";
@Resolver()
export class TaskResolver {
@Query(() => String)
hello(): string {
return "hello frontYnova";
}
@Query(() => [Task])
tasks(): Promise<Task[]> {
return Task.find({});
}
@Query(() => Task, { nullable: true })
async task(@Arg("id", () => Int) id: number): Promise<Task | undefined> {
return await Task.findOne({ where: { id } });
}
@Mutation(() => Task)
createTask(
@Arg("title", () => String)
title: string
): Promise<Task> {
return Task.create({ title, isComplete: false }).save();
}
@Mutation(() => Boolean)
deleteTask(
@Arg("id", () => Int)
id: number
): boolean {
try {
Task.delete({ id });
return true;
} catch {
return false;
}
}
@Mutation(() => Boolean, { nullable: true })
async updateTask(
@Arg("id", () => Int) id: number,
@Arg("title", () => String) title: string,
@Arg("isComplete", () => Boolean) isComplete: boolean
): Promise<boolean | null> {
const task = await Task.findOne({ where: { id } });
if (!task) return null;
try {
await Task.update({ id }, { title, isComplete });
return true;
} catch {
return false;
}
}
}
Resolver Definition
Next, let's define our TaskResolver to handle GraphQL queries and mutations.
// src/resolvers/task.ts
import { Arg, Int, Query, Resolver, Mutation } from "type-graphql";
import { Task } from "../entities/task";
@Resolver()
export class TaskResolver {
@Query(() => String)
hello(): string {
return "hello frontYnova";
}
@Query(() => [Task])
tasks(): Promise<Task[]> {
return Task.find({});
}
@Query(() => Task, { nullable: true })
async task(@Arg("id", () => Int) id: number): Promise<Task | undefined> {
return await Task.findOne({ where: { id } });
}
@Mutation(() => Task)
createTask(
@Arg("title", () => String)
title: string
): Promise<Task> {
return Task.create({ title, isComplete: false }).save();
}
@Mutation(() => Boolean)
deleteTask(
@Arg("id", () => Int)
id: number
): boolean {
try {
Task.delete({ id });
return true;
} catch {
return false;
}
}
@Mutation(() => Boolean, { nullable: true })
async updateTask(
@Arg("id", () => Int) id: number,
@Arg("title", () => String) title: string,
@Arg("isComplete", () => Boolean) isComplete: boolean
): Promise<boolean | null> {
const task = await Task.findOne({ where: { id } });
if (!task) return null;
try {
await Task.update({ id }, { title, isComplete });
return true;
} catch {
return false;
}
}
}
In the resolver, we define several GraphQL operations:
- hello: A simple query returning a greeting string.
- tasks: A query to fetch all tasks.
- task: A query to fetch a single task by ID.
- createTask: A mutation to create a new task.
- deleteTask: A mutation to delete a task by ID.
- updateTask: A mutation to update an existing task.
Server Setup
Next, let's define our TaskResolver to handle GraphQL queries and mutations.
// src/index.ts
import "reflect-metadata";
import express, { Express } from "express";
import { ApolloServer } from "apollo-server-express";
import { buildSchema } from "type-graphql";
import { TaskResolver } from "./resolvers/task";
import { ApolloServerPluginLandingPageGraphQLPlayground } from "apollo-server-core";
import { createConnection } from "typeorm";
import { Task } from "./entities/task";
const main = async () => {
const conn = await createConnection({
type: "postgres",
database: "todolist",
entities: [Task],
logging: true,
synchronize: true,
username: "postgres",
password: "postgres",
port: 5432,
});
const apolloServer = new ApolloServer({
schema: await buildSchema({
resolvers: [TaskResolver],
validate: false,
}),
plugins: [ApolloServerPluginLandingPageGraphQLPlayground],
});
await apolloServer.start();
const app: Express = express();
apolloServer.applyMiddleware({ app });
app.get("/", (_req, res) => res.send("Hello frontYnova"));
const PORT = process.env.PORT || 8000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
};
main().catch((err) => console.log(err));
Happy coding!