A comprehensive GraphQL API built with Apollo Server, Express.js, and PostgreSQL for the CodeVa Internship Program.
- Apollo Server 4 with Express integration
- Comprehensive Schema with queries, mutations, and subscriptions
- Type-safe resolvers with proper error handling
- Real-time subscriptions for posts and comments
- GraphQL Playground for API exploration (development mode)
- JWT-based authentication with access and refresh tokens
- Role-based access control (USER, ADMIN, MODERATOR)
- Secure password hashing with bcrypt
- Token validation middleware for protected operations
- PostgreSQL with Sequelize ORM
- Database migrations for schema management
- Comprehensive models with associations and validations
- Database indexing for optimal performance
- Seed data for development and testing
- DataLoader for efficient database queries
- Query batching to prevent N+1 problems
- Database connection pooling
- Proper indexing strategy
- Rate limiting on GraphQL endpoints
- CORS protection with configurable origins
- Helmet.js for security headers
- Input validation and sanitization
- SQL injection prevention
- Comprehensive error handling with proper GraphQL errors
- Development hot reload with nodemon
- Environment configuration with dotenv
- Health check endpoint for monitoring
- Graceful shutdown handling
- Node.js (v16 or higher)
- PostgreSQL (v12 or higher)
- npm or yarn package manager
-
Clone and navigate to the project:
cd c:\Users\AMN21\codeva_Internship\Advanced\Task_3
-
Install dependencies:
npm install
-
Set up environment variables:
cp .env.example .env
Update the
.env
file with your database credentials:DB_HOST=localhost DB_PORT=5432 DB_NAME=codeva_graphql_db DB_USER=postgres DB_PASSWORD=your_password JWT_SECRET=your_jwt_secret JWT_REFRESH_SECRET=your_refresh_secret
-
Create PostgreSQL database:
CREATE DATABASE codeva_graphql_db;
-
Run database migrations:
npm run db:migrate
-
Seed the database with sample data:
npm run db:seed
npm run dev
npm start
The GraphQL server will be available at:
- GraphQL Endpoint: http://localhost:4000/graphql
- GraphQL Playground: http://localhost:4000/graphql (development only)
- Health Check: http://localhost:4000/health
type User {
id: ID!
username: String!
email: String!
firstName: String!
lastName: String!
fullName: String!
role: UserRole!
isActive: Boolean!
posts: [Post!]!
comments: [Comment!]!
}
type Post {
id: ID!
title: String!
content: String!
slug: String!
status: PostStatus!
author: User!
category: Category
tags: [Tag!]!
comments: [Comment!]!
viewCount: Int!
}
type Comment {
id: ID!
content: String!
status: CommentStatus!
author: User!
post: Post!
parent: Comment
replies: [Comment!]!
}
# Get current user
query Me {
me {
id
username
email
role
}
}
# Get paginated posts with filters
query Posts($filters: PostFilters, $pagination: PaginationInput) {
posts(filters: $filters, pagination: $pagination) {
posts {
id
title
excerpt
author {
username
}
category {
name
}
}
pagination {
currentPage
totalPages
totalItems
}
}
}
# Register new user
mutation Register($input: RegisterInput!) {
register(input: $input) {
token
refreshToken
user {
id
username
email
}
}
}
# Login user
mutation Login($input: LoginInput!) {
login(input: $input) {
token
refreshToken
user {
id
username
role
}
}
}
# Create new post
mutation CreatePost($input: CreatePostInput!) {
createPost(input: $input) {
id
title
slug
status
author {
username
}
}
}
# Subscribe to new posts
subscription PostAdded {
postAdded {
id
title
author {
username
}
}
}
# Subscribe to new comments on a post
subscription CommentAdded($postId: ID!) {
commentAdded(postId: $postId) {
id
content
author {
username
}
}
}
The seeded database includes these demo accounts:
Role | Password | Username | |
---|---|---|---|
ADMIN | admin@codeva.com | Admin123! | admin |
MODERATOR | manaf@codeva.com | User123! | yakubu_manaf |
USER | john@example.com | User123! | john_doe |
USER | jane@example.com | User123! | jane_smith |
-
Login to get tokens:
mutation { login(input: { email: "admin@codeva.com", password: "Admin123!" }) { token refreshToken user { id username role } } }
-
Include token in headers:
{ "Authorization": "Bearer YOUR_JWT_TOKEN" }
npm test
npm run test:coverage
- Start the development server:
npm run dev
- Open http://localhost:4000/graphql in your browser
- Use the demo accounts to test authentication
- Explore the schema documentation in the playground
src/
βββ config/
β βββ database.js # Database configuration
βββ migrations/ # Database migrations
βββ models/ # Sequelize models
β βββ index.js
β βββ User.js
β βββ Post.js
β βββ Comment.js
β βββ Category.js
β βββ Tag.js
β βββ PostTag.js
βββ resolvers/ # GraphQL resolvers
β βββ index.js
β βββ authResolvers.js
β βββ userResolvers.js
β βββ postResolvers.js
β βββ commentResolvers.js
β βββ categoryResolvers.js
β βββ tagResolvers.js
β βββ statsResolvers.js
βββ schema/
β βββ typeDefs.js # GraphQL schema definitions
βββ seeders/ # Database seeders
βββ utils/
β βββ auth.js # Authentication utilities
β βββ dataLoader.js # DataLoader for optimization
βββ server.js # Main server file
PORT
: Server port (default: 4000)NODE_ENV
: Environment (development/production)DB_*
: Database connection settingsJWT_SECRET
: JWT signing secretJWT_REFRESH_SECRET
: Refresh token secretCORS_ORIGIN
: Allowed CORS origin
npm run db:migrate
: Run migrationsnpm run db:seed
: Run seedersnpm run db:reset
: Reset database (drop, create, migrate, seed)
- Set
NODE_ENV=production
- Use strong JWT secrets
- Configure proper CORS origins
- Set up SSL/TLS certificates
- Configure database connection pooling
- Set up monitoring and logging
- Configure rate limiting appropriately
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 4000
CMD ["npm", "start"]
- Batches database queries to prevent N+1 problems
- Caches results within a single request
- Automatically handles query deduplication
- Proper indexing on frequently queried fields
- Connection pooling for concurrent requests
- Efficient association loading with Sequelize
- JWT token expiration and refresh mechanism
- Rate limiting to prevent abuse
- Input validation and sanitization
- SQL injection prevention with parameterized queries
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
This project is part of the CodeVa Internship Program and is for educational purposes.
Yakubu Abdul Manaf
- Email: manafyakubu@gmail.com
- GitHub: [Your GitHub Profile]
- CodeVa Internship Participant from Ghana
- CodeVa Internship Program
- Apollo GraphQL Team
- Sequelize ORM Team
- PostgreSQL Community
Built with β€οΈ in Ghana for the CodeVa Internship Program