

# SDK per la messaggistica client di Chat IVS - Tutorial per JavaScript, parte 1: chat room
<a name="chat-sdk-js-tutorial-chat-rooms"></a>

Questo è il primo di un tutorial a due parti. Scoprirai gli elementi essenziali per utilizzare l'SDK JavaScript per la messaggistica client di Amazon IVS Chat creando un'app funzionale completa utilizzando JavaScript/TypeScript. Chiameremo l'app *Chatterbox*.

Il pubblico di riferimento è costituito da sviluppatori esperti che non conoscono l'SDK di messaggistica di Amazon IVS Chat. Dovresti essere a tuo agio con il linguaggio di programmazione JavaScript/TypeScript e la libreria React.

Per brevità, faremo riferimento all'SDK JavaScript di messaggistica del client Amazon IVS Chat come a SDK JS Chat.

**Nota**: in alcuni casi, gli esempi di codice per JavaScript e TypeScript sono identici, quindi vengono combinati.

Questa prima parte del tutorial è suddivisa in diverse sezioni:

1. [Configurazione di un server di autenticazione/autorizzazione locale](#chat-js-rooms-auth-server)

1. [Creazione di un progetto Chatterbox](#chat-js-rooms-chatterbox)

1. [Connessione a una chat room](#chat-js-rooms-connect)

1. [Creazione di un provider di token](#chat-js-rooms-token-provider)

1. [Osservazione degli aggiornamenti della connessione](#chat-js-rooms-connection-state)

1. [Creazione di un componente del pulsante di invio](#chat-js-rooms-send-button)

1. [Creazione dell'input di un messaggio](#chat-js-rooms-message-input)

1. [Fasi successive](#chat-js-rooms-next-steps)

Per la documentazione completa dell'SDK, inizia con l'[SDK di messaggistica per client di chat Amazon IVS](chat-sdk.md) (qui nella *Guida per l'utente di Chat Amazon IVS*) e [Documentazione di riferimento dell'SDK di messaggistica per client di chat per JavaScript](https://aws.github.io/amazon-ivs-chat-messaging-sdk-js/latest/) su GitHub.

## Prerequisiti
<a name="chat-js-rooms-prerequisites"></a>
+ Acquisisci familiarità con JavaScript/TypeScript e la libreria React. Se non conosci React Native, scopri le nozioni basilari in questo [Tutorial tris](https://react.dev/learn/tutorial-tic-tac-toe).
+ Leggi e comprendi [Nozioni di base su Chat Amazon IVS](getting-started-chat.md).
+ Crea un utente AWS IAM con le capacità CreateChatToken e CreateRoom definite in una policy IAM esistente. Consultare . [Nozioni di base su Chat Amazon IVS](getting-started-chat.md).)
+ Assicurati che la chiavi di accesso segrete di questo utente siano archiviata in un file di credenziali AWS. Per istruzioni, consulta la [Guida per l'utente di AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) (in particolare la sezione [Configurazione e impostazioni del file delle credenziali](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html)).
+ Crea una chat room e salva il relativo ARN. Per informazioni, consulta [Nozioni di base su Chat Amazon IVS](getting-started-chat.md). (Se non salvi l'ARN, potrai cercarlo in un secondo momento con la console o l'API di Chat.)
+ Installa l'ambiente Node.js 14\$1 con il gestore di pacchetti NPM o Yarn.

## Configurazione di un server di autenticazione/autorizzazione locale
<a name="chat-js-rooms-auth-server"></a>

La tua applicazione di backend è responsabile sia della creazione di chat room che della generazione dei token di chat necessari all'SDK JS Chat per autenticare e autorizzare i client ad accedere alle tue chat room. È necessario utilizzare il proprio backend poiché non è possibile archiviare in modo sicuro le chiavi AWS in un'app mobile; gli aggressori sofisticati potrebbero estrarle e accedere al tuo account AWS.

Consulta [Creazione di un token di chat](getting-started-chat-auth.md) nella *Guida introduttiva ad Amazon IVS Chat*. Come mostrato nel diagramma di flusso, l'applicazione lato server è responsabile della creazione di un token di chat. Ciò significa che l'app deve fornire i propri mezzi per generare un token di chat richiedendone uno dall'applicazione lato server.

In questa sezione, imparerai le basi della creazione di un provider di token nel tuo backend. Utilizziamo il framework rapido per creare un server locale live che gestisca la creazione di token di chat utilizzando l'ambiente AWS locale.

Crea un progetto `npm` vuoto usando NPM. Crea una directory che possa contenere la tua applicazione e rendila la tua directory di lavoro:

```
$ mkdir backend & cd backend
```

Utilizza `npm init` per creare un file `package.json` per la tua applicazione:

```
$ npm init
```

Questo comando richiede diverse voci, tra cui il nome e la versione dell'applicazione. Per ora, è sufficiente premere **INVIO** per accettare i valori predefiniti per la maggior parte di essi, con la seguente eccezione:

```
entry point: (index.js)
```

Premi **INVIO** per accettare il nome file predefinito suggerito per `index.js` o inserisci quello che desideri sia il nome del file principale.

A questo punto installa le dipendenze richieste:

```
$ npm install express aws-sdk cors dotenv
```

`aws-sdk` richiede variabili di ambiente di configurazione che vengono caricate automaticamente da un file denominato `.env` situato nella directory principale. Per configurarlo, crea un nuovo file denominato `.env` e inserisci le informazioni di configurazione mancanti:

```
# .env

# The region to send service requests to.
AWS_REGION=us-west-2

# Access keys use an access key ID and secret access key
# that you use to sign programmatic requests to AWS.

# AWS access key ID.
AWS_ACCESS_KEY_ID=...

# AWS secret access key.
AWS_SECRET_ACCESS_KEY=...
```

Ora creiamo un file entry-point nella directory principale con il nome che hai inserito sopra nel`npm init` comando. In questo caso, utilizziamo `index.js` e importiamo tutti i pacchetti richiesti:

```
// index.js
import express from 'express';
import AWS from 'aws-sdk';
import 'dotenv/config';
import cors from 'cors';
```

Ora crea una nuova istanza di `express`:

```
const app = express();
const port = 3000;

app.use(express.json());
app.use(cors({ origin: ['http://127.0.0.1:5173'] }));
```

Dopodiché potrai creare il tuo primo metodo POST dell'endpoint per il provider di token. Individua i parametri richiesti nel corpo della richiesta (`roomId`, `userId`, `capabilities` e `sessionDurationInMinutes`):

```
app.post('/create_chat_token', (req, res) => {
  const { roomIdentifier, userId, capabilities, sessionDurationInMinutes } = req.body || {};
});
```

Aggiungi la convalida dei campi obbligatori:

```
app.post('/create_chat_token', (req, res) => {
  const { roomIdentifier, userId, capabilities, sessionDurationInMinutes } = req.body || {};

  if (!roomIdentifier || !userId) {
    res.status(400).json({ error: 'Missing parameters: `roomIdentifier`, `userId`' });
    return;
  }
});
```

Dopo aver preparato il metodo POST, integriamo `aws-sdk` con `createChatToken` per le funzionalità di autenticazione/autorizzazione di base:

```
app.post('/create_chat_token', (req, res) => {
  const { roomIdentifier, userId, capabilities, sessionDurationInMinutes } = req.body || {};

  if (!roomIdentifier || !userId || !capabilities) {
    res.status(400).json({ error: 'Missing parameters: `roomIdentifier`, `userId`, `capabilities`' });
    return;
  }

  ivsChat.createChatToken({ roomIdentifier, userId, capabilities, sessionDurationInMinutes }, (error, data) => {
    if (error) {
      console.log(error);
      res.status(500).send(error.code);
    } else if (data.token) {
      const { token, sessionExpirationTime, tokenExpirationTime } = data;
      console.log(`Retrieved Chat Token: ${JSON.stringify(data, null, 2)}`);

      res.json({ token, sessionExpirationTime, tokenExpirationTime });
    }
  });
});
```

Alla fine del file, aggiungi un ascoltatore di porte per la tua app `express`:

```
app.listen(port, () => {
  console.log(`Backend listening on port ${port}`);
});
```

A questo punto puoi eseguire il server con il seguente comando dalla root del progetto:

```
$ node index.js
```

**Suggerimento**: questo server accetta richieste di URL all'indirizzo https://localhost:3000.

## Creazione di un progetto Chatterbox
<a name="chat-js-rooms-chatterbox"></a>

Per prima cosa creiamo il progetto React chiamato `chatterbox`. Eseguire il comando: 

```
npx create-react-app chatterbox
```

Puoi integrare l'SDK JS per la messaggistica client di Chat tramite il [gestore pacchetti del nodo](https://www.npmjs.com/) o il [gestore pacchetti Yarn](https://yarnpkg.com/):
+ Npm: `npm install amazon-ivs-chat-messaging`
+ Yarn: `yarn add amazon-ivs-chat-messaging`

## Connessione a una chat room
<a name="chat-js-rooms-connect"></a>

Qui si crea una `ChatRoom` e ci si connette ad essa utilizzando metodi asincroni. La classe `ChatRoom` gestisce la connessione dell'utente a SDK JS Chat. Per connetterti correttamente a una chat room, devi fornire un'istanza di `ChatToken` all'interno della tua applicazione React.

Passa al file `App` creato nel progetto `chatterbox` predefinito ed elimina tutto ciò che si trova tra i due tag `<div>`. Non è necessario alcun codice precompilato. A questo punto, il nostro `App` è piuttosto vuoto.

```
// App.jsx / App.tsx

import * as React from 'react';

export default function App() {
  return <div>Hello!</div>;
}
```

Crea una nuova istanza `ChatRoom` e inviala allo stato usando l'hook `useState`. Richiede l'invio di `regionOrUrl` (la regione AWS in cui è ospitata la chat room) e `tokenProvider` (utilizzato per il flusso di autenticazione/autorizzazione del backend creato nei passaggi successivi).

**Importante**: devi utilizzare la stessa regione AWS in cui hai creato la stanza come descritto in [Guida introduttiva ad Amazon IVS Chat](getting-started-chat-create-room.md). L'API è un servizio regionale AWS. Per un elenco delle regioni supportate e degli endpoint del servizio HTTPS di Amazon IVS Chat, consulta la pagina [delle regioni di Amazon IVS Chat](https://docs.aws.amazon.com/general/latest/gr/ivs.html#ivs_region).

```
// App.jsx / App.tsx

import React, { useState } from 'react';
import { ChatRoom } from 'amazon-ivs-chat-messaging';

export default function App() {
  const [room] = useState(() =>
    new ChatRoom({
      regionOrUrl: process.env.REGION as string,
      tokenProvider: () => {},
    }),
  );

  return <div>Hello!</div>;
}
```

## Creazione di un provider di token
<a name="chat-js-rooms-token-provider"></a>

Come passo successivo, dobbiamo creare una funzione `tokenProvider` senza parametri richiesta dal costruttore `ChatRoom`. Innanzitutto, creeremo una funzione `fetchChatToken` che effettuerà una richiesta POST all'applicazione di backend che hai configurato in [Configurazione di un server di autenticazione/autorizzazione locale](#chat-js-rooms-auth-server). I token di chat contengono le informazioni necessarie all'SDK per stabilire con successo una connessione alla chat room. L'API di Chat utilizza questi token come metodo sicuro per convalidare l'identità di un utente, le funzionalità all'interno di una chat room e la durata della sessione.

Nella struttura di navigazione del progetto, crea un nuovo file TypeScript/JavaScript denominato `fetchChatToken`. Crea una richiesta di recupero per l'applicazione `backend` e restituisci l'oggetto `ChatToken` dalla risposta. Aggiungi le proprietà del corpo della richiesta necessarie per creare un token di chat. Usa le regole definite per il [nome della risorsa Amazon (ARN)](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html). Queste proprietà sono documentate nell'operazione [CreateChatToken](https://docs.aws.amazon.com//ivs/latest/ChatAPIReference/API_CreateChatToken.html#API_CreateChatToken_RequestBody).

**Nota**: l'URL che stai utilizzando qui è lo stesso URL creato dal tuo server locale quando hai eseguito l'applicazione di backend.

------
#### [ TypeScript ]

```
// fetchChatToken.ts

import { ChatToken } from 'amazon-ivs-chat-messaging';

type UserCapability = 'DELETE_MESSAGE' | 'DISCONNECT_USER' | 'SEND_MESSAGE';

export async function fetchChatToken(
  userId: string,
  capabilities: UserCapability[] = [],
  attributes?: Record<string, string>,
  sessionDurationInMinutes?: number,
): Promise<ChatToken> {
  const response = await fetch(`${process.env.BACKEND_BASE_URL}/create_chat_token`, {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      userId,
      roomIdentifier: process.env.ROOM_ID,
      capabilities,
      sessionDurationInMinutes,
      attributes
    }),
  });

  const token = await response.json();

  return {
    ...token,
    sessionExpirationTime: new Date(token.sessionExpirationTime),
    tokenExpirationTime: new Date(token.tokenExpirationTime),
  };
}
```

------
#### [ JavaScript ]

```
// fetchChatToken.js

export async function fetchChatToken(
  userId,
  capabilities = [],
  attributes,
  sessionDurationInMinutes) {
  const response = await fetch(`${process.env.BACKEND_BASE_URL}/create_chat_token`, {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      userId,
      roomIdentifier: process.env.ROOM_ID,
      capabilities,
      sessionDurationInMinutes,
      attributes
    }),
  });

  const token = await response.json();

  return {
    ...token,
    sessionExpirationTime: new Date(token.sessionExpirationTime),
    tokenExpirationTime: new Date(token.tokenExpirationTime),
  };
}
```

------

## Osservazione degli aggiornamenti della connessione
<a name="chat-js-rooms-connection-state"></a>

Reagire ai cambiamenti nello stato della connessione di una chat room è una parte essenziale della creazione di un'app di chat. Cominciamo con la sottoscrizione degli eventi pertinenti:

```
// App.jsx / App.tsx

import React, { useState, useEffect } from 'react';
import { ChatRoom } from 'amazon-ivs-chat-messaging';
import { fetchChatToken } from './fetchChatToken';

export default function App() {
  const [room] = useState(
    () =>
      new ChatRoom({
        regionOrUrl: process.env.REGION as string,
        tokenProvider: () => fetchChatToken('Mike', ['SEND_MESSAGE']),
      }),
  );

  useEffect(() => {
    const unsubscribeOnConnecting = room.addListener('connecting', () => {});
    const unsubscribeOnConnected = room.addListener('connect', () => {});
    const unsubscribeOnDisconnected = room.addListener('disconnect', () => {});

    return () => {
      // Clean up subscriptions.
      unsubscribeOnConnecting();
      unsubscribeOnConnected();
      unsubscribeOnDisconnected();
    };
  }, [room]);

  return <div>Hello!</div>;
}
```

Successivamente, dobbiamo fornire la capacità di leggere lo stato della connessione. Usiamo il nostro hook `useState` per creare uno stato locale in `App` e impostare lo stato della connessione all'interno di ciascun listener.

------
#### [ TypeScript ]

```
// App.tsx

import React, { useState, useEffect } from 'react';
import { ChatRoom, ConnectionState } from 'amazon-ivs-chat-messaging';
import { fetchChatToken } from './fetchChatToken';

export default function App() {  
  const [room] = useState(
    () =>
      new ChatRoom({
        regionOrUrl: process.env.REGION as string,
        tokenProvider: () => fetchChatToken('Mike', ['SEND_MESSAGE']),
      }),
  );
  const [connectionState, setConnectionState] = useState<ConnectionState>('disconnected');

  useEffect(() => {
    const unsubscribeOnConnecting = room.addListener('connecting', () => {
      setConnectionState('connecting');
    });

    const unsubscribeOnConnected = room.addListener('connect', () => {
      setConnectionState('connected');
    });

    const unsubscribeOnDisconnected = room.addListener('disconnect', () => {
      setConnectionState('disconnected');
    });

    return () => {
      unsubscribeOnConnecting();
      unsubscribeOnConnected();
      unsubscribeOnDisconnected();
    };
  }, [room]);

  return <div>Hello!</div>;
}
```

------
#### [ JavaScript ]

```
// App.jsx

import React, { useState, useEffect } from 'react';
import { ChatRoom } from 'amazon-ivs-chat-messaging';
import { fetchChatToken } from './fetchChatToken';

export default function App() {
  const [room] = useState(
    () =>
      new ChatRoom({
        regionOrUrl: process.env.REGION,
        tokenProvider: () => fetchChatToken('Mike', ['SEND_MESSAGE']),
      }),
  );
  const [connectionState, setConnectionState] = useState('disconnected');

  useEffect(() => {
    const unsubscribeOnConnecting = room.addListener('connecting', () => {
      setConnectionState('connecting');
    });

    const unsubscribeOnConnected = room.addListener('connect', () => {
      setConnectionState('connected');
    });

    const unsubscribeOnDisconnected = room.addListener('disconnect', () => {
      setConnectionState('disconnected');
    });

    return () => {
      unsubscribeOnConnecting();
      unsubscribeOnConnected();
      unsubscribeOnDisconnected();
    };
  }, [room]);

  return <div>Hello!</div>;
}
```

------

Dopo esserti iscritto allo stato della connessione, visualizza lo stato e connettiti alla chat room usando il metodo `room.connect` all'interno dell'hook `useEffect`:

```
// App.jsx / App.tsx

// ...

useEffect(() => {
  const unsubscribeOnConnecting = room.addListener('connecting', () => {
    setConnectionState('connecting');
  });

  const unsubscribeOnConnected = room.addListener('connect', () => {
    setConnectionState('connected');
  });

  const unsubscribeOnDisconnected = room.addListener('disconnect', () => {
    setConnectionState('disconnected');
  });

  room.connect();

  return () => {
    unsubscribeOnConnecting();
    unsubscribeOnConnected();
    unsubscribeOnDisconnected();
  };
}, [room]);

// ...

return (
  <div>
    <h4>Connection State: {connectionState}</h4>
  </div>
);

// ...
```

Hai implementato correttamente una connessione alla chat room.

## Creazione di un componente del pulsante di invio
<a name="chat-js-rooms-send-button"></a>

In questa sezione viene creato un pulsante di invio con un design diverso per ogni stato della connessione. Il pulsante di invio facilita l'invio di messaggi in una chat room. Serve anche come indicatore visivo che indica se e quando è possibile inviare messaggi, ad esempio in caso di interruzioni di connessione o sessioni di chat scadute.

Per prima cosa, crea un nuovo file nella directory `src` del tuo progetto Chatterbox e assegnagli il nome `SendButton`. Quindi, crea un componente che mostrerà un pulsante per la tua applicazione di chat. Esporta il tuo `SendButton` e importalo nell'`App`. Nel `<div></div>` vuoto, aggiungi `<SendButton />`.

------
#### [ TypeScript ]

```
// SendButton.tsx

import React from 'react';

interface Props {
  onPress?: () => void;
  disabled?: boolean;
}

export const SendButton = ({ onPress, disabled }: Props) => {
  return (
    <button disabled={disabled} onClick={onPress}>
      Send
    </button>
  );
};

// App.tsx

import { SendButton } from './SendButton';

// ...

return (
  <div>
    <div>Connection State: {connectionState}</div>
    <SendButton />
  </div>
);
```

------
#### [ JavaScript ]

```
// SendButton.jsx

import React from 'react';

export const SendButton = ({ onPress, disabled }) => {
  return (
    <button disabled={disabled} onClick={onPress}>
      Send
    </button>
  );
};

// App.jsx

import { SendButton } from './SendButton';

// ...

return (
  <div>
    <div>Connection State: {connectionState}</div>
    <SendButton />
  </div>
);
```

------

Quindi, in `App` definisci una funzione denominata `onMessageSend` e passala alla proprietà `SendButton onPress`. Definisci un'altra variabile denominata `isSendDisabled` (che impedisce l'invio di messaggi quando la stanza non è connessa) e inviala alla proprietà `SendButton disabled`.

```
// App.jsx / App.tsx

// ...

const onMessageSend = () => {};

const isSendDisabled = connectionState !== 'connected';

return (
  <div>
    <div>Connection State: {connectionState}</div>
    <SendButton disabled={isSendDisabled} onPress={onMessageSend} />
  </div>
);

// ...
```

## Creazione dell'input di un messaggio
<a name="chat-js-rooms-message-input"></a>

La barra dei messaggi di Chatterbox è il componente con cui interagirai per inviare messaggi a una chat room. In genere contiene un input di testo per comporre il messaggio e un pulsante per inviarlo.

Per creare un componente `MessageInput`, crea prima un nuovo file nella directory `src` e assegnagli il nome `MessageInput`. Quindi, crea un componente di input controllato che mostrerà un input per la tua applicazione di chat. Esporta il tuo `MessageInput` e importalo nell'`App` (sopra il `<SendButton />`).

Crea un nuovo stato denominato `messageToSend` usando l'hook `useState`, con una stringa vuota come valore predefinito. Nel corpo della tua app, invia `messageToSend` al `value` di`MessageInput` e invia `setMessageToSend` alla proprietà `onMessageChange`:

------
#### [ TypeScript ]

```
// MessageInput.tsx

import * as React from 'react';

interface Props {
  value?: string;
  onValueChange?: (value: string) => void;
}

export const MessageInput = ({ value, onValueChange }: Props) => {
  return (
    <input type="text" value={value} onChange={(e) => onValueChange?.(e.target.value)} placeholder="Send a message" />
  );
};


// App.tsx

// ...  

import { MessageInput } from './MessageInput';

// ...

export default function App() {
  const [messageToSend, setMessageToSend] = useState('');

// ...

return (
  <div>
    <h4>Connection State: {connectionState}</h4>
    <MessageInput value={messageToSend} onMessageChange={setMessageToSend} />
    <SendButton disabled={isSendDisabled} onPress={onMessageSend} />
  </div>
);
```

------
#### [ JavaScript ]

```
// MessageInput.jsx

import * as React from 'react';

export const MessageInput = ({ value, onValueChange }) => {
  return (
    <input type="text" value={value} onChange={(e) => onValueChange?.(e.target.value)} placeholder="Send a message" />
  );
};

// App.jsx

// ...  

import { MessageInput } from './MessageInput';

// ...

export default function App() {
  const [messageToSend, setMessageToSend] = useState('');

// ...


return (
  <div>
    <h4>Connection State: {connectionState}</h4>
    <MessageInput value={messageToSend} onMessageChange={setMessageToSend} />
    <SendButton disabled={isSendDisabled} onPress={onMessageSend} />
  </div>
);
```

------

## Fasi successive
<a name="chat-js-rooms-next-steps"></a>

Ora che hai terminato con la creazione di una barra dei messaggi per Chatterbox, passa alla parte 2 di questo tutorial JavaScript, [Messaggi ed eventi](chat-sdk-js-tutorial-messages-events.md).