Implement GraphQL with Drizzle
Introduction
In the previous article, I guided you on how to use Drizzle to connect with Postgres. Now, we will continue using it to implement GraphQL.
Next, we need to combine it with the following tools:
drizzle-graphql
This is the official library developed by the Drizzle ORM team itself to automatically generate a GraphQL Schema (including full Queries and Mutations) from your Drizzle Schema.
GraphQL Yoga
- Serves as an extremely lightweight and modern
GraphQL Server Framework(replacing the older/heavierApollo Server). - Functions:
- Listens for
HTTPconnections from the client (for example at port4000/graphql). - Receives
GraphQL (Query/Mutation)queries sent viaPOSTrequests. - Executes handler functions (
Resolvers) and returnsJSONdata to the client. - Provides a built-in
GraphiQLinterface on the browser for you to test queries.
- Listens for
Detail
- In this article, I will guide you on how to implement a simple
CRUD GraphQLsystem. You only need to define theSchemaand connect toPostgres. - You will not need to write much code and will still get a
GraphQLsystem that satisfies the minimum requirements for use.
Create the file src/constant/key.ts to define the provider names:
export const DRIZZLE_DB = 'DRIZZLE_DB'
export const GRAPHQL_SCHEMA = 'GRAPHQL_SCHEMA'
Create the file src/drizzle-orm/schema/schema.ts, which simply includes products and carts:
import {
bigserial,
decimal,
integer,
pgTable,
serial,
text,
timestamp,
varchar,
} from 'drizzle-orm/pg-core'
export const products = pgTable('products', {
id: bigserial('id', {mode: 'number'}).primaryKey(),
name: varchar('name', {length: 255}).notNull(),
description: text('description'),
price: decimal('price', {precision: 10, scale: 2}).notNull(),
views: integer('views').default(0),
createdAt: timestamp('created_at').defaultNow().notNull(),
updatedAt: timestamp('updated_at').defaultNow().notNull(),
})
export const carts = pgTable('carts', {
id: serial('id').primaryKey(),
userId: integer('user_id').notNull().unique(),
itemsJson: varchar('items_json', {length: 2000}).notNull(),
createdAt: timestamp('created_at').defaultNow().notNull(),
updatedAt: timestamp('updated_at').defaultNow(),
})
Create the file src/drizzle-orm/index.ts to create the Pool and Provider for Drizzle:
import {drizzle, type NodePgDatabase} from 'drizzle-orm/node-postgres'
import {Pool} from 'pg'
import {DRIZZLE_DB} from 'src/constant'
import * as schema from './schema/schema'
export type DrizzleDB = NodePgDatabase<typeof schema>
export const createPool = () => {
return new Pool({connectionString: process.env.DATABASE_URL})
}
export const createDrizzle = () => {
const pool = createPool()
return drizzle(pool, {schema})
}
export const drizzleProvider = {
provide: DRIZZLE_DB,
useFactory: createDrizzle,
}
Create the file src/module/drizzle.module.ts to use drizzleProvider:
import {Global, Module} from '@nestjs/common'
import {buildSchema} from 'drizzle-graphql'
import {DRIZZLE_DB, GRAPHQL_SCHEMA} from 'src/constant'
import {drizzleProvider} from 'src/drizzle-orm'
@Global()
@Module({
providers: [
drizzleProvider,
{
provide: GRAPHQL_SCHEMA,
inject: [DRIZZLE_DB],
useFactory: db => {
const {schema: graphQLSchema} = buildSchema(db)
return graphQLSchema
},
},
],
exports: [DRIZZLE_DB, GRAPHQL_SCHEMA],
})
export class DrizzleModule {}
Create the file src/middleware/graphql-yoga.middleware.ts:
import {Inject, Injectable, NestMiddleware} from '@nestjs/common'
import {Request, Response} from 'express'
import {type GraphQLSchema} from 'graphql'
import {createYoga, type YogaServerInstance} from 'graphql-yoga'
import {GRAPHQL_SCHEMA} from 'src/constant'
@Injectable()
export class GraphQLYogaMiddleware implements NestMiddleware {
private yoga: YogaServerInstance<{}, {}>
constructor(@Inject(GRAPHQL_SCHEMA) graphQLSchema: GraphQLSchema) {
this.yoga = createYoga({
schema: graphQLSchema,
graphqlEndpoint: '/graphql',
})
}
use(req: Request, res: Response) {
this.yoga(req, res)
}
}
- This is the
middlewareused to process access toYoga GraphiQL. - The
graphqlEndpoint: '/graphql'part is the path that you can customize according to your needs.
Modify the file src/app.module.ts:
import {Module, type MiddlewareConsumer, type NestModule} from '@nestjs/common'
import {ConfigModule} from '@nestjs/config'
import {GraphQLYogaMiddleware} from './middleware/graphql-yoga.middleware'
import {DrizzleModule} from './module/drizzle.module'
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: '.env',
}),
DrizzleModule,
],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(GraphQLYogaMiddleware).forRoutes('graphql')
}
}
As a result, you can access Yoga GraphiQL using the URL localhost:5000/graphql. The Explorer section already includes the query and mutation information for the carts and products schemas.
The Document section has full data type information for the fields.
Try executing a query as follows, you just need to click on the fields you want to query:
Happy coding!
Comments
Post a Comment