GraphQL + TypeScript + PostgreSQL API
Wonder2210
Posted on June 8, 2020
Introduction
In the current year, one of the most popular stacks is GraphQl and Typescript (and for a while, I think). I started recently a new project, using this stack, I did some GraphQL API's using good Vanilla Javascript before, but even I'm using Typescript for few times. I've never used it for this purpose but I didn't find a tutorial who fits with my requirements, I get it done, then I ask to my self. Why not do a guide?. Here we go
before we are starting :
Why GraphQL ?:
GraphQL provides a complete description of the data in your API, giving clients the power to ask for exactly what they need and nothing more when you have to deal with a great amount of data this is a very nice choice, you can have all the data required with just Running one Query.
Why typescript? :
Typescript is a superset of Javascript that compiles to plain JavaScript.
As JavaScript code grows it gets messier to maintain and reuse, and don't have strong type checking and compile-time error checks, that's where Typescript comes in
Why PostgreSQL?
PostgreSQL is a personal preference, is widely used, open-source, and has a great community, but I'm not going to go deep about it, You can read more about why use it here
Prerequisites
- yarn you can use NPM no matter
- node: v.10 or superior
- postgresql = 12
- some typescript knowledge
1) Folder Structure
This is how's going to be structured the project
graphql_api/
...
dist/
bundle.js
src/
database/
knexfile.ts
config.ts
migrations/
models/
User.ts
Pet.ts
__generated__/
schema/
resolvers/
user.ts
pet.ts
index.ts
graphql/
schema.ts
index.ts/
index.ts
2) Main Dependencies
Apollo server: Apollo Server is a community-maintained open-source GraphQL server. It works with pretty much all Node.js HTTP server frameworks
-
Objection: i used to use sequelize but i really like objection.js because it is an ORM that embraces SQL
Development
Webpack : webpack is used to compile JavaScript modules, node.js by its own doesn't accept files .gql or .graphql , that's where webpack comes in
First, we are going to install
yarn add graphql apollo-server-express express body-parser objection pg knex
and some dev dependencies
yarn add -D typescript @types/graphql @types/express @types/node graphql-tag concurrently nodemon ts-node webpack webpack-cli webpack-node-external
3) Configurations
tsconfig
Webpack
4) Hello World
Add the next scripts to your package.json
json
"scripts":{
"dev": "concurrently \" nodemon ./dist/bundle.js \" \" webpack --watch\" "
}
index.ts
5) Server config
For this project we are gone to use , Executable schema from graphql-tools wich allow us to generate a GraphQLSchema instance from GraphQL schema language beside this you can also combine types and resolvers from multiple files
src/index.ts
typescript
...
const config : Config = {
schema:schema,// schema definition from schema/index.ts
introspection: true,//these lines are required to use
playground: true,// playground
}
const server : ApolloServer = new ApolloServer(config);
server.applyMiddleware({
app,
path: '/graphql'
});
...
schema/index.ts
typescript
import { makeExecutableSchema} from 'graphql-tools';
import schema from './graphql/schema.gql';
import {user,pet} from './resolvers';
const resolvers=[user,pet];
export default makeExecutableSchema({typeDefs:schema, resolvers: resolvers as any});
6) Database
Now we will be working based in the next database diagram, It will be just a register of Users and their pets.
Migration file
For creating the database in Postgres , we'll be using the migrations of knex
and generate the first migration running:
bash
npx knex --knexfile ./src/database/knexfile.ts migrate:make -x ts initial
And your migration file should look's like this
Then run the migration
bash
npx knex --knexfile ./src/database/knexfile.ts migrate:latest
Now we have two tables then we need the models for each table to start executing queries
src/database/models:
then we need to instantiate Knex and give the instance to Objection
typescript
import dbconfig from './database/config';
const db = Knex(dbconfig["development"]);
Model.knex(db);
7) Schema
8) generating types
we need the following packages for better type safeting the resolvers :
bash
yarn add -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/
typescript-resolvers @graphql-codegen/typescript-operations
create the config file for generate types :
/codegen.yml
yml
overwrite: true
schema: "http://localhost:3000/graphql"
documents: null
generates:
src/generated/generated-types.ts:
config:
mappers:
User:'./src/database/User.ts'
UpdateUserInput:'./src/database/User.ts'
Pet:'./src/database/Pet.ts'
plugins:
- "typescript"
- "typescript-resolvers"
add the follow script to packages.json :
json
...
"generate:types": "graphql-codegen --config codegen.yml"
...
once your server is up , then run :
bash
yarn run generate:types
if you want to go deep generating types from graphql you can read more about here, I highly suggest to do
9) resolvers
schema/resolvers/
Now you should be able to execute all the operations defined before
BONUS:
you can see two errors from typescript
it's not terrible at all, but I would prefer to don't have them
then
the first one I get it solved splitting knexfile.ts and put the configuration that is required for knex in a standalone file
And the second one, from the import of the schema , I get it solved with this useful post
and finally, you should have working your own graphql api
Conclusion
Congratulations ! Now you have a GraphQL API
if you get stucked at any of the steps here is the repo on github , In this tutorial we learned about, how to generate types for Typescript from graphql , solve some issues , I hope you enjoyed this post , if is it the case, please follow me here on DEV and also on twitter I'll be posting more often soon , if you have any suggestion for me I would love to know it , leave it below in the comments box ,Thanks!
Posted on June 8, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.