Overview
Build a GraphQL API with Apollo Server. Best for complex data requirements and flexible client queries.
Features
- Apollo Server 4 setup
- Express middleware integration
- Context for authentication
- Introspection control
Installation
npx hanma add graphql-server
Dependencies
@apollo/server, graphql
Code
import { ApolloServer } from "@apollo/server";
import { ApolloServerPluginDrainHttpServer } from "@apollo/server/plugin/drainHttpServer";
import express from "express";
import http from "http";
import cors from "cors";
import type { RequestHandler } from "express";
import { expressMiddleware } from "@apollo/server/express4";
/**
* Apollo ships Express-5 typed middleware
* but runs on Express-4.
* This adapter fixes the type universe.
*/
export function apolloExpress4(...args: Parameters<typeof expressMiddleware>) {
return expressMiddleware(...args) as unknown as RequestHandler;
}
let app: express.Express | null = null;
let httpServer: http.Server | null = null;
let apolloServer: ApolloServer | null = null;
/* ---------------- Schema ---------------- */
const typeDefs = `#graphql
type Query {
hello: String
health: HealthStatus
}
type HealthStatus {
status: String!
timestamp: String!
}
`;
const resolvers = {
Query: {
hello: () => "Hello from GraphQL!",
health: () => ({
status: "ok",
timestamp: new Date().toISOString(),
}),
},
};
export interface GraphQLContext {}
/* ---------------- Start ---------------- */
export async function startGraphQLServer(port = 4000) {
if (httpServer) {
console.warn("GraphQL already running");
return;
}
app = express();
httpServer = http.createServer(app);
apolloServer = new ApolloServer<GraphQLContext>({
typeDefs,
resolvers,
introspection: process.env.NODE_ENV !== "production",
plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
});
await apolloServer.start();
app.use(
"/graphql",
cors<cors.CorsRequest>(),
express.json(),
apolloExpress4(apolloServer, {
context: async () => ({}),
}),
);
app.get("/health", (_req, res) => {
res.json({ status: "ok", timestamp: new Date().toISOString() });
});
await new Promise<void>((resolve) => httpServer!.listen({ port }, resolve));
console.log(`GraphQL running at http://localhost:${port}/graphql`);
}
/* ---------------- Shutdown ---------------- */
export async function shutdownGraphQLServer(signal: string) {
console.log(`Shutdown signal received: ${signal}`);
try {
if (apolloServer) {
await apolloServer.stop();
apolloServer = null;
}
if (httpServer) {
await new Promise<void>((resolve, reject) => {
httpServer!.close((err) => (err ? reject(err) : resolve()));
});
httpServer = null;
}
app = null;
console.log("GraphQL shutdown complete");
process.exit(0);
} catch (err) {
console.error("Shutdown failed", err);
process.exit(1);
}
}
Usage
import { createApolloServer } from './libs/servers/graphql-server';
const server = await createApolloServer();
await server.start();
app.use('/graphql', expressMiddleware(server));
Dependencies
@apollo/servergraphql
Frequently Asked Questions
How do I install Apollo GraphQL Server?
Run the following command:
npx hanma add graphql-serverWhat dependencies are required?
This snippet requires: @apollo/server, graphql. Make sure to install them before using the snippet.
How do I use this snippet?
Copy the code and paste it into your project. The snippet will be saved to
libs/servers/graphql-server.ts.Can I customize this snippet?
Yes! All snippets are copy-paste code that you own. Feel free to modify them to fit your needs.
Does this work with other frameworks?
This snippet is designed for the specific framework. Check the other framework pages for equivalent implementations.