

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# GraphQL e architettura AWS AppSync
<a name="graphql-overview"></a>

**Nota**  
Questa guida presuppone che l'utente abbia una conoscenza pratica dello stile architettonico REST. Ti consigliamo di esaminare questo e altri argomenti di front-end prima di utilizzare GraphQL e. AWS AppSync

GraphQL è un linguaggio di interrogazione e manipolazione per. APIs GraphQL fornisce una sintassi flessibile e intuitiva per descrivere i requisiti e le interazioni dei dati. Consente agli sviluppatori di chiedere esattamente ciò che è necessario e ottenere risultati prevedibili. Consente inoltre di accedere a più fonti in un'unica richiesta, riducendo il numero di chiamate di rete e i requisiti di larghezza di banda, risparmiando così la durata della batteria e i cicli di CPU utilizzati dalle applicazioni. 

L'aggiornamento dei dati è reso semplice dalle mutazioni, che consentono agli sviluppatori di descrivere come i dati dovrebbero cambiare. GraphQL facilita anche la configurazione rapida di soluzioni in tempo reale tramite abbonamenti. Tutte queste funzionalità combinate, insieme a potenti strumenti di sviluppo, rendono GraphQL essenziale per la gestione dei dati delle applicazioni.

GraphQL è un'alternativa a REST. RESTful l'architettura è attualmente una delle soluzioni più popolari per la comunicazione client-server. È incentrato sul concetto che le tue risorse (dati) vengano esposte da un URL. Questi URLs possono essere utilizzati per accedere e manipolare i dati tramite operazioni CRUD (creazione, lettura, aggiornamento, eliminazione) sotto forma di metodi HTTP come`GET`, `POST` e. `DELETE` Il vantaggio di REST è che è relativamente semplice da imparare e implementare. Puoi configurarti rapidamente RESTful APIs per chiamare un'ampia gamma di servizi. 

