Welcome to First GraphQL, a type-safe, lightweight GraphQL API built using TypeScript, Apollo Server 5, and Node.js. This project demonstrates the core concepts of GraphQL, including schema definitions (SDL), queries, mock database integration, and relational resolvers (one-to-many and nested relationships).
- Apollo Server v5: Powered by the latest standalone Apollo Server for quick setup and playground sandbox interaction.
- Strict TypeScript: Fully configured TypeScript compilation for compile-time safety.
- Relational Resolvers:
- Products linked to their parent Categories.
- Categories resolving list of associated Products.
- Products displaying user Reviews.
- Mock Database Integration: In-memory JavaScript arrays representing
products,categories, andreviewsfor instant execution without setting up a heavyweight database server. - Hot Reloading / Auto Compile: Fully integrated watcher scripts compilation (
tsc -w) paired withnodemonfor active developer convenience.
Below is the directory structure of the project, outlining the clean separation of concerns between schema declarations, database mock-ups, resolvers, and application entrypoint.
first-graphql/
βββ dist/ # Compiled JavaScript output (ignored in Git)
βββ src/ # Source files
β βββ gql/ # GraphQL configuration files
β β βββ resolvers/
β β β βββ index.ts # Query and relational resolvers (Product, Category, etc.)
β β βββ schema/
β β βββ index.ts # Schema Definitions (typeDefs) using GraphQL SDL
β βββ db.ts # In-memory mock database containing products, categories, & reviews data
β βββ index.ts # App entrypoint (initializes & starts Apollo Server on port 4000)
βββ .gitignore # Git configuration files
βββ package.json # Project scripts and dependencies definition
βββ tsconfig.json # TypeScript compiler settings
βββ yarn.lock # Dependency lockfile
βββ README.md # Documentation (This file)
- Runtime: Node.js
- Language: TypeScript
- GraphQL Engine: Apollo Server (
@apollo/server,graphql) - Developer Tools:
nodemon(auto restarts node server),tsc(compiler)
Ensure you have Node.js (v16+ recommended) and either Yarn or NPM installed on your machine.
Navigate to the project directory and install the packages:
# Using Yarn
yarn install
# Or using NPM
npm installTo start development with watch compile and automatic server restart:
Open two terminal windows:
- Terminal 1 (Watch and compile TS files to JS):
yarn compile # runs "tsc --w" - Terminal 2 (Run local server with nodemon auto-restart):
yarn dev # runs "nodemon ./dist/index.js"
Builds/compiles once, then runs the server:
yarn start # runs "npm run compile && node ./dist/index.js"Once started, the server will output:
π Server ready at: http://localhost:4000/
Open http://localhost:4000/ in your browser to launch the Apollo Sandbox Explorer, where you can visually write and test queries.
The schema definitions can be found inside src/gql/schema/index.ts. Below are the defined types:
type Product {
id: ID!
name: String
image: String
description: String
price: Float
quantity: Int
onStock: Boolean
categoryId: String
category: Category
reviews: [Review]
}
type Category {
id: ID!
name: String
products: [Product]
}
type Review {
id: ID!
review: String
rating: Float
date: String
productId: String
}
type Query {
products: [Product]
product(productId: ID!): Product
categories: [Category]
category(categoryId: ID!): Category
}The project models the following relational structures between entities:
- A Category can have multiple associated Products (One-to-Many).
- Solved in resolvers by matching the product's
categoryIdto the category'sid. - GraphQL fields:
Category.productsreturns[Product]Product.categoryreturns a singleCategory(Many-to-One)
- A Product can accumulate multiple user Reviews (One-to-Many).
- Solved in resolvers by filtering reviews matching the product's
idto the review'sproductId. - GraphQL fields:
Product.reviewsreturns[Review]
erDiagram
Category ||--o{ Product : "has many"
Product ||--o{ Review : "has many"
Category {
string id PK
string name
}
Product {
string id PK
string name
string image
string description
float price
int quantity
boolean onStock
string categoryId FK
}
Review {
string id PK
string review
float rating
string date
string productId FK
}
You can execute the following queries in the Apollo Sandbox. The expected JSON responses based on the mock data are also included below:
Fetches all products and resolves the nested categories and reviews details for each product.
Query:
query GetAllProducts {
products {
id
name
price
onStock
category {
id
name
}
reviews {
id
review
rating
}
}
}Response (Sample/Truncated):
{
"data": {
"products": [
{
"id": "2a089dca-d882-4305-9e25-d1dfeb93fd12",
"name": "Basketball",
"price": 29.99,
"onStock": true,
"category": {
"id": "4f7f61e5-96c2-445d-80fb-79f58e3d061b",
"name": "Sports"
},
"reviews": [
{
"id": "bd23fdc4-0636-4199-ad18-7ca9870e855f",
"review": "Great basketball for playing with friends!",
"rating": 4.5
}
]
},
{
"id": "73b8ca8b-ca88-483e-99ea-2fedaf2a1dc1",
"name": "Football",
"price": 19.99,
"onStock": true,
"category": {
"id": "4f7f61e5-96c2-445d-80fb-79f58e3d061b",
"name": "Sports"
},
"reviews": [
{
"id": "58db016e-0293-49cc-bf42-9384f8bccaef",
"review": "The football is of good quality and lasts long.",
"rating": 4
}
]
}
]
}
}Query:
query GetSingleProduct($productId: ID!) {
product(productId: $productId) {
name
price
description
quantity
category {
name
}
}
}Variables:
{
"productId": "2a089dca-d882-4305-9e25-d1dfeb93fd12"
}Response:
{
"data": {
"product": {
"name": "Basketball",
"price": 29.99,
"description": "An official size basketball for both indoor and outdoor play.",
"quantity": 30,
"category": {
"name": "Sports"
}
}
}
}Query:
query GetCategoriesAndProducts {
categories {
id
name
products {
id
name
price
}
}
}Response (Sample/Truncated):
{
"data": {
"categories": [
{
"id": "4f7f61e5-96c2-445d-80fb-79f58e3d061b",
"name": "Sports",
"products": [
{
"id": "2a089dca-d882-4305-9e25-d1dfeb93fd12",
"name": "Basketball",
"price": 29.99
},
{
"id": "73b8ca8b-ca88-483e-99ea-2fedaf2a1dc1",
"name": "Football",
"price": 19.99
}
]
},
{
"id": "1b6c2e31-2e03-4487-bedd-d1139c7e5571",
"name": "Mobile phones",
"products": [
{
"id": "42ebd257-b37d-4751-96cd-f160c12a3c28",
"name": "Smartphone",
"price": 599.99
}
]
}
]
}
}Query:
query GetSingleCategory {
category(categoryId: "1b6c2e31-2e03-4487-bedd-d1139c7e5571") {
id
name
products {
name
price
}
}
}Response:
{
"data": {
"category": {
"id": "1b6c2e31-2e03-4487-bedd-d1139c7e5571",
"name": "Mobile phones",
"products": [
{
"name": "Smartphone",
"price": 599.99
},
{
"name": "Laptop",
"price": 899.99
},
{
"name": "Tablet",
"price": 349.99
},
{
"name": "Fitness Tracker",
"price": 79.99
}
]
}
}
}