🚀 Nuova versione beta disponibile! Feedback o problemi? Contattaci

Creazione di uno Schema GraphQL: Guida Passo-Passo

Codegrind Team•Aug 28 2024

Lo schema GraphQL è il cuore di ogni API GraphQL. Definisce la struttura dei dati, le query che possono essere eseguite, le mutazioni per modificare i dati e le subscription per gestire aggiornamenti in tempo reale. Creare uno schema solido e ben strutturato è fondamentale per costruire un’API scalabile, efficiente e facile da manutenere.

In questa guida, esploreremo passo-passo come creare uno schema GraphQL, dalla definizione dei tipi alla gestione delle operazioni complesse.

Cos’è uno Schema GraphQL?

Uno schema GraphQL è una rappresentazione del modello di dati che l’API espone. Definisce i tipi di dati, le relazioni tra di essi, e le operazioni che possono essere eseguite (query, mutazioni e subscription). Lo schema è scritto in un linguaggio di definizione del tipo chiamato SDL (Schema Definition Language).

1. Creazione di un Nuovo Progetto

Iniziamo creando un nuovo progetto Node.js e installando le dipendenze necessarie:

mkdir my-graphql-api
cd my-graphql-api
npm init -y
npm install apollo-server graphql

2. Definizione dello Schema di Base

2.1. Definire i Tipi di Dati

I tipi di dati (o types) rappresentano le entità del dominio dell’applicazione. Per esempio, in un sistema di gestione dei contenuti (CMS), potresti avere tipi come Post, Author, e Comment.

Crea un file chiamato schema.js:

const { gql } = require("apollo-server");

const typeDefs = gql`
  type Post {
    id: ID!
    title: String!
    content: String!
    author: Author!
    comments: [Comment!]!
  }

  type Author {
    id: ID!
    name: String!
    posts: [Post!]!
  }

  type Comment {
    id: ID!
    content: String!
    post: Post!
    author: Author!
  }
`;

module.exports = typeDefs;

2.2. Definire le Query

Le query sono operazioni che permettono di leggere i dati. Ogni query può restituire uno o più tipi definiti nello schema.

const typeDefs = gql`
  # ... (tipi giĂ  definiti)

  type Query {
    posts: [Post!]!
    post(id: ID!): Post
    authors: [Author!]!
    author(id: ID!): Author
  }
`;

In questo esempio, abbiamo definito alcune query per ottenere la lista dei post, un singolo post per ID, la lista degli autori, e un singolo autore per ID.

2.3. Definire le Mutazioni

Le mutazioni sono operazioni che permettono di creare, aggiornare o eliminare dati.

const typeDefs = gql`
  # ... (tipi e query giĂ  definiti)

  type Mutation {
    createPost(title: String!, content: String!, authorId: ID!): Post!
    updatePost(id: ID!, title: String, content: String): Post!
    deletePost(id: ID!): Boolean!
  }
`;

Queste mutazioni consentono di creare un nuovo post, aggiornare un post esistente e cancellare un post.

2.4. Definire le Subscription

Le subscription permettono ai client di iscriversi a eventi in tempo reale, come quando un nuovo post viene creato.

const typeDefs = gql`
  # ... (tipi, query e mutazioni giĂ  definiti)

  type Subscription {
    postCreated: Post!
  }
`;

3. Implementazione dei Resolvers

I resolvers sono funzioni che risolvono le query, le mutazioni e le subscription definite nello schema, fornendo i dati effettivi.

Crea un file chiamato resolvers.js:

const { PubSub } = require("apollo-server");
const pubsub = new PubSub();

const posts = [];
const authors = [];

const resolvers = {
  Query: {
    posts: () => posts,
    post: (parent, args) => posts.find((post) => post.id === args.id),
    authors: () => authors,
    author: (parent, args) => authors.find((author) => author.id === args.id),
  },
  Mutation: {
    createPost: (parent, args) => {
      const post = {
        id: `${posts.length + 1}`,
        title: args.title,
        content: args.content,
        author: authors.find((author) => author.id === args.authorId),
      };
      posts.push(post);
      pubsub.publish("POST_CREATED", { postCreated: post });
      return post;
    },
    updatePost: (parent, args) => {
      const post = posts.find((post) => post.id === args.id);
      if (!post) throw new Error("Post not found");
      if (args.title) post.title = args.title;
      if (args.content) post.content = args.content;
      return post;
    },
    deletePost: (parent, args) => {
      const postIndex = posts.findIndex((post) => post.id === args.id);
      if (postIndex === -1) return false;
      posts.splice(postIndex, 1);
      return true;
    },
  },
  Subscription: {
    postCreated: {
      subscribe: () => pubsub.asyncIterator(["POST_CREATED"]),
    },
  },
};

module.exports = resolvers;

4. Configurazione del Server Apollo

Ora che abbiamo definito lo schema e i resolvers, possiamo configurare il server Apollo per esporre la nostra API GraphQL.

Crea un file chiamato index.js:

const { ApolloServer } = require("apollo-server");
const typeDefs = require("./schema");
const resolvers = require("./resolvers");

const server = new ApolloServer({ typeDefs, resolvers });

server.listen().then(({ url }) => {
  console.log(`Server pronto su ${url}`);
});

5. Eseguire il Server

Avvia il server Node.js:

node index.js

Il server sarà disponibile all’indirizzo http://localhost:4000/. Puoi utilizzare Apollo Studio Explorer per testare le query, le mutazioni e le subscription.

6. Best Practices per la Creazione dello Schema

6.1. Organizzare lo Schema in Moduli

Per mantenere lo schema manutenibile, suddividilo in moduli separati per tipi, query, mutazioni e subscription. Questo rende più facile la gestione e l’evoluzione dello schema nel tempo.

6.2. Utilizzare Tipi Input per le Mutazioni Complesse

Quando le mutazioni accettano molti parametri, utilizza tipi input per migliorare la leggibilitĂ  e la manutenibilitĂ .

input PostInput {
  title: String!
  content: String!
  authorId: ID!
}

type Mutation {
  createPost(input: PostInput!): Post!
}

6.3. Documentare lo Schema

Aggiungi descrizioni ai tipi, campi e operazioni nello schema per migliorare la comprensione e la facilità d’uso dell’API.

"""
Rappresenta un post nel blog.
"""
type Post {
  id: ID!
  title: String!
  content: String!
  author: Author!
}

Conclusione

La creazione di uno schema GraphQL è un passo fondamentale nello sviluppo di un’API. Con un design accurato e l’implementazione di best practices, puoi costruire uno schema scalabile e facile da mantenere, che offre una solida base per l’evoluzione della tua applicazione. Seguendo questa guida passo-passo, hai imparato come definire tipi, query, mutazioni e subscription, e come implementare i resolvers per gestire le operazioni.