Tuttavia, la tecnologia sta diventando sempre più complicata. Man mano che le applicazioni, gli strumenti e i servizi iniziano a scalare per un pubblico mondiale, la necessità di architetture veloci e scalabili è di fondamentale importanza. REST presenta molte lacune quando si tratta di operazioni scalabili. Vedi questo [caso d'uso](https://aws.amazon.com/blogs/architecture/what-to-consider-when-modernizing-apis-with-graphql-on-aws/) per un esempio.

Nelle sezioni seguenti, esamineremo alcuni dei concetti correlati RESTful APIs. Presenteremo quindi GraphQL e come funziona.

Per ulteriori informazioni su GraphQL e sui vantaggi della migrazione a AWS, consulta la guida [decisionale alle implementazioni di GraphQL](https://aws.amazon.com/graphql/guide/).

**Topics**
+ [Che cos'è un'API](what-is-an-api.md)
+ [Che cos'è REST](what-is-rest.md)
+ [Che cos'è GraphQL](what-is-graphql.md)
+ [Confronto tra REST e GraphQL](comparing-rest-graphql.md)
+ [Perché usare GraphQL rispetto a REST](why-use-graphql.md)
+ [Componenti di un'API GraphQL](api-components.md)
+ [Proprietà aggiuntive di GraphQL](graphql-properties.md)

# Che cos'è un'API?
<a name="what-is-an-api"></a>

Un'interfaccia di programmazione delle applicazioni (API) definisce le regole da seguire per comunicare con altri sistemi software. Gli sviluppatori espongono o creano APIs in modo che altre applicazioni possano comunicare con le loro applicazioni in modo programmatico. Ad esempio, l'applicazione timesheet espone un'API che richiede il nome completo di un dipendente e un intervallo di date. Quando riceve queste informazioni, elabora internamente la scheda attività del dipendente e restituisce il numero di ore lavorate in quell'intervallo di date.

Puoi pensare a un'API Web come a un gateway tra client e risorse sul Web.

## Client
<a name="what-is-a-client"></a>

I client sono utenti che desiderano accedere alle informazioni dal Web. Il client può essere una persona o un sistema software che utilizza l'API. Ad esempio, gli sviluppatori possono scrivere programmi che accedono ai dati meteorologici da un sistema meteorologico. Oppure puoi accedere agli stessi dati dal tuo browser quando visiti direttamente il sito web meteo.

## Resources
<a name="what-is-a-resource"></a>

Le risorse sono le informazioni che le diverse applicazioni forniscono ai propri clienti. Le risorse possono essere immagini, video, testo, numeri o qualsiasi tipo di dati. La macchina che fornisce la risorsa al client viene anche chiamata server. Le organizzazioni APIs lo utilizzano per condividere risorse e fornire servizi Web mantenendo la sicurezza, il controllo e l'autenticazione. Inoltre, APIs aiutale a determinare quali clienti possono accedere a risorse interne specifiche.

# Che cos'è REST?
<a name="what-is-rest"></a>

Ad alto livello, Representational State Transfer (REST) è un'architettura software che impone condizioni sul funzionamento di un'API. REST è stato inizialmente creato come linea guida per gestire la comunicazione su una rete complessa come Internet. È possibile utilizzare l'architettura basata su REST per supportare comunicazioni affidabili e ad alte prestazioni su larga scala. Puoi implementarlo e modificarlo facilmente, offrendo visibilità e portabilità multipiattaforma a qualsiasi sistema API.

Gli sviluppatori di API possono progettare APIs utilizzando diverse architetture. APIs quelle che seguono lo stile architettonico REST sono chiamate REST. APIs I servizi Web che implementano l'architettura REST sono chiamati servizi RESTful Web. Il termine RESTful API si riferisce generalmente al RESTful web APIs. Tuttavia, è possibile utilizzare i termini API REST e RESTful API in modo intercambiabile.

Di seguito sono riportati alcuni dei principi dello stile architettonico REST:

## Interfaccia uniforme
<a name="uniform-interface"></a>

L'interfaccia uniforme è fondamentale per la progettazione di qualsiasi RESTful servizio web. Indica che il server trasferisce le informazioni in un formato standard. La risorsa formattata è chiamata rappresentazione in REST. Questo formato può essere diverso dalla rappresentazione interna della risorsa nell'applicazione server. Ad esempio, il server può memorizzare i dati come testo ma inviarli in un formato di rappresentazione HTML.

L'interfaccia uniforme impone quattro vincoli architettonici:

1.  Le richieste devono identificare le risorse. Lo fanno utilizzando un identificatore di risorsa uniforme. 

1.  I client dispongono di informazioni sufficienti nella rappresentazione delle risorse per modificare o eliminare la risorsa, se lo desiderano. Il server soddisfa questa condizione inviando metadati che descrivono ulteriormente la risorsa. 

1.  I clienti ricevono informazioni su come elaborare ulteriormente la rappresentazione. Il server ottiene ciò inviando messaggi autodescrittivi che contengono metadati su come il client può utilizzarli al meglio. 

1.  I clienti ricevono informazioni su tutte le altre risorse correlate di cui hanno bisogno per completare un'attività. Il server ottiene ciò inviando collegamenti ipertestuali nella rappresentazione in modo che i client possano scoprire dinamicamente più risorse. 

## Apolidia
<a name="statelessness"></a>

Nell'architettura REST, l'apolidia si riferisce a un metodo di comunicazione in cui il server completa ogni richiesta del client indipendentemente da tutte le richieste precedenti. I client possono richiedere risorse in qualsiasi ordine e ogni richiesta è stateless o isolata dalle altre richieste. Questo vincolo di progettazione dell'API REST implica che il server possa comprendere e soddisfare completamente la richiesta ogni volta. 

## Sistema a strati
<a name="layered-system"></a>

In un'architettura di sistema a più livelli, il client può connettersi ad altri intermediari autorizzati tra il client e il server e continuerà a ricevere risposte dal server. I server possono anche trasmettere richieste ad altri server. È possibile progettare il servizio RESTful Web in modo che venga eseguito su più server con più livelli come sicurezza, applicazione e logica aziendale, che collaborano per soddisfare le richieste dei clienti. Questi livelli rimangono invisibili al client.

## Cacheabilità
<a name="cacheability"></a>

RESTful i servizi web supportano la memorizzazione nella cache, che è il processo di memorizzazione di alcune risposte sul client o su un intermediario per migliorare i tempi di risposta del server. Ad esempio, supponiamo di visitare un sito Web con immagini di intestazione e piè di pagina comuni su ogni pagina. Ogni volta che visiti una nuova pagina del sito Web, il server deve inviare nuovamente le stesse immagini. Per evitare ciò, il client memorizza nella cache o memorizza queste immagini dopo la prima risposta e quindi utilizza le immagini direttamente dalla cache. RESTful i servizi web controllano la memorizzazione nella cache utilizzando risposte API che si definiscono inseribili nella cache o non memorizzabili nella cache.

## Che cos'è un'API? RESTful
<a name="what-is-a-restful-api"></a>

RESTful L'API è un'interfaccia utilizzata da due sistemi informatici per scambiare informazioni in modo sicuro su Internet. La maggior parte delle applicazioni aziendali deve comunicare con altre applicazioni interne e di terze parti per eseguire varie attività. Ad esempio, per generare buste paga mensili, il sistema contabile interno deve condividere i dati con il sistema bancario del cliente per automatizzare la fatturazione e comunicare con un'applicazione interna per la scheda attività. RESTful APIs supportano questo scambio di informazioni perché seguono standard di comunicazione software sicuri, affidabili ed efficienti.

## Come RESTful APIs funziona?
<a name="how-do-restful-apis-work"></a>

La funzione di base di un' RESTful API è la stessa della navigazione in Internet. Il client contatta il server utilizzando l'API quando richiede una risorsa. Gli sviluppatori di API spiegano come il client deve utilizzare l'API REST nella documentazione dell'API dell'applicazione server. Questi sono i passaggi generali per qualsiasi chiamata all'API REST:

1.  Il client invia una richiesta al server. Il client segue la documentazione dell'API per formattare la richiesta in modo comprensibile al server. 

1.  Il server autentica il client e conferma che il client ha il diritto di effettuare tale richiesta. 

1.  Il server riceve la richiesta e la elabora internamente. 

1.  Il server restituisce una risposta al client. La risposta contiene informazioni che indicano al client se la richiesta è andata a buon fine. La risposta include anche tutte le informazioni richieste dal client. 

I dettagli della richiesta e della risposta dell'API REST variano leggermente a seconda di come gli sviluppatori dell'API progettano l'API.

# Che cos'è GraphQL?
<a name="what-is-graphql"></a>

GraphQL è sia un linguaggio di query che un runtime per APIs l'esecuzione di tali query. GraphQL consente ai clienti di richiedere esattamente i dati di cui hanno bisogno, fornendo un'alternativa più flessibile ed efficiente a REST in molti scenari. A differenza di REST, che si basa su endpoint predefiniti, GraphQL utilizza un unico endpoint in cui i clienti possono specificare i propri requisiti di dati sotto forma di query e mutazioni. 

Vedi [Componenti di un'API GraphQL](https://docs.aws.amazon.com/appsync/latest/devguide/api-components.html) per ulteriori informazioni su come è strutturato GraphQL. APIs 

# Confronto tra REST e GraphQL
<a name="comparing-rest-graphql"></a>

APIs (Application Programming Interfaces) svolgono un ruolo cruciale nel facilitare lo scambio di dati tra le applicazioni. Come affermato in precedenza, APIs sono emersi due approcci importanti per la progettazione: GraphQL e REST. Sebbene entrambi abbiano lo scopo fondamentale di abilitare la comunicazione client-server, differiscono in modo significativo nell'implementazione e nei casi d'uso.

GraphQL e REST condividono diverse caratteristiche chiave: 

1. **Modello client-server**: entrambi utilizzano un'architettura client-server per lo scambio di dati. 

1. **Apolidia: nessuno dei due conserva le informazioni sulla sessione del client** tra una richiesta e l'altra. 

1. **Basato su HTTP**: entrambi utilizzano in genere HTTP come protocollo di comunicazione sottostante. 

1. **Progettazione orientata alle risorse: entrambi progettano** lo scambio di dati attorno alle risorse, che si riferiscono a qualsiasi dato o oggetto a cui il client può accedere e manipolare tramite l'API. 

1. **Flessibilità del formato dei dati**: JSON è il formato di scambio dati più utilizzato in entrambi, sebbene siano supportati anche altri formati come XML e HTML. 

1. Indipendenti dal **linguaggio e dal database: entrambi** possono funzionare con qualsiasi linguaggio di programmazione o struttura di database, il che li rende altamente interoperabili. 

1. **Supporto per la memorizzazione nella cache**: entrambi supportano la memorizzazione nella cache, consentendo a client e server di archiviare i dati a cui si accede di frequente per migliorare le prestazioni. 

Pur condividendo alcuni principi fondamentali, GraphQL e REST differiscono in modo significativo nel loro approccio alla progettazione delle API e al recupero dei dati:

1. **Struttura delle richieste e recupero dei dati**

   REST utilizza diversi metodi HTTP (GET, POST, PUT, DELETE) per eseguire operazioni sulle risorse. Ciò richiede spesso più endpoint per risorse diverse, il che può portare a inefficienze nel recupero dei dati. Ad esempio, l'esecuzione di un'operazione GET per recuperare i dati di un utente può portare a un recupero eccessivo o insufficiente dei dati. Per ottenere i dati corretti, è possibile eseguire operazioni di troncamento o più operazioni. 

   GraphQL utilizza un unico endpoint per tutte le operazioni. Si basa su interrogazioni per il recupero dei dati e su mutazioni per la modifica dei dati. I client possono utilizzare le query per recuperare esattamente i dati di cui hanno bisogno in un'unica richiesta, il che riduce il sovraccarico della rete riducendo al minimo il trasferimento dei dati. 

1. **Schema lato server**

   REST non richiede uno schema lato server, sebbene uno possa essere definito opzionalmente per una progettazione e una documentazione efficienti delle API.

   GraphQL utilizza uno schema lato server fortemente tipizzato per definire dati e servizi dati. Lo schema, scritto in GraphQL Schema Definition Language (SDL), include tipi di oggetti e campi per ogni oggetto e funzioni resolver lato server che definiscono le operazioni per ogni campo.

1. **Funzione Versioni multiple**

   REST spesso include il controllo delle versioni nell'URL, il che può portare al mantenimento simultaneo di più versioni dell'API. Il controllo delle versioni non è obbligatorio, ma può aiutare a prevenire modifiche irreversibili. 

   GraphQL promuove un'evoluzione continua dell'API senza il controllo esplicito delle versioni richiedendo la compatibilità con le versioni precedenti. I campi eliminati restituiscono messaggi di errore, mentre i tag obsoleti eliminano gradualmente i vecchi campi e restituiscono messaggi di avviso. 

1. **Gestione degli errori** 

   REST è tipizzato in modo debole e richiede che la gestione degli errori sia integrata nel codice circostante. Ciò potrebbe non identificare automaticamente gli errori relativi al tipo (ad esempio, l'analisi di un numero come testo). 

   Al contrario, GraphQL è fortemente tipizzato e richiede una definizione dello schema completa. Ciò consente al servizio di identificare automaticamente molti errori di richiesta con un elevato livello di dettaglio.

1. **Casi d'uso**

   REST è più adatto per: 
   + Applicazioni più piccole con requisiti di dati meno complessi. 
   + Scenari in cui i dati e le operazioni vengono utilizzati in modo simile da tutti i client. 
   + Applicazioni senza esigenze complesse di interrogazione dei dati. 

   GraphQL è più adatto per: 
   + Scenari con larghezza di banda limitata, in cui ridurre al minimo le richieste e le risposte è fondamentale. 
   + Applicazioni con più fonti di dati che devono essere combinate su un unico endpoint. 
   + Casi in cui le richieste dei clienti variano in modo significativo e prevedono strutture di risposta diverse.

   Nota che è possibile utilizzare sia GraphQL che REST APIs all'interno di una singola applicazione per diverse aree di funzionalità. Inoltre, puoi aggiornare un' RESTful API per includere funzionalità GraphQL senza una riscrittura completa. Vedi [Come creare resolver GraphQL per sorgenti di AWS dati per un esempio.](https://aws.amazon.com/graphql/resolvers/)

# Perché usare GraphQL rispetto a REST?
<a name="why-use-graphql"></a>

REST è uno degli stili architettonici fondamentali del web. APIs Tuttavia, man mano che il mondo diventa più interconnesso, la necessità di sviluppare applicazioni robuste e scalabili diventerà una questione sempre più urgente. Sebbene REST venga spesso utilizzato per creare siti Web APIs, sono stati identificati diversi inconvenienti ricorrenti RESTful nelle implementazioni:

1. **Richieste di dati**: utilizzando RESTful APIs, in genere si richiedono i dati necessari tramite gli endpoint. Il problema sorge quando si hanno dati che potrebbero non essere impacchettati in modo così ordinato. I dati necessari possono essere protetti da più livelli di astrazione e l'unico modo per recuperarli è utilizzare più endpoint, il che significa effettuare più richieste per estrarre tutti i dati.

1. **Overfetching e underfetching**: per aggravare i problemi legati alle richieste multiple, i dati di ciascun endpoint sono definiti in modo rigoroso, il che significa che restituirai tutti i dati definiti per quell'API, anche se tecnicamente non li volevi.

   Ciò può comportare un *recupero eccessivo, il che significa che le nostre richieste restituiscono* dati superflui. Ad esempio, supponiamo che tu stia richiedendo i dati del personale dell'azienda e desideri conoscere i nomi dei dipendenti di un determinato reparto. L'endpoint che restituisce i dati conterrà i nomi, ma potrebbe contenere anche altri dati come il titolo professionale o la data di nascita. Poiché l'API è fissa, non puoi semplicemente richiedere i nomi; il resto dei dati viene fornito con essa.

   La situazione opposta, in cui non restituiamo una quantità sufficiente di dati, si chiama *under-fetching*. Per ottenere tutti i dati richiesti, potrebbe essere necessario effettuare più richieste al servizio. A seconda di come sono strutturati i dati, potreste imbattervi in interrogazioni inefficienti con conseguenti problemi come il temuto problema n\$11.

1. **Iterazioni di sviluppo lente**: molti sviluppatori le personalizzano RESTful APIs per adattarsi al flusso delle loro applicazioni. Tuttavia, man mano che le applicazioni crescono, sia il front-end che il backend potrebbero richiedere modifiche estese. Di conseguenza, APIs potrebbero non adattarsi più alla forma dei dati in modo efficiente o di impatto. Ciò si traduce in iterazioni di prodotto più lente a causa della necessità di modifiche all'API.

1. **Prestazioni su larga scala**: a causa di questi problemi di aggravamento, ci sono molte aree in cui la scalabilità ne risentirà. Le prestazioni sul lato applicativo potrebbero risentirne perché le richieste restituiranno troppi o troppo pochi dati (con conseguente aumento delle richieste). Entrambe le situazioni causano inutili sollecitazioni sulla rete con conseguenti scarse prestazioni. Per quanto riguarda gli sviluppatori, la velocità di sviluppo può essere ridotta perché i dati richiesti APIs sono fissi e non sono più sufficienti.

Il punto di forza di GraphQL è quello di superare gli svantaggi di REST. Ecco alcune delle soluzioni chiave che GraphQL offre agli sviluppatori:

1. **Endpoint singoli**: GraphQL utilizza un singolo endpoint per interrogare i dati. Non è necessario crearne più di uno APIs per adattarlo alla forma dei dati. Ciò si traduce in un minor numero di richieste che passano attraverso la rete.

1. **Recupero**: GraphQL risolve i problemi perenni di sovra e insufficiente recupero semplicemente definendo i dati necessari. GraphQL ti consente di modellare i dati in base alle tue esigenze in modo da ricevere solo ciò che hai richiesto.

1. **Astrazione**: APIs GraphQL contiene alcuni componenti e sistemi che descrivono i dati utilizzando uno standard indipendente dal linguaggio. In altre parole, la forma e la struttura dei dati sono standardizzate in modo che sia il front-end che il backend sappiano come verranno inviati sulla rete. Ciò consente agli sviluppatori di entrambe le parti di lavorare con i sistemi GraphQL e non con essi.

1. **Iterazioni rapide**: a causa della standardizzazione dei dati, potrebbero non essere necessarie modifiche su un lato dello sviluppo sull'altro. Ad esempio, le modifiche alla presentazione del frontend potrebbero non comportare modifiche estese al backend perché GraphQL consente di modificare facilmente le specifiche dei dati. Puoi semplicemente definire o modificare la forma dei dati per adattarla alle esigenze dell'applicazione man mano che cresce. Ciò si traduce in un minor potenziale di lavoro di sviluppo.

Questi sono solo alcuni dei vantaggi di GraphQL. Nelle prossime sezioni, scoprirai come è strutturato GraphQL e le proprietà che lo rendono un'alternativa unica a REST.

# Componenti di un'API GraphQL
<a name="api-components"></a>

Un'API GraphQL standard è composta da un unico schema che gestisce la forma dei dati che verranno interrogati. Lo schema è collegato a una o più fonti di dati come un database o una funzione Lambda. Tra i due si trovano uno o più resolver che gestiscono la logica aziendale per le tue richieste. Ogni componente svolge un ruolo importante nell'implementazione di GraphQL. Le sezioni seguenti introdurranno questi tre componenti e il ruolo che svolgono nel servizio GraphQL.

![\[GraphQL API components: schema, resolvers, and data sources interconnected with AppSync.\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/images/appsync-architecture-graphql-api.png)


**Topics**
+ [Schemi GraphQL](schema-components.md)
+ [Fonti di dati](data-source-components.md)
+ [Risolutori](resolver-components.md)

# Schemi GraphQL
<a name="schema-components"></a>

Lo schema GraphQL è alla base di un'API GraphQL. Serve come modello che definisce la forma dei dati. È anche un contratto tra il client e il server che definisce come i dati verranno recuperati and/or e modificati.

Gli schemi GraphQL sono scritti nello *Schema Definition Language* (SDL). SDL è composto da tipi e campi con una struttura consolidata:
+ **Tipi**: I tipi sono il modo in cui GraphQL definisce la forma e il comportamento dei dati. GraphQL supporta una moltitudine di tipi che verranno spiegati più avanti in questa sezione. Ogni tipo definito nello schema conterrà il proprio ambito. All'interno dell'ambito ci saranno uno o più campi che possono contenere un valore o una logica che verrà utilizzata nel servizio GraphQL. I tipi ricoprono molti ruoli diversi, i più comuni sono gli oggetti o gli scalari (tipi di valori primitivi).
+ **Campi**: i campi esistono nell'ambito di un tipo e contengono il valore richiesto dal servizio GraphQL. Sono molto simili alle variabili di altri linguaggi di programmazione. La forma dei dati definiti nei campi determinerà il modo in cui i dati sono strutturati in un' request/response operazione. Ciò consente agli sviluppatori di prevedere cosa verrà restituito senza sapere come viene implementato il backend del servizio.

Per visualizzare l'aspetto di uno schema, esaminiamo il contenuto di un semplice schema GraphQL. Nel codice di produzione, lo schema si trova in genere in un file chiamato `schema.graphql` o. `schema.json` Supponiamo che stiamo esaminando un progetto che implementa un servizio GraphQL. Questo progetto archivia i dati del personale dell'azienda e il `schema.graphql` file viene utilizzato per recuperare i dati sul personale e aggiungere nuovo personale a un database. Il codice potrebbe essere simile al seguente:

------
#### [ schema.graphql ]

```
type Person {                                  
   id: ID!
   name: String                                  
   age: Int
}
type Query {                                   
  people: [Person]
}
type Mutation {
  addPerson(id: ID!, name: String, age: Int): Person
}
```

------

Possiamo vedere che ci sono tre tipi definiti nello schema:`Person`,`Query`, e`Mutation`. Guardando`Person`, possiamo immaginare che questo sia il modello per un esempio di un dipendente dell'azienda, il che renderebbe questo tipo un oggetto. All'interno del suo ambito `id``name`, vediamo e`age`. Questi sono i campi che definiscono le proprietà di a`Person`. Ciò significa che la nostra fonte `Person` di dati memorizza ciascuno `name` come tipo `String` scalare (primitivo) e `age` come tipo `Int` scalare (primitivo). `id`Funziona come un identificatore speciale e univoco per ciascuno. `Person` È anche un valore obbligatorio, come indicato dal `!` simbolo.

I due tipi di oggetti successivi si comportano in modo diverso. GraphQL riserva alcune parole chiave per tipi di oggetti speciali che definiscono il modo in cui i dati verranno popolati nello schema. Un `Query` tipo recupererà i dati dalla fonte. Nel nostro esempio, la nostra query potrebbe recuperare `Person` oggetti da un database. Questo potrebbe ricordarvi le `GET` operazioni RESTful terminologiche. A `Mutation` modificherà i dati. Nel nostro esempio, la nostra mutazione può aggiungere altri `Person` oggetti al database. Questo potrebbe ricordarti di operazioni che cambiano lo stato come o`PUT`. `POST` I comportamenti di tutti i tipi di oggetti speciali verranno spiegati più avanti in questa sezione.

Supponiamo che `Query` nel nostro esempio recuperi qualcosa dal database. Se osserviamo i campi di`Query`, vediamo un campo chiamato`people`. Il suo valore di campo è`[Person]`. Ciò significa che vogliamo recuperare alcune istanze `Person` del database. Tuttavia, l'aggiunta di parentesi indica che vogliamo restituire un elenco di tutte le `Person` istanze e non solo uno specifico.

Il `Mutation` tipo è responsabile dell'esecuzione di operazioni di modifica dello stato come la modifica dei dati. Una mutazione è responsabile dell'esecuzione di alcune operazioni di modifica dello stato sulla fonte di dati. Nel nostro esempio, la nostra mutazione contiene un'operazione chiamata `addPerson` che aggiunge un nuovo `Person` oggetto al database. La mutazione utilizza a `Person` e prevede un input per i campi `id``name`, e. `age`

A questo punto, forse vi starete chiedendo come `addPerson` funzionano operazioni come quelle senza un'implementazione di codice, dato che presumibilmente esegue un certo comportamento e assomiglia molto a una funzione con un nome di funzione e parametri. Attualmente non funzionerà perché uno schema funge solo da dichiarazione. Per implementare il comportamento di`addPerson`, dovremmo aggiungervi un resolver. Un resolver è un'unità di codice che viene eseguita ogni volta che viene chiamato il campo associato (in questo caso, l'`addPerson`operazione). Se desideri utilizzare un'operazione, a un certo punto dovrai aggiungere l'implementazione del resolver. In un certo senso, puoi pensare all'operazione dello schema come alla dichiarazione di funzione e al resolver come alla definizione. I resolver verranno spiegati in una sezione diversa.

Questo esempio mostra solo i modi più semplici in cui uno schema può manipolare i dati. Puoi creare applicazioni complesse, robuste e scalabili sfruttando le funzionalità di GraphQL e. AWS AppSync Nella prossima sezione, definiremo tutti i diversi tipi e comportamenti sul campo che puoi utilizzare nel tuo schema.

# Tipi GraphQL
<a name="graphql-types"></a>

GraphQL supporta molti tipi diversi. Come hai visto nella sezione precedente, i tipi definiscono la forma o il comportamento dei dati. Sono gli elementi costitutivi fondamentali di uno schema GraphQL. 

I tipi possono essere classificati in input e output. Gli input sono tipi che possono essere passati come argomento per i tipi di oggetti speciali (`Query`,, ecc.)`Mutation`, mentre i tipi di output vengono utilizzati strettamente per archiviare e restituire dati. Di seguito è riportato un elenco di tipi e delle relative categorizzazioni:
+ **Oggetti**: un oggetto contiene campi che descrivono un'entità. Ad esempio, un oggetto potrebbe essere qualcosa come un oggetto `book` con campi che ne descrivono le caratteristiche come `authorName``publishingYear`, ecc. Sono strettamente tipi di output.
+ **Scalari**: sono tipi primitivi come int, string, ecc. In genere vengono assegnati ai campi. Usando il `authorName` campo come esempio, potrebbe essere assegnato lo `String` scalare per memorizzare un nome come «John Smith». Gli scalari possono essere sia di tipo di input che di output.
+ **Ingressi**: gli input consentono di passare un gruppo di campi come argomento. Sono strutturati in modo molto simile agli oggetti, ma possono essere passati come argomenti a oggetti speciali. Gli input consentono di definire scalari, enumerazioni e altri input nel relativo ambito. Gli input possono essere solo tipi di input.
+ **Oggetti speciali**: gli oggetti speciali eseguono operazioni di modifica dello stato e svolgono la maggior parte del lavoro pesante del servizio. Esistono tre tipi di oggetti speciali: interrogazione, mutazione e sottoscrizione. Le query in genere recuperano i dati; le mutazioni manipolano i dati; le sottoscrizioni si aprono e mantengono una connessione bidirezionale tra client e server per una comunicazione costante. Gli oggetti speciali non vengono né input né output date le loro funzionalità.
+ Enumerazioni: **le enumerazioni** sono elenchi predefiniti di valori legali. Se chiami un enum, i suoi valori possono essere solo quelli definiti nel suo ambito. Ad esempio, se aveste un enum chiamato che `trafficLights` rappresenta un elenco di segnali stradali, potrebbe avere valori come `redLight` e `greenLight` ma no. `purpleLight` Un vero semaforo avrà solo un certo numero di segnali, quindi puoi usare l'enum per definirli e forzarli a essere gli unici valori legali durante il riferimento. `trafficLight` Gli enum possono essere sia di tipo di input che di output.
+ **Unioni/interfacce**: le unioni consentono di restituire uno o più elementi in una richiesta a seconda dei dati richiesti dal client. Ad esempio, se si dispone `Book` di un tipo con un `title` campo e un `Author` tipo con un `name` campo, è possibile creare un'unione tra entrambi i tipi. *Se il cliente volesse cercare in un database la frase «Giulio Cesare», il sindacato potrebbe restituire *Giulio Cesare* (l'opera di William Shakespeare) tratto da `Book` `title` e *Giulio Cesare* (l'autore di Commentarii de Bello Gallico) dal.* `Author` `name` Le unioni possono essere solo tipi di output.

  Le interfacce sono insiemi di campi che gli oggetti devono implementare. È un po' simile alle interfacce nei linguaggi di programmazione come Java, in cui è necessario implementare i campi definiti nell'interfaccia. Ad esempio, supponiamo che tu abbia creato un'interfaccia chiamata `Book` che contenesse un `title` campo. Supponiamo che in seguito tu `Novel` abbia creato un tipo chiamato implementato`Book`. `Novel`Dovresti includere un `title` campo. Tuttavia, `Novel` potresti includere anche altri campi non presenti nell'interfaccia come `pageCount` o`ISBN`. Le interfacce possono essere solo tipi di output.

Le sezioni seguenti spiegheranno come funziona ogni tipo in GraphQL.

## Oggetti
<a name="object-components"></a>

Gli oggetti GraphQL sono il tipo principale che vedrai nel codice di produzione. In GraphQL, puoi pensare a un oggetto come a un raggruppamento di campi diversi (simili alle variabili in altri linguaggi), con ogni campo definito da un tipo (tipicamente uno scalare o un altro oggetto) che può contenere un valore. Gli oggetti rappresentano un'unità di dati che può retrieved/manipulated provenire dall'implementazione del servizio.

I tipi di oggetti vengono dichiarati utilizzando la `Type` parola chiave. Modifichiamo leggermente il nostro esempio di schema:

```
type Person {
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}

type Occupation {
  title: String
}
```

I tipi di oggetti qui sono `Person` e`Occupation`. Ogni oggetto ha i propri campi con i propri tipi. Una caratteristica di GraphQL è la possibilità di impostare campi su altri tipi. Puoi vedere che il `occupation` campo `Person` contiene un tipo di `Occupation` oggetto. Possiamo fare questa associazione perché GraphQL descrive solo i dati e non l'implementazione del servizio.

## Scalari
<a name="scalar-components"></a>

Gli scalari sono essenzialmente tipi primitivi che contengono valori. Nel AWS AppSync, esistono due tipi di scalari: gli scalari e gli AWS AppSync scalari GraphQL predefiniti. Gli scalari vengono in genere utilizzati per memorizzare i valori dei campi all'interno dei tipi di oggetti. I tipi GraphQL predefiniti includono`Int`,`Float`, `String``Boolean`, e. `ID` Usiamo nuovamente l'esempio precedente:

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}

type Occupation {
  title: String
}
```

Individuando i `title` campi `name` e, entrambi contengono uno `String` scalare. `Name`potrebbe restituire un valore di stringa come "`John Smith`" e il titolo potrebbe restituire qualcosa come "»`firefighter`. Alcune implementazioni GraphQL supportano anche scalari personalizzati che utilizzano la `Scalar` parola chiave e implementano il comportamento del tipo. Tuttavia, AWS AppSync attualmente **non supporta** scalari personalizzati. Per un elenco di scalari, vedi Tipi [scalari](https://docs.aws.amazon.com//appsync/latest/devguide/scalars.html) in. AWS AppSync

## Input
<a name="input-components"></a>

A causa del concetto di tipi di input e output, esistono alcune restrizioni quando si passano argomenti. I tipi che di solito devono essere passati, in particolare gli oggetti, sono limitati. È possibile utilizzare il tipo di input per aggirare questa regola. Gli input sono tipi che contengono scalari, enumerazioni e altri tipi di input.

Gli input sono definiti utilizzando la parola chiave: `input`

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}

type Occupation {
  title: String
}

input personInput { 
  id: ID!
  name: String
  age: Int
  occupation: occupationInput
}

input occupationInput {
  title: String
}
```

Come puoi vedere, possiamo avere input separati che imitano il tipo originale. Questi input verranno spesso utilizzati nelle operazioni sul campo in questo modo:

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}

type Occupation {
  title: String
}

input occupationInput {
  title: String
}

type Mutation {
  addPerson(id: ID!, name: String, age: Int, occupation: occupationInput): Person
}
```

Nota come stiamo ancora passando `occupationInput` al posto di `Occupation` creare un`Person`. 

Questo è solo uno scenario per gli input. Non hanno necessariamente bisogno di copiare gli oggetti in scala 1:1e, nel codice di produzione, molto probabilmente non lo userete in questo modo. È buona norma sfruttare gli schemi GraphQL definendo solo ciò che è necessario inserire come argomenti.

Inoltre, gli stessi input possono essere utilizzati in più operazioni, ma non è consigliabile farlo. Ogni operazione dovrebbe idealmente contenere una propria copia unica degli input nel caso in cui i requisiti dello schema cambino.

## Oggetti speciali
<a name="special-object-components"></a>

GraphQL riserva alcune parole chiave per oggetti speciali che definiscono alcune delle logiche aziendali relative al modo in cui lo schema utilizzerà retrieve/manipulate i dati. Al massimo, può esserci una di queste parole chiave in uno schema. Fungono da punti di ingresso per tutti i dati richiesti che i tuoi clienti eseguono sul tuo servizio GraphQL. 

Gli oggetti speciali vengono definiti anche utilizzando la `type` parola chiave. Sebbene vengano utilizzati in modo diverso dai normali tipi di oggetti, la loro implementazione è molto simile.

------
#### [ Queries ]

Le query sono molto simili alle `GET` operazioni in quanto eseguono un recupero di sola lettura per ottenere dati dalla fonte. In GraphQL, `Query` definisce tutti i punti di ingresso per i client che effettuano richieste verso il tuo server. Ci sarà sempre un'implementazione GraphQL `Query` nella tua implementazione GraphQL.

Ecco i `Query` tipi di oggetti modificati che abbiamo usato nel nostro precedente esempio di schema:

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}
type Occupation {
  title: String
}
type Query {                                   
  people: [Person]
}
```

Il nostro `Query` contiene un campo chiamato `people` che restituisce un elenco di `Person` istanze dalla fonte di dati. Supponiamo di dover modificare il comportamento della nostra applicazione e ora dobbiamo restituire un elenco delle sole `Occupation` istanze per uno scopo separato. Potremmo semplicemente aggiungerlo alla query:

```
type Query {                                   
  people: [Person]
  occupations: [Occupation]
}
```

In GraphQL, possiamo trattare la nostra query come l'unica fonte di richieste. Come puoi vedere, questo è potenzialmente molto più semplice RESTful delle implementazioni che potrebbero utilizzare endpoint diversi per ottenere lo stesso risultato (e). `.../api/1/people` `.../api/1/occupations`

Supponendo di avere un'implementazione del resolver per questa query, ora possiamo eseguire una query vera e propria. Sebbene il `Query` tipo esista, dobbiamo chiamarlo esplicitamente affinché venga eseguito nel codice dell'applicazione. Questo può essere fatto usando la `query` parola chiave:

```
query getItems {
   people {
      name
   }
   occupations {
      title
   }
}
```

Come puoi vedere, questa query viene chiamata `getItems` e restituisce `people` (un elenco di `Person` oggetti) e `occupations` (un elenco di `Occupation` oggetti). Nel`people`, stiamo restituendo solo il `name` campo di ciascuno`Person`, mentre stiamo restituendo il `title` campo di ciascuno`Occupation`. La risposta potrebbe essere simile a questa:

```
{
  "data": {
    "people": [
      {
        "name": "John Smith"
      },
      {
        "name": "Andrew Miller"
      },
      .
      .
      .
    ],
    "occupations": [
      {
        "title": "Firefighter"
      },
      {
        "title": "Bookkeeper"
      },
      .
      .
      .
    ]
  }
}
```

La risposta di esempio mostra come i dati seguono la forma della query. Ogni voce recuperata viene elencata nell'ambito del campo. `people`e `occupations` stanno restituendo le cose come elenchi separati. Sebbene utile, potrebbe essere più comodo modificare la query per restituire un elenco di nomi e occupazioni delle persone:

```
query getItems {
   people {
      name   
      occupation {
        title
      }
}
```

Questa è una modifica legale perché il nostro `Person` tipo contiene un `occupation` campo di tipo`Occupation`. Se elencati nell'ambito di`people`, restituiamo ciascuno `Person` di essi `name` insieme a quello associato `Occupation` da`title`. La risposta potrebbe essere simile a questa:

```
}
  "data": {
    "people": [
      {
        "name": "John Smith",
        "occupation": {
          "title": "Firefighter"
        }
      },
      {
        "name": "Andrew Miller",
        "occupation": {
          "title": "Bookkeeper"
        }
      },
      .
      .
      .
    ]
  }
}
```

------
#### [ Mutations ]

Le mutazioni sono simili a operazioni che cambiano lo stato come o`PUT`. `POST` Eseguono un'operazione di scrittura per modificare i dati nell'origine, quindi recuperano la risposta. Definiscono i punti di ingresso per le richieste di modifica dei dati. A differenza delle query, una mutazione può essere inclusa o meno nello schema a seconda delle esigenze del progetto. Ecco la mutazione dall'esempio dello schema:

```
type Mutation {
  addPerson(id: ID!, name: String, age: Int): Person
}
```

Il `addPerson` campo rappresenta un punto di ingresso che aggiunge un `Person` all'origine dati. `addPerson`è il nome del campo;`id`,`name`, e `age` sono i parametri; ed `Person` è il tipo restituito. Guardando indietro al `Person` tipo:

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}
```

Abbiamo aggiunto il `occupation` campo. Tuttavia, non possiamo impostare questo campo su `Occupation` direttamente perché gli oggetti non possono essere passati come argomenti; sono strettamente tipi di output. Dovremmo invece passare un input con gli stessi campi di un argomento:

```
input occupationInput {
  title: String
}
```

 Possiamo anche aggiornare facilmente il nostro `addPerson` per includerlo come parametro quando creiamo nuove `Person` istanze:

```
type Mutation {
  addPerson(id: ID!, name: String, age: Int, occupation: occupationInput): Person
}
```

Ecco lo schema aggiornato:

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}

type Occupation {
  title: String
}

input occupationInput {
  title: String
}

type Mutation {
  addPerson(id: ID!, name: String, age: Int, occupation: occupationInput): Person
}
```

Nota che `occupation` passerà nel `title` campo da `occupationInput` per completare la creazione dell'oggetto `Person` anziché dell'`Occupation`oggetto originale. Supponendo di avere un'implementazione del resolver per`addPerson`, ora possiamo eseguire una mutazione effettiva. Sebbene il `Mutation` tipo esista, dobbiamo chiamarlo esplicitamente affinché venga eseguito nel codice dell'applicazione. Questo può essere fatto usando la `mutation` parola chiave:

```
mutation createPerson {
  addPerson(id: ID!, name: String, age: Int, occupation: occupationInput) {
    name
    age
    occupation {
      title
    }
  }
}
```

Questa mutazione si chiama`createPerson`, ed `addPerson` è l'operazione. Per crearne una nuova`Person`, possiamo inserire gli argomenti per`id`, `name``age`, e`occupation`. Nell'ambito di`addPerson`, possiamo vedere anche altri campi come `name``age`, ecc. Questa è la tua risposta; questi sono i campi che verranno restituiti al termine dell'`addPerson`operazione. Ecco la parte finale dell'esempio:

```
mutation createPerson {
  addPerson(id: "1", name: "Steve Powers", age: "50", occupation: "Miner") {
    id
    name
    age
    occupation {
      title
    }
  }
}
```

Utilizzando questa mutazione, un risultato potrebbe essere simile al seguente:

```
{
  "data": {
    "addPerson": {
      "id": "1",
      "name": "Steve Powers",
      "age": "50",
      "occupation": {
        "title": "Miner"
      }
    }
  }
}
```

Come puoi vedere, la risposta ha restituito i valori richiesti nello stesso formato definito nella nostra mutazione. È buona norma restituire tutti i valori che sono stati modificati per ridurre la confusione e la necessità di ulteriori query in futuro. Le mutazioni consentono di includere più operazioni nel suo ambito. Verranno eseguite in sequenza nell'ordine indicato nella mutazione. Ad esempio, se creiamo un'altra operazione chiamata `addOccupation` che aggiunge titoli di lavoro all'origine dati, possiamo richiamarla nella mutazione successiva. `addPerson` `addPerson`verrà gestito per primo seguito da. `addOccupation`

------
#### [ Subscriptions ]

Gli abbonamenti vengono utilizzati [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications)per aprire una connessione bidirezionale duratura tra il server e i suoi client. In genere, un client si iscrive o ascolta il server. Ogni volta che il server apporta una modifica sul lato server o esegue un evento, il client sottoscritto riceverà gli aggiornamenti. Questo tipo di protocollo è utile quando sono sottoscritti più client e devono essere avvisati delle modifiche che avvengono nel server o in altri client. Ad esempio, gli abbonamenti possono essere utilizzati per aggiornare i feed dei social media. Potrebbero esserci due utenti, l'utente A e l'utente B, entrambi abbonati agli aggiornamenti automatici delle notifiche ogni volta che ricevono messaggi diretti. L'utente A sul client A potrebbe inviare un messaggio diretto all'utente B sul client B. Il client dell'utente A invierebbe il messaggio diretto, che verrebbe elaborato dal server. Il server invierebbe quindi il messaggio diretto all'account dell'utente B inviando una notifica automatica al client B.

Ecco un esempio di a `Subscription` che potremmo aggiungere all'esempio dello schema:

```
type Subscription {                                   
  personAdded: Person
}
```

Il `personAdded` campo invierà un messaggio ai clienti abbonati ogni volta che ne `Person` viene aggiunto uno nuovo alla fonte di dati. Supponendo di avere un'implementazione del resolver per`personAdded`, ora possiamo usare l'abbonamento. Sebbene il `Subscription` tipo esista, dobbiamo chiamarlo esplicitamente affinché venga eseguito nel codice dell'applicazione. Questo può essere fatto usando la `subscription` parola chiave:

```
subscription personAddedOperation {
  personAdded {
    id
    name
  }
}
```

L'abbonamento viene chiamato `personAddedOperation` e l'operazione è`personAdded`. `personAdded`restituirà i `name` campi `id` e delle nuove `Person` istanze. Guardando l'esempio di mutazione, abbiamo aggiunto un'operazione che `Person` utilizza questa:

```
addPerson(id: "1", name: "Steve Powers", age: "50", occupation: "Miner")
```

Se i nostri clienti erano abbonati agli aggiornamenti di quelli appena aggiunti`Person`, potrebbero vederlo dopo l'`addPerson`esecuzione:

```
{
  "data": {
    "personAdded": {
      "id": "1",
      "name": "Steve Powers"
    }
  }
}
```

Di seguito è riportato un riepilogo di ciò che offrono gli abbonamenti:

Gli abbonamenti sono canali bidirezionali che consentono al client e al server di ricevere aggiornamenti rapidi ma costanti. In genere utilizzano il WebSocket protocollo, che crea connessioni standardizzate e sicure.

Gli abbonamenti sono agili in quanto riducono il sovraccarico di configurazione della connessione. Una volta sottoscritto, un cliente può continuare a utilizzare tale abbonamento per lunghi periodi di tempo. In genere utilizzano le risorse informatiche in modo efficiente, consentendo agli sviluppatori di personalizzare la durata dell'abbonamento e di configurare le informazioni richieste.

In generale, gli abbonamenti consentono al cliente di effettuare più abbonamenti contemporaneamente. Per quanto riguarda AWS AppSync, gli abbonamenti vengono utilizzati solo per ricevere aggiornamenti in tempo reale dal servizio. AWS AppSync Non possono essere utilizzati per eseguire interrogazioni o mutazioni.

L'alternativa principale agli abbonamenti è il polling, che invia interrogazioni a intervalli prestabiliti per richiedere dati. Questo processo è in genere meno efficiente degli abbonamenti e mette a dura prova sia il client che il backend.

------

Una cosa che non è stata menzionata nel nostro esempio di schema è il fatto che anche i tipi di oggetti speciali devono essere definiti in una `schema` radice. Quindi, quando esporti uno schema in AWS AppSync, potrebbe assomigliare a questo:

------
#### [ schema.graphql ]

```
schema {
  query: Query
  mutation: Mutation
  subscription: Subscription
}

.
.
.

type Query {                                   
  # code goes here
}
type Mutation {                                   
  # code goes here
}
type Subscription {                                   
  # code goes here
}
```

------

## Enumerazioni
<a name="enum-components"></a>

Le enumerazioni, o enumerazioni, sono scalari speciali che limitano gli argomenti legali di un tipo o di un campo. Ciò significa che ogni volta che un enum viene definito nello schema, il tipo o il campo associato sarà limitato ai valori nell'enum. Gli enum sono serializzati come stringhe scalari. Nota che diversi linguaggi di programmazione possono gestire le enumerazioni GraphQL in modo diverso. Ad esempio, non JavaScript ha un supporto enum nativo, quindi i valori enum possono essere mappati invece su valori int.

Le enumerazioni vengono definite utilizzando la parola chiave. `enum` Ecco un esempio:

```
enum trafficSignals {
  solidRed
  solidYellow
  solidGreen
  greenArrowLeft
  ...
}
```

Quando si chiama l'`trafficLights`enum, gli argomenti possono essere solo`solidRed`, `solidYellow``solidGreen`, ecc. È comune usare le enumerazioni per rappresentare cose che hanno un numero distinto ma limitato di scelte.

## Unioni/interfacce
<a name="union-interface-components"></a>

Vedi [Interfacce e unioni in GraphQL](https://docs.aws.amazon.com/appsync/latest/devguide/interfaces-and-unions.html).

# Campi GraphQL
<a name="graphql-fields"></a>

I campi rientrano nell'ambito di un tipo e contengono il valore richiesto dal servizio GraphQL. Sono molto simili alle variabili di altri linguaggi di programmazione. Ad esempio, ecco un tipo di `Person` oggetto:

```
type Person {                                  
   name: String                                  
   age: Int
}
```

I campi in questo caso sono `name` e `age` e contengono rispettivamente un `String` e un `Int` valore. I campi oggetto come quelli mostrati sopra possono essere usati come input nei campi (operazioni) delle query e delle mutazioni. Ad esempio, vedi quanto segue: `Query`

```
type Query {                                   
  people: [Person]
}
```

Il `people` campo richiede tutte le istanze di `Person` dalla fonte di dati. Quando aggiungi o recuperi un file `Person` nel tuo server GraphQL, puoi aspettarti che i dati seguano il formato dei tuoi tipi e campi, ovvero la struttura dei tuoi dati nello schema determina come saranno strutturati nella tua risposta:

```
}
  "data": {
    "people": [
      {
        "name": "John Smith",
        "age": "50"
      },
      {
        "name": "Andrew Miller",
        "age": "60"
      },
      .
      .
      .
    ]
  }
}
```

I campi svolgono un ruolo importante nella strutturazione dei dati. Di seguito sono illustrate un paio di proprietà aggiuntive che possono essere applicate ai campi per una maggiore personalizzazione.

## Elenchi
<a name="list-components"></a>

Gli elenchi restituiscono tutti gli elementi di un tipo specificato. È possibile aggiungere un elenco al tipo di campo utilizzando le parentesi`[]`: 

```
type Person { 
  name: String
  age: Int
}
type Query {                                   
  people: [Person]
}
```

In`Query`, le parentesi che lo circondano `Person` indicano che si desidera restituire tutte le istanze di `Person` dalla fonte di dati come matrice. Nella risposta, i `age` valori `name` e di ciascuno `Person` verranno restituiti come un unico elenco delimitato:

```
}
  "data": {
    "people": [
      {
        "name": "John Smith",         # Data of Person 1
        "age": "50"
      },
      {
        "name": "Andrew Miller",      # Data of Person 2
        "age": "60"
      },
      .                               # Data of Person N
      .
      .
    ]
  }
}
```

Non sei limitato a tipi di oggetti speciali. È inoltre possibile utilizzare elenchi nei campi dei tipi di oggetti normali.

## Non-null
<a name="non-null-components"></a>

I valori non nulli indicano un campo che non può essere nullo nella risposta. È possibile impostare un campo su un valore diverso da nullo utilizzando il simbolo: `!`

```
type Person { 
  name: String!
  age: Int
}
type Query {                                   
  people: [Person]
}
```

Il `name` campo non può essere esplicitamente nullo. Se dovessi interrogare l'origine dati e fornissi un input nullo per questo campo, verrebbe generato un errore.

È possibile combinare elenchi e valori non nulli. Confronta queste domande:

```
type Query {                                   
  people: [Person!]      # Use case 1
}

.
.
.

type Query {                                   
  people: [Person]!      # Use case 2
}

.
.
.

type Query {                                   
  people: [Person!]!     # Use case 3
}
```

Nel caso d'uso 1, l'elenco non può contenere elementi nulli. Nel caso d'uso 2, l'elenco stesso non può essere impostato su null. Nel caso d'uso 3, l'elenco e i relativi elementi non possono essere nulli. Tuttavia, in ogni caso, è comunque possibile restituire elenchi vuoti.

Come puoi vedere, ci sono molti componenti mobili in GraphQL. In questa sezione, abbiamo mostrato la struttura di uno schema semplice e i diversi tipi e campi supportati da uno schema. Nella sezione seguente, scoprirai gli altri componenti di un'API GraphQL e come funzionano con lo schema.

# Fonti di dati
<a name="data-source-components"></a>

Nella sezione precedente, abbiamo appreso che uno schema definisce la forma dei dati. Tuttavia, non abbiamo mai spiegato da dove provenissero quei dati. Nei progetti reali, lo schema è come un gateway che gestisce tutte le richieste fatte al server. Quando viene effettuata una richiesta, lo schema funge da singolo endpoint che si interfaccia con il client. Lo schema accederà, elaborerà e inoltrerà i dati dalla fonte dati al client. Guarda l'infografica qui sotto:

![\[GraphQL schema integrating multiple Servizi AWS for a single endpoint API architecture.\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/images/aws-flow-infographic.png)


AWS AppSync e GraphQL implementano in modo eccellente le soluzioni Backend For Frontend (BFF). Lavorano in tandem per ridurre la complessità su larga scala astraendo il backend. Se il tuo servizio utilizza diverse fonti di dati e/o microservizi, puoi essenzialmente eliminare parte della complessità definendo la forma dei dati di ciascuna fonte (sottografo) in un unico schema (supergrafo). Ciò significa che l'API GraphQL non si limita a utilizzare un'unica fonte di dati. Puoi associare un numero qualsiasi di fonti di dati all'API GraphQL e specificare nel codice come interagiranno con il servizio.

Come puoi vedere nell'infografica, lo schema GraphQL contiene tutte le informazioni di cui i client hanno bisogno per richiedere dati. Ciò significa che tutto può essere elaborato in un'unica richiesta anziché in più richieste come nel caso di REST. Queste richieste passano attraverso lo schema, che è l'unico endpoint del servizio. Quando le richieste vengono elaborate, un resolver (spiegato nella sezione successiva) esegue il proprio codice per elaborare i dati dalla fonte di dati pertinente. Quando viene restituita la risposta, il sottografo collegato all'origine dati verrà popolato con i dati dello schema. 

AWS AppSync supporta molti tipi di fonti di dati diversi. Nella tabella seguente, descriveremo ogni tipo, elencheremo alcuni dei vantaggi di ciascuno e forniremo link utili per un contesto aggiuntivo.


| Origine dati | Description | Vantaggi | Informazioni supplementari | 
| --- | --- | --- | --- | 
| Amazon DynamoDB | «Amazon DynamoDB è un servizio di database NoSQL completamente gestito che offre prestazioni veloci e prevedibili con una scalabilità perfetta. DynamoDB consente di scaricare gli oneri di gestione e dimensionamento di un database distribuito in modo da non doversi più preoccupare di provisioning dell'hardware, installazione e configurazione, replica, applicazione di patch al software e dimensionamento del cluster. DynamoDB offre anche la crittografia a riposo, che elimina l'onere operativo e la complessità associati alla protezione dei dati sensibili». |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/data-source-components.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/data-source-components.html)  | 
| AWS Lambda | "AWS Lambda è un servizio di elaborazione che consente di eseguire codice senza effettuare il provisioning o la gestione di server.Lambda esegue il codice su un'infrastruttura di elaborazione ad alta disponibilità e gestisce tutta l'amministrazione delle risorse di elaborazione, compresa la manutenzione del server e del sistema operativo, il provisioning e la scalabilità automatica della capacità e la registrazione. Con Lambda, tutto ciò che devi fare è fornire il codice in uno dei runtime linguistici supportati da Lambda». |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/data-source-components.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/data-source-components.html)  | 
| OpenSearch | «Amazon OpenSearch Service è un servizio gestito che semplifica l'implementazione, il funzionamento e la scalabilità OpenSearch dei cluster nel AWS cloud. Amazon OpenSearch Service supporta un sistema operativo OpenSearch Elasticsearch legacy (fino alla versione 7.10, l'ultima versione open source del software). Quando si crea un cluster, è possibile scegliere il motore di ricerca da usare.**OpenSearch**è un motore di ricerca e analisi completamente open source per casi d'uso come l'analisi dei log, il monitoraggio delle applicazioni in tempo reale e l'analisi dei clickstream. Per ulteriori informazioni, consulta la [documentazione relativa ad OpenSearch](https://opensearch.org/docs/).**Amazon OpenSearch Service fornisce** tutte le risorse per il OpenSearch cluster e lo avvia. Inoltre, rileva e sostituisce automaticamente i nodi di OpenSearch servizio guasti, riducendo il sovraccarico associato alle infrastrutture autogestite. Puoi scalare il tuo cluster con una singola chiamata API o pochi clic nella console». |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/data-source-components.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/data-source-components.html)  | 
| Endpoint HTTP | Puoi utilizzare gli endpoint HTTP come fonti di dati. AWS AppSync può inviare richieste agli endpoint con le informazioni pertinenti come parametri e payload. La risposta HTTP verrà esposta al resolver, che restituirà la risposta finale al termine delle sue operazioni. |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/data-source-components.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/data-source-components.html)  | 
| Amazon EventBridge | "EventBridge è un servizio serverless che utilizza gli eventi per connettere tra loro i componenti delle applicazioni, semplificando la creazione di applicazioni scalabili basate sugli eventi. Utilizzatelo per indirizzare gli eventi da fonti quali applicazioni, AWS servizi e software di terze parti sviluppati internamente alle applicazioni destinate ai consumatori all'interno dell'organizzazione. EventBridge offre un modo semplice e coerente per importare, filtrare, trasformare e fornire eventi in modo da poter creare nuove applicazioni rapidamente». |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/data-source-components.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/data-source-components.html)  | 
| Database relazionali | «Amazon Relational Database Service (Amazon RDS) è un servizio Web che semplifica la configurazione, il funzionamento e la scalabilità di un database relazionale nel cloud. AWS Fornisce una capacità ridimensionabile e conveniente per un database relazionale standard del settore e gestisce le attività comuni di amministrazione dei database». |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/data-source-components.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/data-source-components.html)  | 
| Nessuna fonte di dati | Se non hai intenzione di utilizzare un servizio di origine dati, puoi impostarlo sunone. Una fonte di none dati, sebbene sia ancora esplicitamente classificata come fonte di dati, non è un supporto di archiviazione. Nonostante ciò, è ancora utile in alcuni casi per la manipolazione e il trasferimento dei dati. |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/data-source-components.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/data-source-components.html)  | 

**Suggerimento**  
Per ulteriori informazioni su come interagiscono le sorgenti di dati AWS AppSync, consulta [Allegare un'](https://docs.aws.amazon.com//appsync/latest/devguide/attaching-a-data-source.html)origine dati.

# Risolutori
<a name="resolver-components"></a>

Nelle sezioni precedenti, hai appreso i componenti dello schema e dell'origine dati. Ora, dobbiamo affrontare il modo in cui lo schema e le fonti di dati interagiscono. Tutto inizia con il resolver.

Un resolver è un'unità di codice che gestisce il modo in cui i dati di quel campo verranno risolti quando viene effettuata una richiesta al servizio. I resolver sono associati a campi specifici all'interno dei tipi dello schema. Sono più comunemente usati per implementare le operazioni di modifica dello stato per le operazioni sui campi di interrogazione, mutazione e sottoscrizione. Il resolver elaborerà la richiesta del client, quindi restituirà il risultato, che può essere un gruppo di tipi di output come oggetti o scalari:

![\[GraphQL schema with resolvers connecting to various AWS data sources for a single endpoint.\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/images/aws-flow-infographic.png)


## Runtime del resolver
<a name="resolver-components-runtime"></a>

In AWS AppSync, devi prima specificare un runtime per il tuo resolver. Un runtime del resolver indica l'ambiente in cui viene eseguito un resolver. Determina anche la lingua in cui verranno scritti i resolver. AWS AppSync attualmente supporta APPSYNC\$1JS for JavaScript e Velocity Template Language (VTL). [Vedi le [funzionalità JavaScript di runtime per i resolver e le funzioni per o il riferimento all'utilità dei modelli di mappatura Resolver](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference-js.html) per JavaScript VTL.](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference.html)

## Struttura del resolver
<a name="resolver-components-structure"></a>

Dal punto di vista del codice, i resolver possono essere strutturati in un paio di modi. ****Esistono resolver di unità e pipeline.****

### Risolver di unità
<a name="resolver-components-unit"></a>

Un resolver di unità è composto da codice che definisce un singolo gestore di richieste e risposte che vengono eseguiti su un'origine dati. Il gestore di richieste accetta un oggetto di contesto come argomento e restituisce il payload della richiesta utilizzato per chiamare l'origine dei dati. Il gestore della risposta riceve un payload dall'origine dati con il risultato della richiesta eseguita. Il gestore di risposte trasforma il payload in una risposta GraphQL per risolvere il campo GraphQL.

![\[GraphQL request flow showing request and response handlers interacting with a data source.\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/images/unit-resolver-js.png)


### Resolver per pipeline
<a name="resolver-components-pipeline"></a>

Quando si implementano i risolutori di pipeline, esiste una struttura generale che seguono:
+ **Prima della fase**: quando viene effettuata una richiesta dal client, ai resolver per i campi dello schema utilizzati (in genere le query, le mutazioni, le sottoscrizioni) vengono trasmessi i dati della richiesta. Il resolver inizierà a elaborare i dati della richiesta con un gestore del passaggio precedente, che consente di eseguire alcune operazioni di preelaborazione prima che i dati passino attraverso il resolver.
+ **Funzione/i**: dopo l'esecuzione del passaggio precedente, la richiesta viene passata all'elenco delle funzioni. La prima funzione dell'elenco verrà eseguita sulla fonte di dati. Una funzione è un sottoinsieme del codice del resolver contenente il proprio gestore di richieste e risposte. Un gestore di richieste raccoglierà i dati della richiesta ed eseguirà operazioni sulla fonte dei dati. Il gestore della risposta elaborerà la risposta dell'origine dati prima di restituirla all'elenco. Se è presente più di una funzione, i dati della richiesta verranno inviati alla funzione successiva nell'elenco da eseguire. Le funzioni nell'elenco verranno eseguite in serie nell'ordine definito dallo sviluppatore. Una volta eseguite tutte le funzioni, il risultato finale viene passato alla fase successiva.
+ **Dopo la fase**: la fase successiva è una funzione di gestione che consente di eseguire alcune operazioni finali sulla risposta finale della funzione prima di passarla alla risposta GraphQL.

![\[GraphQL request flow diagram showing interactions between request, data sources, and response components.\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/images/appsync-js-resolver-logic.png)


## Struttura del gestore Resolver
<a name="resolver-components-handlers"></a>

I gestori sono in genere funzioni chiamate e: `Request` `Response`

```
export function request(ctx) {
    // Code goes here
}

export function response(ctx) {
    // Code goes here
}
```

In un risolutore di unità, ci sarà solo un set di queste funzioni. In un resolver a pipeline, ci sarà un set di queste per la fase prima e dopo e un set aggiuntivo per funzione. Per vedere come potrebbe apparire, esaminiamo un tipo semplice: `Query`

```
type Query {
	helloWorld: String!
}
```

Questa è una semplice interrogazione con un campo chiamato `helloWorld` of type`String`. Supponiamo di voler sempre che questo campo restituisca la stringa «Hello World». Per implementare questo comportamento, dobbiamo aggiungere il resolver a questo campo. In un risolutore di unità, potremmo aggiungere qualcosa del genere:

```
export function request(ctx) {
    return {}
}

export function response(ctx) {
    return "Hello World"
}
```

`request`Può semplicemente essere lasciato vuoto perché non stiamo richiedendo o elaborando dati. Possiamo anche supporre che la nostra fonte di dati sia`None`, indicando che questo codice non deve eseguire alcuna chiamata. La risposta restituisce semplicemente «Hello World». Per testare questo resolver, dobbiamo fare una richiesta utilizzando il tipo di query:

```
query helloWorldTest {
  helloWorld
}
```

Questa è una query chiamata `helloWorldTest` che restituisce il `helloWorld` campo. Quando viene eseguito, il `helloWorld` field resolver esegue e restituisce anche la risposta:

```
{
  "data": {
    "helloWorld": "Hello World"
  }
}
```

Restituire costanti come questa è la cosa più semplice che si possa fare. In realtà, restituirai input, elenchi e altro. Ecco un esempio più complicato:

```
type Book {
  id: ID!
  title: String
}

type Query {
  getBooks: [Book]
}
```

Qui stiamo restituendo un elenco di`Books`. Supponiamo di utilizzare una tabella DynamoDB per archiviare i dati dei libri. I nostri gestori potrebbero avere il seguente aspetto:

```
/**
 * Performs a scan on the dynamodb data source
 */
export function request(ctx) {
  return { operation: 'Scan' };
}

/**
 * return a list of scanned post items
 */
export function response(ctx) {
  return ctx.result.items;
}
```

La nostra richiesta ha utilizzato un'operazione di scansione integrata per cercare tutte le voci della tabella, memorizzato i risultati nel contesto e quindi li ha passati alla risposta. La risposta ha preso gli elementi del risultato e li ha restituiti nella risposta:

```
{
  "data": {
    "getBooks": {
      "items": [
        {
          "id": "abcdefgh-1234-1234-1234-abcdefghijkl",
          "title": "book1"
        },
        {
          "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
          "title": "book2"
        },

        ...

      ]
    }
  }
}
```

## Contesto del risolutore
<a name="resolver-components-context"></a>

In un resolver, ogni fase della catena di gestori deve essere a conoscenza dello stato dei dati dei passaggi precedenti. Il risultato di un gestore può essere memorizzato e passato a un altro come argomento. GraphQL definisce quattro argomenti di base del resolver:


****  

| Argomenti di base del resolver | Description | 
| --- | --- | 
| obj, root, parent e così via. | Il risultato del genitore. | 
| args | Gli argomenti forniti al campo nella query GraphQL. | 
| context | Un valore che viene fornito a ogni resolver e contiene importanti informazioni contestuali come l'utente attualmente connesso o l'accesso a un database. | 
| info | Un valore che contiene informazioni specifiche sul campo relative alla query corrente e i dettagli dello schema. | 

Nel AWS AppSync, l'argomento `[context](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html)` (ctx) può contenere tutti i dati sopra menzionati. È un oggetto creato su richiesta e contiene dati come credenziali di autorizzazione, dati sui risultati, errori, metadati di richiesta, ecc. Il contesto è un modo semplice per i programmatori di manipolare i dati provenienti da altre parti della richiesta. Riprendi questo frammento:

```
/**
 * Performs a scan on the dynamodb data source
 */
export function request(ctx) {
  return { operation: 'Scan' };
}

/**
 * return a list of scanned post items
 */
export function response(ctx) {
  return ctx.result.items;
}
```

Alla richiesta viene fornito il contesto (ctx) come argomento; questo è lo stato della richiesta. Esegue una scansione di tutti gli elementi di una tabella, quindi memorizza il risultato nel contesto in`result`. Il contesto viene quindi passato all'argomento response, che accede a `result` e ne restituisce il contenuto.

## Richieste e analisi
<a name="resolver-ast"></a>

Quando si effettua una query sul servizio GraphQL, questa deve essere sottoposta a un processo di analisi e convalida prima di essere eseguita. La tua richiesta verrà analizzata e tradotta in un albero di sintassi astratto. Il contenuto dell'albero viene convalidato eseguendo diversi algoritmi di convalida rispetto allo schema. Dopo la fase di convalida, i nodi dell'albero vengono attraversati ed elaborati. I resolver vengono richiamati, i risultati vengono archiviati nel contesto e viene restituita la risposta. Ad esempio, prendiamo questa query:

```
query {
  Person {  //object type
    name  //scalar
    age   //scalar
  } 
}
```

Stiamo tornando `Person` con i campi a e. `name` `age` Quando si esegue questa query, l'albero avrà un aspetto simile a questo:

![\[Hierarchical diagram showing query, Person, name, and age nodes connected by arrows.\]](http://docs.aws.amazon.com/it_it/appsync/latest/devguide/images/ast-1.png)


Dall'albero, sembra che questa richiesta cercherà la radice di `Query` nello schema. All'interno della query, il `Person` campo verrà risolto. Dagli esempi precedenti, sappiamo che questo potrebbe essere un input dell'utente, un elenco di valori, ecc. `Person` è molto probabilmente legato a un tipo di oggetto che contiene i campi di cui abbiamo bisogno (`name`e`age`). Una volta trovati, questi due campi secondari vengono risolti nell'ordine indicato (`name`seguiti da`age`). Una volta che l'albero è stato completamente risolto, la richiesta viene completata e verrà rispedita al client.

# Proprietà aggiuntive di GraphQL
<a name="graphql-properties"></a>

GraphQL è costituito da diversi principi di progettazione per mantenere la semplicità e la robustezza su larga scala.

## Dichiarativo
<a name="declarative-property"></a>

GraphQL è dichiarativo, il che significa che l'utente descriverà (modellerà) i dati dichiarando solo i campi su cui desidera interrogare. La risposta restituirà solo i dati per queste proprietà. Ad esempio, ecco un'operazione che recupera un `Book` oggetto in una tabella DynamoDB con il valore ISBN 13 di: `id` *9780199536061*

```
{
  getBook(id: "9780199536061") {
    name
    year
    author
  }
}
```

La risposta restituirà i campi nel payload (`name``year`, e) e `author` nient'altro:

```
{
  "data": {
    "getBook": {
      "name": "Anna Karenina",
      "year": "1878",
      "author": "Leo Tolstoy",
    }
  }
}
```

Grazie a questo principio di progettazione, GraphQL elimina i problemi perenni di sovra-fetching e insufficiente che REST APIs affronta nei sistemi complessi. Ciò si traduce in una raccolta dati più efficiente e in prestazioni di rete migliorate.

## Gerarchico
<a name="hierarchical-property"></a>

GraphQL è flessibile in quanto i dati richiesti possono essere modellati dall'utente per soddisfare le esigenze dell'applicazione. I dati richiesti seguono sempre i tipi e la sintassi delle proprietà definite nell'API GraphQL. Ad esempio, il seguente frammento mostra l'`getBook`operazione con un nuovo campo denominato scope `quotes` che restituisce tutte le stringhe di virgolette e le pagine memorizzate collegate a: `Book` *9780199536061*

```
{
  getBook(id: "9780199536061") {
    name
    year
    author
    quotes {
      description
      page
    }
  }
}
```

L'esecuzione di questa query restituisce il seguente risultato:

```
{
  "data": {
    "getBook": {
      "name": "Anna Karenina",
      "year": "1878",
      "author": "Leo Tolstoy",
      "quotes": [
         {
            "description": "The highest Petersburg society is essentially one: in it everyone knows everyone else, everyone even visits everyone else.",
            "page": 135
         },
         { 
            "description": "Happy families are all alike; every unhappy family is unhappy in its own way.",
            "page": 1
         },
         {        
            "description": "To Konstantin, the peasant was simply the chief partner in their common labor.",
            "page": 251
         }
      ]
    }
  }
}
```

Come puoi vedere, i `quotes` campi collegati al libro richiesto sono stati restituiti come matrice nello stesso formato descritto dalla nostra query. Sebbene non sia stato mostrato qui, GraphQL ha l'ulteriore vantaggio di non essere esigente riguardo alla posizione dei dati che sta recuperando. `Books`e `quotes` potrebbero essere archiviati separatamente, ma GraphQL recupererà comunque le informazioni finché esiste l'associazione. Ciò significa che la tua query può recuperare moltitudini di dati autonomi in un'unica richiesta.

## Introspettiva
<a name="introspective-property"></a>

GraphQL è autodocumentante o introspettivo. Supporta diverse operazioni integrate che consentono agli utenti di visualizzare i tipi e i campi sottostanti all'interno dello schema. Ad esempio, ecco un `Foo` tipo con un `description` campo `date` and:

```
type Foo {
	date: String
	description: String
}
```

Potremmo usare l'`_type`operazione per trovare i metadati di digitazione sotto lo schema:

```
{
  __type(name: "Foo") {
    name                   # returns the name of the type
    fields {               # returns all fields in the type
      name                 # returns the name of each field
      type {               # returns all types for each field
        name               # returns the scalar type
      }
    }
  }
}
```

Ciò restituirà una risposta:

```
{
  "__type": {
    "name": "Foo",                     # The type name
    "fields": [
      {
        "name": "date",                # The date field
        "type": { "name": "String" }   # The date's type
      },
      {
        "name": "description",         # The description field
        "type": { "name": "String" }   # The description's type
      },
    ]
  }
}
```

Questa funzionalità può essere utilizzata per scoprire quali tipi e campi sono supportati da un particolare schema GraphQL. GraphQL supporta un'ampia varietà di queste operazioni introspettive. [Per ulteriori informazioni, consulta Introspection.](https://graphql.org/learn/introspection/)

## Digitazione forte
<a name="strong-typing-property"></a>

GraphQL supporta la digitazione avanzata tramite il suo sistema di tipi e campi. Quando definisci qualcosa nel tuo schema, deve avere un tipo che possa essere convalidato prima del runtime. Deve inoltre seguire le specifiche di sintassi di GraphQL. Questo concetto non è diverso dalla programmazione in altri linguaggi. Ad esempio, ecco il `Foo` tipo precedente:

```
type Foo {
	date: String
	description: String
}
```

Possiamo vedere che `Foo` è l'oggetto che verrà creato. All'interno di un'istanza di`Foo`, ci sarà un `description` campo `date` and, entrambi di tipo `String` primitivo (scalare). Sintatticamente, vediamo che `Foo` è stato dichiarato e i suoi campi esistono all'interno del suo ambito. Questa combinazione di controllo dei tipi e sintassi logica assicura che l'API GraphQL sia concisa e ovvia. [Le specifiche di digitazione e sintassi di GraphQL sono disponibili qui.](https://spec.graphql.org/)