What is GraphQL?

  • GraphQL is a powerful query language that simplifies API development by allowing clients to request exactly the data they need through a single endpoint.
  • Unlike REST, which requires multiple endpoints, GraphQL’s flexibility and strongly typed schema make it ideal for modern applications.

Why We Use GraphQL?

  • Flexible Data Retrieval: Clients specify only the fields they need, reducing data waste.
  • Single Endpoint: All operations(queries and mutations) are handled via one URL(e.g., /graphql)
  • Strongly Typed Schema: Defines a clear contract between the frontend and the backend.
  • Dynamic Queries: Supports pagination and filtering naturally, unlike REST’s query parameter complexity.
  • Evolves easily: Add new fields without breaking existing clients.

Queries vs. Mutations: What’s the Difference?

Queries:

  • Queries are GraphQL operations used to read r fetch data from the server. GET requests in REST API but more flexible because the client specifies exactly what data it wants.
  • Retrieve information without modifying it.

Mutation:

  • Mutations are GraphQL operations used to write or modify data on the server.
  • They’re similar to POST, PUT or DELETE requests in REST, allowing changes like creating, updating or deleting resources.
  • Alter data or perform actions that change the server’s state.

Key difference:

  • Queries = Read: No side effects; just fetching data.
  • Mutations = Write: Cuase changes(e.g,. saving to the database)
  • In GraphQL, both queries and mutations are sent to the same endpoints(e.g,. /graphql), which algns with the single endpoint.

GraphQL API Development Flow

1. Model (MongoDB Schema)

  • Why First: The Model defines how data(e.g.Suppliers) stored in MongoDB. It’s foundation because everything else(Schema, resolver) depends on what data you can save and retrieve.
  • What to Do: Create suppliermodek.ts to define the supplier’s fields(e.g.supplier_name, supplier_code)

Example code:

import mongoose, { Schema, Document } from "mongoose";
export interface ISupplier extends Document {
_id?: mongoose.Types.ObjectId;
supplier_code: string;
supplier_name: string;
email: string;
}
const SupplierSchema: Schema = new Schema({
supplier_code: { type: String },
supplier_name: { type: String, required: true },
email: { type: String },
});
SupplierSchema.pre<ISupplier>("save", async function (next) {
if (!this.isNew) return next();
const lastSupplier = await SupplierModel.findOne().sort({ _id: -1 });
const lastSupplierNo = lastSupplier ? parseInt(String(lastSupplier.supplier_code), 10) : 0;
this.supplier_code = String(lastSupplierNo + 1).padStart(3, "0");
next();
});
const SupplierModel = mongoose.model<ISupplier>("supplier", SupplierSchema);
export default SupplierModel;

2. Schema(GraphQL Type Definitions)

  • Why second: The schema defines the API’s contract- what data the frontend can send and receive. It needs to align with the model’s structure, so it is after the model.
  • What to do: It relies on the model to know available fields and their structure.

Example code:

import { gql } from "apollo-server-express";
const suppliertypeDefs = gql`
type Supplier {
id: ID
supplier_code: String!
supplier_name: String!
email: String
}
input SupplierInput {
supplier_name: String!
email: String
}
type SupplierResponse {
statusCode: Int!
message: String!
supplier: Supplier}
type Mutation {
addSupplier(input: SupplierInput): SupplierResponse}
`;
export default suppliertypeDefs;

3. Resolver(Logic to Handle Requests)

  • Why third: The resolver is the logic that connects the scheam to the model. It used the model to save data and returns it is in format defined by the schema, so it comes last.
  • What to do: Resolvers depend on the model for data operations and the schema for response formatting.

Example code:

import SupplierModel, { ISupplier } from
"../models/suppliermodel";
const supplierresolvers = {
Mutation: {
addSupplier: async (_: any, { input }: { input: Partial<ISupplier> }) => {
try {
const newSupplier = new SupplierModel({
...input,
date: new Date(),
});
const savedSupplier = await newSupplier.save();
return {
statusCode: 201,
message: "Supplier added successfully",
supplier: {
...savedSupplier.toObject(),
id: savedSupplier._id!.toString(),
},};} catch (error: any) {
return {
statusCode: 500,
message: error.message || "Error adding supplier",};}
},},};
export default supplierresolvers;

4. Integrate into Server(Apollo Server Setup)

  • Why Last: Once have the model, schema, and resolver you integrate them into your Apollo Server to make the API live.
  • What to Do: Update index.ts to include the schema and resolver, connect to MongoDB and start the server.

5. Update Constants:

  • This step is specific to projects needing shared configurations.
  • Centralizes reusable constants, like customer or supplier details, for consistency across the application.

    GraphQL simplifies API development , making it efficient and developer eco-friendly.

    Leave a Reply