🚀 Nuova versione beta disponibile! Feedback o problemi? Contattaci

Direttive in GraphQL: Guida Completa

Codegrind TeamAug 28 2024

Le direttive in GraphQL sono uno strumento potente che consente di modificare il comportamento delle query, delle mutazioni e dello schema stesso in modo dinamico. Con le direttive, è possibile controllare quali campi devono essere inclusi in una risposta, gestire la cache, applicare logiche di autenticazione, e molto altro. In questa guida, esploreremo le direttive predefinite in GraphQL, come @include e @skip, e impareremo a creare direttive personalizzate per soddisfare esigenze specifiche.

1. Cosa Sono le Direttive in GraphQL?

Le direttive in GraphQL sono annotazioni speciali che possono essere applicate a campi, frammenti, query, mutazioni e tipi all’interno dello schema. Esse permettono di alterare il comportamento della richiesta o della definizione dello schema in base a determinate condizioni.

Le direttive possono essere utilizzate per:

  • Condizionare l’inclusione di campi.
  • Deprecare campi o tipi.
  • Applicare logiche di validazione, caching o autorizzazione.
  • Modificare lo schema a runtime.

2. Direttive Predefinite in GraphQL

GraphQL fornisce alcune direttive predefinite che sono supportate da qualsiasi implementazione GraphQL. Le due direttive più comuni sono @include e @skip.

2.1. Direttiva @include

La direttiva @include consente di includere un campo in una query solo se una condizione specificata è vera.

Esempio di Uso

query getUser($withEmail: Boolean!) {
  user(id: "1") {
    id
    name
    email @include(if: $withEmail)
  }
}

In questo esempio, il campo email verrà incluso nella risposta solo se la variabile $withEmail è true.

2.2. Direttiva @skip

La direttiva @skip è l’opposto di @include e permette di saltare un campo in una query se una determinata condizione è vera.

Esempio di Uso

query getUser($withoutEmail: Boolean!) {
  user(id: "1") {
    id
    name
    email @skip(if: $withoutEmail)
  }
}

Qui, il campo email sarà omesso dalla risposta se la variabile $withoutEmail è true.

2.3. Direttiva @deprecated

La direttiva @deprecated viene utilizzata per indicare che un campo o un tipo non dovrebbe più essere utilizzato. È utile per mantenere la compatibilità con versioni precedenti dell’API mentre si migrano i client verso nuovi campi o tipi.

Esempio di Uso

type User {
  id: ID!
  username: String! @deprecated(reason: "Use 'name' instead")
  name: String!
}

In questo caso, username è marcato come deprecato e il messaggio di avviso indica di usare name al suo posto.

3. Creare Direttive Personalizzate

Oltre alle direttive predefinite, GraphQL permette di creare direttive personalizzate che possono essere applicate a livello di schema o query. Le direttive personalizzate sono molto potenti e possono essere utilizzate per implementare logiche specifiche, come l’autenticazione, la validazione, o la manipolazione dei dati.

3.1. Definire una Direttiva Personalizzata

Le direttive personalizzate sono definite nello schema GraphQL con la parola chiave directive.

Esempio: Direttiva @auth per l’Autenticazione

directive @auth(role: String) on FIELD_DEFINITION

type Query {
  posts: [Post!]! @auth(role: "admin")
}

type Post {
  id: ID!
  title: String!
  content: String!
}

In questo esempio, la direttiva @auth è applicata alla query posts, richiedendo che solo gli utenti con il ruolo di “admin” possano accedere ai post.

3.2. Implementare la Logica della Direttiva

Per implementare la logica dietro una direttiva personalizzata, è necessario creare un SchemaDirectiveVisitor in Apollo Server.

Esempio di Implementazione in Apollo Server

const {
  SchemaDirectiveVisitor,
  AuthenticationError,
} = require("apollo-server");
const { defaultFieldResolver } = require("graphql");

class AuthDirective extends SchemaDirectiveVisitor {
  visitFieldDefinition(field) {
    const { resolve = defaultFieldResolver } = field;
    const { role } = this.args;

    field.resolve = async function (...args) {
      const context = args[2];
      if (context.user.role !== role) {
        throw new AuthenticationError("Not authorized");
      }
      return resolve.apply(this, args);
    };
  }
}

const typeDefs = gql`
  directive @auth(role: String) on FIELD_DEFINITION

  type Query {
    posts: [Post!]! @auth(role: "admin")
  }

  type Post {
    id: ID!
    title: String!
    content: String!
  }
`;

const resolvers = {
  Query: {
    posts: () => posts, // Assume "posts" è un array di oggetti Post
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
  schemaDirectives: {
    auth: AuthDirective,
  },
  context: ({ req }) => {
    // Simulazione di un utente autenticato
    const user = { role: "admin" };
    return { user };
  },
});

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

In questo esempio, la direttiva @auth controlla se l’utente ha il ruolo richiesto per accedere ai dati. Se l’utente non ha il ruolo corretto, viene lanciato un errore di autenticazione.

4. Best Practices per l’Uso delle Direttive

4.1. Evitare l’Abuso di Direttive

Sebbene le direttive siano potenti, è importante non abusarne. L’uso eccessivo di direttive può rendere lo schema difficile da leggere e manutenere. Utilizza le direttive solo quando offrono un chiaro vantaggio rispetto a soluzioni alternative.

4.2. Documentare le Direttive

Assicurati di documentare chiaramente le direttive personalizzate nel tuo schema, spiegando come e quando dovrebbero essere utilizzate. Questo aiuta gli altri sviluppatori a comprendere e utilizzare correttamente le direttive.

4.3. Testare Direttamente le Direttive

Le direttive personalizzate possono introdurre logiche complesse che necessitano di test approfonditi. Implementa test automatizzati per verificare che le direttive si comportino come previsto in tutte le situazioni.

4.4. Considerare l’Impatto sulle Performance

Alcune direttive, come quelle che coinvolgono operazioni di autenticazione o caching, possono avere un impatto sulle performance. Assicurati di misurare e ottimizzare l’uso delle direttive in produzione.

Conclusione

Le direttive in GraphQL sono un potente strumento per estendere e personalizzare il comportamento delle query, delle mutazioni e dello schema. Comprendendo come utilizzare le direttive predefinite e come creare direttive personalizzate, puoi aggiungere logiche avanzate al tuo schema GraphQL, migliorando la flessibilità e l’efficienza della tua API. Seguendo le best practices delineate in questa guida, sarai in grado di utilizzare le direttive in modo efficace e sicuro.