ITSkillsCenter
Développement Web

GraphQL : API moderne pour applications web

3 min de lecture
Miniature - GraphQL : API moderne pour applications web

Ce que vous saurez faire à la fin

  1. Monter un serveur GraphQL Apollo
  2. Schéma, résolveurs, mutations, subscriptions
  3. Résoudre N+1 avec DataLoader
  4. Sécuriser avec depth-limit et auth
  5. Consommer avec Apollo Client React

Étape 1 — Installation

npm install @apollo/server graphql

Étape 2 — Schéma et résolveurs

import { ApolloServer } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";

const typeDefs = `#graphql
  type Client {
    id: ID!
    nom: String!
    factures: [Facture!]!
  }
  type Facture {
    id: ID!
    montant: Float!
    client: Client!
  }
  type Query {
    client(id: ID!): Client
    clients: [Client!]!
  }
`;

const resolvers = {
  Query: {
    client: (_, { id }, { db }) => db.findClient(id),
    clients: (_, __, { db }) => db.allClients(),
  },
  Client: {
    factures: (parent, _, { db }) => db.facturesDuClient(parent.id),
  },
};

const server = new ApolloServer({ typeDefs, resolvers });
const { url } = await startStandaloneServer(server, { listen: { port: 4000 } });

Étape 3 — Mutations

const typeDefs = `#graphql
  input CreerClientInput {
    nom: String!
    ville: String
  }
  type Mutation {
    creerClient(input: CreerClientInput!): Client!
  }
`;

const resolvers = {
  Mutation: {
    creerClient: (_, { input }, { db }) => db.createClient(input),
  },
};

Étape 4 — DataLoader anti-N+1

npm install dataloader
import DataLoader from "dataloader";

function createLoaders(db) {
  return {
    clientLoader: new DataLoader(async (ids) => {
      const rows = await db.query("SELECT * FROM clients WHERE id = ANY($1)", [ids]);
      return ids.map(id => rows.find(r => r.id === id));
    }),
  };
}

// Context par requête
await startStandaloneServer(server, {
  context: async () => ({ db, ...createLoaders(db) }),
});

const resolvers = {
  Facture: {
    client: (parent, _, { clientLoader }) => clientLoader.load(parent.client_id),
  },
};

Étape 5 — Auth

import jwt from "jsonwebtoken";

context: async ({ req }) => {
  const token = req.headers.authorization?.replace("Bearer ", "");
  let user = null;
  if (token) {
    try { user = jwt.verify(token, process.env.JWT_SECRET); } catch {}
  }
  return { user };
}

const resolvers = {
  Query: {
    utilisateurs: (_, __, { user }) => {
      if (!user || user.role !== "admin") throw new Error("interdit");
      return db.listUsers();
    },
  },
};

Étape 6 — Subscriptions

import { PubSub } from "graphql-subscriptions";
const pubsub = new PubSub();

const typeDefs = `#graphql
  type Subscription {
    venteCreee: Facture!
  }
`;

const resolvers = {
  Mutation: {
    creerFacture: async (_, { input }) => {
      const f = await db.createFacture(input);
      pubsub.publish("VENTE_CREEE", { venteCreee: f });
      return f;
    },
  },
  Subscription: {
    venteCreee: {
      subscribe: () => pubsub.asyncIterator("VENTE_CREEE"),
    },
  },
};

Étape 7 — Sécurité

import depthLimit from "graphql-depth-limit";

const server = new ApolloServer({
  typeDefs,
  resolvers,
  validationRules: [depthLimit(5)],
});

Étape 8 — Client React

npm install @apollo/client
import { ApolloClient, InMemoryCache, ApolloProvider, gql, useQuery } from "@apollo/client";

const client = new ApolloClient({
  uri: "http://localhost:4000/",
  cache: new InMemoryCache(),
});

function Clients() {
  const { data, loading } = useQuery(gql`query { clients { id nom } }`);
  if (loading) return <p>Chargement...</p>;
  return <ul>{data.clients.map(c => <li key={c.id}>{c.nom}</li>)}</ul>;
}

Étape 9 — Codegen TypeScript

npm install -D @graphql-codegen/cli @graphql-codegen/typescript-react-apollo

npx graphql-codegen

Étape 10 — Checklist prod

✓ Désactiver introspection en prod
✓ depthLimit + rate-limit + complexity
✓ DataLoader sur résolveurs relationnels
✓ Persisted queries
✓ Tracing Apollo Studio
✓ Auth obligatoire sur mutations
✓ Validation Zod des inputs
Besoin d'un site web ?

Confiez-nous la Création de Votre Site Web

Site vitrine, e-commerce ou application web — nous transformons votre vision en réalité digitale. Accompagnement personnalisé de A à Z.

À partir de 250.000 FCFA
Parlons de Votre Projet
Publicité