

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# Diseñar GraphQL APIs con AWS AppSync
<a name="designing-a-graphql-api"></a>

AWS AppSync le permite crear GraphQL APIs utilizando la experiencia de la consola. Puede echar un vistazo a esto en la sección [Lanzamiento de un esquema de ejemplo](https://docs.aws.amazon.com/appsync/latest/devguide/quickstart.html). Sin embargo, esa guía no mostraba todo el catálogo de opciones y configuraciones que podía utilizar. AWS AppSync

Si decide crear una API de GraphQL en la consola, puede explorar varias opciones. Si ha leído nuestra guía de [Lanzamiento de un esquema de ejemplo](https://docs.aws.amazon.com/appsync/latest/devguide/quickstart.html), le mostramos cómo crear una API a partir de un modelo predefinido. En las siguientes secciones, te guiaremos por el resto de las opciones y configuraciones para crear GraphQL APIs en. AWS AppSync

En esta sección, analizará los conceptos siguientes:

1. [Blank APIs or imports](blank-import-api.md#aws-appsync-blank-import-api): esta guía explica todo el proceso de creación de una API de GraphQL. Aprenderá a crear un GraphQL a partir de una plantilla en blanco sin modelo, a configurar los orígenes de datos del esquema y a añadir su primer solucionador a un campo.

1. [Real-time data](aws-appsync-real-time-data.md#aws-appsync-real-time-data-anchor): Esta guía te mostrará las posibles opciones para crear una API utilizando AWS AppSync el WebSocket motor.

1. [Merged APIs](merged-api.md#aws-appsync-merged-api): Esta guía le mostrará cómo crear un nuevo GraphQL APIs asociando y fusionando datos de varios GraphQL existentes. APIs

1. [Creación de GraphQL APIs con introspección de RDS](rds-introspection.md): esta guía muestra cómo integrar sus tablas de Amazon RDS mediante una API de datos.

# Estructuración de una API de GraphQL (en blanco o importada) APIs
<a name="blank-import-api"></a>

Para crear su API de GraphQL a partir de una plantilla en blanco, antes sería útil revisar los conceptos relacionados con GraphQL. Hay tres componentes fundamentales de una API de GraphQL:

1. El **esquema** es el archivo que contiene la forma y la definición de los datos. Cuando un cliente realice una solicitud a su servicio GraphQL, los datos devueltos seguirán la especificación del esquema. Para obtener más información, consulte [Esquemas de GraphQL](schema-components.md#aws-appsync-schema-components).

1. El **origen de datos** se adjunta a su esquema. Cuando se realiza una solicitud, aquí es donde se recuperan y modifican los datos. Para obtener más información, consulte [Orígenes de datos](data-source-components.md#aws-appsync-data-source-components).

1. El **solucionador** se encuentra entre el esquema y el origen de datos. Cuando se realiza una solicitud, el solucionador realiza la operación con los datos del origen y, a continuación, devuelve el resultado como respuesta. Para obtener más información, consulte [Solucionadores](resolver-components.md#aws-appsync-resolver-components).

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


AWS AppSync la gestiona APIs al permitirle crear, editar y almacenar el código para sus esquemas y resoluciones. Los orígenes de datos procederán de repositorios externos, como bases de datos, tablas de DynamoDB y funciones de Lambda. Si utilizas un AWS servicio para almacenar tus datos o planeas hacerlo, AWS AppSync ofrece una experiencia prácticamente perfecta a la hora de asociar los datos de tus AWS cuentas a tu GraphQL. APIs

En la siguiente sección, aprenderás a crear cada uno de estos componentes mediante el servicio. AWS AppSync 

**Topics**
+ [Diseño de esquemas de GraphQL](designing-your-schema.md)
+ [Asociación de un origen de datos](attaching-a-data-source.md)
+ [Configuración de solucionadores de AWS AppSync](resolver-config-overview.md)
+ [Utilizándolo APIs con el CDK](using-your-api.md)

# Diseño de esquemas de GraphQL
<a name="designing-your-schema"></a>

El esquema GraphQL es la base de cualquier implementación de servidor GraphQL. Cada API de GraphQL se define mediante un **solo** esquema que contiene tipos y campos que describen cómo se rellenarán los datos de las solicitudes. Los datos que fluyen a través de la API y las operaciones realizadas deben validarse con respecto al esquema.

En general, el [sistema de tipos de GraphQL](https://graphql.org/learn/schema/#type-system) describe las funcionalidades de un servidor GraphQL y se utiliza para determinar si una consulta es válida. El sistema de tipos de un servidor suele denominarse esquema de ese servidor y puede constar de diferentes tipos de objetos, tipos escalares, tipos de entradas, etc. GraphQL es declarativo y tiene establecimiento inflexible de tipos, lo que significa que los tipos estarán bien definidos en tiempo de ejecución y solo devolverán lo que se haya especificado.

AWS AppSync permite definir y configurar esquemas de GraphQL. En la siguiente sección se describe cómo crear esquemas de GraphQL desde cero utilizando AWS AppSync los servicios.

## Estructuración de un esquema de GraphQL
<a name="schema-structure"></a>

**sugerencia**  
Recomendamos consultar la sección [Esquemas](https://docs.aws.amazon.com//appsync/latest/devguide/schema-components.html) antes de continuar.

GraphQL es una poderosa herramienta para implementar servicios de API. Según el [sitio web de GraphQL](https://graphql.org/), GraphQL es lo siguiente:

«*GraphQL es un lenguaje de consulta APIs y un entorno de ejecución para completar esas consultas con los datos existentes. GraphQL proporciona una descripción completa y comprensible de los datos de tu API, da a los clientes la posibilidad de pedir exactamente lo que necesitan y nada más, facilita la evolución APIs con el tiempo y habilita potentes herramientas para desarrolladores.* »

Esta sección cubre la primera parte de la implementación de GraphQL, el esquema. Siguiendo la cita anterior, un esquema cumple la función de “proporcionar una descripción completa y comprensible de los datos de su API”. En otras palabras, un esquema GraphQL es una representación textual de los datos, las operaciones y las relaciones entre ellos de su servicio. El esquema se considera el punto de entrada principal para la implementación del servicio GraphQL. Como era de esperar, suele ser una de las primeras cosas que hace en su proyecto. Recomendamos consultar la sección [Esquemas](https://docs.aws.amazon.com//appsync/latest/devguide/schema-components.html) antes de continuar.

Para citar la sección [Esquemas](https://docs.aws.amazon.com//appsync/latest/devguide/schema-components.html), los esquemas de GraphQL se escriben en el *lenguaje de definición de esquema* (SDL). SDL está compuesto por tipos y campos con una estructura establecida:
+ **Tipos**: los tipos son la forma en que GraphQL define la forma y el comportamiento de los datos. GraphQL admite una multitud de tipos que se explicarán más adelante en esta sección. Cada tipo que se defina en su esquema tendrá su propio ámbito. Dentro del ámbito habrá uno o más campos que pueden contener un valor o una lógica que se utilice en el servicio GraphQL. Los tipos cumplen muchos roles diferentes, siendo las más comunes los objetos o los escalares (tipos de valores primitivos).
+ **Campos**: los campos existen dentro del ámbito de un tipo y contienen el valor que se solicita al servicio GraphQL. Se parecen mucho a las variables de otros lenguajes de programación. La forma de los datos que defina en sus campos determinará cómo se estructuran los datos en una request/response operación. Esto permite a los desarrolladores predecir lo que se va a devolver sin saber cómo se implementa el backend del servicio.

Los esquemas más simples contendrán tres categorías de datos diferentes:

1. **Raíces del esquema**: las raíces definen los puntos de entrada de su esquema. Señala los campos que realizarán alguna operación con los datos, como añadir, eliminar o modificar algo.

1. **Tipos**: son tipos básicos que se utilizan para representar la forma de los datos. Casi se puede pensar en ellos como objetos o representaciones abstractas de algo con características definidas. Por ejemplo, podría crear un objeto `Person` que represente a una persona en una base de datos. Las características de cada persona se definirán dentro de `Person` como campos. Pueden ser cualquier cosa, como el nombre, la edad, el trabajo, la dirección, etc. de la persona.

1. **Tipos de objetos especiales**: son los tipos que definen el comportamiento de las operaciones del esquema. Cada tipo de objeto especial se define una vez por cada esquema. Primero se colocan en la raíz del esquema y, a continuación, se definen en el cuerpo del esquema. Cada campo de un tipo de objeto especial define una sola operación que debe implementar el solucionador.

Para poner esto en perspectiva, imagine que está creando un servicio que almacena autores y los libros que han escrito. Cada autor tiene un nombre y una serie de libros que han escrito. Cada libro tiene un nombre y una lista de autores asociados. También queremos poder añadir o recuperar libros y autores. Una representación UML simple de esta relación puede tener este aspecto:

![\[UML diagram showing Author and Book classes with attributes and methods, linked by association.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/GraphQL-UML-1.png)


En GraphQL, las entidades `Author` y `Book` representan dos tipos de objetos diferentes en el esquema:

```
type Author {
}

type Book {
}
```

`Author` contiene `authorName` y `Books`, mientras que `Book` contiene `bookName` y `Authors`. Estos se pueden representar como los campos incluidos en el ámbito de sus tipos:

```
type Author {
  authorName: String
  Books: [Book]
}

type Book {
  bookName: String
  Authors: [Author]
}
```

Como puede ver, las representaciones de tipos se parecen mucho al diagrama. Sin embargo, los métodos son algo más complicados. Se colocarán como campo en uno de algunos tipos de objetos especiales. La categorización de los objetos especiales depende de su comportamiento. GraphQL contiene tres tipos de objetos especiales fundamentales: consultas, mutaciones y suscripciones. Para obtener más información sobre los objetos, consulte [Objetos especiales](https://docs.aws.amazon.com//appsync/latest/devguide/graphql-types.html#special-object-components).

Como tanto `getAuthor` como `getBook` solicitan datos, se colocarán en un tipo de objeto especial de `Query`:

```
type Author {
  authorName: String
  Books: [Book]
}

type Book {
  bookName: String
  Authors: [Author]
}

type Query {
  getAuthor(authorName: String): Author
  getBook(bookName: String): Book
}
```

Las operaciones están vinculadas a la consulta, que a su vez está vinculada al esquema. Cuando se añade una raíz de esquema, se define el tipo de objeto especial (en este caso, `Query`) como uno de los puntos de entrada. Esto se puede hacer con la palabra clave `schema`:

```
schema {
  query: Query
}

type Author {
  authorName: String
  Books: [Book]
}

type Book {
  bookName: String
  Authors: [Author]
}

type Query {
  getAuthor(authorName: String): Author
  getBook(bookName: String): Book
}
```

Si nos fijamos en los dos últimos métodos, `addAuthor` y `addBook` añaden datos a la base de datos, por lo que se definirán en un tipo de objeto `Mutation` especial. Sin embargo, por la página [Tipos](https://docs.aws.amazon.com/appsync/latest/devguide/graphql-types.html#input-components), también sabemos que no se permiten entradas que hagan referencia directamente a objetos porque son estrictamente tipos de salida. En este caso, no podemos usar `Author` ni `Book`, por lo que necesitamos crear un tipo de entrada con los mismos campos. En este ejemplo, añadimos `AuthorInput` y`BookInput`, que aceptan los mismos campos de sus tipos correspondientes. A continuación, creamos nuestra mutación usando las entradas como parámetros:

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

type Author {
  authorName: String
  Books: [Book]
}

input AuthorInput {
  authorName: String
  Books: [BookInput]
}

type Book {
  bookName: String
  Authors: [Author]
}

input BookInput {
  bookName: String
  Authors: [AuthorInput]
}

type Query {
  getAuthor(authorName: String): Author
  getBook(bookName: String): Book
}

type Mutation {
  addAuthor(input: [BookInput]): Author
  addBook(input: [AuthorInput]): Book
}
```

Repasemos lo que acabamos de hacer:

1. Hemos creado un esquema con los tipos `Book` y `Author` para representar nuestras entidades.

1. Hemos añadido los campos que contienen las características de nuestras entidades.

1. Hemos añadido una consulta para recuperar esta información de la base de datos.

1. Hemos añadido una mutación para manipular los datos de la base de datos.

1. Hemos añadido tipos de entrada para reemplazar los parámetros de nuestro objeto en la mutación y cumplir con las reglas de GraphQL.

1. Hemos añadido la consulta y la mutación a nuestro esquema de raíz para que la implementación de GraphQL entienda la ubicación del tipo de raíz.

Como puede ver, el proceso de creación de un esquema requiere muchos conceptos del modelado de datos (especialmente del modelado de bases de datos) en general. Puede considerarse que el esquema se ajusta a la forma de los datos de la fuente. También sirve como modelo que el solucionador implementará. En las siguientes secciones, aprenderá a crear un esquema utilizando diversas herramientas y servicios AWS respaldados.

**nota**  
Los ejemplos de las secciones siguientes no están pensados para ejecutarse en una aplicación real. Con ellos solo se pretende mostrar los comandos para que pueda crear sus propias aplicaciones.

## Creación de esquemas
<a name="creating-schema"></a>

El esquema estará en un archivo llamado`schema.graphql`. AWS AppSync permite a los usuarios crear nuevos esquemas para su APIs GraphQL utilizando varios métodos. En este ejemplo, crearemos una API en blanco junto con un esquema en blanco.

------
#### [ Console ]

1. [Inicia sesión en la consola Consola de administración de AWS y ábrelaAppSync.](https://console.aws.amazon.com/appsync/)

   1. En el **Panel**, elija **Crear API**.

   1. **En **Opciones de API**, selecciona **GraphQL APIs**, **Diseña desde cero** y, a continuación, Siguiente.**

      1. En **Nombre de la API**, cambie el nombre previamente cumplimentado por el que su aplicación necesite.

      1. Para obtener **los detalles de contacto**, puede introducir un punto de contacto para identificar al administrador de la API. Se trata de un campo opcional.

      1. En **Configuración de API privada**, puede habilitar las características de API privadas. Solo se puede acceder a una API privada desde un punto de conexión de VPC (VPCE) configurado. Para obtener más información, consulta [Privado APIs](https://docs.aws.amazon.com/appsync/latest/devguide/using-private-apis.html).

         No le recomendamos habilitar esta característica para este ejemplo. Seleccione **Siguiente** después de revisar sus entradas.

   1. En **Crear un tipo de GraphQL**, puede elegir crear una tabla de DynamoDB para utilizarla como origen de datos u omitir este paso y hacerlo más adelante.

      Para este ejemplo, elija **Crear recursos de GraphQL más adelante**. Crearemos un recurso en una sección aparte.

   1. Revise la información indicada y, a continuación, seleccione **Crear API**.

1. Estará en el panel de control de tu API específica. Lo notará porque el nombre de la API aparecerá en la parte superior del panel de control. **Si este no es el caso, puedes seleccionarla **APIs**en la **barra lateral** y, a continuación, elegir tu API en el APIs panel de control.**

   1. En la **barra lateral** situada debajo del nombre de la API, seleccione **Esquema**.

1. En el **Editor de esquemas**, puede configurar su archivo `schema.graphql`. Puede estar vacío o lleno de tipos generados a partir de un modelo. A la derecha, tiene la sección **Solucionadores** para asociar solucionadores a los campos del esquema. En esta sección no nos fijaremos en los solucionadores.

------
#### [ CLI ]

**nota**  
Cuando utilice la CLI, asegúrese de tener los permisos correctos para acceder y crear recursos en el servicio. Es posible que desee establecer políticas de [privilegios mínimos](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege) para los usuarios que no sean administradores y que necesiten acceder al servicio. Para obtener más información sobre AWS AppSync las políticas, consulte [Administración de identidad y acceso](https://docs.aws.amazon.com//appsync/latest/devguide/security-iam.html) para. AWS AppSync  
Además, le recomendamos leer primero la versión de consola si aún no lo ha hecho.

1. Si aún no lo ha hecho, [instale](https://docs.aws.amazon.com//cli/latest/userguide/cli-chap-getting-started.html) la CLI de AWS y añadas su [configuración](https://docs.aws.amazon.com//cli/latest/userguide/cli-configure-quickstart.html).

1. Cree un objeto de API de GraphQL ejecutando el comando [https://docs.aws.amazon.com/cli/latest/reference/appsync/create-graphql-api.html](https://docs.aws.amazon.com/cli/latest/reference/appsync/create-graphql-api.html).

   Deberá escribir dos parámetros para este comando concreto:

   1. El `name` de su API.

   1. El `authentication-type` o el tipo de credenciales utilizado para acceder a la API (IAM, OIDC, etc.).
**nota**  
Otros parámetros, como `Region`, deben configurarse pero normalmente se utilizarán de forma predeterminada en los valores de configuración de la CLI.

   Un comando de ejemplo puede tener este aspecto:

   ```
   aws appsync create-graphql-api --name testAPI123 --authentication-type API_KEY
   ```

   Aparecerá un resultado en la CLI. A continuación se muestra un ejemplo:

   ```
   {
       "graphqlApi": {
           "xrayEnabled": false,
           "name": "testAPI123",
           "authenticationType": "API_KEY",
           "tags": {},
           "apiId": "abcdefghijklmnopqrstuvwxyz",
           "uris": {
               "GRAPHQL": "https://zyxwvutsrqponmlkjihgfedcba.appsync-api.us-west-2.amazonaws.com/graphql",
               "REALTIME": "wss://zyxwvutsrqponmlkjihgfedcba.appsync-realtime-api.us-west-2.amazonaws.com/graphql"
           },
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz"
       }
   }
   ```

1. 
**nota**  
Se trata de un comando opcional que toma un esquema existente y lo carga en el servicio de AWS AppSync mediante un blob de base 64. No utilizaremos este comando para este ejemplo.

   Ejecute el comando [https://docs.aws.amazon.com/cli/latest/reference/appsync/start-schema-creation.html](https://docs.aws.amazon.com/cli/latest/reference/appsync/start-schema-creation.html).

   Deberá escribir dos parámetros para este comando concreto:

   1. Su `api-id` del paso anterior.

   1. La `definition` del esquema es un blob binario codificado en base 64.

   Un comando de ejemplo puede tener este aspecto:

   ```
    aws appsync start-schema-creation --api-id abcdefghijklmnopqrstuvwxyz --definition "aa1111aa-123b-2bb2-c321-12hgg76cc33v"
   ```

   Se devolverá un resultado:

   ```
   {
       "status": "PROCESSING"
   }
   ```

   Este comando no devolverá el resultado final después del procesamiento. Para ver el resultado, debe usar un comando diferente, [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/get-schema-creation-status.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/get-schema-creation-status.html). Tenga en cuenta que estos dos comandos son asíncronos, por lo que puede comprobar el estado de la salida incluso mientras se crea el esquema.

------
#### [ CDK ]

**sugerencia**  
[Antes de usar la CDK, te recomendamos que consultes la [documentación oficial](https://docs.aws.amazon.com/cdk/v2/guide/home.html) de la CDK junto con AWS AppSync su referencia.](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
Los pasos que se indican a continuación solo mostrarán un ejemplo general del fragmento de código utilizado para añadir un recurso concreto. **No** se pretende que esta sea una solución funcional en su código de producción. También, se presupone que ya tiene una aplicación en funcionamiento.

1. El punto de partida del CDK es ligeramente diferente. Lo ideal es que el archivo `schema.graphql` ya esté creado. Solo necesita crear un nuevo archivo con la extensión de archivo `.graphql`. Puede ser un archivo vacío.

1. En general, puede que tenga que añadir la directiva de importación al servicio que utilice. Por ejemplo, puede seguir estas formas:

   ```
   import * as x from 'x'; # import wildcard as the 'x' keyword from 'x-service'
   import {a, b, ...} from 'c'; # import {specific constructs} from 'c-service'
   ```

   Para añadir una API de GraphQL, tu archivo de pila debe importar el AWS AppSync servicio:

   ```
   import * as appsync from 'aws-cdk-lib/aws-appsync';
   ```
**nota**  
Esto significa que vamos a importar todo el servicio con la palabra clave `appsync`. Para usar esto en tu aplicación, tus AWS AppSync construcciones usarán el formato. `appsync.construct_name` Por ejemplo, si quisiéramos crear una API de GraphQL, diríamos `new appsync.GraphqlApi(args_go_here)`. En el siguiente paso se describe esto.

1. La API de GraphQL más básica incluirá un `name` para la API y la ruta de `schema`.

   ```
   const add_api = new appsync.GraphqlApi(this, 'API_ID', {
     name: 'name_of_API_in_console',
     schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'schema_name.graphql')),
   });
   ```
**nota**  
Repasemos lo que hace este fragmento de código. Dentro del ámbito de `api`, creamos una nueva API de GraphQL llamando a `appsync.GraphqlApi(scope: Construct, id: string, props: GraphqlApiProps)`. El alcance es `this`, que hace referencia al objeto actual. El id es*API\$1ID*, que será el nombre del recurso de tu API de GraphQL CloudFormation cuando se cree. `GraphqlApiProps` contiene el `name` de la API de GraphQL y el `schema`. `schema`Generará un esquema (`SchemaFile.fromAsset`) buscando el `.graphql` archivo (`__dirname`) en la ruta absoluta (*schema\$1name.graphql*). En un escenario real, es probable que su archivo de esquema esté dentro de la aplicación del CDK.  
Para usar los cambios realizados en la API de GraphQL, deberá volver a implementar la aplicación.

------

## Adición de tipos a los esquemas
<a name="adding-schema-types"></a>

Ahora que ha añadido su esquema, puede empezar a agregar los tipos tanto de entrada como de salida. Tenga en cuenta que los tipos que aparecen aquí no deben usarse en código real; son solo ejemplos que le ayudarán a entender el proceso.

En primer lugar, crearemos un tipo de objeto. En el código real, no es necesario empezar con estos tipos. Puede crear cualquier tipo que desee en cualquier momento siempre que siga las reglas y la sintaxis de GraphQL.

**nota**  
Las siguientes secciones usarán el **editor de esquemas**, así que manténgalo abierto.

------
#### [ Console ]
+ Puede crear un tipo de objeto utilizando la palabra clave `type` junto con el nombre del tipo:

  ```
  type Type_Name_Goes_Here {}
  ```

  Dentro del ámbito del tipo, puede añadir campos que representen las características del objeto:

  ```
  type Type_Name_Goes_Here {
    # Add fields here
  }
  ```

  A continuación se muestra un ejemplo:

  ```
  type Obj_Type_1 {
    id: ID!
    title: String
    date: AWSDateTime
  }
  ```
**nota**  
En este paso, hemos añadido un tipo de objeto genérico con un campo `id` obligatorio almacenado como `ID`, un campo `title` almacenado como `String` y un campo `date` almacenado como `AWSDateTime`. Para ver una lista de tipos y campos, y lo que hacen, consulte [Esquemas](https://docs.aws.amazon.com//appsync/latest/devguide/schema-components.html). Para ver una lista de escalares y lo que hacen, consulte [Referencia de tipos](https://docs.aws.amazon.com/appsync/latest/devguide/type-reference.html).

------
#### [ CLI ]

**nota**  
Le recomendamos leer primero la versión de consola si aún no lo ha hecho.
+ Puede crear un tipo de objeto ejecutando el comando [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html).

  Para este comando en particular, deberá introducir varios parámetros:

  1. El `api-id` de su API.

  1. La `definition` o el contenido de su tipo. En el ejemplo de la consola, esto era:

     ```
     type Obj_Type_1 {
       id: ID!
       title: String
       date: AWSDateTime
     }
     ```

  1. El `format` de su entrada. En este ejemplo, usaremos `SDL`.

  Un comando de ejemplo puede tener este aspecto:

  ```
  aws appsync create-type --api-id abcdefghijklmnopqrstuvwxyz --definition "type Obj_Type_1{id: ID! title: String date: AWSDateTime}" --format SDL
  ```

  Aparecerá un resultado en la CLI. A continuación se muestra un ejemplo:

  ```
  {
      "type": {
          "definition": "type Obj_Type_1{id: ID! title: String date: AWSDateTime}",
          "name": "Obj_Type_1",
          "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Obj_Type_1",
          "format": "SDL"
      }
  }
  ```
**nota**  
En este paso, hemos añadido un tipo de objeto genérico con un campo `id` obligatorio almacenado como `ID`, un campo `title` almacenado como `String` y un campo `date` almacenado como `AWSDateTime`. Para ver una lista de tipos y campos, y lo que hacen, consulte [Esquemas](https://docs.aws.amazon.com//appsync/latest/devguide/schema-components.html). Para ver una lista de escalares y lo que hacen, consulte [Referencia de tipos](https://docs.aws.amazon.com/appsync/latest/devguide/type-reference.html).  
Por otra parte, puede que se haya dado cuenta de que introducir la definición directamente funciona para tipos más pequeños pero no es factible para añadir tipos más grandes o múltiples. Puede optar por añadir todo el contenido en un archivo `.graphql` y, a continuación, [pasarlo como entrada](https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-parameters-file.html).

------
#### [ CDK ]

**sugerencia**  
[Antes de usar la CDK, le recomendamos que consulte la [documentación oficial](https://docs.aws.amazon.com/cdk/v2/guide/home.html) de la CDK junto con su referencia a AWS AppSync la misma.](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
Los pasos que se indican a continuación solo mostrarán un ejemplo general del fragmento de código utilizado para añadir un recurso concreto. **No** se pretende que esta sea una solución funcional en su código de producción. También, se presupone que ya tiene una aplicación en funcionamiento.

Para añadir un tipo, debe añadirlo a su archivo `.graphql`. El ejemplo de la consola era:

```
type Obj_Type_1 {
  id: ID!
  title: String
  date: AWSDateTime
}
```

Puede añadir sus tipos directamente al esquema como cualquier otro archivo.

**nota**  
Para usar los cambios realizados en la API de GraphQL, deberá volver a implementar la aplicación.

------

El [tipo de objeto](https://graphql.org/learn/schema/#object-types-and-fields) tiene campos que son de [tipo escalar](https://graphql.org/learn/schema/#scalar-types), como cadenas y números enteros. AWS AppSync también te permite usar tipos escalares mejorados, `AWSDateTime` además de los escalares básicos de GraphQL. Además, todos los campos que terminen con un signo de exclamación son obligatorios. 

El tipo escalar `ID` en concreto es un identificador exclusivo que puede ser `String` o `Int`. Puede controlarlos en el código de resolución para la asignación automática.

Existen similitudes entre los tipos de objetos especiales, como `Query` y los tipos de objetos “normales”, como en el ejemplo anterior, en el sentido de que ambos utilizan la palabra clave `type` y se consideran objetos. Sin embargo, en el caso de los tipos de objetos especiales (`Query`, `Mutation`, y `Subscription`), su comportamiento es muy diferente, ya que se exponen como puntos de entrada a la API. También se centran más en dar forma a las operaciones que a los datos. Para obtener más información, consulte la sección sobre [tipos de consultas y mutaciones](https://graphql.org/learn/schema/#the-query-and-mutation-types).

En cuanto a los tipos de objetos especiales, el siguiente paso podría ser añadir uno o más para realizar operaciones con los datos con forma. En un escenario real, cada esquema de GraphQL debe tener al menos un tipo de consulta raíz para solicitar datos. Puede considerar la consulta como uno de los puntos de entrada (o puntos de conexión) de su servidor GraphQL. Añadamos una consulta como ejemplo.

------
#### [ Console ]
+ Para crear una consulta, basta con añadirla al archivo de esquema como cualquier otro tipo. Una consulta requeriría un tipo `Query` y una entrada en la raíz de la manera siguiente:

  ```
  schema {
    query: Name_of_Query
  }
  
  type Name_of_Query {
    # Add field operation here
  }
  ```

  Ten en cuenta que *Name\$1of\$1Query* en un entorno de producción simplemente se llamará `Query` en la mayoría de los casos. Se recomienda mantenerlo en este valor. Dentro del tipo de consulta, puede añadir campos. Cada campo realizará una operación en la solicitud. El resultado es que la mayoría de estos campos, si no todos, se asociarán a un solucionador. Sin embargo, en esta sección o abordaremos eso. En cuanto al formato de la operación de campo, podría ser como este:

  ```
  Name_of_Query(params): Return_Type # version with params
  Name_of_Query: Return_Type # version without params
  ```

  A continuación se muestra un ejemplo:

  ```
  schema {
    query: Query
  }
  
  type Query {
    getObj: [Obj_Type_1]
  }
  
  type Obj_Type_1 {
    id: ID!
    title: String
    date: AWSDateTime
  }
  ```
**nota**  
En este paso, agregamos un tipo `Query` y lo definimos en nuestra raíz de `schema`. Nuestro tipo `Query` definió un campo `getObj` que devuelve una lista de objetos `Obj_Type_1`. Tenga en cuenta que `Obj_Type_1` es el objeto del paso anterior. En el código de producción, sus operaciones de campo normalmente funcionarán con datos moldeados por objetos como `Obj_Type_1`. Además, campos como `getObj` suelen tener un solucionador para ejecutar la lógica empresarial. Este tema se tratará en otra sección.  
Como nota adicional, agrega AWS AppSync automáticamente una raíz del esquema durante las exportaciones, por lo que técnicamente no es necesario agregarla directamente al esquema. Nuestro servicio procesará automáticamente los esquemas duplicados. Lo añadimos aquí como práctica recomendada.

------
#### [ CLI ]

**nota**  
Le recomendamos leer primero la versión de consola si aún no lo ha hecho.

1. Cree una raíz de `schema` con una definición `query` ejecutando el comando [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html).

   Para este comando en particular, deberá introducir varios parámetros:

   1. El `api-id` de su API.

   1. La `definition` o el contenido de su tipo. En el ejemplo de la consola, esto era:

      ```
      schema {
        query: Query
      }
      ```

   1. El `format` de su entrada. En este ejemplo, usaremos `SDL`.

   Un comando de ejemplo puede tener este aspecto:

   ```
   aws appsync create-type --api-id abcdefghijklmnopqrstuvwxyz --definition "schema {query: Query}" --format SDL
   ```

   Aparecerá un resultado en la CLI. A continuación se muestra un ejemplo:

   ```
   {
       "type": {
           "definition": "schema {query: Query}",
           "name": "schema",
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/schema",
           "format": "SDL"
       }
   }
   ```
**nota**  
Tenga en cuenta que si no ha introducido algo correctamente en el comando `create-type`, puede actualizar la raíz del esquema (o cualquier tipo del esquema) ejecutando el comando [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-type.html). En este ejemplo, cambiaremos temporalmente la raíz del esquema para que contenga una definición de `subscription`.  
Para este comando en particular, deberá introducir varios parámetros:  
El `api-id` de su API.
El `type-name` de su tipo. En el ejemplo de la consola, esto era `schema`.
La `definition` o el contenido de su tipo. En el ejemplo de la consola, esto era:  

      ```
      schema {
        query: Query
      }
      ```
El esquema después de añadir una `subscription` será como el siguiente:  

      ```
      schema {
        query: Query
        subscription: Subscription
      }
      ```
El `format` de su entrada. En este ejemplo, usaremos `SDL`.
Un comando de ejemplo puede tener este aspecto:  

   ```
   aws appsync update-type --api-id abcdefghijklmnopqrstuvwxyz --type-name schema --definition "schema {query: Query subscription: Subscription}" --format SDL
   ```
Aparecerá un resultado en la CLI. A continuación se muestra un ejemplo:  

   ```
   {
       "type": {
           "definition": "schema {query: Query subscription: Subscription}",
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/schema",
           "format": "SDL"
       }
   }
   ```
En este ejemplo, seguirá funcionando la adición de archivos preformateados.

1. Cree un tipo de `Query` ejecutando el comando [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html).

   Para este comando en particular, deberá introducir varios parámetros:

   1. El `api-id` de su API.

   1. La `definition` o el contenido de su tipo. En el ejemplo de la consola, esto era:

      ```
      type Query {
        getObj: [Obj_Type_1]
      }
      ```

   1. El `format` de su entrada. En este ejemplo, usaremos `SDL`.

   Un comando de ejemplo puede tener este aspecto:

   ```
   aws appsync create-type --api-id abcdefghijklmnopqrstuvwxyz --definition "type Query {getObj: [Obj_Type_1]}" --format SDL
   ```

   Aparecerá un resultado en la CLI. A continuación se muestra un ejemplo:

   ```
   {
       "type": {
           "definition": "Query {getObj: [Obj_Type_1]}",
           "name": "Query",
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Query",
           "format": "SDL"
       }
   }
   ```
**nota**  
En este paso, hemos añadido un tipo `Query` y lo hemos definido en su raíz de `schema`. Nuestro tipo `Query` ha definido un campo `getObj` que devuelve una lista de objetos `Obj_Type_1`.  
En el código de raíz de `schema` `query: Query`, la parte `query:` indica que se ha definido una consulta en el esquema, mientras que la parte `Query` indica el nombre real del objeto especial. 

------
#### [ CDK ]

**sugerencia**  
[Antes de usar la CDK, te recomendamos que consultes la [documentación oficial](https://docs.aws.amazon.com/cdk/v2/guide/home.html) de la CDK junto con AWS AppSync su referencia.](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
Los pasos que se indican a continuación solo mostrarán un ejemplo general del fragmento de código utilizado para añadir un recurso concreto. **No** se pretende que esta sea una solución funcional en su código de producción. También, se presupone que ya tiene una aplicación en funcionamiento.

Deberá añadir la consulta y la raíz del esquema al archivo `.graphql`. Nuestro caso era parecido al ejemplo siguiente, pero en este lo sustituirá con su código de esquema actual:

```
schema {
  query: Query
}

type Query {
  getObj: [Obj_Type_1]
}

type Obj_Type_1 {
  id: ID!
  title: String
  date: AWSDateTime
}
```

Puede añadir sus tipos directamente al esquema como cualquier otro archivo.

**nota**  
Actualizar la raíz del esquema es opcional. Lo hemos añadido a este ejemplo como práctica recomendada.  
Para usar los cambios realizados en la API de GraphQL, deberá volver a implementar la aplicación.

------

Ahora ya ha visto un ejemplo de creación tanto de objetos como de objetos especiales (consultas). También ha visto cómo se pueden interconectar para describir datos y operaciones. Puede tener esquemas con solo la descripción de los datos y una o más consultas. Sin embargo, nos gustaría añadir otra operación para añadir datos al origen de datos. Vamos a añadir otro tipo de objeto especial denominado `Mutation` que modifica los datos.

------
#### [ Console ]
+ Una mutación se llamará `Mutation`. Como en `Query`, las operaciones de campo de dentro de `Mutation` describirán una operación y se asociarán a un solucionador. Tenga en cuenta también que debemos definirla en la raíz `schema` porque es un tipo de objeto especial. Aquí tiene un ejemplo de mutación:

  ```
  schema {
    mutation: Name_of_Mutation
  }
  
  type Name_of_Mutation {
    # Add field operation here
  }
  ```

  Una mutación típica aparecerá en la raíz en forma de consulta. La mutación se define con la `type` palabra clave junto con el nombre. *Name\$1of\$1Mutation*normalmente se llamará así`Mutation`, por lo que recomendamos mantenerlo así. Cada campo realizará también una operación. En cuanto al formato de la operación de campo, podría ser como este:

  ```
  Name_of_Mutation(params): Return_Type # version with params
  Name_of_Mutation: Return_Type # version without params
  ```

  A continuación se muestra un ejemplo:

  ```
  schema {
    query: Query
    mutation: Mutation
  }
  
  type Obj_Type_1 {
    id: ID!
    title: String
    date: AWSDateTime
  }
  
  type Query {
    getObj: [Obj_Type_1]
  }
  
  type Mutation {
    addObj(id: ID!, title: String, date: AWSDateTime): Obj_Type_1
  }
  ```
**nota**  
En este paso, hemos añadido un tipo `Mutation` con un campo `addObj`. Vamos a resumir lo que hace este campo:  

  ```
  addObj(id: ID!, title: String, date: AWSDateTime): Obj_Type_1
  ```
`addObj` está utilizando el objeto `Obj_Type_1` para realizar una operación. Esto es evidente debido a los campos, pero la sintaxis lo demuestra en el tipo de retorno `: Obj_Type_1`. Dentro de `addObj`, acepta los campos `id`, `title` y `date` del objeto `Obj_Type_1` como parámetros. Como puede ver, es muy parecido a la declaración de un método. Sin embargo, aún no hemos descrito el comportamiento de nuestro método. Como se ha afirmado antes, el esquema solo está ahí para definir cuáles serán los datos y las operaciones, no cómo funcionan. La lógica empresarial real se implementará más adelante, cuando creemos nuestros primeros solucionadores.  
Una vez que haya terminado con su esquema, hay una opción para exportarlo como archivo `schema.graphql`. En el **editor de esquemas**, puede elegir **Exportar esquema** para descargar el archivo en un formato compatible.  
Como nota adicional, agrega AWS AppSync automáticamente una raíz del esquema durante las exportaciones, por lo que técnicamente no es necesario agregarla directamente al esquema. Nuestro servicio procesará automáticamente los esquemas duplicados. Lo añadimos aquí como práctica recomendada.

------
#### [ CLI ]

**nota**  
Le recomendamos leer primero la versión de consola si aún no lo ha hecho.

1. Actualice su esquema de raíz ejecutando el comando [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-type.html).

   Para este comando en particular, deberá introducir varios parámetros:

   1. El `api-id` de su API.

   1. El `type-name` de su tipo. En el ejemplo de la consola, esto era `schema`.

   1. La `definition` o el contenido de su tipo. En el ejemplo de la consola, esto era:

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

   1. El `format` de su entrada. En este ejemplo, usaremos `SDL`.

   Un comando de ejemplo puede tener este aspecto:

   ```
   aws appsync update-type --api-id abcdefghijklmnopqrstuvwxyz --type-name schema --definition "schema {query: Query mutation: Mutation}" --format SDL
   ```

   Aparecerá un resultado en la CLI. A continuación se muestra un ejemplo:

   ```
   {
       "type": {
           "definition": "schema {query: Query mutation: Mutation}",
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/schema",
           "format": "SDL"
       }
   }
   ```

1. Cree un tipo de `Mutation` ejecutando el comando [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html).

   Para este comando en particular, deberá introducir varios parámetros:

   1. El `api-id` de su API.

   1. La `definition` o el contenido de su tipo. En el ejemplo de la consola, esto era:

      ```
      type Mutation {
        addObj(id: ID!, title: String, date: AWSDateTime): Obj_Type_1
      }
      ```

   1. El `format` de su entrada. En este ejemplo, usaremos `SDL`.

   Un comando de ejemplo puede tener este aspecto:

   ```
   aws appsync create-type --api-id abcdefghijklmnopqrstuvwxyz --definition "type Mutation {addObj(id: ID! title: String date: AWSDateTime): Obj_Type_1}" --format SDL
   ```

   Aparecerá un resultado en la CLI. A continuación se muestra un ejemplo:

   ```
   {
       "type": {
           "definition": "type Mutation {addObj(id: ID! title: String date: AWSDateTime): Obj_Type_1}",
           "name": "Mutation",
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Mutation",
           "format": "SDL"
       }
   }
   ```

------
#### [ CDK ]

**sugerencia**  
[Antes de usar la CDK, te recomendamos que consultes la [documentación oficial](https://docs.aws.amazon.com/cdk/v2/guide/home.html) de la CDK junto con AWS AppSync su referencia.](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
Los pasos que se indican a continuación solo mostrarán un ejemplo general del fragmento de código utilizado para añadir un recurso concreto. **No** se pretende que esta sea una solución funcional en su código de producción. También, se presupone que ya tiene una aplicación en funcionamiento.

Deberá añadir la consulta y la raíz del esquema al archivo `.graphql`. Nuestro caso era parecido al ejemplo siguiente, pero en este lo sustituirá con su código de esquema actual:

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

type Obj_Type_1 {
  id: ID!
  title: String
  date: AWSDateTime
}

type Query {
  getObj: [Obj_Type_1]
}

type Mutation {
  addObj(id: ID!, title: String, date: AWSDateTime): Obj_Type_1
}
```

**nota**  
Actualizar la raíz del esquema es opcional. Lo hemos añadido a este ejemplo como práctica recomendada.  
Para usar los cambios realizados en la API de GraphQL, deberá volver a implementar la aplicación.

------

## Consideraciones opcionales: uso de enumeraciones como estados
<a name="optional-consideration-enums"></a>

Llegados a este punto, ya sabe cómo hacer un esquema básico. Sin embargo, hay muchas cosas que se pueden añadir para aumentar la funcionalidad del esquema. Una característica común que se encuentra en las aplicaciones es el uso de enumeraciones como estados. Puede usar una enumeración para forzar la elección de un valor específico de un conjunto de valores cuando se invoque. Esto es adecuado para cosas que sabe que no van a cambiar drásticamente durante largos períodos de tiempo. Hipotéticamente, podríamos añadir una enumeración que devuelva el código de estado o cadena en la respuesta. 

Como ejemplo, supongamos que vamos a crear una aplicación de redes sociales que almacene los datos de las publicaciones de un usuario en el backend. Nuestro esquema contiene un tipo `Post` que representa los datos de una publicación individual:

```
type Post {
  id: ID!
  title: String
  date: AWSDateTime
  poststatus: PostStatus
}
```

Nuestra `Post` contendrá un `id` único, un título de `title`, una `date` de publicación y una enumeración denominada `PostStatus` que representa el estado de la publicación a medida que la aplicación la procesa. Para nuestras operaciones, tendremos una consulta que devolverá todos los datos de la publicación:

```
type Query {
  getPosts: [Post]
}
```

También tendremos una mutación que añade publicaciones al origen de datos:

```
type Mutation {
  addPost(id: ID!, title: String, date: AWSDateTime, poststatus: PostStatus): Post
}
```

Si observamos nuestro esquema, la enumeración `PostStatus` podría tener varios estados. Tal vez que queramos que los tres estados básicos se llamen `success` (publicación procesada correctamente), `pending` (publicación procesada) y `error` (publicación que no se puede procesar). Para añadir la enumeración, podemos hacer lo siguiente:

```
enum PostStatus {
  success
  pending
  error
}
```

El esquema completo podría ser como este:

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

type Post {
  id: ID!
  title: String
  date: AWSDateTime
  poststatus: PostStatus
}

type Mutation {
  addPost(id: ID!, title: String, date: AWSDateTime, poststatus: PostStatus): Post
}

type Query {
  getPosts: [Post]
}

enum PostStatus {  
  success
  pending
  error
}
```

Si un usuario añade una `Post` en la aplicación, se llamará a la operación `addPost` para procesar esos datos. A medida que el solucionador adjunto a `addPost` procese los datos, actualizará continuamente `poststatus` con el estado de la operación. Cuando se consulte, `Post` contendrá el estado final de los datos. Tenga en cuenta que solo estamos describiendo cómo queremos que funcionen los datos en el esquema. Estamos haciendo muchas suposiciones sobre la implementación de nuestros solucionadores, que implementarán la lógica empresarial real para gestionar los datos a fin de cumplir con la solicitud.

## Consideraciones opcionales: suscripciones
<a name="optional-consideration-subscriptions"></a>

Las suscripciones en AWS AppSync se invocan como respuesta a una mutación. Se puede configurar con un tipo `Subscription` y una directiva `@aws_subscribe()` en el esquema para indicar qué mutaciones invocan una o varias suscripciones. Para obtener más información sobre cómo configurar suscripciones, consulte [Datos en tiempo real](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-data.html).

## Consideraciones opcionales: relaciones y paginación
<a name="optional-consideration-relations-and-pagination"></a>

Supongamos que tiene un millón de `Posts` almacenadas en una tabla de DynamoDB y desea devolver algunos de esos datos. Sin embargo, la consulta de ejemplo anterior solo devuelve todas las publicaciones. No le interesa buscarlas todas cada vez que realice una solicitud. Más bien, le interesa [paginarlas](https://graphql.org/learn/pagination/). Realice los cambios siguientes en su esquema:
+ En el campo `getPosts`, añada dos argumentos de entrada: `nextToken` (iterador) y `limit` (límite de iteración).
+ Añada un nuevo tipo de `PostIterator` que contenga los campos `Posts` (recupera la lista de objetos `Post`) y `nextToken` (iterador).
+ Modifique `getPosts` para que devuelva `PostIterator` y no una lista de objetos de `Post`.

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

type Post {
  id: ID!
  title: String
  date: AWSDateTime
  poststatus: PostStatus
}

type Mutation {
  addPost(id: ID!, title: String, date: AWSDateTime, poststatus: PostStatus): Post
}

type Query {
  getPosts(limit: Int, nextToken: String): PostIterator
}

enum PostStatus {
  success
  pending
  error
}

type PostIterator {
  posts: [Post]
  nextToken: String
}
```

El tipo `PostIterator` le permite devolver una parte de la lista de objetos de `Post` y un `nextToken` para obtener la parte siguiente. Dentro de `PostIterator`, hay una lista de elementos de `Post` (`[Post]`) que se devuelve con un token de paginación (`nextToken`). En AWS AppSync, se conectaría a Amazon DynamoDB a través de un solucionador y se generaría automáticamente como un token cifrado. Así se convierte el valor del argumento `limit` en el parámetro `maxResults` y el argumento `nextToken` en el parámetro `exclusiveStartKey`. Para ver ejemplos y los ejemplos de plantillas integradas en la AWS AppSync consola, consulte [Resolver reference () JavaScript](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

# Adjuntar una fuente de datos en AWS AppSync
<a name="attaching-a-data-source"></a>

Las fuentes de datos son recursos de tu AWS cuenta con los que GraphQL APIs puede interactuar. AWS AppSync admite múltiples fuentes de datos AWS Lambda, como Amazon DynamoDB, bases de datos relacionales (Amazon Aurora Serverless), OpenSearch Amazon Service y puntos de enlace HTTP. Se puede configurar una AWS AppSync API para interactuar con varias fuentes de datos, lo que le permite agregar datos en una sola ubicación. AWS AppSync puede utilizar AWS los recursos existentes de su cuenta o aprovisionar tablas de DynamoDB en su nombre a partir de una definición de esquema.

La sección siguiente muestra cómo asociar un origen de datos a la API de GraphQL.

## Tipos de orígenes de datos
<a name="data-source-types"></a>

Ahora que ha creado un esquema en la AWS AppSync consola, puede adjuntarle una fuente de datos. Al crear una API por primera vez, existe la opción de aprovisionar una tabla de Amazon DynamoDB durante la creación del esquema predefinido. Sin embargo, en esta sección no hablaremos de esa opción. Puede ver un ejemplo de esto en la sección [Lanzamiento de un esquema](https://docs.aws.amazon.com//appsync/latest/devguide/schema-launch-start.html).

En su lugar, analizaremos todas las fuentes de datos AWS AppSync compatibles. Para elegir la solución adecuada para su aplicación se tienen en cuenta numerosos factores. Las siguientes secciones proporcionarán más contexto para cada origen de datos. Para obtener información general sobre los orígenes de datos, consulte [Orígenes de datos](https://docs.aws.amazon.com/appsync/latest/devguide/data-source-components.html).

### Amazon DynamoDB
<a name="data-source-type-ddb"></a>

Amazon DynamoDB es una de las principales soluciones AWS de almacenamiento para aplicaciones escalables. El componente principal de DynamoDB es la **tabla**, que es simplemente una recopilación de datos. Por lo general, las tablas se crean a partir de entidades como `Book` o `Author`. La información de las entradas de la tabla se almacena como **elementos**, que son grupos de campos únicos para cada entrada. Un elemento completo representa un elemento de la base row/record de datos. Por ejemplo, un elemento de una entrada de `Book` puede incluir `title` y `author` junto con sus valores. Cada uno de los campos, como el de `title` y el de `author`, se denominan **atributos**, que son similares a los valores de las columnas en las bases de datos relacionales. 

Como puede adivinar, las tablas se utilizarán para almacenar datos de su aplicación. AWS AppSync le permite conectar las tablas de DynamoDB a la API de GraphQL para manipular los datos. Tomemos este [caso de uso](https://aws.amazon.com/blogs/mobile/new-real-time-multi-group-app-with-aws-amplify-graphql-build-a-twitter-community-clone/) del *blog Frontend web y móvil*. Esta aplicación permite a los usuarios registrarse en una aplicación de redes sociales. Los usuarios pueden unirse a grupos y cargar publicaciones que se difunden a otros usuarios suscritos al grupo. Su aplicación almacena información de usuarios, de publicaciones y de grupos de usuarios en DynamoDB. La API de GraphQL (gestionada por AWS AppSync) interactúa con la tabla de DynamoDB. Cuando un usuario realiza cambios en el sistema que se vaya a reflejar en el frontend, la API de GraphQL los recupera y los difunde a otros usuarios en tiempo real.

### AWS Lambda
<a name="data-source-type-lam"></a>

Lambda es un servicio basado en eventos que crea automáticamente los recursos necesarios para ejecutar código como respuesta a un evento. Lambda utiliza **funciones**, es decir, instrucciones de grupo que contienen el código, las dependencias y las configuraciones para ejecutar un recurso. Las funciones se ejecutan automáticamente cuando detectan un **disparador**, es decir, un grupo de actividades que invocan la función. Un desencadenante puede ser cualquier cosa, como una aplicación que realiza una llamada a la API, un AWS servicio de tu cuenta que activa un recurso, etc. Cuando se activen, las funciones procesarán **eventos**, que son documentos JSON que contienen los datos que se van a modificar.

Lambda es ideal para ejecutar código sin tener que aprovisionar los recursos para ejecutarlo. Tomemos este [caso de uso](https://aws.amazon.com/blogs/mobile/building-a-graphql-api-with-java-and-aws-lambda/) del *blog Frontend web y móvil*. Este caso de uso es algo parecido al que se muestra en la sección de DynamoDB. En esta aplicación, la API de GraphQL es responsable de definir las operaciones para acciones como la incorporación de publicaciones (mutaciones) y la obtención de esos datos (consultas). Para implementar la funcionalidad de sus operaciones (por ejemplo, `getPostsByAuthor ( author: String ! ) : [ Post ]` o `getPost ( id: String ! ) : Post`), utilizan las funciones de Lambda para procesar las solicitudes entrantes. En *la opción 2: AWS AppSync con el solucionador Lambda*, utilizan el AWS AppSync servicio para mantener su esquema y vincular una fuente de datos Lambda a una de las operaciones. Cuando se llama a la operación, Lambda interactúa con el Amazon RDS proxy para ejecutar la lógica empresarial en la base de datos.

### Amazon RDS
<a name="data-source-type-RDS"></a>

Amazon RDS permite crear y configurar rápidamente bases de datos relacionales. En Amazon RDS, creará una **instancia de base de datos** genérica que servirá como entorno de base de datos aislado en la nube. En esta instancia, utilizará un **motor de base** de datos, que es de hecho el software de RDBMS (PostgreSQL, MySQL, etc.). El servicio reduce gran parte del trabajo de back-end, ya que proporciona escalabilidad mediante la AWS«infraestructura» y los servicios de seguridad, como la aplicación de parches y el cifrado, y reduce los costes administrativos de las implementaciones.

Tomemos el mismo [caso de uso](https://aws.amazon.com/blogs/mobile/building-a-graphql-api-with-java-and-aws-lambda/) de la sección Lambda. En *la opción 3: AWS AppSync con Amazon RDS Resolver*, se presenta otra opción que consiste en vincular la API GraphQL directamente AWS AppSync a Amazon RDS. Mediante una [API de datos](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/data-api.html), asocian la base de datos con la API de GraphQL. Un solucionador se adjunta a un campo (normalmente una consulta, una mutación o una suscripción) e implementa las instrucciones SQL necesarias para acceder a la base de datos. Cuando el cliente realiza una solicitud de llamada del campo, el solucionador ejecuta las instrucciones y devuelve la respuesta.

### Amazon EventBridge
<a name="data-source-type-eventbridge"></a>

En EventBridge, crearás **buses de eventos**, que son canalizaciones que reciben eventos de los servicios o aplicaciones que adjuntas (la **fuente de eventos**) y los procesarán en función de un conjunto de reglas. Un **evento** es un cambio de estado de un entorno de ejecución, mientras que una **regla** es un conjunto de filtros para eventos. Una regla sigue un **patrón de eventos** o los metadatos del cambio de estado de un evento (ID, región, número de cuenta, ARN, etc.). Cuando un evento coincide con el patrón de eventos, EventBridge lo enviará a través de la canalización hasta el servicio de destino (**objetivo**) y activará la acción especificada en la regla.

EventBridge es adecuado para enrutar las operaciones que cambian de estado a algún otro servicio. Tomemos este [caso de uso](https://aws.amazon.com/blogs/mobile/appsync-eventbridge/) del *blog Frontend web y móvil*. El ejemplo muestra una solución de comercio electrónico en la que varios equipos mantienen servicios diversos. Uno de estos servicios proporciona al cliente actualizaciones de los pedidos en cada paso de la entrega (pedido realizado, en curso, enviado, entregado, etc.) en el frontend. Sin embargo, el equipo de frontend que gestiona este servicio no tiene acceso directo a los datos del sistema de pedidos, ya que los mantiene un equipo de backend independiente. El sistema de pedidos del equipo de backend también se describe como una caja negra, por lo que es difícil obtener información sobre la forma en que estructuran sus datos. Sin embargo, el equipo de backend creó un sistema que publicaba los datos de los pedidos a través de un bus de eventos gestionado por. EventBridge Para acceder a los datos procedentes del bus de eventos y dirigirlos al front-end, el equipo de front-end creó un nuevo objetivo que apuntaba a su API GraphQL ubicada en ella. AWS AppSync También han creado una regla para enviar solo los datos relevantes para la actualización del pedido. Cuando se realiza una actualización, los datos del bus de eventos se envían a la API de GraphQL. El esquema de la API procesa los datos y, a continuación, los pasa al frontend.

### Orígenes de datos none
<a name="data-source-type-none"></a>

Si no tiene pensado utilizar un origen de datos, puede configurarlo como `none`. Un origen de datos `none`, aunque se siga considerando explícitamente un origen de datos, no es un medio de almacenamiento. Por lo general, un solucionador invocará uno o más orígenes de datos en algún momento para procesar la solicitud. Sin embargo, hay situaciones en las que tal vez no sea necesario manipular un origen de datos. Si se configura el origen de datos en `none`, se ejecutará la solicitud, se omitirá el paso de invocación de datos y, a continuación, se ejecutará la respuesta.

Tomemos el mismo [caso de uso](https://aws.amazon.com/blogs/mobile/appsync-eventbridge/) de la sección. EventBridge En el esquema, la mutación procesa la actualización del estado y, a continuación, la envía a los suscriptores. Al recordar cómo funcionan los solucionadores, normalmente hay al menos una invocación al origen de datos. Sin embargo, en este escenario, el bus de eventos ya ha enviado los datos automáticamente. Esto significa que no es necesario que la mutación realice una invocación al origen de datos, sino que el estado del pedido puede gestionarse simplemente de forma local. La mutación se establece en `none`, que actúa como un valor de transferencia sin invocar el origen de datos. A continuación, se rellena el esquema con los datos, que se envían a los suscriptores.

### OpenSearch
<a name="data-source-type-opensearch"></a>

Amazon OpenSearch Service es un conjunto de herramientas para implementar la búsqueda de texto completo, la visualización de datos y el registro. Puede utilizar este servicio para consultar los datos estructurados que ha cargado.

En este servicio, crearás instancias de OpenSearch. Estos se denominan **nodos**. En un nodo, agregará al menos un **índice**. Conceptualmente, los índices se parece un poco a las tablas de bases de datos relacionales. (Sin embargo, OpenSearch no es compatible con ACID, por lo que no debe usarse de esa manera). Rellenarás tu índice con los datos que subas al OpenSearch servicio. Cuando se carguen los datos, se indexarán en una o más particiones que existan en el índice. Una **partición** es como una subdivisión del índice que contiene algunos de sus datos y se puede consultar por separado de otras particiones. Una vez cargados, los datos se estructurarán como archivos JSON denominados **documentos**. A continuación, puede consultar los datos del documento en el nodo.

### Puntos de conexión HTTP
<a name="data-source-type-http"></a>

Puedes usar puntos de enlace HTTP como fuentes de datos. AWS AppSync puede enviar solicitudes a los puntos finales con la información relevante, como los parámetros y la carga útil. La respuesta HTTP estará expuesta al solucionador, que devolverá la respuesta final cuando finalice sus operaciones.

## Adición de un origen de datos
<a name="adding-a-data-source"></a>

Si ha creado una fuente de datos, puede vincularla al AWS AppSync servicio y, más específicamente, a la API.

------
#### [ Console ]

1. Inicie sesión en la [AppSyncconsola Consola de administración de AWS y ábrala](https://console.aws.amazon.com/appsync/).

   1. En el **panel**, elija su API.

   1. En la **barra lateral**, seleccione **Origen de datos**.

1. Elija **Crear origen de datos**.

   1. Asigne un nombre al origen de datos. También puede asignarle una descripción, pero eso es opcional.

   1. Elija el **tipo de origen de datos**.

   1. Para DynamoDB, elija su región y, a continuación, la tabla dentro de la región. Para dictar las reglas de interacción con su tabla, elija crear un nuevo rol de tabla genérico o importe un rol existente para la tabla. Puede habilitar el [control de versiones](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html), que permite crear automáticamente versiones de los datos para cada solicitud cuando hay varios clientes intentando actualizar los datos al mismo tiempo. El control de versiones se utiliza para conservar y mantener múltiples variantes de datos con el fin de detectar y resolver conflictos. También puede habilitar la generación automática de esquemas, que toma el origen de datos y genera algunas de las operaciones CRUD, `List` y `Query` necesarias para acceder a ella en el esquema. 

      Para OpenSearch ello, tendrás que elegir tu región y, a continuación, el dominio (clúster) de la región. Para dictar las reglas de interacción con su dominio, elija crear un nuevo rol de tabla genérico o importe un rol existente para la tabla. 

      Para Lambda, elija su región y, a continuación, el ARN de la función de Lambda de la región. Para dictar las reglas de interacción con su función de Lambda, elija crear un nuevo rol de tabla genérico o importe un rol existente para la tabla. 

      Para HTTP, introduzca su punto de conexión HTTP.

      Para EventBridge ello, tendrás que elegir tu región y, a continuación, el autobús del evento en la región. Para dictar las reglas de interacción con su bus de eventos, elija crear un nuevo rol de tabla genérico o importe un rol existente para la tabla. 

      Para RDS, elija su región y, a continuación, el almacén secreto (nombre de usuario y contraseña), el nombre de la base de datos y el esquema.

      Para none, añada un origen de datos sin un origen de datos real. Esto sirve para gestionar los solucionadores de forma local y no a través de un origen de datos real.
**nota**  
Si importa roles existentes, estos necesitan una política de confianza. Para obtener más información, consulte la [política de confianza de IAM](#iam-trust-policy.title).

1. Seleccione **Crear**.
**nota**  
Como alternativa, si va a crear un origen de datos de DynamoDB, puede ir a la página **Esquema** de la consola, elegir **Crear recursos** en la parte superior de la página y, a continuación, rellenar un modelo predefinido para convertirlo en una tabla. En esta opción, rellenará o importará el tipo base, configurará los datos básicos de la tabla, incluida la clave de partición, y revisará los cambios del esquema.

------
#### [ CLI ]
+ Cree su origen de datos ejecutando el comando [https://docs.aws.amazon.com/cli/latest/reference/appsync/create-data-source.html](https://docs.aws.amazon.com/cli/latest/reference/appsync/create-data-source.html).

  Para este comando en particular, deberá introducir varios parámetros:

  1. El `api-id` de su API.

  1. El `name` de su tabla.

  1. El `type` de su origen de datos. Según el tipo de origen de datos que elija, es posible que deba introducir una etiqueta `service-role-arn` y `-config`.

  Un comando de ejemplo puede tener este aspecto:

  ```
   aws appsync create-data-source --api-id abcdefghijklmnopqrstuvwxyz --name data_source_name --type data_source_type --service-role-arn arn:aws:iam::107289374856:role/role_name --[data_source_type]-config {params}
  ```

------
#### [ CDK ]

**sugerencia**  
[Antes de usar la CDK, te recomendamos que consultes la [documentación oficial](https://docs.aws.amazon.com/cdk/v2/guide/home.html) de la CDK junto con AWS AppSync su referencia.](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
Los pasos que se indican a continuación solo mostrarán un ejemplo general del fragmento de código utilizado para añadir un recurso concreto. **No** se pretende que esta sea una solución funcional en su código de producción. También, se presupone que ya tiene una aplicación en funcionamiento.

Para añadir un origen de datos concreto, añada el constructo a su archivo de pila. Puede encontrar una lista de los tipos de orígenes de datos aquí:
+  [ DynamoDbDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.DynamoDbDataSource.html) 
+  [ EventBridgeDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.EventBridgeDataSource.html) 
+  [ HttpDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.HttpDataSource.html) 
+  [ LambdaDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.LambdaDataSource.html) 
+  [ NoneDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.NoneDataSource.html) 
+  [ OpenSearchDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.OpenSearchDataSource.html) 
+  [ RdsDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.RdsDataSource.html) 

1. En general, puede que tenga que añadir la directiva de importación al servicio que utilice. Por ejemplo, puede seguir estas formas:

   ```
   import * as x from 'x'; # import wildcard as the 'x' keyword from 'x-service'
   import {a, b, ...} from 'c'; # import {specific constructs} from 'c-service'
   ```

   Por ejemplo, así es como puede importar los servicios AWS AppSync y DynamoDB:

   ```
   import * as appsync from 'aws-cdk-lib/aws-appsync';
   import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
   ```

1. Algunos servicios, como RDS, requieren una configuración adicional en el archivo de pila antes de crear el origen de datos (por ejemplo, la creación de VPC, las funciones y las credenciales de acceso). Consulte los ejemplos de las páginas de CDK correspondientes para obtener más información.

1. Para la mayoría de las fuentes de datos, especialmente AWS los servicios, creará una nueva instancia de la fuente de datos en el archivo de pila. Normalmente, será como esta:

   ```
   const add_data_source_func = new service_scope.resource_name(scope: Construct, id: string, props: data_source_props);
   ```

   Por ejemplo, a continuación se muestra un ejemplo de tabla de Amazon DynamoDB:

   ```
   const add_ddb_table = new dynamodb.Table(this, 'Table_ID', {
     partitionKey: {
       name: 'id',
       type: dynamodb.AttributeType.STRING,
     },
     sortKey: {
       name: 'id',
       type: dynamodb.AttributeType.STRING,
     },
     tableClass: dynamodb.TableClass.STANDARD,
   });
   ```
**nota**  
La mayoría de los orígenes de datos tendrán al menos un accesorio obligatorio (se indicará **sin** el símbolo `?`). Consulte la documentación del CDK para ver qué accesorios se necesitan.

1. A continuación, debe enlazar el origen de datos a la API de GraphQL. El método recomendado es añadirlo al crear una función para su solucionador de canalizaciones. Por ejemplo, el fragmento de código siguiente es una función que analiza todos los elementos de una tabla de DynamoDB:

   ```
   const add_func = new appsync.AppsyncFunction(this, 'func_ID', {
     name: 'func_name_in_console',
     add_api,
     dataSource: add_api.addDynamoDbDataSource('data_source_name_in_console', add_ddb_table),
     code: appsync.Code.fromInline(`
         export function request(ctx) {
           return { operation: 'Scan' };
         }
   
         export function response(ctx) {
           return ctx.result.items;
         }
     `),
     runtime: appsync.FunctionRuntime.JS_1_0_0,
   });
   ```

   En los accesorios de `dataSource`, puede llamar a la API de GraphQL (`add_api`) y usar uno de sus métodos integrados (`addDynamoDbDataSource`) para realizar la asociación entre la tabla y la API de GraphQL. Los argumentos son el nombre de este enlace que existirá en la AWS AppSync consola (`data_source_name_in_console`en este ejemplo) y el método de tabla (`add_ddb_table`). Encontrará más información sobre este tema en la sección siguiente cuando empiece a crear solucionadores.

   Existen métodos alternativos para enlazar un origen de datos. Técnicamente, podría añadir `api` a la lista de accesorios de la función de tabla. Por ejemplo, este es el fragmento de código del paso 3, pero con un accesorio `api` que contiene una API de GraphQL:

   ```
   const add_api = new appsync.GraphqlApi(this, 'API_ID', {
     ...
   });
   
   const add_ddb_table = new dynamodb.Table(this, 'Table_ID', {
   
    ...
   
     api: add_api
   });
   ```

   Como alternativa, puede llamar al constructo `GraphqlApi` por separado:

   ```
   const add_api = new appsync.GraphqlApi(this, 'API_ID', {
     ...
   });
   
   const add_ddb_table = new dynamodb.Table(this, 'Table_ID', {
     ...
   });
   
   const link_data_source = add_api.addDynamoDbDataSource('data_source_name_in_console', add_ddb_table);
   ```

   Recomendamos crear la asociación únicamente en los accesorios de la función. De lo contrario, tendrás que vincular la función de resolución a la fuente de datos manualmente en la AWS AppSync consola (si quieres seguir utilizando el valor de la consola`data_source_name_in_console`) o crear una asociación independiente en la función con otro nombre, por ejemplo`data_source_name_in_console_2`. Esto se debe a las limitaciones en la forma en que los accesorios procesan la información.
**nota**  
Deberá volver a implementar la aplicación para ver los cambios.

------

### Política de confianza de IAM
<a name="iam-trust-policy"></a>

Si utiliza una función de IAM existente para su fuente de datos, debe conceder a esa función los permisos adecuados para realizar operaciones en el AWS recurso, por ejemplo, `PutItem` en una tabla de Amazon DynamoDB. También debe modificar la política de confianza de ese rol para poder usarlo para el acceso AWS AppSync a los recursos, como se muestra en el siguiente ejemplo de política:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
        "Effect": "Allow",
        "Principal": {
            "Service": "appsync.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
        }
    ]
}
```

------

También puede añadir condiciones a su política de confianza para limitar el acceso al origen de datos según lo desee. Actualmente, las claves `SourceArn` y `SourceAccount` se pueden utilizar en estas condiciones. Por ejemplo, la política siguiente limita el acceso a su origen de datos a la cuenta `123456789012`:

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "appsync.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "123456789012"
        }
      }
    }
  ]
}
```

------

Como alternativa, puede limitar el acceso a un origen de datos a una API específica, por ejemplo `abcdefghijklmnopq`, mediante la política siguiente:

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "appsync.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "arn:aws:appsync:us-west-2:123456789012:apis/abcdefghijklmnopq"
        }
      }
    }
  ]
}
```

------

Puedes limitar el acceso a todos los AWS AppSync APIs usuarios de una región específica, por ejemplo`us-east-1`, mediante la siguiente política:

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "appsync.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "arn:aws:appsync:us-east-1:123456789012:apis/*"
        }
      }
    }
  ]
}
```

------

En la sección siguiente ([Configuración de los solucionadores](https://docs.aws.amazon.com//appsync/latest/devguide/resolver-config-overview.html)), añadiremos nuestra lógica empresarial de solucionador y la asociaremos a los campos de nuestro esquema para procesar los datos de nuestro origen de datos.

Para obtener más información sobre la configuración de la política de roles, consulte [Modificación de un rol](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_manage_modify.html) en la *Guía del usuario de IAM*.

Para obtener más información sobre el acceso de los AWS Lambda solucionadores entre cuentas AWS AppSync, consulte [Crear dispositivos de resolución multicuenta AWS Lambda](https://aws.amazon.com/blogs/mobile/appsync-lambda-cross-account/) para. AWS AppSync

# Configuración de solucionadores en AWS AppSync
<a name="resolver-config-overview"></a>

En las secciones anteriores, vimos cómo crear el esquema de GraphQL y el origen de datos, para luego vincularlos juntos en el servicio de AWS AppSync. En su esquema, tal vez haya establecido uno o más campos (operaciones) en la consulta y la mutación. Si bien el esquema describía los tipos de datos que las operaciones solicitarían al origen de datos, no se implementó el comportamiento de esas operaciones con respecto a los datos. 

El comportamiento de una operación se implementa siempre en el solucionador, que esta vinculado al campo que realiza la operación. Para obtener más información sobre el funcionamiento general de los solucionadores, consulte la página [Solucionadores](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-components.html).

En AWS AppSync, su solucionador está vinculado a un tiempo de ejecución, que es el entorno en el que se ejecuta su solucionador. Los tiempos de ejecución determinan el lenguaje en el que se escribirá la resolución. Actualmente se admiten dos tiempos de ejecución: APPSYNC\$1JS (JavaScript) y Apache Velocity Template Language (VTL). 

Al implementar los solucionadores, estos siguen una estructura general:
+ **Paso anterior**: cuando el cliente realiza una solicitud, los datos de esta se envían a los solucionadores de los campos de esquema que se usan (normalmente, las consultas, las mutaciones y las suscripciones). El solucionador empezará a procesar los datos de la solicitud con un controlador previo paso a paso, que permite realizar algunas operaciones de preprocesamiento antes de que los datos pasen por el solucionador.
+ **Funciones**: una vez ejecutado el paso anterior, la solicitud se pasa a la lista de funciones. La primera función de la lista se ejecuta conforme al origen de datos. Una función es un subconjunto del código de su solucionador, que contiene su propio controlador de solicitudes y respuestas. Un controlador de solicitudes toma los datos de la solicitud y realiza operaciones con el origen de datos. El controlador de respuestas procesa la respuesta del origen de datos antes de devolverla a la lista. Si hay más de una función, los datos de la solicitud se envían a la siguiente función de la lista que se ejecutará. Las funciones de la lista se ejecutan en serie en el orden definido por el desarrollador. Una vez ejecutadas todas las funciones, el resultado final se envía al paso posterior.
+ **Paso posterior**: el paso posterior es una función de controlador que permite realizar algunas operaciones finales en la respuesta de la función final antes de pasarla a la respuesta de GraphQL.

Este flujo es un ejemplo de un solucionador de canalizaciones. Los solucionadores de canalizaciones son compatibles con ambos tiempos de ejecución. Sin embargo, esta es una explicación simplificada de lo que pueden hacer los solucionadores de canalizaciones. Además, solo describimos una posible configuración del solucionador. Para obtener más información sobre las configuraciones de solucionador compatibles, consulte el artículo [Descripción general de los solucionadores de JavaScript](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html) para APPSYNC\$1JS o [Información general sobre las plantillas de mapeo de solucionador](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-overview.html) para VTL.

Como puede ver, los solucionadores son modulares. Para que los componentes del solucionador funcionen correctamente, deben poder observar el estado de la ejecución desde otros componentes. En la sección [Solucionadores](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-components.html) ya hemos visto que a cada componente del solucionador se le puede pasar información crítica sobre el estado de la ejecución en forma de un conjunto de argumentos (`args`, `context`, etc.). En AWS AppSync, esto lo controla estrictamente el `context`. Se trata de un contenedor de la información acerca del campo que se está solucionando. Aquí se puede incluir de todo, desde los argumentos que se pasan hasta los resultados, pasando por los datos de autorización, los datos del encabezado, etc. Para obtener más información sobre el contexto, consulte [Referencia al objeto del contexto del solucionador](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html) para APPSYNC\$1JS o [Referencia de contexto de las plantillas de mapeo del solucionador](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference.html) para VTL.

El contexto no es la única herramienta que puede utilizar para implementar su solucionador. AWS AppSync admite una amplia gama de utilidades para la generación de valor, el manejo de errores, el análisis, la conversión, etc. Puede ver una lista de utilidades [aquí](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference-js.html) para APPSYNC\$1JS o [aquí](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference.html) para VTL.

En las siguientes secciones, verá cómo configurar solucionadores en su API de GraphQL.

**Topics**
+ [Creación de consultas básicas (JavaScript)](configuring-resolvers-js.md)
+ [Creación de consultas básicas (VTL)](configuring-resolvers.md)

# Creación de consultas básicas (JavaScript)
<a name="configuring-resolvers-js"></a>

Los solucionadores de GraphQL conectan los campos de un esquema de tipo a un origen de datos. Los solucionadores son el mecanismo mediante el cual se atienden las solicitudes.

Resolvers que se AWS AppSync utilizan JavaScript para convertir una expresión de GraphQL en un formato que pueda utilizar la fuente de datos. Como alternativa, las plantillas de asignación se pueden escribir en [Apache Velocity Template Language (VTL)](https://velocity.apache.org/engine/2.0/vtl-reference.html) para convertir una expresión de GraphQL en un formato que el origen de datos pueda utilizar.

En esta sección se describe cómo configurar los resolutores mediante. JavaScript La sección [Tutoriales de resolución (JavaScript)](https://docs.aws.amazon.com/appsync/latest/devguide/tutorials-js.html) proporciona tutoriales detallados sobre cómo implementar resolutores utilizando. JavaScript La sección de [referencia del solucionador (JavaScript)](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html) proporciona una explicación de las operaciones de utilidad que se pueden utilizar con los JavaScript resolutores.

Recomendamos seguir esta guía antes de intentar utilizar alguno de los tutoriales mencionados anteriormente.

En esta sección se mostrará cómo crear y configurar solucionadores para consultas y mutaciones.

**nota**  
En esta guía se supone que ha creado su esquema y que tiene al menos una consulta o mutación. Si busca suscripciones (datos en tiempo real), consulte [esta](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-data.html) guía.

En esta sección, proporcionaremos algunos pasos generales para configurar solucionadores junto con un ejemplo que usa el esquema siguiente:

```
// schema.graphql file

input CreatePostInput {
  title: String
  date: AWSDateTime
}

type Post {
  id: ID!
  title: String
  date: AWSDateTime
}

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

type Query {
  getPost: [Post]
}
```

## Creación de solucionadores de consultas básicos
<a name="create-basic-query-resolver-js"></a>

En esta sección se mostrará cómo crear un solucionador de consultas básico.

------
#### [ Console ]

1. Inicie sesión en la [AppSyncconsola Consola de administración de AWS](https://console.aws.amazon.com/appsync/) y ábrala.

   1. En el **APIs panel de control**, elige tu API de GraphQL.

   1. En la **barra lateral**, seleccione **Esquema**.

1. Introduzca los detalles del esquema y el origen de datos. Consulte las secciones [Diseño del esquema](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html) y [Asociar un origen de datos](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html) para obtener más información.

1. Junto al editor **Esquemas**, hay una ventana llamada **Solucionadores**. Este cuadro contiene una lista de los tipos y campos definidos en la ventana **Esquema**. Puede asociar solucionadores a los campos. Lo más probable es que asocie solucionadores a sus operaciones de campo. En esta sección se analizarán las configuraciones de consultas sencillas. En el tipo **Consulta**, seleccione **Asociar** junto al campo de la consulta.

1. En la página **Asociar solucionador**, en **Tipo de solucionador**, puede elegir entre solucionadores de canalización o unitarios. Para obtener más información sobre estos tipos, consulte [Solucionadores](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-components.html). En esta guía se utilizará `pipeline resolvers`.
**sugerencia**  
Al crear solucionadores de canalización, sus orígenes de datos se asociarán a las funciones de canalización. Las funciones se crean después de crear el propio solucionador de canalizaciones, por lo que no existe la opción de configurarlo en esta página. Si utiliza un solucionador unitario, el origen de datos se vincula directamente al solucionador, por lo que deberá configurarlo en esta página.

   Para el **tiempo de ejecución de Resolver**, selecciona `APPSYNC_JS` habilitar el JavaScript tiempo de ejecución.

1. Puede habilitar el [almacenamiento en caché](https://docs.aws.amazon.com/appsync/latest/devguide/enabling-caching.html) para esta API. También recomendamos desactivar esta característica por el momento. Seleccione **Crear**.

1. En la página **Editar solucionador**, hay un editor de código llamado **Código de solucionador** que le permite implementar la lógica para el controlador y la respuesta del solucionador (antes y después de los pasos). Para obtener más información, consulte la [descripción general de los JavaScript resolutores](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html). 
**nota**  
En nuestro ejemplo, vamos a dejar la solicitud en blanco y la respuesta establecida para devolver el último resultado del origen de datos del [contexto](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html):  

   ```
   import {util} from '@aws-appsync/utils';
   
   export function request(ctx) {
       return {};
   }
   
   export function response(ctx) {
       return ctx.prev.result;
   }
   ```

   Bajo esta sección, hay una tabla llamada **Funciones**. Las funciones permiten implementar código que se puede reutilizar en varios solucionadores. En lugar de tener que reescribir o copiar el código constantemente, puede almacenar el código fuente como una función para añadirla a un solucionador siempre que lo necesite. 

   Las funciones constituyen la mayor parte de la lista de operaciones de una canalización. Al utilizar varias funciones en un solucionador, se establece el orden de las funciones y estas se ejecutan en ese orden en secuencia. Se ejecutan después de la función de solicitud y antes de que comience la función de respuesta.

   Para añadir una función nueva, en **Funciones**, seleccione **Añadir función** y, a continuación, **Crear nueva función**. Como alternativa, puede que vea el botón **Crear función** para seleccionarlo.

   1. Elija un origen de datos. Será el origen de datos en el que actuará el solucionador.
**nota**  
En nuestro ejemplo, asociamos un solucionador para `getPost`, que recupera un objeto `Post` según el `id`. Supongamos que ya hemos configurado una tabla de DynamoDB para este esquema. Su clave de partición está establecida en `id` y está vacía.

   1. Introduzca un `Function name`.

   1. En **Código de función**, deberá implementar el comportamiento de la función. Esto puede resultar confuso, pero cada función tendrá su propio controlador local de solicitudes y respuestas. Se ejecuta la solicitud, luego se invoca el origen de datos para gestionar la solicitud y, a continuación, el controlador de respuestas procesa la respuesta del origen de datos. El resultado se almacena en el objeto de [contexto](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html). Después, se ejecutará la siguiente función de la lista o se pasará al controlador de respuestas posterior al paso si es el último. 
**nota**  
En nuestro ejemplo, asociamos un solucionador a `getPost`, que obtiene una lista de objetos `Post` del origen de datos. Nuestra función de solicitud solicitará los datos de nuestra tabla, la tabla pasará su respuesta al contexto (ctx) y, a continuación, la respuesta devolverá el resultado en el contexto. AWS AppSync Su punto fuerte reside en su interconexión con otros servicios. AWS Dado que utilizamos DynamoDB, tenemos un [conjunto de operaciones](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html) para simplificar este tipo de acciones. También tenemos algunos ejemplos repetitivos para otros tipos de orígenes de datos.  
Nuestro código será como este:  

      ```
      import { util } from '@aws-appsync/utils';
      
      /**
       * 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;
      }
      ```
En este paso, hemos añadido dos funciones:  
`request`: el controlador de solicitudes realiza la operación de recuperación en el origen de datos. El argumento contiene el objeto de contexto (`ctx`) o datos que están disponibles para todos los solucionadores que realizan una operación determinada. Por ejemplo, puede contener datos de autorización, los nombres de los campos que se están resolviendo, etc. La instrucción return realiza una operación [https://docs.aws.amazon.com//appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-scan](https://docs.aws.amazon.com//appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-scan) (vea ejemplos [aquí](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Scan.html)). Dado que trabajamos con DynamoDB, podemos usar algunas de las operaciones de ese servicio. El escaneo realiza una búsqueda básica de todos los elementos de nuestra tabla. El resultado de esta operación se almacena en el objeto de contexto como un contenedor de `result` antes de pasarlo al controlador de respuestas. La `request` se ejecuta antes de la respuesta en la canalización.
`response`: el controlador de respuestas que devuelve la salida de `request`. El argumento es el objeto de contexto actualizado y la declaración de retorno es `ctx.prev.result`. En este punto de la guía, es posible que no esté familiarizado con este valor. `ctx` hace referencia al objeto de contexto. `prev`, a la operación anterior en la canalización, que era nuestra `request`. `result` contiene los resultados del solucionador a medida que se desplaza por la canalización. Si lo junta todo, `ctx.prev.result` devuelve el resultado de la última operación realizada, que fue el controlador de solicitudes.

   1. Cuando haya terminado, elija **Crear**.

1. De vuelta a la pantalla de solucionador, en **Funciones**, seleccione el menú desplegable **Añadir función** y añada la función a su lista de funciones.

1. Seleccione **Guardar** para actualizar el solucionador.

------
#### [ CLI ]

**Para añadir su función**
+ Cree una función para su solucionador de canalizaciones mediante el comando `[create-function](https://docs.aws.amazon.com/cli/latest/reference/appsync/create-function.html)`.

  Para este comando en particular, deberá introducir varios parámetros:

  1. El `api-id` de su API.

  1. El `name` de la función de la consola. AWS AppSync 

  1. El `data-source-name` o el nombre del origen de datos que la función utilizará. Ya debe estar creado y vinculado a su API de GraphQL en el servicio de AWS AppSync .

  1. El `runtime` o el entorno y el idioma de la función. Para JavaScript, el nombre debe ser`APPSYNC_JS`, y el tiempo de ejecución,`1.0.0`.

  1. El `code` o los controladores de solicitud y respuesta de su función. Si bien puede escribirlo manualmente, es mucho más fácil agregarlo a un archivo.txt (o un formato similar) y luego pasarlo como argumento. 
**nota**  
Nuestro código de consulta estará en un archivo que se transfiere como argumento:  

     ```
     import { util } from '@aws-appsync/utils';
     
     /**
      * 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;
     }
     ```

  Un comando de ejemplo puede tener este aspecto:

  ```
  aws appsync create-function \
  --api-id abcdefghijklmnopqrstuvwxyz \
  --name get_posts_func_1 \
  --data-source-name table-for-posts \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0 \
  --code file://~/path/to/file/{filename}.{fileType}
  ```

  Aparecerá un resultado en la CLI. A continuación se muestra un ejemplo:

  ```
  {
      "functionConfiguration": {
          "functionId": "ejglgvmcabdn7lx75ref4qeig4",
          "functionArn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/functions/ejglgvmcabdn7lx75ref4qeig4",
          "name": "get_posts_func_1",
          "dataSourceName": "table-for-posts",
          "maxBatchSize": 0,
          "runtime": {
              "name": "APPSYNC_JS",
              "runtimeVersion": "1.0.0"
          },
          "code": "Code output goes here"
      }
  }
  ```
**nota**  
Asegúrese de grabar el `functionId` en algún lugar, ya que se utilizará para asociar la función al solucionador.

**Para crear su primer solucionador**
+ Cree una función de canalización para `Query` ejecutando el comando `[create-resolver](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html)`.

  Para este comando en particular, deberá introducir varios parámetros:

  1. El `api-id` de su API.

  1. El `type-name` o el tipo de objeto especial de su esquema (consulta, mutación, suscripción).

  1. El `field-name` o la operación de campo de dentro del tipo de objeto especial al que desee asociar el solucionador.

  1. El `kind`, que especifica un solucionador unitario o de canalización. Configúrelo en `PIPELINE` para habilitar las funciones de canalización.

  1. La `pipeline-config` o las funciones que se van a asociar al solucionador. Asegúrese de conocer los valores de `functionId` de sus funciones. El orden de la lista es importante.

  1. El`runtime`, que era `APPSYNC_JS` (JavaScript). La `runtimeVersion` actualmente es `1.0.0`.

  1. El `code`, que contiene los controladores de los pasos de antes y de después.
**nota**  
Nuestro código de consulta estará en un archivo que se transfiere como argumento:  

     ```
     import { util } from '@aws-appsync/utils';
     
     /**
      * Sends a request to `put` an item in the DynamoDB data source
      */
     export function request(ctx) {
       const { id, ...values } = ctx.args;
       return {
         operation: 'PutItem',
         key: util.dynamodb.toMapValues({ id }),
         attributeValues: util.dynamodb.toMapValues(values),
       };
     }
     
     /**
      * returns the result of the `put` operation
      */
     export function response(ctx) {
       return ctx.result;
     }
     ```

  Un comando de ejemplo puede tener este aspecto:

  ```
  aws appsync create-resolver \
  --api-id abcdefghijklmnopqrstuvwxyz \
  --type-name Query \
  --field-name getPost \
  --kind PIPELINE \
  --pipeline-config functions=ejglgvmcabdn7lx75ref4qeig4 \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0 \
  --code file:///path/to/file/{filename}.{fileType}
  ```

  Aparecerá un resultado en la CLI. A continuación se muestra un ejemplo:

  ```
  {
      "resolver": {
          "typeName": "Mutation",
          "fieldName": "getPost",
          "resolverArn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Mutation/resolvers/getPost",
          "kind": "PIPELINE",
          "pipelineConfig": {
              "functions": [
                  "ejglgvmcabdn7lx75ref4qeig4"
              ]
          },
          "maxBatchSize": 0,
          "runtime": {
              "name": "APPSYNC_JS",
              "runtimeVersion": "1.0.0"
          },
          "code": "Code output goes here"
      }
  }
  ```

------
#### [ CDK ]

**sugerencia**  
[Antes de utilizar la CDK, le recomendamos que consulte la [documentación oficial](https://docs.aws.amazon.com/cdk/v2/guide/home.html) de la CDK junto con AWS AppSync su referencia.](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
Los pasos que se indican a continuación solo mostrarán un ejemplo general del fragmento de código utilizado para añadir un recurso concreto. **No** se pretende que esta sea una solución funcional en su código de producción. También, se presupone que ya tiene una aplicación en funcionamiento.

Una aplicación básica necesitará lo siguiente:

1. Directivas de importación de servicios

1. Código de esquema

1. Generador de orígenes de datos

1. Código de función

1. Código de solucionador

En las secciones [Diseñar el esquema](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html) y [Asociar un origen de datos](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html), sabemos que el archivo de pila incluirá las directivas de importación del siguiente formato:

```
import * as x from 'x'; # import wildcard as the 'x' keyword from 'x-service'
import {a, b, ...} from 'c'; # import {specific constructs} from 'c-service'
```

**nota**  
En las secciones anteriores, solo explicamos cómo importar AWS AppSync componentes fijos. En código real, deberá importar más servicios simplemente para ejecutar la aplicación. En nuestro ejemplo, si tuviéramos que crear una aplicación CDK muy sencilla, al menos importaríamos el AWS AppSync servicio junto con nuestra fuente de datos, que era una tabla de DynamoDB. También necesitaríamos importar otros constructos para implementar la aplicación:  

```
import * as cdk from 'aws-cdk-lib';
import * as appsync from 'aws-cdk-lib/aws-appsync';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
import { Construct } from 'constructs';
```
Resumamos cada uno de estos elementos:  
`import * as cdk from 'aws-cdk-lib';`: permite definir la aplicación del CDK y sus constructos, como la pila. También contiene funciones de utilidad útiles para nuestra aplicación, como la manipulación de metadatos. Si conoce esta directiva de importación, pero se pregunta por qué la biblioteca principal de cdk no se utiliza aquí, consulte la página [Migración](https://docs.aws.amazon.com/cdk/v2/guide/migrating-v2.html).
`import * as appsync from 'aws-cdk-lib/aws-appsync';`: importa el [servicio de AWS AppSync](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html).
`import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';`: importa el [servicio de DynamoDB](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb-readme.html).
`import { Construct } from 'constructs';`: lo necesitamos para definir el [constructo](https://docs.aws.amazon.com/cdk/v2/guide/constructs.html) raíz.

El tipo de importación depende de los servicios que llame. Te recomendamos consultar la documentación del CDK para ver ejemplos. El esquema de la parte superior de la página será un archivo independiente en su aplicación de CDK, en forma de archivo `.graphql`. En el archivo de pila, podemos asociarlo a un nuevo GraphQL mediante el siguiente formulario:

```
const add_api = new appsync.GraphqlApi(this, 'graphQL-example', {
  name: 'my-first-api',
  schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'schema.graphql')),
});
```

**nota**  
En el ámbito `add_api`, añadiremos una nueva API de GraphQL con la palabra clave `new` seguida de `appsync.GraphqlApi(scope: Construct, id: string , props: GraphqlApiProps)`. Nuestro ámbito es `this`, el identificador de CFN es `graphQL-example`, y nuestros accesorios son `my-first-api` (nombre de la API en la consola) y `schema.graphql` (la ruta absoluta al archivo de esquema).

Para añadir un origen de datos, añádala primero a la pila. Luego, asóciela a la API de GraphQL mediante el método específico del origen. La asociación se producirá cuando ponga en funcionamiento su solucionador. Mientras tanto, usemos un ejemplo para crear la tabla de DynamoDB con `dynamodb.Table`:

```
const add_ddb_table = new dynamodb.Table(this, 'posts-table', {
  partitionKey: {
    name: 'id',
    type: dynamodb.AttributeType.STRING,
  },
});
```

**nota**  
Si usáramos esto en nuestro ejemplo, añadiríamos una nueva tabla de DynamoDB con el identificador de CFN de `posts-table` y una clave de partición de `id (S)`.

A continuación, debemos implementar nuestro solucionador en el archivo de pila. A continuación, se muestra un ejemplo de una consulta sencilla que busca todos los elementos de una tabla de DynamoDB:

```
const add_func = new appsync.AppsyncFunction(this, 'func-get-posts', {
  name: 'get_posts_func_1',
  add_api,
  dataSource: add_api.addDynamoDbDataSource('table-for-posts', add_ddb_table),
  code: appsync.Code.fromInline(`
      export function request(ctx) {
        return { operation: 'Scan' };
      }

      export function response(ctx) {
        return ctx.result.items;
      }
  `),
  runtime: appsync.FunctionRuntime.JS_1_0_0,
});

new appsync.Resolver(this, 'pipeline-resolver-get-posts', {
  add_api,
  typeName: 'Query',
  fieldName: 'getPost',
  code: appsync.Code.fromInline(`
      export function request(ctx) {
        return {};
      }

      export function response(ctx) {
        return ctx.prev.result;
      }
 `),
  runtime: appsync.FunctionRuntime.JS_1_0_0,
  pipelineConfig: [add_func],
});
```

**nota**  
En primer lugar, creamos una función llamada `add_func`. Este orden de creación puede parecer un poco contradictorio, pero hay que crear las funciones en el solucionador de canalizaciones antes de crear el solucionador propiamente dicho. Una función tiene el siguiente formato:  

```
AppsyncFunction(scope: Construct, id: string, props: AppsyncFunctionProps)
```
Nuestro alcance era `this`, nuestro identificador de CFN era `func-get-posts` y nuestros accesorios contenían los detalles reales de la función. Dentro de los accesorios, hemos incluido:  
La `name` de la función que estará presente en la AWS AppSync consola (). `get_posts_func_1`
La API de GraphQL que hemos creado antes (`add_api`).
El origen de datos; este es el punto en el que vinculamos el origen de datos al valor de la API GraphQL y, a continuación, la asociamos a la función. Tomamos la tabla que hemos creado (`add_ddb_table`) y la asociamos a la API GraphQL (`add_api`) mediante uno de los métodos de `GraphqlApi` ([https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.GraphqlApi.html#addwbrdynamowbrdbwbrdatawbrsourceid-table-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.GraphqlApi.html#addwbrdynamowbrdbwbrdatawbrsourceid-table-options)). El valor del identificador (`table-for-posts`) es el nombre del origen de datos de la consola de AWS AppSync . Para obtener una lista de métodos específicos del origen, consulte las páginas siguientes:  
[ DynamoDbDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.DynamoDbDataSource.html) 
 [ EventBridgeDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.EventBridgeDataSource.html) 
 [ HttpDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.HttpDataSource.html) 
 [ LambdaDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.LambdaDataSource.html) 
 [ NoneDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.NoneDataSource.html) 
 [ OpenSearchDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.OpenSearchDataSource.html) 
 [ RdsDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.RdsDataSource.html) 
El código contiene los controladores de solicitudes y respuestas de nuestra función, que son fáciles de escanear y devolver.
El tiempo de ejecución especifica que queremos usar la versión 1.0.0 del tiempo de ejecución APPSYNC\$1JS. Tenga en cuenta que actualmente esta es la única versión disponible para APPSYNC\$1JS.
Luego, debemos asociar la función al solucionador de canalización. Hemos creado nuestro solucionador usando este formulario:  

```
Resolver(scope: Construct, id: string, props: ResolverProps)
```
Nuestro alcance era `this`, nuestro identificador de CFN era `pipeline-resolver-get-posts` y nuestros accesorios contenían los detalles reales de la función. Dentro de los accesorios, hemos incluido:  
La API de GraphQL que hemos creado antes (`add_api`).
El nombre del tipo de objeto especial; se trata de una operación de consulta, por lo que simplemente hemos añadido el valor `Query`.
El nombre de campo (`getPost`) es el nombre del campo del esquema en el tipo `Query`.
El código contiene sus controladores de antes y después. Nuestro ejemplo simplemente devuelve los resultados que estaban en el contexto después de que la función realizara su operación.
El tiempo de ejecución especifica que queremos usar la versión 1.0.0 del tiempo de ejecución APPSYNC\$1JS. Tenga en cuenta que actualmente esta es la única versión disponible para APPSYNC\$1JS.
La configuración de la canalización contiene la referencia a la función que hemos creado (`add_func`).

------

Para resumir lo que ocurrió en este ejemplo, vio una AWS AppSync función que implementaba un controlador de solicitudes y respuestas. La función se ha encargado de interactuar con el origen de datos. El controlador de solicitudes envió una `Scan` operación a AWS AppSync, indicándole qué operación debía realizar en la fuente de datos de DynamoDB. El controlador de respuestas ha devuelto la lista de elementos (`ctx.result.items`). A continuación, la lista de elementos se ha asignado automáticamente al tipo GraphQL de `Post`. 

## Creación de solucionadores de mutaciones básicos
<a name="creating-basic-mutation-resolvers-js"></a>

En esta sección se mostrará cómo crear un solucionador de mutaciones básico.

------
#### [ Console ]

1. [Inicie sesión en la consola Consola de administración de AWS y ábrala. AppSync](https://console.aws.amazon.com/appsync/)

   1. En el **APIs panel de control**, elige tu API de GraphQL.

   1. En la **barra lateral**, seleccione **Esquema**.

1. En la sección **Solucionadores** y el tipo **Mutación**, seleccione **Asociar** junto al campo.
**nota**  
En nuestro ejemplo, vamos a asociar un solucionador para `createPost`, que añade un objeto `Post` a nuestra table. Supongamos que utilizamos la misma tabla de DynamoDB de la última sección. Su clave de partición está establecida en `id` y está vacía.

1. En la página **Asociar solucionador**, en **Tipo de solucionador**, elija `pipeline resolvers`. Le recordamos que puede encontrar más información sobre los solucionadores [aquí](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-components.html). Para el **tiempo de ejecución de Resolver**, selecciona `APPSYNC_JS` habilitar el JavaScript tiempo de ejecución.

1. Puede habilitar el [almacenamiento en caché](https://docs.aws.amazon.com/appsync/latest/devguide/enabling-caching.html) para esta API. También recomendamos desactivar esta característica por el momento. Seleccione **Crear**.

1. Seleccione **Añadir función** y, a continuación, **Crear nueva función**. Como alternativa, puede que vea el botón **Crear función** para seleccionarlo.

   1. Elija el origen su origen de datos. Debería ser el origen cuyos datos va a manipular con la mutación.

   1. Introduzca un `Function name`.

   1. En **Código de función**, deberá implementar el comportamiento de la función. Se trata de una mutación, por lo que lo ideal es que la solicitud realice alguna operación de cambio de estado en el origen de datos invocado. La función de respuesta procesará el resultado.
**nota**  
`createPost` va a añadir o “poner” una nueva `Post` en la tabla con nuestros parámetros como datos. Podríamos añadir algo parecido a esto:   

      ```
      import { util } from '@aws-appsync/utils';
      
      /**
       * Sends a request to `put` an item in the DynamoDB data source
       */
      export function request(ctx) {
        return {
          operation: 'PutItem',
          key: util.dynamodb.toMapValues({id: util.autoId()}),
          attributeValues: util.dynamodb.toMapValues(ctx.args.input),
        };
      }
      
      /**
       * returns the result of the `put` operation
       */
      export function response(ctx) {
        return ctx.result;
      }
      ```
En este paso, hemos añadido también las funciones `request` y `response`:  
`request`: el controlador de solicitudes acepta el contexto como argumento. La instrucción return del controlador de solicitudes ejecuta un comando [https://docs.aws.amazon.com//appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-putitem](https://docs.aws.amazon.com//appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-putitem), que es una operación de DynamoDB integrada (consulte [aquí](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/getting-started-step-2.html) o [aquí](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html#WorkingWithItems.WritingData) para ver ejemplos). El comando `PutItem` añade un objeto de `Post` a nuestra tabla de DynamoDB tomando el valor `key` de la partición (generado automáticamente por `util.autoid()`) y los `attributes` de la entrada del argumento de contexto (son los valores que transferiremos en nuestra solicitud). La `key` es el `id` y `attributes` son los argumentos de los campos `date` y `title`. Ambos se preformatean mediante el elemento auxiliar [https://docs.aws.amazon.com//appsync/latest/devguide/dynamodb-helpers-in-util-dynamodb-js.html#utility-helpers-in-toMap-js](https://docs.aws.amazon.com//appsync/latest/devguide/dynamodb-helpers-in-util-dynamodb-js.html#utility-helpers-in-toMap-js) para que funcionen con la tabla de DynamoDB.
`response`: la respuesta acepta el contexto actualizado y devuelve el resultado del controlador de solicitudes.

   1. Cuando haya terminado, elija **Crear**.

1. De vuelta a la pantalla de solucionador, en **Funciones**, seleccione el menú desplegable **Añadir función** y añada la función a su lista de funciones.

1. Seleccione **Guardar** para actualizar el solucionador.

------
#### [ CLI ]

**Para añadir su función**
+ Cree una función para su solucionador de canalizaciones mediante el comando `[create-function](https://docs.aws.amazon.com/cli/latest/reference/appsync/create-function.html)`.

  Para este comando en particular, deberá introducir varios parámetros:

  1. El `api-id` de su API.

  1. El `name` de la función de la AWS AppSync consola.

  1. El `data-source-name` o el nombre del origen de datos que la función utilizará. Ya debe estar creado y vinculado a su API de GraphQL en el servicio de AWS AppSync .

  1. El `runtime` o el entorno y el idioma de la función. Para JavaScript, el nombre debe ser`APPSYNC_JS`, y el tiempo de ejecución,`1.0.0`.

  1. El `code` o los controladores de solicitud y respuesta de su función. Si bien puede escribirlo manualmente, es mucho más fácil añadirlo a un archivo.txt (o un formato similar) y luego transferirlo como argumento. 
**nota**  
Nuestro código de consulta estará en un archivo que se transfiere como argumento:  

     ```
     import { util } from '@aws-appsync/utils';
     
     /**
      * Sends a request to `put` an item in the DynamoDB data source
      */
     export function request(ctx) {
       return {
         operation: 'PutItem',
         key: util.dynamodb.toMapValues({id: util.autoId()}),
         attributeValues: util.dynamodb.toMapValues(ctx.args.input),
       };
     }
     
     /**
      * returns the result of the `put` operation
      */
     export function response(ctx) {
       return ctx.result;
     }
     ```

  Un comando de ejemplo puede tener este aspecto:

  ```
  aws appsync create-function \
  --api-id abcdefghijklmnopqrstuvwxyz \
  --name add_posts_func_1 \
  --data-source-name table-for-posts \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0 \
  --code file:///path/to/file/{filename}.{fileType}
  ```

  Aparecerá un resultado en la CLI. A continuación se muestra un ejemplo:

  ```
  {
      "functionConfiguration": {
          "functionId": "vulcmbfcxffiram63psb4dduoa",
          "functionArn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/functions/vulcmbfcxffiram63psb4dduoa",
          "name": "add_posts_func_1",
          "dataSourceName": "table-for-posts",
          "maxBatchSize": 0,
          "runtime": {
              "name": "APPSYNC_JS",
              "runtimeVersion": "1.0.0"
          },
          "code": "Code output foes here"
      }
  }
  ```
**nota**  
Asegúrese de grabar el `functionId` en algún lugar, ya que se utilizará para asociar la función al solucionador.

**Para crear su primer solucionador**
+ Cree una función de canalización para `Mutation` ejecutando el comando `[create-resolver](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html)`.

  Para este comando en particular, deberá introducir varios parámetros:

  1. El `api-id` de su API.

  1. El `type-name` o el tipo de objeto especial de su esquema (consulta, mutación, suscripción).

  1. El `field-name` o la operación de campo de dentro del tipo de objeto especial al que desee asociar el solucionador.

  1. El `kind`, que especifica un solucionador unitario o de canalización. Configúrelo en `PIPELINE` para habilitar las funciones de canalización.

  1. La `pipeline-config` o las funciones que se van a asociar al solucionador. Asegúrese de conocer los valores de `functionId` de sus funciones. El orden de la lista es importante.

  1. El`runtime`, que era `APPSYNC_JS` (JavaScript). La `runtimeVersion` actualmente es `1.0.0`.

  1. El `code`, que contiene los pasos de antes y de después.
**nota**  
Nuestro código de consulta estará en un archivo que se transfiere como argumento:  

     ```
     import { util } from '@aws-appsync/utils';
     
     /**
      * Sends a request to `put` an item in the DynamoDB data source
      */
     export function request(ctx) {
       const { id, ...values } = ctx.args;
       return {
         operation: 'PutItem',
         key: util.dynamodb.toMapValues({ id }),
         attributeValues: util.dynamodb.toMapValues(values),
       };
     }
     
     /**
      * returns the result of the `put` operation
      */
     export function response(ctx) {
       return ctx.result;
     }
     ```

  Un comando de ejemplo puede tener este aspecto:

  ```
  aws appsync create-resolver \
  --api-id abcdefghijklmnopqrstuvwxyz \
  --type-name Mutation \
  --field-name createPost \
  --kind PIPELINE \
  --pipeline-config functions=vulcmbfcxffiram63psb4dduoa \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0 \
  --code file:///path/to/file/{filename}.{fileType}
  ```

  Aparecerá un resultado en la CLI. A continuación se muestra un ejemplo:

  ```
  {
      "resolver": {
          "typeName": "Mutation",
          "fieldName": "createPost",
          "resolverArn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Mutation/resolvers/createPost",
          "kind": "PIPELINE",
          "pipelineConfig": {
              "functions": [
                  "vulcmbfcxffiram63psb4dduoa"
              ]
          },
          "maxBatchSize": 0,
          "runtime": {
              "name": "APPSYNC_JS",
              "runtimeVersion": "1.0.0"
          },
          "code": "Code output goes here"
      }
  }
  ```

------
#### [ CDK ]

**sugerencia**  
[Antes de utilizar la CDK, le recomendamos que consulte la [documentación oficial](https://docs.aws.amazon.com/cdk/v2/guide/home.html) de la CDK junto con AWS AppSync su referencia.](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
Los pasos que se indican a continuación solo mostrarán un ejemplo general del fragmento de código utilizado para añadir un recurso concreto. **No** se pretende que esta sea una solución funcional en su código de producción. También, se presupone que ya tiene una aplicación en funcionamiento.
+ Para realizar una mutación, si usted se encuentra en el mismo proyecto, puede añadirla al archivo de pila como la consulta. Esta es una función modificada y un solucionador para una mutación que añade una nueva `Post` a la tabla:

  ```
  const add_func_2 = new appsync.AppsyncFunction(this, 'func-add-post', {
    name: 'add_posts_func_1',
    add_api,
    dataSource: add_api.addDynamoDbDataSource('table-for-posts-2', add_ddb_table),
        code: appsync.Code.fromInline(`
            export function request(ctx) {
              return {
                operation: 'PutItem',
                key: util.dynamodb.toMapValues({id: util.autoId()}),
                attributeValues: util.dynamodb.toMapValues(ctx.args.input),
              };
            }
  
            export function response(ctx) {
              return ctx.result;
            }
        `), 
    runtime: appsync.FunctionRuntime.JS_1_0_0,
  });
  
  new appsync.Resolver(this, 'pipeline-resolver-create-posts', {
    add_api,
    typeName: 'Mutation',
    fieldName: 'createPost',
        code: appsync.Code.fromInline(`
            export function request(ctx) {
              return {};
            }
  
            export function response(ctx) {
              return ctx.prev.result;
            }
        `),
    runtime: appsync.FunctionRuntime.JS_1_0_0,
    pipelineConfig: [add_func_2],
  });
  ```
**nota**  
Como esta mutación y la consulta tienen una estructura similar, nos limitaremos a explicar los cambios que hemos hecho para realizar la mutación.   
En la función, hemos cambiado el identificador de CFN por `func-add-post` y el nombre por `add_posts_func_1` a para reflejar el hecho de que estamos añadiendo `Posts` a la tabla. En la fuente de datos, hicimos una nueva asociación con nuestra tabla (`add_ddb_table`) de la AWS AppSync consola, `table-for-posts-2` ya que el `addDynamoDbDataSource` método así lo requiere. Tenga en cuenta que esta nueva asociación sigue utilizando la misma tabla que creamos anteriormente, pero ahora tenemos dos conexiones a ella en la AWS AppSync consola: una para la consulta as `table-for-posts` y otra para la mutación as`table-for-posts-2`. El código se ha modificado para añadir una `Post` mediante la generación automática de su valor de `id` y la aceptación de la entrada de un cliente para el resto de los campos.  
En el solucionador, hemos cambiado el valor del identificador por `pipeline-resolver-create-posts` para reflejar el hecho de que estamos añadiendo `Posts` a la tabla. Para reflejar la mutación en el esquema, se cambiado el nombre del tipo por `Mutation`, y el nombre, `createPost`. La configuración de la canalización se ha establecido en nuestra nueva función de mutación `add_func_2`.

------

Para resumir lo que ocurre en este ejemplo, convierte AWS AppSync automáticamente los argumentos definidos en el `createPost` campo del esquema de GraphQL en operaciones de DynamoDB. El ejemplo almacena los registros en DynamoDB mediante una clave de `id`, que se crea automáticamente con nuestro texto auxiliar `util.autoId()`. Todos los demás campos que pase a los argumentos de contexto (`ctx.args.input`) a partir de solicitudes realizadas en la AWS AppSync consola o de otro modo se almacenarán como atributos de la tabla. Tanto la clave como los atributos se asignan automáticamente a un formato de DynamoDB compatible mediante el texto auxiliar `util.dynamodb.toMapValues(values)`.

AWS AppSync también admite flujos de trabajo de prueba y depuración para la edición de resoluciones. Puede usar un objeto `context` simulado para ver el valor transformado de la plantilla antes de invocarlo. De forma opcional, puede ver la solicitud completa en un origen de datos de forma interactiva cuando ejecute una consulta. [Para obtener más información, consulte [Probar y depurar solucionadores (JavaScript) y Supervisión y registro](https://docs.aws.amazon.com/appsync/latest/devguide/test-debug-resolvers-js.html).](https://docs.aws.amazon.com/appsync/latest/devguide/monitoring.html#aws-appsync-monitoring)

## Solucionadores avanzados
<a name="advanced-resolvers-js"></a>

Si sigue la sección de paginación opcional de [Diseño del esquema](designing-your-schema.md#aws-appsync-designing-your-schema), deberá añadir el solucionador a la solicitud para poder utilizar la paginación. En nuestro ejemplo, se ha utilizado una paginación de consultas llamada `getPosts` para devolver solo una parte de los elementos solicitados a la vez. Nuestro código de solucionador en ese campo puede ser como este:

```
/**
 * Performs a scan on the dynamodb data source
 */
export function request(ctx) {
  const { limit = 20, nextToken } = ctx.args;
  return { operation: 'Scan', limit, nextToken };
}

/**
 * @returns the result of the `put` operation
 */
export function response(ctx) {
  const { items: posts = [], nextToken } = ctx.result;
  return { posts, nextToken };
}
```

En la solicitud, transferimos el contexto de esta. `limit`El nuestro es*20*, lo que significa que devolvemos hasta 20 `Posts` en la primera consulta. Nuestro cursor `nextToken` está fijo en la primera entrada de `Post` en el origen de datos. Se transfieren a los argumentos. A continuación, la solicitud escanea desde la primera `Post` hasta el número límite de escaneo. El origen de datos almacena el resultado en el contexto, que se transfiere a la respuesta. La respuesta devuelve las `Posts` recuperadas y, a continuación, establece el `nextToken` en la entrada de la `Post` que se encuentra justo después del límite. La siguiente solicitud se envía para hacer exactamente lo mismo, pero empezando por el desplazamiento justo después de la primera consulta. Tenga en cuenta que este tipo de solicitudes se realizan de forma secuencial y no en paralelo.

# Probar y depurar resolutores en AWS AppSync () JavaScript
<a name="test-debug-resolvers-js"></a>

AWS AppSync ejecuta resolutores en un campo GraphQL contra una fuente de datos. Cuando se trabaja con solucionadores de canalizaciones, las funciones interactúan con los orígenes de datos. Como se describe en la [descripción general de los JavaScript resolutores](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html), las funciones se comunican con las fuentes de datos mediante controladores de solicitudes y respuestas escritos JavaScript y que se ejecutan en tiempo de ejecución. `APPSYNC_JS` Esto le permite proporcionar lógica y condiciones personalizadas antes y después de comunicarse con el origen de datos.

Para ayudar a los desarrolladores a escribir, probar y depurar estos resolutores, la AWS AppSync consola también proporciona herramientas para crear una solicitud y una respuesta de GraphQL con datos simulados para cada solucionador de campo individual. Además, puedes realizar consultas, mutaciones y suscripciones en la AWS AppSync consola y ver un registro detallado de toda la solicitud de Amazon CloudWatch. Esto incluye los resultados del origen de datos.

## Prueba con datos simulados
<a name="testing-with-mock-data-js"></a>

Cuando se invoca a un solucionador de GraphQL, este contiene un objeto `context` que incluye información útil sobre la solicitud. Por ejemplo, contiene los argumentos de un cliente, información de identidad y datos del campo principal de GraphQL. También almacena los resultados del origen de datos, que puede usar en el controlador de respuestas. Si desea más información acerca de esta estructura y las utilidades auxiliares disponibles para programar, consulte [Resolver context object reference](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html).

Al escribir o editar una función de solucionador, puede pasar un objeto *simulado* o *de contexto de prueba* al editor de la consola. Esto le permite ver cómo se evalúan los controladores de solicitudes y de respuestas sin que se utilice en realidad ningún origen de datos. Por ejemplo, puede transferir un argumento `firstname: Shaggy` de prueba y ver cómo se evalúa cuando utiliza `ctx.args.firstname` en el código de la plantilla. También puede probar la evaluación de cualquier utilidad auxiliar, como `util.autoId()` o `util.time.nowISO8601()`.

### Prueba de solucionadores
<a name="test-a-resolver-js"></a>

En este ejemplo, se utilizará la AWS AppSync consola para probar los resolutores.

1. Inicie sesión en la [AppSyncconsola Consola de administración de AWS](https://console.aws.amazon.com/appsync/) y ábrala.

   1. En el **APIs panel de control**, elige tu API de GraphQL.

   1. En la **barra lateral**, seleccione **Funciones**.

1. Seleccione una función existente.

1. En la parte superior de la página **Actualizar función**, seleccione **Seleccionar contexto de prueba** y, a continuación, **Crear nuevo contexto**.

1. Seleccione un objeto de contexto de ejemplo o rellene el JSON manualmente en la ventana **Configurar contexto de prueba** que aparece a continuación.

1. Introduzca un **Nombre de contexto de texto**.

1. Seleccione el botón **Guardar**.

1. Para evaluar el solucionador con el objeto de contexto simulado, elija **Run Test (Ejecutar prueba)**.

Veamos un ejemplo más práctico. Imagine que tiene una aplicación que almacena un tipo de GraphQL llamado `Dog`, que genera automáticamente un identificador para los objetos y los almacena en Amazon DynamoDB. También desea escribir algunos valores tomándolos de los argumentos de una mutación de GraphQL y permitir que solo determinados usuarios vean la respuesta. En el siguiente fragmento de código se muestra el aspecto que podría tener el esquema:

```
type Dog {
  breed: String
  color: String
}

type Mutation {
  addDog(firstname: String, age: Int): Dog
}
```

Puedes escribir una AWS AppSync función y añadirla a tu `addDog` resolución para gestionar la mutación. Para probar AWS AppSync la función, puede rellenar un objeto de contexto, como en el siguiente ejemplo. Se incluyen argumentos del cliente como `name` y `age`, así como un `username` rellenado en el objeto `identity`:

```
{
    "arguments" : {
        "firstname": "Shaggy",
        "age": 4
    },
    "source" : {},
    "result" : {
        "breed" : "Miniature Schnauzer",
        "color" : "black_grey"
    },
    "identity": {
        "sub" : "uuid",
        "issuer" : " https://cognito-idp.{region}.amazonaws.com/{userPoolId}",
        "username" : "Nadia",
        "claims" : { },
        "sourceIp" :[  "x.x.x.x" ],
        "defaultAuthStrategy" : "ALLOW"
    }
}
```

Puedes probar la AWS AppSync función con el siguiente código:

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  return {
    operation: 'PutItem',
    key: util.dynamodb.toMapValues({ id: util.autoId() }),
    attributeValues: util.dynamodb.toMapValues(ctx.args),
  };
}

export function response(ctx) {
  if (ctx.identity.username === 'Nadia') {
    console.log("This request is allowed")
    return ctx.result;
  }
  util.unauthorized();
}
```

El controlador de solicitudes y respuestas evaluado tiene los datos de su objeto de contexto de prueba y el valor generado de `util.autoId()`. Además, si cambia el `username` por un valor distinto de `Nadia`, no se devolverán resultados, porque la comprobación de autorización daría error. Para obtener más información acerca del control de acceso preciso, consulte [Casos de uso de autorizaciones](security-authorization-use-cases.md#aws-appsync-security-authorization-use-cases).

### Probando los controladores de solicitudes y respuestas con AWS AppSync APIs
<a name="testing-with-appsync-api-js"></a>

Puede usar el comando de API `EvaluateCode` para probar el código de forma remota con datos simulados. Para empezar a usar el comando, asegúrese de haber añadido el permiso `appsync:evaluateMappingCode` a su política. Por ejemplo:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "appsync:evaluateCode",
            "Resource": "arn:aws:appsync:us-east-1:111122223333:*"
        }
    ]
}
```

------

Puede aprovechar el comando utilizando la tecla [AWS CLI](https://aws.amazon.com/cli/)o [AWS SDKs](https://aws.amazon.com/tools/). Por ejemplo, tome el `Dog` esquema y sus controladores de solicitudes y respuestas de AWS AppSync funciones de la sección anterior. Con la CLI de la estación local, guarde el código en un archivo denominado `code.js` y, a continuación, guarde el objeto `context` en un archivo denominado `context.json`. Ejecute el siguiente comando desde el intérprete de comandos:

```
$ aws appsync evaluate-code \
  --code file://code.js \
  --function response \
  --context file://context.json \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0
```

La respuesta contiene un `evaluationResult` que incluye la carga útil devuelta por el controlador. También contiene un objeto `logs` que incluye la lista de registros generados por el controlador durante la evaluación. Esto facilita la depuración de la ejecución de código y la consulta de información sobre la evaluación como ayuda para solucionar problemas. Por ejemplo:

```
{
    "evaluationResult": "{\"breed\":\"Miniature Schnauzer\",\"color\":\"black_grey\"}",
    "logs": [
        "INFO - code.js:13:5: \"This request is allowed\""
    ]
}
```

El `evaluationResult` se puede analizar como JSON, lo que da como resultado: 

```
{
  "breed": "Miniature Schnauzer",
  "color": "black_grey"
}
```

Cuando se utiliza el SDK, puede incorporar fácilmente pruebas de su conjunto de pruebas favorito para validar el comportamiento de los controladores. Recomendamos crear pruebas con el [marco de pruebas Jest](https://jestjs.io/), pero cualquier conjunto de pruebas funciona. En el siguiente fragmento de código se muestra una ejecución de validación hipotética. Tenga en cuenta que esperamos que la respuesta de la evaluación sea un JSON válido, por lo que utilizamos `JSON.parse` para recuperar el JSON de la respuesta de cadena:

```
const AWS = require('aws-sdk')
const fs = require('fs')
const client = new AWS.AppSync({ region: 'us-east-2' })
const runtime = {name:'APPSYNC_JS',runtimeVersion:'1.0.0')

test('request correctly calls DynamoDB', async () => {
  const code = fs.readFileSync('./code.js', 'utf8')
  const context = fs.readFileSync('./context.json', 'utf8')
  const contextJSON = JSON.parse(context)
  
  const response = await client.evaluateCode({ code, context, runtime, function: 'request' }).promise()
  const result = JSON.parse(response.evaluationResult)
  
  expect(result.key.id.S).toBeDefined()
  expect(result.attributeValues.firstname.S).toEqual(contextJSON.arguments.firstname)
})
```

 Esto produce el siguiente resultado:

```
Ran all test suites.
> jest

PASS ./index.test.js
✓ request correctly calls DynamoDB (543 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 totalTime: 1.511 s, estimated 2 s
```

## Depuración de una consulta en tiempo real
<a name="debugging-a-live-query-js"></a>

No hay nada que sustituya a una end-to-end prueba y un registro para depurar una aplicación de producción. AWS AppSync te permite registrar los errores y los detalles completos de las solicitudes a través de Amazon CloudWatch. Además, puedes usar la AWS AppSync consola para probar las consultas, mutaciones y suscripciones de GraphQL y transmitir en directo los datos de registro de cada solicitud de vuelta al editor de consultas para depurarlos en tiempo real. Para las suscripciones, los registros muestran la información del tiempo de conexión.

Para ello, debes tener habilitados los CloudWatch registros de Amazon con antelación, tal y como se describe en [Supervisión y registro](monitoring.md#aws-appsync-monitoring). A continuación, en la AWS AppSync consola, selecciona la pestaña **Consultas** y, a continuación, introduce una consulta GraphQL válida. En la sección inferior derecha, haga clic y arrastre la ventana **Registros** para abrir la vista de registros. Utilice el icono de flecha de reproducción de la parte superior de la página para ejecutar la consulta de GraphQL. Al cabo de un momento, los registros completos de la solicitud y la respuesta de la operación se enviarán a esta sección y podrá verlos en la consola.

# Configuración y uso de resolutores de canalización en AWS AppSync () JavaScript
<a name="pipeline-resolvers-js"></a>

AWS AppSync ejecuta resolutores en un campo de GraphQL. En algunos casos, las aplicaciones requieren la ejecución de varias operaciones para resolver un único campo de GraphQL. Con los solucionadores de canalización, los desarrolladores ahora pueden componer operaciones llamadas Funciones y ejecutarlas de forma secuencial. Los solucionadores de canalización son útiles para las aplicaciones que, por ejemplo, requieren realizar una comprobación de autorización antes de recuperar datos para un campo.

[Para obtener más información sobre la arquitectura de un solucionador de JavaScript canalización, consulta la descripción general de los JavaScript resolutores.](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html#anatomy-of-a-pipeline-resolver-js)

## Paso 1: creación de un solucionador de canalización
<a name="create-a-pipeline-resolver-js"></a>

En la AWS AppSync consola, vaya a la página del **esquema**.

Guarde el siguiente esquema:

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

type Mutation {
    signUp(input: Signup): User
}

type Query {
    getUser(id: ID!): User
}

input Signup {
    username: String!
    email: String!
}

type User {
    id: ID!
    username: String
    email: AWSEmail
}
```

Vamos a conectar un solucionador de canalización al campo **signUp** en el tipo **Mutation (Mutación)**. En el tipo **Mutación** en el lado derecho, elija **Asociar** junto al campo de mutación `signUp`. Configura el solucionador en `pipeline resolver` y el tiempo de ejecución en `APPSYNC_JS` y, a continuación, crea el solucionador.

Nuestro solucionador de canalización inicia sesión a un usuario. Para ello, primero valida la entrada de dirección de correo electrónico y, a continuación, guarda al usuario en el sistema. Vamos a encapsular la validación de correo electrónico dentro de una función **validateEmail** y el guardado del usuario dentro de una función **saveUser**. La función **validateEmail** se ejecuta en primer lugar y, si el correo electrónico es válido, se ejecuta la función **saveUser**.

El flujo de ejecución será como se indica a continuación:

1. Controlador de solicitudes de solucionador Mutation.signUp

1. Función validateEmail

1. Función saveUser

1. Controlador de respuestas de solucionador Mutation.signup

Dado que probablemente reutilizaremos la función **validateEmail** en otros solucionadores de nuestra API, queremos para evitar el acceso a `ctx.args`, ya que estos cambiarán de un campo GraphQL a otro. En su lugar, podemos utilizar `ctx.stash` para almacenar el atributo de correo electrónico desde el argumento de campo de entrada `signUp(input: Signup)`.

Actualice su código de solucionador sustituyendo sus funciones de solicitud y respuesta:

```
export function request(ctx) {
    ctx.stash.email = ctx.args.input.email
    return {};
}

export function response(ctx) {
    return ctx.prev.result;
}
```

Seleccione **Crear** o **Guardar** para actualizar el solucionador.

## Paso 2: creación de una función
<a name="create-a-function-js"></a>

En la página del solucionador de canalización, en la sección **Funciones**, haga clic en **Agregar función** y luego en **Crear la función nueva**. También es posible crear funciones sin pasar por la página de resolución; para ello, en la AWS AppSync consola, vaya a la página de **funciones**. Elija el botón **Crear una función**. Vamos a crear una función que comprueba si un mensaje de correo electrónico es válido y proviene de un dominio específico. Si el correo electrónico no es válido, la función genera un error. De lo contrario, reenvía cualquier entrada.

Asegúrese de haber creado un origen de datos del tipo **NINGUNO**. Elija este origen de datos en la lista de **Nombre del origen de datos**. Para el **nombre de a función**, escriba `validateEmail`. En el área de **código de la función**, sobrescriba todo con este fragmento:

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const { email } = ctx.stash;
  const valid = util.matches(
    '^[a-zA-Z0-9_.+-]+@(?:(?:[a-zA-Z0-9-]+\.)?[a-zA-Z]+\.)?(myvaliddomain)\.com',
    email
  );
  if (!valid) {
    util.error(`"${email}" is not a valid email.`);
  }

  return { payload: { email } };
}

export function response(ctx) {
  return ctx.result;
}
```

Revise la información indicada y, a continuación, seleccione **Crear**. Acabamos de crear nuestra función **validateEmail**. Repita estos pasos para crear la función **SaveUser** con el siguiente código (para simplificar, utilizamos un origen de datos **NINGUNO** y simulamos que el usuario se ha guardado en el sistema después de ejecutar la función):

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  return ctx.prev.result;
}

export function response(ctx) {
  ctx.result.id = util.autoId();
  return ctx.result;
}
```

Acabamos de crear la función **saveUser**.

## Paso 3: adición de una función a un solucionador de canalización
<a name="adding-a-function-to-a-pipeline-resolver-js"></a>

Nuestras funciones deberían haberse agregado automáticamente al solucionador de canalización que acabamos de crear. Si este no es el caso, o si ha creado las funciones a través de la página **Funciones**, puede volver a hacer clic en **Agregar función** en la página `signUp` del solucionador para asociarlas. Agregue las funciones **validateEmail** y **saveUser** al solucionador. La función **validateEmail** se debe colocar antes de la función **saveUser**. A medida que agrega más funciones, puede utilizar las opciones **mover hacia arriba** y **mover hacia abajo** para reorganizar el orden de ejecución de las funciones. Revise sus cambios y, a continuación, elija **Guardar**.

## Paso 4: ejecución de una consulta
<a name="running-a-query-js"></a>

En la AWS AppSync consola, vaya a la página de **consultas**. En el explorador, asegúrese de utilizar la mutación. Si no es así, seleccione `Mutation` en la lista desplegable y, a continuación, elija `+`. Escriba la siguiente consulta:

```
mutation {
  signUp(input: {email: "nadia@myvaliddomain.com", username: "nadia"}) {
    id
    username
  }
}
```

Debería devolver algo parecido a esto:

```
{
  "data": {
    "signUp": {
      "id": "256b6cc2-4694-46f4-a55e-8cb14cc5d7fc",
      "username": "nadia"
    }
  }
}
```

Hemos registrado correctamente nuestro usuario y validado el correo electrónico de entrada utilizando un solucionador de canalización.

# Creación de consultas básicas (VTL)
<a name="configuring-resolvers"></a>

**nota**  
Ahora admitimos de forma básica el tiempo de ejecución APPSYNC\$1JS y su documentación. Considere la opción de utilizar el tiempo de ejecución APPSYNC\$1JS y sus guías [aquí](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html).

Los solucionadores de GraphQL conectan los campos de un esquema de tipo a un origen de datos. Los resolutores son el mecanismo mediante el cual se tramitan las solicitudes. AWS AppSync pueden crear y conectar automáticamente resolutores a partir de un esquema o crear un esquema y conectar resolutores desde una tabla existente sin necesidad de escribir ningún código.

Resolvers que se AWS AppSync utilizan JavaScript para convertir una expresión de GraphQL en un formato que pueda utilizar la fuente de datos. Como alternativa, las plantillas de asignación se pueden escribir en [Apache Velocity Template Language (VTL)](https://velocity.apache.org/engine/2.0/vtl-reference.html) para convertir una expresión de GraphQL en un formato que el origen de datos pueda utilizar.

En esta sección se mostrará cómo configurar los solucionadores mediante VTL. [En la guía de programación de plantillas de mapeo de Resolver encontrará una guía de programación tipo tutorial introductorio para escribir [resolutores, y en la referencia contextual de la plantilla de mapeo](resolver-mapping-template-reference-programming-guide.md#aws-appsync-resolver-mapping-template-reference-programming-guide) de Resolver encontrará utilidades auxiliares para su uso durante la programación.](resolver-context-reference.md#aws-appsync-resolver-mapping-template-context-reference) AWS AppSync también incluye flujos de prueba y depuración integrados que puedes usar cuando editas o creas desde cero. Para obtener más información, consulte la sección sobre la [prueba y depuración de solucionadores](test-debug-resolvers.md#aws-appsync-test-debug-resolvers).

Recomendamos seguir esta guía antes de intentar utilizar alguno de los tutoriales mencionados anteriormente.

En esta sección, veremos cómo crear un solucionador, añadir un solucionador para mutaciones y usar configuraciones avanzadas.

## Cree su primer solucionador
<a name="create-your-first-resolver"></a>

Siguiendo los ejemplos de las secciones anteriores, el primer paso es crear un solucionador para su tipo de `Query`.

------
#### [ Console ]

1. [Inicia sesión en la consola Consola de administración de AWS y ábrelaAppSync .](https://console.aws.amazon.com/appsync/)

   1. En el **APIs panel de control**, elige tu API de GraphQL.

   1. En la **barra lateral**, seleccione **Esquema**.

1. En la parte derecha de la página, hay una ventana llamada **Solucionadores**. Este cuadro contiene una lista de los tipos y campos definidos en la ventana **Esquema** del lado izquierdo de la página. Puede asociar solucionadores a los campos. Por ejemplo, en el tipo de **Consulta**, seleccione **Asociar** junto al campo `getTodos`.

1. En la página **Crear un solucionador**, elija el origen de datos que creó en la guía [Asociar un origen de datos](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html). En la ventana **Configurar plantillas de asignación**, puede elegir las plantillas de asignación genéricas de solicitud y respuesta utilizando la lista desplegable de la derecha o escribir las suyas propias.
**nota**  
El emparejamiento de una plantilla de asignación de solicitudes con una plantilla de asignación de respuestas se denomina solucionador unitario. Los solucionadores unitarios suelen estar diseñados para realizar operaciones rutinarias; recomendamos usarlos solo para operaciones singulares con un número reducido de orígenes de datos. Para operaciones más complejas, recomendamos utilizar solucionadores de canalización, que pueden ejecutar varias operaciones con diversos orígenes de datos de forma secuencial.  
Para obtener más información acerca de la diferencia entre las plantillas de asignación de solicitudes y respuestas, consulte [Solucionadores unitarios](https://docs.aws.amazon.com//appsync/latest/devguide/resolver-mapping-template-reference-overview.html#unit-resolvers).  
Para obtener más información sobre el uso de solucionadores de canalización, consulte [Solucionadores de canalización](pipeline-resolvers.md#aws-appsync-pipeline-resolvers).

1. Para los casos de uso más comunes, la AWS AppSync consola tiene plantillas integradas que puedes usar para obtener elementos de fuentes de datos (por ejemplo, todas las consultas de elementos, búsquedas individuales, etc.). Por ejemplo en la versión sencilla del esquema que se da en la sección [Diseño del esquema](designing-your-schema.md#aws-appsync-designing-your-schema) en la que `getTodos` no tenía paginación, la plantilla de asignación de solicitudes para enumerar elementos es la siguiente:

   ```
   {
       "version" : "2017-02-28",
       "operation" : "Scan"
   }
   ```

1. Siempre se necesita una plantilla de asignación de respuestas para complementar la solicitud. La consola ofrece un valor predeterminado con el siguiente valor de acceso directo para las listas:

   ```
   $util.toJson($ctx.result.items)
   ```

   En este ejemplo, el objeto `context` (con el alias `$ctx`) para las listas de elementos tiene la forma `$context.result.items`. Si su operación de GraphQL devuelve un solo elemento, sería `$context.result`. AWS AppSync proporciona funciones auxiliares para operaciones comunes como la función `$util.toJson` enumerada anteriormente, para dar formato a las respuestas correctamente. Para ver una lista completa de funciones, consulte [Referencia de utilidad de la plantilla de asignación de solucionadores](resolver-util-reference.md#aws-appsync-resolver-mapping-template-util-reference).

1. Seleccione **Guardar solucionador**.

------
#### [ API ]

1. Cree un objeto de resolución llamando a la API de [https://docs.aws.amazon.com/appsync/latest/APIReference/API_CreateResolver.html](https://docs.aws.amazon.com/appsync/latest/APIReference/API_CreateResolver.html).

1. Puede modificar los campos del solucionador llamando a la API de [https://docs.aws.amazon.com/appsync/latest/APIReference/API_UpdateResolver.html](https://docs.aws.amazon.com/appsync/latest/APIReference/API_UpdateResolver.html).

------
#### [ CLI ]

1. Cree un solucionador ejecutando el comando [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html).

   Deberá escribir 6 parámetros para este comando concreto:

   1. El `api-id` de su API.

   1. El `type-name` del tipo que quiere modificar en su esquema. En el ejemplo de la consola, esto era `Query`.

   1. El `field-name` del campo que quiere modificar en su tipo. En el ejemplo de la consola, esto era `getTodos`.

   1. El `data-source-name` del origen de datos que creó en la guía [Asociar un origen de datos](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html).

   1. La `request-mapping-template`, que es el cuerpo de la solicitud. En el ejemplo de la consola, esto era:

      ```
      {
          "version" : "2017-02-28",
          "operation" : "Scan"
      }
      ```

   1. La `response-mapping-template`, que es el cuerpo de la respuesta. En el ejemplo de la consola, esto era:

      ```
      $util.toJson($ctx.result.items)
      ```

   Un comando de ejemplo puede tener este aspecto:

   ```
   aws appsync create-resolver --api-id abcdefghijklmnopqrstuvwxyz --type-name Query --field-name getTodos --data-source-name TodoTable --request-mapping-template "{ "version" : "2017-02-28", "operation" : "Scan", }" --response-mapping-template ""$"util.toJson("$"ctx.result.items)"
   ```

   Aparecerá un resultado en la CLI. A continuación se muestra un ejemplo:

   ```
   {
       "resolver": {
           "kind": "UNIT",
           "dataSourceName": "TodoTable",
           "requestMappingTemplate": "{ version : 2017-02-28, operation : Scan, }",
           "resolverArn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Query/resolvers/getTodos",
           "typeName": "Query",
           "fieldName": "getTodos",
           "responseMappingTemplate": "$util.toJson($ctx.result.items)"
       }
   }
   ```

1. Para modificar las plantillas de and/or mapeo de campos de un solucionador, ejecute el [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-resolver.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-resolver.html)comando.

   Con la excepción del parámetro `api-id`, los parámetros utilizados en el comando `create-resolver` se sobrescribirán con los nuevos valores del comando `update-resolver`.

------

## Adición de un solucionador para mutaciones
<a name="adding-a-resolver-for-mutations"></a>

El siguiente paso es crear un solucionador para su tipo de `Mutation`.

------
#### [ Console ]

1. Inicie sesión en la [AppSync consola Consola de administración de AWS y ábrala](https://console.aws.amazon.com/appsync/).

   1. En el **APIs panel de control**, elige tu API de GraphQL.

   1. En la **barra lateral**, seleccione **Esquema**.

1. En el tipo de **Mutación**, seleccione **Asociar** junto al campo `addTodo`.

1. En la página **Crear un solucionador**, elija el origen de datos que creó en la guía [Asociar un origen de datos](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html).

1. En la ventana **Configurar plantillas de asignación**, modifique la plantilla de solicitud, ya que se trata de una mutación en la que se añade un elemento nuevo a DynamoDB. Use la siguiente plantilla de asignación de solicitud.

   ```
   {
       "version" : "2017-02-28",
       "operation" : "PutItem",
       "key" : {
           "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
       },
       "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args)
   }
   ```

1. AWS AppSync convierte automáticamente los argumentos definidos en el `addTodo` campo del esquema de GraphQL en operaciones de DynamoDB. En el ejemplo anterior se almacenan registros en DynamoDB mediante una clave de `id`, que se transfiere desde el argumento de mutación como `$ctx.args.id`. Todos los demás campos que transfiera se mapearán automáticamente en atributos de DynamoDB con `$util.dynamodb.toMapValuesJson($ctx.args)`.

   Para este solucionador, use la siguiente plantilla de mapeo de respuesta:

   ```
   $util.toJson($ctx.result)
   ```

   AWS AppSync también admite flujos de trabajo de prueba y depuración para la edición de resoluciones. Puede usar un objeto `context` simulado para ver el valor transformado de la plantilla antes de la invocación. De forma opcional, puede ver la ejecución de la solicitud completa en un origen de datos de forma interactiva cuando ejecute una consulta. Para obtener más información, consulte las secciones sobre [prueba y depuración de solucionadores](test-debug-resolvers.md#aws-appsync-test-debug-resolvers) y sobre [monitorización y registro](monitoring.md#aws-appsync-monitoring).

1. Seleccione **Guardar solucionador**.

------
#### [ API ]

También puede hacerlo APIs utilizando los comandos de la sección [Cree su primera resolución](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers.html#create-your-first-resolver) y los detalles de los parámetros de esta sección.

------
#### [ CLI ]

También puede hacer esto en la CLI utilizando los comandos de la sección [Cree su primer solucionador](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers.html#create-your-first-resolver) y los detalles de los parámetros de esta sección.

------

En este momento, si no usa los solucionadores avanzados, puede empezar a utilizar su API de GraphQL tal como se indica en [Uso de la API](using-your-api.md#aws-appsync-using-your-api).

## Solucionadores avanzados
<a name="advanced-resolvers"></a>

Si está siguiendo la sección avanzada y crea un esquema de ejemplo en [Diseño del esquema](designing-your-schema.md#aws-appsync-designing-your-schema) para realizar un análisis paginado, utilice la siguiente plantilla de solicitud para el campo `getTodos`:

```
{
    "version" : "2017-02-28",
    "operation" : "Scan",
    "limit": $util.defaultIfNull(${ctx.args.limit}, 20),
    "nextToken": $util.toJson($util.defaultIfNullOrBlank($ctx.args.nextToken, null))
}
```

En este caso de uso de paginación el mapeo de la respuesta es algo más que un acceso directo, ya que debe contener tanto el *cursor* (de modo que el cliente sepa en qué página comenzar a continuación) como el conjunto de resultados. La plantilla de mapeo es la siguiente:

```
{
    "todos": $util.toJson($context.result.items),
    "nextToken": $util.toJson($context.result.nextToken)
}
```

Los campos de la plantilla de mapeo de respuesta anterior tienen que coincidir con los campos definidos en su tipo `TodoConnection`.

En el caso de las relaciones en las que tiene una tabla `Comments` y usted está solucionando el campo de comentarios del tipo `Todo` (que devuelve un tipo de `[Comment]`), puede utilizar una plantilla de asignación que ejecute una consulta en la segunda tabla. Para ello, ya debe haber creado un origen de datos para la tabla `Comments` tal como se indica en [Asociar un origen de datos](attaching-a-data-source.md#aws-appsync-getting-started-build-a-schema-from-scratch).

**nota**  
Usamos una operación de consulta en otra tabla solo con fines ilustrativos. También podría usar otra operación realizada en DynamoDB en su lugar. Además, puede extraer los datos de otra fuente de datos, como AWS Lambda Amazon OpenSearch Service, ya que la relación está controlada por su esquema de GraphQL.

------
#### [ Console ]

1. Inicia sesión en la [AppSync consola Consola de administración de AWS](https://console.aws.amazon.com/appsync/) y ábrela.

   1. En el **APIs panel de control**, elige tu API de GraphQL.

   1. En la **barra lateral**, seleccione **Esquema**.

1. En el tipo **Todo**, seleccione **Asociar** junto al campo `comments`.

1. En la página **Crear solucionador**, elija el origen de datos de la tabla **Comentarios**. El nombre predeterminado de la tabla **Comentarios** en las guías de inicio rápido es `AppSyncCommentTable`, pero puede variar en función del nombre que le haya dado.

1. Añada el siguiente fragmento de código a su plantilla de asignación de solicitud:

   ```
   {
       "version": "2017-02-28",
       "operation": "Query",
       "index": "todoid-index",
       "query": {
           "expression": "todoid = :todoid",
           "expressionValues": {
               ":todoid": {
                   "S": $util.toJson($context.source.id)
               }
           }
       }
   }
   ```

1. `context.source` hace referencia al objeto principal del campo actual que se está resolviendo. En este ejemplo, `source.id` hace referencia al objeto `Todo` individual, que se usa a continuación para la expresión de consulta.

   Puede utilizar la plantilla de mapeo de respuesta de acceso directo de la siguiente manera:

   ```
   $util.toJson($ctx.result.items)
   ```

1. Seleccione **Guardar solucionador**.

1. Por último, en la página **Esquema**, asocie un solucionador al campo `addComment` y especifique el origen de datos para la tabla `Comments`. La plantilla de mapeo de solicitud en este caso es un elemento `PutItem` sencillo con el elemento `todoid` específico en el que se realiza el comentario como argumento, pero usa la utilidad `$utils.autoId()` para crear una clave de ordenación única para el comentario de la siguiente manera:

   ```
   {
       "version": "2017-02-28",
       "operation": "PutItem",
       "key": {
           "todoid": { "S": $util.toJson($context.arguments.todoid) },
           "commentid": { "S": "$util.autoId()" }
       },
       "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args)
   }
   ```

   Utilice una plantilla de respuesta de acceso directo de la siguiente manera:

   ```
   $util.toJson($ctx.result)
   ```

------
#### [ API ]

También puedes hacerlo APIs utilizando los comandos de la sección [Crea tu primera resolución](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers.html#create-your-first-resolver) y los detalles de los parámetros de esta sección.

------
#### [ CLI ]

También puede hacer esto en la CLI utilizando los comandos de la sección [Cree su primer solucionador](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers.html#create-your-first-resolver) y los detalles de los parámetros de esta sección.

------

# Desactivación de las plantillas de mapeo de VTL con solucionadores de Lambda directos (VTL)
<a name="direct-lambda-reference"></a>

**nota**  
Ahora admitimos de forma básica el tiempo de ejecución APPSYNC\$1JS y su documentación. Considere la opción de utilizar el tiempo de ejecución APPSYNC\$1JS y sus guías [aquí](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html).

Con los resolutores Lambda directos, puede evitar el uso de plantillas de mapeo de VTL al utilizar fuentes de datos. AWS Lambda AWS AppSync puede proporcionar una carga útil predeterminada a la función de Lambda, así como una traducción predeterminada de la respuesta de una función de Lambda a un tipo de GraphQL. Puedes elegir entre proporcionar una plantilla de solicitud, una plantilla de respuesta o ninguna de las dos, y la AWS AppSync gestionarás en consecuencia. 

Para obtener más información sobre la carga útil de solicitud predeterminada y la traducción de respuestas que AWS AppSync proporciona, consulte la referencia de resolución de [Direct Lambda](resolver-mapping-template-reference-lambda.md#direct-lambda-resolvers). Para obtener más información sobre la configuración de una fuente de AWS Lambda datos y la configuración de una política de confianza de IAM, consulte [Adjuntar](attaching-a-data-source.md) una fuente de datos. 

## Configurar solucionadores de Lambda directos
<a name="direct-lambda-reference-resolvers"></a>

En las secciones siguientes, se muestra cómo asociar orígenes de datos de Lambda y cómo añadir solucionadores de Lambda a los campos.

### Añadir un origen de datos de Lambda
<a name="direct-lambda-datasource"></a>

Para poder activar los solucionadores de Lambda directos, debe añadir un origen de datos de Lambda.

------
#### [ Console ]

1. [Inicie sesión en la consola Consola de administración de AWS y ábrala. AppSync](https://console.aws.amazon.com/appsync/)

   1. En el **APIs panel de control**, elige tu API de GraphQL.

   1. En la **barra lateral**, seleccione **Origen de datos**.

1. Elija **Crear origen de datos**.

   1. En **Nombre de origen de datos**, introduzca un nombre para el origen de datos (por ejemplo, **myFunction**). 

   1. En **Tipo de origen de datos**, elija **AWS Lambda Ninguno**.

   1. En **Región**, elija la región apropiada.

   1. En **ARN de la función**, elija la función de Lambda en la lista desplegable. Puede buscar el nombre de la función o introducir manualmente el ARN de la función que desee utilizar. 

   1. Cree un nuevo rol de IAM (recomendado) o elija un rol existente que tenga el permiso de IAM `lambda:invokeFunction`. Los roles existentes necesitan una política de confianza, tal y como se explica en la sección [Asociar un origen de datos](attaching-a-data-source.md). 

      El siguiente es un ejemplo de política de IAM que tiene los permisos necesarios para llevar a cabo operaciones en el recurso:

------
#### [ JSON ]

****  

      ```
      { 
           "Version":"2012-10-17",		 	 	  
           "Statement": [ 
               { 
                   "Effect": "Allow", 
                   "Action": [ "lambda:invokeFunction" ], 
                   "Resource": [ 
                       "arn:aws:lambda:us-west-2:123456789012:function:myFunction", 
                       "arn:aws:lambda:us-west-2:123456789012:function:myFunction:*" 
                   ] 
               } 
           ] 
       }
      ```

------

1. Pulse el botón **Crear**.

------
#### [ CLI ]

1. Cree un origen de datos ejecutando el comando [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-data-source.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-data-source.html).

   Deberá escribir 4 parámetros para este comando concreto:

   1. El `api-id` de su API.

   1. El `name` de origen de datos. En el ejemplo de la consola, este es el **nombre del origen de datos**.

   1. El `type` de origen de datos. En el ejemplo de la consola, se trata de una **función AWS Lambda **.

   1. El `lambda-config`, que es el **ARN de la función** el ejemplo de la consola.
**nota**  
Hay otros parámetros, como `Region`, que deben configurarse pero que normalmente se utilizarán de forma predeterminada en los valores de configuración de la CLI.

   Un comando de ejemplo puede tener este aspecto:

   ```
   aws appsync create-data-source --api-id abcdefghijklmnopqrstuvwxyz --name myFunction --type AWS_LAMBDA --lambda-config lambdaFunctionArn=arn:aws:lambda:us-west-2:102847592837:function:appsync-lambda-example
   ```

   Aparecerá un resultado en la CLI. A continuación se muestra un ejemplo:

   ```
   {
       "dataSource": {
           "dataSourceArn": "arn:aws:appsync:us-west-2:102847592837:apis/abcdefghijklmnopqrstuvwxyz/datasources/myFunction",
           "type": "AWS_LAMBDA",
           "name": "myFunction",
           "lambdaConfig": {
               "lambdaFunctionArn": "arn:aws:lambda:us-west-2:102847592837:function:appsync-lambda-example"
           }
       }
   }
   ```

1. Para modificar los atributos de un origen de datos, ejecute el comando [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-data-source.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-data-source.html).

   Con la excepción del parámetro `api-id`, los parámetros utilizados en el comando `create-data-source` se sobrescribirán con los nuevos valores del comando `update-data-source`.

------

### Activar los solucionadores de Lambda directos
<a name="direct-lambda-enable-templates"></a>

Tras crear una fuente de datos Lambda y configurar la función de IAM adecuada para poder AWS AppSync invocar la función, puede vincularla a una función de resolución o de canalización. 

------
#### [ Console ]

1. [Inicie sesión en la consola Consola de administración de AWS y ábrala. AppSync](https://console.aws.amazon.com/appsync/)

   1. En el **APIs panel de control**, elige tu API de GraphQL.

   1. En la **barra lateral**, seleccione **Esquema**.

1. En la ventana **Solucionadores**, elija un campo u operación y, a continuación, seleccione el botón **Asociar**.

1. En la página **Crear nuevo solucionador**, elija la función de Lambda en la lista desplegable.

1. Para aprovechar los solucionadores de Lambda directos, confirme que las plantillas de asignación de solicitud y respuesta estén deshabilitadas en la sección **Configurar plantillas de asignación**.

1. Pulse el botón **Guardar solucionador**.

------
#### [ CLI ]
+ Cree un solucionador ejecutando el comando [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html).

  Deberá escribir 6 parámetros para este comando concreto:

  1. El `api-id` de su API.

  1. El `type-name` del tipo de su esquema.

  1. El `field-name` del campo de su esquema.

  1. El `data-source-name` o el nombre de su función de Lambda.

  1. La `request-mapping-template`, que es el cuerpo de la solicitud. En el ejemplo de la consola, esto estaba deshabilitado:

     ```
     " "
     ```

  1. La `response-mapping-template`, que es el cuerpo de la respuesta. En el ejemplo de la consola, esto también estaba deshabilitado:

     ```
     " "
     ```

  Un comando de ejemplo puede tener este aspecto:

  ```
  aws appsync create-resolver --api-id abcdefghijklmnopqrstuvwxyz --type-name Subscription --field-name onCreateTodo --data-source-name LambdaTest --request-mapping-template " " --response-mapping-template " "
  ```

  Aparecerá un resultado en la CLI. A continuación se muestra un ejemplo:

  ```
  {
      "resolver": {
          "resolverArn": "arn:aws:appsync:us-west-2:102847592837:apis/abcdefghijklmnopqrstuvwxyz/types/Subscription/resolvers/onCreateTodo",
          "typeName": "Subscription",
          "kind": "UNIT",
          "fieldName": "onCreateTodo",
          "dataSourceName": "LambdaTest"
      }
  }
  ```

------

Al deshabilitar las plantillas de asignación, en AWS AppSync se producen varios comportamientos adicionales:
+ Al deshabilitar una plantilla de mapeo, indica AWS AppSync que acepta las traducciones de datos predeterminadas especificadas en la referencia de resolución de Direct [Lambda](resolver-mapping-template-reference-lambda.md#direct-lambda-resolvers).
+ Al deshabilitar la plantilla de asignación de solicitudes, el origen de datos de Lambda recibirá una carga compuesta por todo el objeto [Context](resolver-context-reference.md).
+ Al deshabilitar la plantilla de asignación de respuestas, el resultado de la invocación de Lambda se traducirá en función de la versión de la plantilla de asignación de solicitudes o de si la plantilla de asignación de solicitudes también está deshabilitada. 

# Prueba y depuración de resolutores en AWS AppSync (VTL)
<a name="test-debug-resolvers"></a>

**nota**  
Ahora admitimos de forma básica el tiempo de ejecución APPSYNC\$1JS y su documentación. Considere la opción de utilizar el tiempo de ejecución APPSYNC\$1JS y sus guías [aquí](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html).

AWS AppSync ejecuta resolutores en un campo GraphQL contra una fuente de datos. Como se describe en [Resolver mapping template overview](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview), los solucionadores se comunican con los orígenes de datos mediante un lenguaje de plantillas. Esto permite personalizar el comportamiento y aplicar lógica y condiciones antes y después de comunicarse con el origen de datos. Encontrará una guía de programación introductoria similar a un tutorial para escribir solucionadores en [Resolver mapping template programming guide](resolver-mapping-template-reference-programming-guide.md#aws-appsync-resolver-mapping-template-reference-programming-guide).

Para ayudar a los desarrolladores a escribir, probar y depurar estos resolutores, la AWS AppSync consola también proporciona herramientas para crear una solicitud y una respuesta de GraphQL con datos simulados para cada solucionador de campo individual. Además, puedes realizar consultas, mutaciones y suscripciones en la AWS AppSync consola y ver un registro detallado de Amazon CloudWatch de toda la solicitud. Esto incluye los resultados del origen de datos.

## Prueba con datos simulados
<a name="testing-with-mock-data"></a>

Cuando se invoca a un solucionador de GraphQL, este contiene un objeto `context` que incluye información sobre la solicitud. Por ejemplo, contiene los argumentos de un cliente, información de identidad y datos del campo principal de GraphQL. También contiene los resultados del origen de datos, que puede usar en la plantilla de respuesta. Si desea más información acerca de esta estructura y las utilidades auxiliares disponibles para programar, consulte la [Referencia del contexto de las plantillas de mapeo de solucionador](resolver-context-reference.md#aws-appsync-resolver-mapping-template-context-reference).

Al escribir o editar un solucionador, puede pasar un objeto *simulado* o *de contexto de prueba* al editor de la consola. Esto le permite ver cómo se evalúan la plantillas de solicitud y de respuesta sin que se utilice en realidad ningún origen de datos. Por ejemplo, puede transferir un argumento `firstname: Shaggy` de prueba y ver cómo se evalúa cuando utiliza `$ctx.args.firstname` en el código de la plantilla. También puede probar la evaluación de cualquier utilidad auxiliar, como `$util.autoId()` o `util.time.nowISO8601()`.

### Prueba de solucionadores
<a name="test-a-resolver"></a>

En este ejemplo, se utilizará la AWS AppSync consola para probar los resolutores.

1. Inicie sesión en la [AppSyncconsola Consola de administración de AWS](https://console.aws.amazon.com/appsync/) y ábrala.

   1. En el **APIs panel**, elige tu API de GraphQL.

   1. En la **barra lateral**, seleccione **Esquema**.

1. Si aún no lo ha hecho, en el tipo y junto al campo, seleccione **Asociar** para añadir su solucionador.

   Para obtener más información acerca de cómo crear un solucionador completo, consulte [Configuring resolvers](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers.html).

   De lo contrario, seleccione el solucionador que ya esté en el campo.

1. En la parte superior de la página **Editar el solucionador**, seleccione **Seleccionar contexto de prueba** y, a continuación, **Crear nuevo contexto**.

1. Seleccione un objeto de contexto de ejemplo o rellene el JSON manualmente en la ventana **Contexto de ejecución** que aparece a continuación.

1. Introduzca un **Nombre de contexto de texto**.

1. Seleccione el botón **Guardar**.

1. En la parte superior de la página **Editar solucionador**, seleccione **Ejecutar prueba**.

Veamos un ejemplo más práctico. Imagine que tiene una aplicación que almacena un tipo de GraphQL llamado `Dog`, que genera automáticamente un identificador para los objetos y los almacena en Amazon DynamoDB. También desea escribir algunos valores tomándolos de los argumentos de una mutación de GraphQL y permitir que solo determinados usuarios vean la respuesta. El esquema podría tener el siguiente aspecto:

```
type Dog {
  breed: String
  color: String
}

type Mutation {
  addDog(firstname: String, age: Int): Dog
}
```

Al añadir un solucionador para la mutación `addDog`, puede rellenar un objeto de contexto como el que aparece en el ejemplo a continuación. Se incluyen argumentos del cliente como `name` y `age`, así como un `username` rellenado en el objeto `identity`:

```
{
    "arguments" : {
        "firstname": "Shaggy",
        "age": 4
    },
    "source" : {},
    "result" : {
        "breed" : "Miniature Schnauzer",
        "color" : "black_grey"
    },
    "identity": {
        "sub" : "uuid",
        "issuer" : " https://cognito-idp.{region}.amazonaws.com/{userPoolId}",
        "username" : "Nadia",
        "claims" : { },
        "sourceIp" :[  "x.x.x.x" ],
        "defaultAuthStrategy" : "ALLOW"
    }
}
```

Puede probarlo utilizando las siguientes plantillas de mapeo de solicitud y de respuesta:

 **Plantilla de solicitud** 

```
{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key" : {
        "id" : { "S" : "$util.autoId()" }
    },
    "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args)
}
```

 **Plantilla de respuesta** 

```
#if ($context.identity.username == "Nadia")
  $util.toJson($ctx.result)
#else
  $util.unauthorized()
#end
```

La plantilla evaluada tiene los datos del objeto de contexto de prueba y el valor generado por `$util.autoId()`. Además, si cambia el `username` por un valor distinto de `Nadia`, no se devolverán resultados, porque la comprobación de autorización daría error. Para obtener más información acerca del control de acceso preciso, consulte [Casos de uso de autorizaciones](security-authorization-use-cases.md#aws-appsync-security-authorization-use-cases).

### Probando plantillas de mapeo con AWS AppSync APIs
<a name="testing-with-appsync-api"></a>

Puede usar el comando de API `EvaluateMappingTemplate` para probar las plantillas de mapeo de forma remota con datos simulados. Para empezar a usar el comando, asegúrese de haber añadido el permiso `appsync:evaluateMappingTemplate` a su política. Por ejemplo:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "appsync:evaluateMappingTemplate",
            "Resource": "arn:aws:appsync:us-east-1:111122223333:*"
        }
    ]
}
```

------

Puede aprovechar el comando mediante la tecla [AWS CLI](https://aws.amazon.com/cli/)o [AWS SDKs](https://aws.amazon.com/tools/). Por ejemplo, tome el `Dog` esquema y sus plantillas de request/response mapeo de la sección anterior. Con la CLI de la estación local, guarde la plantilla de solicitudes en un archivo denominado `request.vtl` y, a continuación, guarde el objeto `context` en un archivo denominado `context.json`. Ejecute el siguiente comando desde el intérprete de comandos:

```
aws appsync evaluate-mapping-template --template file://request.vtl --context file://context.json
```

El comando devuelve la siguiente respuesta:

```
{
  "evaluationResult": "{\n    \"version\" : \"2017-02-28\",\n    \"operation\" : \"PutItem\",\n    \"key\" : {\n        \"id\" : { \"S\" : \"afcb4c85-49f8-40de-8f2b-248949176456\" }\n    },\n    \"attributeValues\" : {\"firstname\":{\"S\":\"Shaggy\"},\"age\":{\"N\":4}}\n}\n"
}
```

`evaluationResult`Contiene los resultados de la prueba de la plantilla proporcionada con el `context` proporcionado. También puede probar sus plantillas con AWS SDKs. Este es un ejemplo del uso del AWS SDK para la JavaScript versión 2: 

```
const AWS = require('aws-sdk')
const client = new AWS.AppSync({ region: 'us-east-2' })

const template = fs.readFileSync('./request.vtl', 'utf8')
const context = fs.readFileSync('./context.json', 'utf8')

client
  .evaluateMappingTemplate({ template, context })
  .promise()
  .then((data) => console.log(data))
```

Cuando se utiliza el SDK, puede incorporar fácilmente pruebas de su conjunto de pruebas favorito para validar el comportamiento de la plantilla. Recomendamos crear pruebas con el [marco de pruebas Jest](https://jestjs.io/), pero cualquier conjunto de pruebas funciona. En el siguiente fragmento de código se muestra una ejecución de validación hipotética. Tenga en cuenta que esperamos que la respuesta de la evaluación sea un JSON válido, por lo que utilizamos `JSON.parse` para recuperar el JSON de la respuesta de cadena:

```
const AWS = require('aws-sdk')
const fs = require('fs')
const client = new AWS.AppSync({ region: 'us-east-2' })

test('request correctly calls DynamoDB', async () => {
  const template = fs.readFileSync('./request.vtl', 'utf8')
  const context = fs.readFileSync('./context.json', 'utf8')
  const contextJSON = JSON.parse(context)
  
  const response = await client.evaluateMappingTemplate({ template, context }).promise()
  const result = JSON.parse(response.evaluationResult)
  
  expect(result.key.id.S).toBeDefined()
  expect(result.attributeValues.firstname.S).toEqual(contextJSON.arguments.firstname)
})
```

 Esto produce el siguiente resultado:

```
Ran all test suites.
> jest

PASS ./index.test.js
✓ request correctly calls DynamoDB (543 ms)

Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.511 s, estimated 2 s
```

## Depuración de una consulta en tiempo real
<a name="debugging-a-live-query"></a>

No hay nada que sustituya a una end-to-end prueba y un registro para depurar una aplicación de producción. AWS AppSync te permite registrar los errores y los detalles completos de las solicitudes a través de Amazon CloudWatch. Además, puedes usar la AWS AppSync consola para probar las consultas, mutaciones y suscripciones de GraphQL y transmitir en directo los datos de registro de cada solicitud de vuelta al editor de consultas para depurarlos en tiempo real. Para las suscripciones, los registros muestran la información del tiempo de conexión.

Para ello, debes tener habilitados los CloudWatch registros de Amazon con antelación, tal y como se describe en [Supervisión y registro](monitoring.md#aws-appsync-monitoring). A continuación, en la AWS AppSync consola, selecciona la pestaña **Consultas** y, a continuación, introduce una consulta GraphQL válida. En la sección inferior derecha, haga clic y arrastre la ventana **Registros** para abrir la vista de registros. Utilice el icono de flecha de reproducción de la parte superior de la página para ejecutar la consulta de GraphQL. Al cabo de unos momentos, los registros completos de la solicitud y la respuesta de la operación se enviarán a esta sección y podrá verlos en la consola.

# Configuración y uso de solucionadores de canalización en AWS AppSync (VTL)
<a name="pipeline-resolvers"></a>

**nota**  
Ahora admitimos de forma básica el tiempo de ejecución APPSYNC\$1JS y su documentación. Considere la opción de utilizar el tiempo de ejecución APPSYNC\$1JS y sus guías [aquí](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html).

AWS AppSync ejecuta resolutores en un campo GraphQL. En algunos casos, las aplicaciones requieren la ejecución de varias operaciones para resolver un único campo de GraphQL. Con los solucionadores de canalización, los desarrolladores ahora pueden componer operaciones llamadas Funciones y ejecutarlas de forma secuencial. Los solucionadores de canalización son útiles para las aplicaciones que, por ejemplo, requieren realizar una comprobación de autorización antes de recuperar datos para un campo.

Un solucionador de canalización se compone de una plantilla de mapeo **Antes**, una plantilla de mapeo **Después** y una lista de funciones. Cada función tiene una plantilla de mapeo de **solicitudes** y **respuestas** que ejecuta con un origen de datos. Puesto que un solucionador de canalización delega la ejecución a una lista de funciones, no está vinculado a ningún origen de datos. Las funciones y los solucionadores de unidad son primitivos que ejecutan operaciones frente a los orígenes de datos. Para obtener más información, consulte [Información general sobre las plantillas de mapeo de solucionador](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview).

## Paso 1: creación de un solucionador de canalización
<a name="create-a-pipeline-resolver"></a>

**En la AWS AppSync consola, ve a la página del esquema.**

Guarde el siguiente esquema:

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

type Mutation {
    signUp(input: Signup): User
}

type Query {
    getUser(id: ID!): User
}

input Signup {
    username: String!
    email: String!
}

type User {
    id: ID!
    username: String
    email: AWSEmail
}
```

Vamos a conectar un solucionador de canalización al campo **signUp** en el tipo **Mutation (Mutación)**. En el tipo **Mutación** en el lado derecho, elija **Asociar** junto al campo de mutación `signUp`. En la página de creación de solucionadores, haga clic en **Acciones** y, a continuación, en **Actualizar el tiempo de ejecución**. Elija `Pipeline Resolver`, luego `VTL` y, a continuación, **Actualizar**. Ahora, la página ahora debería mostrar tres secciones: un área de texto **Plantilla de mapeo Antes**, una sección **Funciones** y un área de texto **Plantilla de mapeo Después**.

Nuestro solucionador de canalización inicia sesión a un usuario. Para ello, primero valida la entrada de dirección de correo electrónico y, a continuación, guarda al usuario en el sistema. Vamos a encapsular la validación de correo electrónico dentro de una función **validateEmail** y el guardado del usuario dentro de una función **saveUser**. La función **validateEmail** se ejecuta en primer lugar y, si el correo electrónico es válido, se ejecuta la función **saveUser**.

El flujo de ejecución será como se indica a continuación:

1. Plantilla de mapeo de solicitud de solucionador Mutation.signUp

1. Función validateEmail

1. Función saveUser

1. Plantilla de mapeo de respuesta de solucionador Mutation.signUp

Dado que probablemente reutilizaremos la función **validateEmail** en otros solucionadores de nuestra API, queremos para evitar el acceso a `$ctx.args`, ya que estos cambiarán de un campo GraphQL a otro. En su lugar, podemos utilizar `$ctx.stash` para almacenar el atributo de correo electrónico desde el argumento de campo de entrada `signUp(input: Signup)`.

Plantilla de mapeo **ANTES**:

```
## store email input field into a generic email key
$util.qr($ctx.stash.put("email", $ctx.args.input.email))
{}
```

La consola ofrece un acceso directo predeterminado de plantilla de mapeo **DESPUÉS** que vamos a utilizar:

```
$util.toJson($ctx.result)
```

Seleccione **Crear** o **Guardar** para actualizar el solucionador.

## Paso 2: creación de una función
<a name="create-a-function"></a>

En la página del solucionador de canalización, en la sección **Funciones**, haga clic en **Agregar función** y luego en **Crear la función nueva**. También es posible crear funciones sin pasar por la página de resolución; para ello, en la AWS AppSync consola, vaya a la página de **funciones**. Elija el botón **Crear una función**. Vamos a crear una función que comprueba si un mensaje de correo electrónico es válido y proviene de un dominio específico. Si el correo electrónico no es válido, la función genera un error. De lo contrario, reenvía cualquier entrada.

En la nueva página de funciones, seleccione **Acciones** y, a continuación, **Actualizar tiempo de ejecución**. Elija `VTL` y, a continuación, **Actualizar**. Asegúrese de haber creado un origen de datos del tipo **NINGUNO**. Elija este origen de datos en la lista de **Nombre del origen de datos**. Para el **nombre de función**, introduzca `validateEmail`. En el área de **código de la función**, sobrescriba todo con este fragmento:

```
#set($valid = $util.matches("^[a-zA-Z0-9_.+-]+@(?:(?:[a-zA-Z0-9-]+\.)?[a-zA-Z]+\.)?(myvaliddomain)\.com", $ctx.stash.email))
#if (!$valid)
    $util.error("$ctx.stash.email is not a valid email.")
#end
{
    "payload": { "email": $util.toJson(${ctx.stash.email}) }
}
```

Péguelo en la plantilla de mapeo de respuestas:

```
$util.toJson($ctx.result)
```

Revise sus modificaciones y, a continuación, elija **Crear**. Acabamos de crear nuestra función **validateEmail**. Repita estos pasos para crear la función **SaveUser** con las siguientes plantillas de mapeo de solicitudes y respuestas (para simplificar, utilizamos un origen de datos **NINGUNO** y simulamos que el usuario se ha guardado en el sistema después de ejecutar la función): 

Plantilla de mapeo de solicitudes:

```
## $ctx.prev.result contains the signup input values. We could have also
## used $ctx.args.input.
{
    "payload": $util.toJson($ctx.prev.result)
}
```

Plantilla de mapeo de respuestas:

```
## an id is required so let's add a unique random identifier to the output
$util.qr($ctx.result.put("id", $util.autoId()))
$util.toJson($ctx.result)
```

Acabamos de crear la función **saveUser**.

## Paso 3: adición de una función a un solucionador de canalización
<a name="adding-a-function-to-a-pipeline-resolver"></a>

Nuestras funciones deberían haberse agregado automáticamente al solucionador de canalización que acabamos de crear. Si este no es el caso, o si ha creado las funciones a través de la página **Funciones**, puede volver a hacer clic en **Agregar función** en la página del solucionador para asociarlas. Agregue las funciones **validateEmail** y **saveUser** al solucionador. La función **validateEmail** se debe colocar antes de la función **saveUser**. A medida que agrega más funciones, puede utilizar las opciones **mover hacia arriba** y **mover hacia abajo** para reorganizar el orden de ejecución de las funciones. Revise sus cambios y, a continuación, elija **Guardar**.

## Paso 4: Ejecución de una consulta
<a name="executing-a-query"></a>

En la AWS AppSync consola, vaya a la página de **consultas**. En el explorador, asegúrese de utilizar la mutación. Si no es así, seleccione `Mutation` en la lista desplegable y, a continuación, elija `+`. Escriba la siguiente consulta:

```
mutation {
  signUp(input: {
    email: "nadia@myvaliddomain.com"
    username: "nadia"
  }) {
    id
    email
  }
}
```

Debería devolver algo parecido a esto:

```
{
  "data": {
    "signUp": {
      "id": "256b6cc2-4694-46f4-a55e-8cb14cc5d7fc",
      "email": "nadia@myvaliddomain.com"
    }
  }
}
```

Hemos registrado correctamente nuestro usuario y validado el correo electrónico de entrada utilizando un solucionador de canalización. Para seguir un tutorial más completo centrado en los solucionadores de canalización, puede ir al [tutorial de solucionadores de canalización](tutorial-pipeline-resolvers.md#aws-appsync-tutorial-pipeline-resolvers) 

# Uso de una AWS AppSync API con el AWS CDK
<a name="using-your-api"></a>

**sugerencia**  
[Antes de usar la CDK, te recomendamos que consultes la [documentación oficial](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html) de la CDK junto con AWS AppSync su referencia.](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
También recomendamos asegurarse de que las instalaciones de la [CLI de AWS](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) y [NPM](https://docs.npmjs.com/) funcionan en el sistema.

En esta sección, vamos a crear una aplicación de CDK sencilla que pueda añadir y obtener elementos de una tabla de DynamoDB. Se trata de un ejemplo de inicio rápido en el que se utiliza parte del código de las secciones [Diseñar un esquema](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html), [Adjuntar una fuente de datos](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html) y [Configurar](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html) resolutores (). JavaScript

## Configuración de un proyecto de CDK
<a name="Setting-up-a-cdk-project"></a>

**aviso**  
Es posible que estos pasos no sean completamente precisos en función del entorno. Suponemos que su sistema tiene instaladas las utilidades necesarias, una forma de interactuar con AWS los servicios y las configuraciones adecuadas.

El primer paso es instalar el AWS CDK. En su CLI, puede introducir el comando siguiente:

```
npm install -g aws-cdk
```

A continuación, debe crear un directorio del proyecto y, luego, navegar hasta él. Un ejemplo de un conjunto de comandos para crear un directorio y navegar a él es:

```
mkdir example-cdk-app
cd example-cdk-app
```

A continuación, debe crear una aplicación. Nuestro servicio utiliza TypeScript principalmente. Ejecute el siguiente comando en el directorio de su proyecto:

```
cdk init app --language typescript
```

Al hacerlo, se instalará una aplicación CDK junto con sus archivos de inicialización:

![\[Terminal output showing Git repository initialization and npm install completion.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-init-app-example.png)


La estructura de proyecto puede tener un aspecto similar al siguiente:

![\[Project directory structure showing folders and files for an example CDK app.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-init-directories.png)


Se dará cuenta de que tenemos varios directorios importantes:
+ `bin`: el archivo bin inicial creará la aplicación. No trataremos este tema en esta guía.
+ `lib`: el directorio lib contiene los archivos de pila. Los archivos de pila se podrían comparar a unidades de ejecución individuales. Las construcciones estarán dentro de nuestros archivos de pila. Básicamente, se trata de recursos para un servicio que se activará CloudFormation cuando se despliegue la aplicación. Aquí es donde se realizará la mayor parte de nuestra codificación.
+ `node_modules`: este directorio lo creó NPM y contiene todas las dependencias de paquetes que instaló mediante el comando `npm`.

Nuestro archivo de pila inicial puede contener algo como esto:

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
// import * as sqs from 'aws-cdk-lib/aws-sqs';

export class ExampleCdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here

    // example resource
    // const queue = new sqs.Queue(this, 'ExampleCdkAppQueue', {
    //   visibilityTimeout: cdk.Duration.seconds(300)
    // });
  }
}
```

Este es el código reutilizable para crear una pila en nuestra aplicación. La mayor parte del código de este ejemplo se incluirá en el ámbito de esta clase.

Para comprobar que el archivo de pila está en la aplicación, en el directorio de la aplicación, ejecute el siguiente comando en el terminal:

```
cdk ls
```

Debería aparecer una lista de sus pilas. Si no es así, es posible que tenga que volver a realizar los pasos o consultar la documentación oficial para obtener ayuda.

Si quiere compilar los cambios de código antes de implementarlos, siempre puede ejecutar el siguiente comando en el terminal:

```
npm run build
```

Y, para ver los cambios antes de la implementación:

```
cdk diff
```

Antes de añadir nuestro código al archivo de pila, vamos a realizar un arranque. El arranque nos permite aprovisionar recursos para el CDK antes de que se implemente la aplicación. Puede encontrar más información sobre este proceso [aquí](https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html). El comando para crear un arranque es:

```
cdk bootstrap aws://ACCOUNT-NUMBER/REGION
```

**sugerencia**  
Este paso requiere varios permisos de IAM en su cuenta. Se denegará el arranque si no los tiene. Si esto ocurre, es posible que tenga que eliminar los recursos incompletos que ha causado el arranque, como el bucket de S3 que genera.

El arranque generará varios recursos. El mensaje final tendrá el siguiente aspecto:

![\[Terminal output showing successful bootstrapping of an AWS environment.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-init-bootstrap-final.png)


Esto se hace una vez por cuenta y región, por lo que no tendrá que hacerlo con frecuencia. Los principales recursos del bootstrap son la CloudFormation pila y el bucket de Amazon S3.

El bucket de Amazon S3 se utiliza para almacenar archivos y roles de IAM que conceden los permisos necesarios para realizar las implementaciones. Los recursos necesarios se definen en una CloudFormation pila, denominada pila bootstrap, que suele tener ese nombre. `CDKToolkit` Como cualquier CloudFormation pila, aparece en la CloudFormation consola una vez desplegada:

![\[CDKToolkit stack with CREATE_COMPLETE status in CloudFormation console.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-init-bootstrap-cfn-console.png)


Lo mismo puede decirse del bucket:

![\[S3 bucket details showing name, region, access settings, and creation date.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-init-bootstrap-bucket-console.png)


Para importar los servicios que necesitamos en nuestro archivo de pila, podemos usar el siguiente comando:

```
npm install aws-cdk-lib # V2 command
```

**sugerencia**  
Si tiene problemas con la V2, puede instalar las bibliotecas individuales mediante los comandos de la V1:  

```
npm install @aws-cdk/aws-appsync @aws-cdk/aws-dynamodb
```
No recomendamos esta opción porque la V1 está en desuso.

## Implementación de un proyecto de CDK: esquema
<a name="implementing-a-cdk-project-schema"></a>

Ahora podemos empezar a implementar nuestro código. En primer lugar, debemos crear nuestro esquema. Simplemente puede crear un archivo `.graphql` en su aplicación:

```
mkdir schema
touch schema.graphql
```

En nuestro ejemplo, incluimos un directorio de nivel superior llamado `schema` que contiene nuestro `schema.graphql`:

![\[File structure showing a schema folder containing schema.graphql file.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-schema-directory.png)


Dentro de nuestro esquema, vamos a incluir un ejemplo sencillo:

```
input CreatePostInput {
    title: String
    content: String
}

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

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

type Query {
    getPost: [Post]
}
```

De vuelta a nuestro archivo de pila, debemos asegurarnos de que estén definidas las siguientes directivas de importación:

```
import * as cdk from 'aws-cdk-lib';
import * as appsync from 'aws-cdk-lib/aws-appsync';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
import { Construct } from 'constructs';
```

Dentro de la clase, añadiremos código para crear nuestra API de GraphQL y conectarla a nuestro archivo `schema.graphql`:

```
export class ExampleCdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    
    // makes a GraphQL API
    const api = new appsync.GraphqlApi(this, 'post-apis', {
      name: 'api-to-process-posts',
      schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'),
    });
  }
}
```

También añadiremos código para imprimir la URL de GraphQL, la clave de API y la región:

```
export class ExampleCdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    
    // Makes a GraphQL API construct
    const api = new appsync.GraphqlApi(this, 'post-apis', {
      name: 'api-to-process-posts',
      schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'),
    });

    // Prints out URL
    new cdk.CfnOutput(this, "GraphQLAPIURL", {
      value: api.graphqlUrl
    });

    // Prints out the AppSync GraphQL API key to the terminal
    new cdk.CfnOutput(this, "GraphQLAPIKey", {
      value: api.apiKey || ''
    });

    // Prints out the stack region to the terminal
    new cdk.CfnOutput(this, "Stack Region", {
      value: this.region
    });
  }
}
```

En este punto, volveremos a implementar nuestra aplicación:

```
cdk deploy
```

El resultado es el siguiente:

![\[Deployment output showing ExampleCdkAppStack details, including GraphQL API URL and stack region.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-deploy-schema.png)


Parece que nuestro ejemplo fue exitoso, pero revisemos la AWS AppSync consola para confirmarlo:

![\[GraphQL interface showing successful API request with response data displayed.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-deploy-schema-result-1.png)


Parece que nuestra API se ha creado. Ahora, comprobaremos el esquema asociado a la API:

![\[GraphQL schema defining CreatePostInput, Post type, Mutation, and Query operations.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-deploy-schema-result-2.png)


Esto parece coincidir con nuestro código de esquema, por lo que se ha realizado correctamente. Otra forma de confirmarlo desde el punto de vista de los metadatos es observar la CloudFormation pila:

![\[CloudFormation stack showing ExampleCdkAppStack update complete and CDKToolkit creation complete.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-deploy-schema-result-3.png)


Cuando implementamos nuestra aplicación CDK, esta activa CloudFormation recursos, como el bootstrap. Cada pila de nuestra aplicación se mapea 1:1 con una CloudFormation pila. Si vuelve al código de la pila, verá que el nombre de la pila se ha tomado del nombre de la clase`ExampleCdkAppStack`. Puede ver los recursos que creó, que también se ajustan a nuestras convenciones de nomenclatura, en nuestra construcción de la API de GraphQL:

![\[Expanded view of post-apis resource showing Schema, DefaultApiKey, and CDKMetadata.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-deploy-schema-result-4.png)


## Implementación de un proyecto de CDK: origen de datos
<a name="implementing-a-cdk-project-data-source"></a>

A continuación, debemos añadir nuestro origen de datos. En nuestro ejemplo, se utilizará una tabla de DynamoDB. Dentro de la clase de pila, añadiremos código para crear una tabla nueva:

```
export class ExampleCdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Makes a GraphQL API construct
    const api = new appsync.GraphqlApi(this, 'post-apis', {
      name: 'api-to-process-posts',
      schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'),
    });

    //creates a DDB table
    const add_ddb_table = new dynamodb.Table(this, 'posts-table', {
      partitionKey: {
        name: 'id',
        type: dynamodb.AttributeType.STRING,
      },
    });

    // Prints out URL
    new cdk.CfnOutput(this, "GraphQLAPIURL", {
      value: api.graphqlUrl
    });

    // Prints out the AppSync GraphQL API key to the terminal
    new cdk.CfnOutput(this, "GraphQLAPIKey", {
      value: api.apiKey || ''
    });

    // Prints out the stack region to the terminal
    new cdk.CfnOutput(this, "Stack Region", {
      value: this.region
    });
  }
}
```

Llegados a este punto, volvamos a implementarla:

```
cdk deploy
```

Deberíamos comprobar la consola de DynamoDB para ver nuestra nueva tabla:

![\[DynamoDB console showing ExampleCdkAppStack-poststable as Active with Provisioned capacity.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-deploy-ddb-result-1.png)


El nombre de nuestra pila es correcto y el nombre de la tabla coincide con nuestro código. Si volvemos a comprobar nuestra CloudFormation pila, ahora veremos la nueva tabla:

![\[Expanded view of a logical ID in CloudFormation showing post-apis, posts-table, and CDKMetadata.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-deploy-ddb-result-2.png)


## Implementación de un proyecto de CDK: solucionador
<a name="implementing-a-cdk-project-resolver"></a>

En este ejemplo, se utilizarán dos solucionadores: uno para consultar la tabla y otro para añadirle elementos. Como utilizamos solucionadores de canalizaciones, tendremos que declarar dos solucionadores de canalizaciones con una función en cada uno. En la consulta, añadiremos el siguiente código:

```
export class ExampleCdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Makes a GraphQL API construct
    const api = new appsync.GraphqlApi(this, 'post-apis', {
      name: 'api-to-process-posts',
      schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'),
    });

    //creates a DDB table
    const add_ddb_table = new dynamodb.Table(this, 'posts-table', {
      partitionKey: {
        name: 'id',
        type: dynamodb.AttributeType.STRING,
      },
    });

    // Creates a function for query
    const add_func = new appsync.AppsyncFunction(this, 'func-get-post', {
      name: 'get_posts_func_1',
      api,
      dataSource: api.addDynamoDbDataSource('table-for-posts', add_ddb_table),
      code: appsync.Code.fromInline(`
          export function request(ctx) {
          return { operation: 'Scan' };
          }

          export function response(ctx) {
          return ctx.result.items;
          }
  `),
      runtime: appsync.FunctionRuntime.JS_1_0_0,
    });

    // Creates a function for mutation
    const add_func_2 = new appsync.AppsyncFunction(this, 'func-add-post', {
      name: 'add_posts_func_1',
      api,
      dataSource: api.addDynamoDbDataSource('table-for-posts-2', add_ddb_table),
      code: appsync.Code.fromInline(`
          export function request(ctx) {
            return {
            operation: 'PutItem',
            key: util.dynamodb.toMapValues({id: util.autoId()}),
            attributeValues: util.dynamodb.toMapValues(ctx.args.input),
            };
          }

          export function response(ctx) {
            return ctx.result;
          }
      `),
      runtime: appsync.FunctionRuntime.JS_1_0_0,
    });

    // Adds a pipeline resolver with the get function
    new appsync.Resolver(this, 'pipeline-resolver-get-posts', {
      api,
      typeName: 'Query',
      fieldName: 'getPost',
      code: appsync.Code.fromInline(`
          export function request(ctx) {
          return {};
          }

          export function response(ctx) {
          return ctx.prev.result;
          }
  `),
      runtime: appsync.FunctionRuntime.JS_1_0_0,
      pipelineConfig: [add_func],
    });

    // Adds a pipeline resolver with the create function
    new appsync.Resolver(this, 'pipeline-resolver-create-posts', {
      api,
      typeName: 'Mutation',
      fieldName: 'createPost',
      code: appsync.Code.fromInline(`
          export function request(ctx) {
          return {};
          }

          export function response(ctx) {
          return ctx.prev.result;
          }
  `),
      runtime: appsync.FunctionRuntime.JS_1_0_0,
      pipelineConfig: [add_func_2],
    });

    // Prints out URL
    new cdk.CfnOutput(this, "GraphQLAPIURL", {
      value: api.graphqlUrl
    });

    // Prints out the AppSync GraphQL API key to the terminal
    new cdk.CfnOutput(this, "GraphQLAPIKey", {
      value: api.apiKey || ''
    });

    // Prints out the stack region to the terminal
    new cdk.CfnOutput(this, "Stack Region", {
      value: this.region
    });
  }
}
```

En este fragmento, añadimos un solucionador de canalizaciones llamado `pipeline-resolver-create-posts` con una función llamada `func-add-post` asociada. Este es el código que añadirá `Posts` a la tabla. El otro solucionador de canalizaciones se ha denominado `pipeline-resolver-get-posts`, con una función llamada `func-get-post` que recupera `Posts` añadidos a la tabla.

Implementaremos esto para añadirlo al AWS AppSync servicio:

```
cdk deploy
```

Comprobemos la AWS AppSync consola para ver si estaban conectadas a nuestra API GraphQL:

![\[GraphQL API schema showing mutation and query fields with Pipeline resolvers.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-1.png)


Parece correcto. En el código, estos dos solucionadores estaban conectados a la API de GraphQL que creamos (indicada por el valor de accesorios `api` presente tanto en los solucionadores como en las funciones). En la API de GraphQL, los campos a los que asociamos nuestros solucionadores también estaban especificados en los accesorios (definidos por `typename` y los accesorios `fieldname` de cada solucionador).

Veamos si el contenido de los solucionadores es correcto empezando por `pipeline-resolver-get-posts`:

![\[Code snippet showing request and response functions in a resolver, with an arrow pointing to them.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-2.png)


Los controladores de antes y después coinciden con nuestro valor de accesorios `code`. También podemos ver una función llamada `add_posts_func_1`, que coincide con el nombre de la función que asociamos en el solucionador.

Veamos el contenido del código de esa función:

![\[Function code showing request and response methods for a PutItem operation.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-3.png)


Esto coincide con los accesorios `code` de la función `add_posts_func_1`. Nuestra consulta se ha cargado correctamente, así que revisemos la consulta:

![\[Resolver code with request and response functions, and a get_posts_func_1 function listed below.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-4.png)


También coinciden con el código. Si nos fijamos en `get_posts_func_1`:

![\[Code snippet showing two exported functions: request returning 'Scan' operation and response returning items.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-5.png)


Todo parece estar en su sitio. Para confirmarlo desde el punto de vista de los metadatos, podemos volver a revisar nuestra pila en CloudFormation :

![\[List of logical IDs for AWS resources including API, table, functions, and pipelines.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-6.png)


Ahora, necesitamos probar este código realizando algunas solicitudes.

## Implementación de un proyecto de CDK: solicitudes
<a name="implementing-a-cdk-project-requests"></a>

Para probar nuestra aplicación en la AWS AppSync consola, hicimos una consulta y una mutación:

![\[GraphQL code snippet showing a query to get post details and a mutation to create a post.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-request-1.png)


`MyMutation` contiene una operación `createPost` con los argumentos `1970-01-01T12:30:00.000Z` y `first post`. Devuelve los `date` y `title` que hemos introducido, así como el valor `id` generado automáticamente. Al ejecutar la mutación, se obtiene el resultado:

```
{
  "data": {
    "createPost": {
      "date": "1970-01-01T12:30:00.000Z",
      "id": "4dc1c2dd-0aa3-4055-9eca-7c140062ada2",
      "title": "first post"
    }
  }
}
```

Si comprobamos rápidamente la tabla de DynamoDB, podemos ver nuestra entrada en la tabla cuando la escaneamos:

![\[DynamoDB table entry showing id, date, and title fields for a single item.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/cdk-code-request-2.png)


Al volver a la AWS AppSync consola, si ejecutamos la consulta para recuperarlo`Post`, obtenemos el siguiente resultado:

```
{
  "data": {
    "getPost": [
      {
        "id": "9f62c4dd-49d5-48d5-b835-143284c72fe0",
        "date": "1970-01-01T12:30:00.000Z",
        "title": "first post"
      }
    ]
  }
}
```

# Uso de suscripciones para aplicaciones de datos en tiempo real en AWS AppSync
<a name="aws-appsync-real-time-data"></a>

**importante**  
A partir del 13 de marzo de 2025, podrás crear una PubSub API en tiempo real con la WebSockets tecnología de AWS AppSync Events. Para obtener más información, consulta [Publicar eventos WebSocket en](https://docs.aws.amazon.com/appsync/latest/eventapi/publish-websocket.html) la *Guía para desarrolladores de AWS AppSync eventos*.

AWS AppSyncpermite utilizar las suscripciones para implementar actualizaciones de aplicaciones en tiempo real, notificaciones push, etc. Cuando los clientes invocan las operaciones de suscripción de GraphQL, se establece y mantiene automáticamente una conexión WebSocket segura. AWS AppSync De este modo, las aplicaciones pueden distribuir los datos en tiempo real desde una fuente de datos a los suscriptores y, al mismo tiempo, gestionar AWS AppSync continuamente los requisitos de conexión y escalado de la aplicación. En las siguientes secciones, se mostrará cómo AWS AppSync funcionan las suscripciones.

## Directivas de suscripción del esquema de GraphQL
<a name="graphql-schema-subscription-directives"></a>

Las suscripciones en AWS AppSync se invocan como respuesta a una mutación. Esto significa que puede crear cualquier fuente de datos en tiempo AWS AppSync real especificando una directiva de esquema de GraphQL en una mutación.

Las bibliotecas AWS Amplify cliente gestionan automáticamente la gestión de las conexiones de las suscripciones. Las bibliotecas utilizan pure WebSockets como protocolo de red entre el cliente y el servicio.

**nota**  
Para controlar la autorización en el momento de la conexión a una suscripción, puede utilizar AWS Identity and Access Management (IAM) AWS Lambda, los grupos de identidades de Amazon Cognito o los grupos de usuarios de Amazon Cognito para la autorización a nivel de campo. Para obtener controles de acceso detallados a las suscripciones, puede adjuntar resolutores a sus campos de suscripción y realizar una lógica utilizando la identidad de la persona que llama y las fuentes de datos. AWS AppSync Para obtener más información, consulte [Configuración de la autorización y la autenticación para proteger su GraphQL APIs](security-authz.md).

Las suscripciones se activan a partir de mutaciones y el conjunto de mutaciones seleccionado se envía a los suscriptores.

En el siguiente ejemplo se muestra cómo usar las suscripciones de GraphQL. No especifica una fuente de datos porque la fuente de datos puede ser Lambda, Amazon DynamoDB o Amazon Service. OpenSearch 

Para comenzar a utilizar las suscripciones, debe agregar un punto de entrada de la suscripción a su esquema de este modo:

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

Imagine que dispone de un sitio donde se publican blogs y que desea suscribirse a nuevos blogs y a los cambios en los blogs existentes. Para ello, puede añadir la siguiente definición `Subscription` a su esquema:

```
type Subscription {
    addedPost: Post
    updatedPost: Post
    deletedPost: Post
}
```

Imagine también que tiene las siguientes mutaciones:

```
type Mutation {
    addPost(id: ID! author: String! title: String content: String url: String): Post!
    updatePost(id: ID! author: String! title: String content: String url: String ups: Int! downs: Int! expectedVersion: Int!): Post!
    deletePost(id: ID!): Post!
}
```

Puede convertir estos campos a tiempo real añadiendo una directiva `@aws_subscribe(mutations: ["mutation_field_1", "mutation_field_2"])` para cada una de las suscripciones de las que desea recibir notificaciones, tal y como se indica a continuación:

```
type Subscription {
    addedPost: Post
    @aws_subscribe(mutations: ["addPost"])
    updatedPost: Post
    @aws_subscribe(mutations: ["updatePost"])
    deletedPost: Post
    @aws_subscribe(mutations: ["deletePost"])
}
```

Dado que la mutación `@aws_subscribe(mutations: ["",..,""])` tiene una matriz de entradas de mutaciones, puede especificar varias mutaciones que inician una suscripción. Si se suscribe desde un cliente, su consulta de GraphQL podría tener el siguiente aspecto:

```
subscription NewPostSub {
    addedPost {
        __typename
        version
        title
        content
        author
        url
    }
}
```

Esta consulta de suscripción es necesaria para las conexiones de cliente y para las herramientas.

En el caso del WebSockets cliente puro, el filtrado del conjunto de selecciones se realiza por cliente, ya que cada cliente puede definir su propio conjunto de selecciones. En este caso, el conjunto de selecciones de la suscripción debe ser un subconjunto del conjunto de selecciones de la mutación. Por ejemplo, una suscripción `addedPost{author title}` vinculada a la mutación `addPost(...){id author title url version}` solo recibe el autor y el título de la publicación. No recibe el resto de campos. Sin embargo, si la mutación no incluye el autor en su conjunto de selecciones, el suscriptor obtiene un valor `null` para el campo de autor (o bien un error, en caso de que el campo de autor se defina como obligatorio o no nulo en el esquema).

El conjunto de selección de suscripciones es esencial cuando se utiliza pure WebSockets. Si un campo no está definido explícitamente en la suscripción, AWS AppSync no lo devuelve.

En el ejemplo anterior, las suscripciones no tenía argumentos. Imaginemos que su esquema es similar al siguiente:

```
type Subscription {
    updatedPost(id:ID! author:String): Post
    @aws_subscribe(mutations: ["updatePost"])
}
```

En este caso, el cliente define una suscripción de este modo:

```
subscription UpdatedPostSub {
    updatedPost(id:"XYZ", author:"ABC") {
        title
        content
    }
}
```

El tipo que devuelve el campo `subscription` del esquema debe coincidir con el tipo devuelto para el campo de mutación correspondiente. En el ejemplo anterior, tanto `addPost` como `addedPost` se devolvían con el tipo `Post`.

Para configurar las suscripciones en el cliente, consulte [Creación de una aplicación cliente mediante el cliente de Amplify](building-a-client-app.md).

## Uso de argumentos de suscripción
<a name="using-subscription-arguments"></a>

Un aspecto importante del uso de las suscripciones de GraphQL es comprender cuándo y cómo se deben usar los argumentos. Puede hacer cambios sutiles para modificar la forma y el momento de informar a los clientes acerca de las mutaciones que se han producido. Para ello, consulte el esquema de ejemplo del capítulo de inicio rápido, en el que se crean “Todos”. Para este esquema de ejemplo se definen las mutaciones siguientes:

```
type Mutation {
    createTodo(input: CreateTodoInput!): Todo
    updateTodo(input: UpdateTodoInput!): Todo
    deleteTodo(input: DeleteTodoInput!): Todo
}
```

En el ejemplo de muestra, los clientes pueden suscribirse a las actualizaciones de cualquier `Todo` utilizando la opción `onUpdateTodo` `subscription` sin argumentos:

```
subscription OnUpdateTodo {
  onUpdateTodo {
    description
    id
    name
    when
  }
}
```

Puede filtrar su `subscription` utilizando sus argumentos. Por ejemplo, para activar solo una `subscription` cuando se actualiza un `todo` con un `ID` específico, especifique el valor `ID`:

```
subscription OnUpdateTodo {
  onUpdateTodo(id: "a-todo-id") {
    description
    id
    name
    when
  }
}
```

También se pueden transferir varios argumentos. Por ejemplo, la siguiente `subscription` muestra cómo recibir notificaciones de cualquier actualización de `Todo` en un lugar y hora específicos:

```
subscription todosAtHome {
  onUpdateTodo(when: "tomorrow", where: "at home") {
    description
    id
    name
    when
    where
  }
}
```

Tenga en cuenta que todos los argumentos son opcionales. Si no especifica ningún argumento en su `subscription`, se suscribirá a todas las actualizaciones de `Todo` que se produzcan en su aplicación. Sin embargo, puede actualizar la definición de campo de su `subscription` para requerir el argumento `ID`. De este modo, forzaría la respuesta de un `todo` específico en lugar de la de todos los `todo`:

```
onUpdateTodo(
  id: ID!,
  name: String,
  when: String,
  where: String,
  description: String
): Todo
```

### El valor nulo del argumento tiene un significado
<a name="argument-null-value-has-meaning"></a>

Al realizar una consulta de suscripción AWS AppSync, el valor de un `null` argumento filtrará los resultados de forma diferente a cuando se omita el argumento por completo.

Volvamos al ejemplo de la API de todos, donde podríamos crear todos. Consulte el ejemplo de esquema del capítulo de inicio rápido.

Vamos a modificar nuestro esquema para incluir un nuevo campo `owner`, del tipo `Todo`, que describa quién es el propietario. El campo `owner` no es obligatorio y solo se puede configurar en `UpdateTodoInput`. Consulte la siguiente versión simplificada del esquema:

```
type Todo {
  id: ID!
  name: String!
  when: String!
  where: String!
  description: String!
  owner: String
}

input CreateTodoInput {
  name: String!
  when: String!
  where: String!
  description: String!
}

input UpdateTodoInput {
  id: ID!
  name: String
  when: String
  where: String
  description: String
  owner: String
}

type Subscription {
    onUpdateTodo(
        id: ID,
        name: String,
        when: String,
        where: String,
        description: String
    ): Todo @aws_subscribe(mutations: ["updateTodo"])
}
```

La siguiente suscripción devuelve todas las actualizaciones de `Todo`:

```
subscription MySubscription {
  onUpdateTodo {
    description
    id
    name
    when
    where
  }
}
```

Si modifica la suscripción anterior para agregar el argumento del campo `owner: null`, ahora está planteando una pregunta diferente. Ahora, esta suscripción registra al cliente para recibir notificaciones de todas las actualizaciones de `Todo` que no hayan indicado un propietario.

```
subscription MySubscription {
  onUpdateTodo(owner: null) {
    description
    id
    name
    when
    where
  }
}
```

**nota**  
**A partir del 1 de enero de 2022, MQTT over ya no WebSockets está disponible como protocolo para las suscripciones a GraphQL en. AWS AppSync APIs Pure WebSockets es el único protocolo compatible. AWS AppSync**  
Los clientes basados en el AWS AppSync SDK o las bibliotecas Amplify, lanzadas después de noviembre de 2019, utilizan pure automáticamente de forma WebSockets predeterminada. La actualización de los clientes a la última versión les permite utilizar AWS AppSync el WebSockets motor puro.  
 WebSockets Los Pure vienen con un tamaño de carga mayor (240 KB), una variedad más amplia de opciones de cliente y CloudWatch métricas mejoradas. Para obtener más información sobre el uso de WebSocket clientes puros, consulte[Crear un cliente en tiempo real en WebSocket AWS AppSync](real-time-websocket-client.md).

# Creación de genéricos pub/sub APIs con tecnología sin servidor WebSockets en AWS AppSync
<a name="aws-appsync-real-time-create-generic-api-serverless-websocket"></a>

**importante**  
A partir del 13 de marzo de 2025, podrás crear una PubSub API en tiempo real con la WebSockets tecnología de AWS AppSync Events. Para obtener más información, consulta [Publicar eventos WebSocket en](https://docs.aws.amazon.com/appsync/latest/eventapi/publish-websocket.html) la *Guía para desarrolladores de AWS AppSync eventos*.

Algunas aplicaciones solo requieren aplicaciones sencillas, WebSocket APIs donde los clientes escuchan un canal o tema específico. Los datos JSON genéricos sin un formato específico ni requisitos estrictamente definidos se pueden distribuir a los clientes que escuchan algunos de estos canales en un patrón de publicación suscripción (pub/sub) puro y simple.

 AWS AppSync Utilízalo para implementar código GraphQL de forma sencilla y pub/sub WebSocket APIs con poco o ningún conocimiento sobre GraphQL en cuestión de minutos, ya que genera automáticamente código GraphQL tanto en el backend de la API como en el lado del cliente.

## Crea y configura pub-sub APIs
<a name="aws-appsync-real-time-enhanced-filtering-using-pub-sub-apis"></a>

Para empezar, siga estos pasos: 

1. [Inicie sesión en la consola Consola de administración de AWS y ábrala. AppSync ](https://console.aws.amazon.com/appsync/)

   1. En el **Panel**, elija **Crear API**.

1. En la siguiente pantalla, seleccione **Crear una API en tiempo real** y, a continuación, seleccione **Siguiente**.

1. Introduce un nombre descriptivo para tu pub/sub API.

1. Puede habilitar las características de [API privada](https://docs.aws.amazon.com/appsync/latest/devguide/using-private-apis.html), pero le recomendamos que mantenga esta opción desactivada por ahora. Elija **Siguiente**.

1. Puedes optar por generar automáticamente una pub/sub API que funcione utilizando WebSockets. También recomendamos mantener esta característica desactivada por el momento. Elija **Siguiente**.

1. Seleccione **Crear API** y, a continuación, espere un par de minutos. Se creará una nueva API AWS AppSync pub/sub preconfigurada en tu cuenta. AWS 

La API utiliza AWS AppSync los solucionadores locales integrados (para obtener más información sobre el uso de los solucionadores locales, consulte el [tutorial sobre resoluciones locales](https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-local-resolvers-js.html) en la *Guía para AWS AppSync desarrolladores*) para administrar varios pub/sub canales y WebSocket conexiones temporales, lo que entrega y filtra automáticamente los datos a los clientes suscritos basándose únicamente en el nombre del canal. Las llamadas a la API se autorizan con una clave de API.

Una vez implementada la API, verá un par de pasos adicionales para generar el código de cliente e integrarlo con su aplicación cliente. Para ver un ejemplo de cómo integrar rápidamente un cliente, en esta guía se utilizará una sencilla aplicación web de React.

1. Para empezar cree una aplicación de React reutilizable usando [NPM](https://www.npmjs.com/get-npm) en su máquina local:

   ```
   $ npx create-react-app mypubsub-app 
   $ cd mypubsub-app
   ```
**nota**  
En este ejemplo, se utilizan las [bibliotecas Amplify](https://docs.amplify.aws/lib/) para conectar los clientes a la API de backend. Sin embargo, no es necesario crear un proyecto de CLI de Amplify a nivel local. Si bien React es el cliente preferido para este ejemplo, las bibliotecas de Amplify también son compatibles con los clientes de iOS, Android y Flutter, y proporcionan las mismas capacidades en estos tiempos de ejecución diferentes. [Los clientes Amplify compatibles proporcionan abstracciones sencillas para interactuar con los backends de la API de AWS AppSync GraphQL con pocas líneas de código, incluidas WebSocket capacidades integradas totalmente compatibles con el protocolo en tiempo real:AWS AppSync WebSocket ](https://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html)  

   ```
   $ npm install @aws-amplify/api
   ```

1. En la AWS AppSync consola, selecciona Descargar y **JavaScript**, a continuación, **Descargar** para descargar un único archivo con los detalles de configuración de la API y el código de operaciones de GraphQL generado.

1. Copie el archivo descargado en la carpeta `/src` de su proyecto de React.

1. A continuación, reemplace el contenido del archivo `src/App.js` reutilizable existente por el código de cliente de muestra disponible en la consola.

1. Utilice el comando siguiente para compilar y ejecutar la aplicación a nivel local:

   ```
   $ npm start
   ```

1. Para probar el envío y la recepción de datos en tiempo real, abre dos ventanas del navegador y accede*localhost:3000*. La aplicación de muestra está configurada para enviar datos JSON genéricos a un canal codificado denominado*robots*.

1.  En una de las ventanas del navegador, introduzca el siguiente blob JSON en el cuadro de texto y, a continuación, haz clic en **Enviar**: 

   ```
   {
     "robot":"r2d2",
     "planet": "tatooine"
   }
   ```

Ambas instancias del navegador están suscritas al *robots* canal y reciben los datos publicados en tiempo real, que se muestran en la parte inferior de la aplicación web:

![\[Ejemplo de aplicación React para API pub/sub\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/pub-sub-react.png)


Todo el código de la API GraphQL necesario, incluidos el esquema, los resolutores y las operaciones, se generan automáticamente para permitir un caso de uso genérico pub/sub . En el backend, los datos se publican en el punto final en tiempo real con una mutación de GraphQL como la siguiente: AWS AppSync

```
mutation PublishData {
    publish(data: "{\"msg\": \"hello world!\"}", name: "channel") {
        data
        name
    }
}
```

Los suscriptores acceden a los datos publicados que se envían al canal temporal específico con una suscripción de GraphQL relacionada:

```
subscription SubscribeToData {
    subscribe(name:"channel") {
        name
        data
    }
}
```

## Implementación de pub-sub APIs en aplicaciones existentes
<a name="aws-appsync-real-time-enhanced-filtering-existing-apps"></a>

En caso de que solo necesite implementar una función en tiempo real en una aplicación existente, esta configuración genérica de pub/sub API se puede integrar fácilmente en cualquier aplicación o tecnología de API. Si bien utilizar un único punto final de API para acceder, manipular y combinar de forma segura los datos de una o más fuentes de datos en una sola llamada de red con GraphQL, no es necesario convertir o reconstruir una aplicación existente basada en REST desde cero para aprovechar las capacidades en tiempo real AWS AppSync de GraphQL. Por ejemplo, podrías tener una carga de trabajo CRUD existente en un punto final de API independiente en el que los clientes envíen y reciban mensajes o eventos de la aplicación existente a la pub/sub API genérica solo en tiempo real y pub/sub con fines específicos. 

# Definir filtros de suscripciones mejorados en AWS AppSync
<a name="aws-appsync-real-time-enhanced-filtering"></a>

**importante**  
A partir del 13 de marzo de 2025, podrás crear una PubSub API en tiempo real con la WebSockets tecnología de AWS AppSync Events. Para obtener más información, consulta [Publicar eventos WebSocket en](https://docs.aws.amazon.com/appsync/latest/eventapi/publish-websocket.html) la *Guía para desarrolladores de AWS AppSync eventos*.

En AWS AppSync, puedes definir y habilitar la lógica empresarial para el filtrado de datos en el backend directamente en los solucionadores de suscripciones de la API GraphQL mediante filtros que admitan operadores lógicos adicionales. A diferencia de los argumentos de suscripción que se definen en la consulta de suscripción en el cliente, en este caso sí puede configurar estos filtros. Para obtener más información acerca de los argumentos de suscripción, consulte [Uso de argumentos de suscripción](aws-appsync-real-time-data.md#using-subscription-arguments). Para ver una lista de operadores, consulte [AWS AppSync referencia de la utilidad de plantilla de mapeo de resolución](resolver-util-reference.md).

Para los fines de este documento, dividimos el filtrado de datos en tiempo real en las siguientes categorías:
+ **Filtrado básico**: filtrado basado en los argumentos definidos por el cliente en la consulta de suscripción.
+ **Filtrado mejorado**: filtrado basado en la lógica definida de forma centralizada en el backend del AWS AppSync servicio.

En las siguientes secciones se explica cómo configurar los filtros de suscripción mejorados y se muestran sus aplicaciones prácticas.

## Definición de suscripciones en su esquema de GraphQL
<a name="aws-appsync-real-time-enhanced-filtering-using-subscription-filters"></a>

Para usar filtros de suscripción mejorados, defina la suscripción en el esquema de GraphQL y, a continuación, defina el filtro mejorado mediante una extensión de filtrado. Para ilustrar cómo funciona el filtrado de suscripciones mejorado AWS AppSync, utilice el siguiente esquema de GraphQL, que define la API de un sistema de gestión de tickets, como ejemplo:

```
type Ticket {
	id: ID
	createdAt: AWSDateTime
	content: String
	severity: Int
	priority: Priority
	category: String
	group: String
	status: String
	
}

type Mutation {
	createTicket(input: TicketInput): Ticket
}

type Query {
	getTicket(id: ID!): Ticket
}

type Subscription {
	onSpecialTicketCreated: Ticket @aws_subscribe(mutations: ["createTicket"])
	onGroupTicketCreated(group: String!): Ticket @aws_subscribe(mutations: ["createTicket"])
}



enum Priority {
	none
	lowest
	low
	medium
	high
	highest
}

input TicketInput {
	content: String
	severity: Int
	priority: Priority
	category: String
	group: String
```

Supongamos que crea un origen de datos `NONE` para su API y, a continuación, adjunta un solucionador a la mutación `createTicket` utilizando este origen de datos. Los controladores pueden tener un aspecto similar al siguiente:

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
	return {
		payload: {
			id: util.autoId(),
			createdAt: util.time.nowISO8601(),
			status: 'pending',
			...ctx.args.input,
		},
	};
}

export function response(ctx) {
	return ctx.result;
}
```

**nota**  
Los filtros mejorados están habilitados en el controlador del solucionador de GraphQL en una suscripción determinada. Para obtener más información, consulte [Referencia al solucionador](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

Para implementar el comportamiento del filtro mejorado, debe usar la función `extensions.setSubscriptionFilter()` para definir una expresión de filtro evaluada en función de los datos publicados de una mutación de GraphQL que pueda interesar a los clientes suscritos. Para obtener más información acerca de las extensiones de filtrado, consulte [Extensiones](https://docs.aws.amazon.com//appsync/latest/devguide/extensions-js.html).

En la siguiente sección, se explica cómo utilizar extensiones de filtrado para implementar filtros mejorados.

## Creación de filtros de suscripciones mejorados mediante extensiones de filtrado
<a name="aws-appsync-real-time-enhanced-filtering-defining-filters"></a>

Los filtros mejorados están escritos en JSON en el controlador de respuestas de los solucionadores de la suscripción. Los filtros se pueden agrupar en una lista llamada `filterGroup`. Los filtros se definen mediante al menos una regla, cada una con campos, operadores y valores. Definamos un nuevo solucionador para `onSpecialTicketCreated` que configure un filtro mejorado. Puede configurar varias reglas en un filtro, que se evalúan mediante la lógica AND. Por su parte, varios filtros de un grupo de filtros se evalúan mediante la lógica OR:

```
import { util, extensions } from '@aws-appsync/utils';

export function request(ctx) {
	// simplfy return null for the payload
	return { payload: null };
}

export function response(ctx) {
	const filter = {
		or: [
			{ severity: { ge: 7 }, priority: { in: ['high', 'medium'] } },
			{ category: { eq: 'security' }, group: { in: ['admin', 'operators'] } },
		],
	};
	extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter));

  // important: return null in the response
	return null;
}
```

Según los filtros definidos en el ejemplo anterior, los tickets importantes se distribuyen automáticamente a los clientes de la API suscritos si se crea un ticket con:
+ nivel de `priority` `high` o `medium`

  AND 
+ nivel de `severity` mayor o igual que `7` (`ge`)

OR 
+ ticket de `classification` con la definición de `Security` 

  AND 
+ asignación de `group` establecida en `admin` o `operators`

![\[Ejemplo que muestra una consulta de filtrado de tickets\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/aws-priority-example.png)


Los filtros definidos en el solucionador de suscripciones (filtrado mejorado) tienen prioridad sobre el filtrado basado únicamente en los argumentos de suscripción (filtrado básico). Para obtener más información acerca de los argumentos de suscripción, consulte [Uso de argumentos de suscripción](https://docs.aws.amazon.com//appsync/latest/devguide/aws-appsync-real-time-data.html#using-subscription-arguments).

Si un argumento está definido en el esquema de GraphQL de la suscripción y es obligatorio, el filtrado basado en el argumento en cuestión solo se lleva a cabo si el argumento está definido como una regla en el método `extensions.setSubscriptionFilter()` del solucionador. Sin embargo, si no hay métodos de filtrado de `extensions` en el solucionador de suscripciones, los argumentos definidos en el cliente se utilizan únicamente para el filtrado básico. No puede utilizar el filtrado básico y el filtrado mejorado a la vez.

Puede usar la [variable `context`](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html) de la lógica de extensión del filtro de la suscripción para acceder a la información contextual sobre la solicitud. Por ejemplo, si utiliza autorizadores personalizados de grupos de usuarios de Amazon Cognito, OIDC o Lambda para la autorización, puede recuperar información sobre sus usuarios en `context.identity` cuando se establezca la suscripción. Puede usar esa información para establecer filtros basados en la identidad de sus usuarios.

Supongamos ahora que desea implementar el comportamiento de filtro mejorado para `onGroupTicketCreated`. La suscripción `onGroupTicketCreated` requiere un nombre `group` obligatorio como argumento. Cuando se crean, a los tickets se les asigna automáticamente un estado `pending`. Puedes configurar un filtro de suscripción para recibir solo los tickets recién creados que pertenezcan al grupo proporcionado:

```
import { util, extensions } from '@aws-appsync/utils';

export function request(ctx) {
	// simplfy return null for the payload
	return { payload: null };
}

export function response(ctx) {
	const filter = { group: { eq: ctx.args.group }, status: { eq: 'pending' } };
	extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter));

	return null;
}
```

Cuando los datos se publican mediante una mutación, como en el siguiente ejemplo:

```
mutation CreateTicket {
  createTicket(input: {priority: medium, severity: 2, group: "aws"}) {
    id
    priority
    severity
    status
    group
    createdAt
  }
}
```

Los clientes suscritos esperan que los datos se envíen automáticamente tan pronto WebSockets como se cree un ticket con la `createTicket` mutación:

```
subscription OnGroup {
  onGroupTicketCreated(group: "aws") {
    category
    status
    severity
    priority
    id
    group
    createdAt
    content
  }
}
```

Los clientes se pueden suscribir sin argumentos porque la lógica de filtrado está implementada en el AWS AppSync servicio con un filtrado mejorado, lo que simplifica el código del cliente. Los clientes reciben datos solo si se cumplen los criterios de filtro definidos.

## Definición de filtros mejorados para campos de esquema anidados
<a name="aws-appsync-real-time-enhanced-filters-nested-schema-fields.title"></a>

Puede utilizar el filtrado de suscripciones mejorado para filtrar los campos de esquema anidados. Supongamos que modificamos el esquema de la sección anterior para incluir los tipos de ubicación y dirección:

```
type Ticket {
	id: ID
	createdAt: AWSDateTime
	content: String
	severity: Int
	priority: Priority
	category: String
	group: String
	status: String
	location: ProblemLocation
}

type Mutation {
	createTicket(input: TicketInput): Ticket
}

type Query {
	getTicket(id: ID!): Ticket
}

type Subscription {
	onSpecialTicketCreated: Ticket @aws_subscribe(mutations: ["createTicket"])
	onGroupTicketCreated(group: String!): Ticket @aws_subscribe(mutations: ["createTicket"])
}

type ProblemLocation {
	address: Address
}

type Address {
	country: String
}

enum Priority {
	none
	lowest
	low
	medium
	high
	highest
}

input TicketInput {
	content: String
	severity: Int
	priority: Priority
	category: String
	group: String
	location: AWSJSON
```

Con este esquema, puede usar un separador `.` para representar el anidamiento. En el siguiente ejemplo, se agrega una regla de filtrado para un campo de esquema anidado en `location.address.country`. La suscripción se activará si la dirección del ticket se define como `USA`:

```
import { util, extensions } from '@aws-appsync/utils';

export const request = (ctx) => ({ payload: null });

export function response(ctx) {
	const filter = {
		or: [
			{ severity: { ge: 7 }, priority: { in: ['high', 'medium'] } },
			{ category: { eq: 'security' }, group: { in: ['admin', 'operators'] } },
			{ 'location.address.country': { eq: 'USA' } },
		],
	};
	extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter));
	return null;
}
```

En el ejemplo anterior, `location` representa el nivel de anidamiento uno, `address` representa el nivel de anidamiento dos y `country` representa el nivel de anidamiento tres, todos los cuales están separados por el separador `.`.

Puede probar esta suscripción mediante la mutación `createTicket`:

```
mutation CreateTicketInUSA {
  createTicket(input: {location: "{\"address\":{\"country\":\"USA\"}}"}) {
    category
    content
    createdAt
    group
    id
    location {
      address {
        country
      }
    }
    priority
    severity
    status
  }
}
```

## Definición de filtros mejorados desde el cliente
<a name="aws-appsync-real-time-enhanced-filtering-defining-from-client"></a>

Puede usar el filtrado básico en GraphQL con [argumentos de suscripciones](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-data.html#using-subscription-arguments). El cliente que realiza la llamada en la consulta de suscripción define los valores de los argumentos. Cuando los filtros mejorados están habilitados en una resolución de AWS AppSync suscripciones con el `extensions` filtrado, los filtros secundarios definidos en la resolución tienen prioridad y prioridad.

Configure filtros mejorados dinámicos definidos por el cliente en la suscripción usando un argumento `filter`. Al configurar estos filtros, debe actualizar el esquema de GraphQL para que refleje el nuevo argumento:

```
...
type Subscription {
    onSpecialTicketCreated(filter: String): Ticket
        @aws_subscribe(mutations: ["createTicket"])
}
...
```

A continuación, el cliente puede enviar una consulta de suscripción como en el siguiente ejemplo:

```
subscription onSpecialTicketCreated($filter: String) {
     onSpecialTicketCreated(filter: $filter) {
        id
        group
        description
        priority
        severity
     }
 }
```

Puede configurar la variable de consulta de la siguiente manera:

```
{"filter" : "{\"severity\":{\"le\":2}}"}
```

La utilidad de solucionador `util.transform.toSubscriptionFilter()` se puede implementar en la plantilla de mapeo de respuestas de suscripción para aplicar el filtro definido en el argumento de suscripción a cada cliente:

```
import { util, extensions } from '@aws-appsync/utils';

export function request(ctx) {
	// simplfy return null for the payload
	return { payload: null };
}

export function response(ctx) {
	const filter = ctx.args.filter;
	extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter));
	return null;
}
```

Con esta estrategia, los clientes pueden definir sus propios filtros que utilizan una lógica de filtrado mejorada y operadores adicionales. Los filtros se asignan cuando un cliente determinado invoca la consulta de suscripción en una conexión segura. WebSocket Para obtener más información sobre la utilidad de transformación para mejorar el filtrado, incluido el formato de la carga útil de la variable de `filter` consulta, consulte la descripción general de los [JavaScriptresolutores](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html).

## Restricciones adicionales al filtrado mejorado
<a name="aws-appsync-real-time-enhanced-filtering-additional-restrictions"></a>

A continuación, se muestran varios casos de uso en los que se imponen restricciones adicionales a los filtros mejorados:
+ Los filtros mejorados no admiten el filtrado de las listas de objetos de nivel superior. En este caso de uso, los datos publicados de la mutación se ignoran en las suscripciones mejoradas.
+ AWS AppSync admite hasta cinco niveles de anidación. Los filtros más allá del nivel cinco de los campos de esquema de anidamiento se ignoran. Observe la respuesta de GraphQL que aparece a continuación. El campo `continent` en `venue.address.country.metadata.continent` está permitido porque es un nido de nivel cinco. Sin embargo, `financial` en `venue.address.country.metadata.capital.financial` es un nido de nivel seis, por lo que el filtro no funcionará:

  ```
  {
      "data": {
          "onCreateFilterEvent": {
              "venue": {
                  "address": {
                      "country": {
                          "metadata": {
                              "capital": {
                                  "financial": "New York"
                              },
                              "continent" : "North America"
                          }
                      },
                      "state": "WA"
                  },
                  "builtYear": 2023
              },
              "private": false,
          }
      }
  }
  ```

# Cancelar la suscripción de WebSocket las conexiones mediante filtros en AWS AppSync
<a name="aws-appsync-real-time-invalidation"></a>

**importante**  
A partir del 13 de marzo de 2025, podrás crear una PubSub API en tiempo real con la WebSockets tecnología AWS AppSync de Events. Para obtener más información, consulta [Publicar eventos WebSocket en](https://docs.aws.amazon.com/appsync/latest/eventapi/publish-websocket.html) la *Guía para desarrolladores de AWS AppSync eventos*.

En AWS AppSync, puedes cancelar la suscripción por la fuerza y cerrar (invalidar) una WebSocket conexión desde un cliente conectado en función de una lógica de filtrado específica. Esto resulta útil en contextos de autorización, por ejemplo, cuando se elimina un usuario de un grupo.

La invalidación de la suscripción se produce en respuesta a una carga útil definida en una mutación. Le recomendamos que considere las mutaciones utilizadas para invalidar las conexiones a una suscripción como operaciones administrativas de su API y que ajuste el ámbito de los permisos en consecuencia limitando su uso a un usuario administrador, un grupo o un servicio de backend. Por ejemplo, si utiliza directivas de autorización de esquemas como `@aws_auth(cognito_groups: ["Administrators"])` o `@aws_iam`. Para obtener más información, consulte [Uso de modos de autorización adicionales](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html#using-additional-authorization-modes).

Los filtros de invalidación utilizan la misma sintaxis y lógica que los [filtros de suscripción mejorados](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-enhanced-filtering.html). Defina estos filtros mediante las siguientes utilidades:
+ `extensions.invalidateSubscriptions()`: definido en el controlador de respuestas del solucionador de GraphQL para una mutación.
+ `extensions.setSubscriptionInvalidationFilter()`: definido en el controlador de respuestas del solucionador de GraphQL de las suscripciones vinculadas a la mutación.

[Para obtener más información sobre las extensiones de filtrado por invalidación, consulta la descripción general de los resolutores. JavaScript](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html)

## Uso de la invalidación de suscripciones
<a name="aws-appsync-real-time-invalidation-using-invalidations"></a>

Para ver cómo funciona la invalidación de suscripciones AWS AppSync, usa el siguiente esquema de GraphQL:

```
type User {
  userId: ID!
  groupId: ID!
}
    
type Group {
  groupId: ID!
  name: String!
  members: [ID!]!
}

type GroupMessage {
  userId: ID!
  groupId: ID!
  message: String!
}

type Mutation {
    createGroupMessage(userId: ID!, groupId : ID!, message: String!): GroupMessage
    removeUserFromGroup(userId: ID!, groupId : ID!) : User @aws_iam
}

type Subscription {
    onGroupMessageCreated(userId: ID!, groupId : ID!): GroupMessage
        @aws_subscribe(mutations: ["createGroupMessage"])
}

type Query {
	none: String
}
```

Defina un filtro de invalidación en el código del solucionador de mutaciones `removeUserFromGroup`:

```
import { extensions } from '@aws-appsync/utils';

export function request(ctx) {
	return { payload: null };
}

export function response(ctx) {
	const { userId, groupId } = ctx.args;
	extensions.invalidateSubscriptions({
		subscriptionField: 'onGroupMessageCreated',
		payload: { userId, groupId },
	});
	return { userId, groupId };
}
```

Cuando se invoca la mutación, los datos definidos en el objeto `payload` se utilizan para cancelar la suscripción definida en `subscriptionField`. También se define un filtro de invalidación en la plantilla de mapeo de respuestas de la suscripción `onGroupMessageCreated`. 

Si la `extensions.invalidateSubscriptions()` carga útil contiene un ID que coincide con el IDs del cliente suscrito, tal como se define en el filtro, se cancela la suscripción correspondiente. Además, la conexión está cerrada. WebSocket Defina el código del solucionador de suscripciones para la suscripción `onGroupMessageCreated`:

```
import { util, extensions } from '@aws-appsync/utils';

export function request(ctx) {
	// simplfy return null for the payload
	return { payload: null };
}

export function response(ctx) {
	const filter = { groupId: { eq: ctx.args.groupId } };
	extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter));

	const invalidation = { groupId: { eq: ctx.args.groupId }, userId: { eq: ctx.args.userId } };
	extensions.setSubscriptionInvalidationFilter(util.transform.toSubscriptionFilter(invalidation));

	return null;
}
```

Tenga en cuenta que el controlador de respuestas de suscripción puede tener definidos filtros de suscripción y filtros de invalidación al mismo tiempo.

Por ejemplo, supongamos que el cliente A suscribe a un nuevo usuario con el ID `user-1` en el grupo con el ID `group-1` mediante la siguiente solicitud de suscripción:

```
onGroupMessageCreated(userId : "user-1", groupId: :"group-1"){...}
```

AWS AppSync ejecuta el solucionador de suscripciones, que genera filtros de suscripción e invalidación tal como se definió en la plantilla de mapeo de `onGroupMessageCreated` respuestas anterior. Para el cliente A, los filtros de suscripción solo permiten enviar datos a `group-1`, y los filtros de invalidación están definidos tanto para `user-1` como para `group-1`.

Ahora, supongamos que el cliente B suscribe a un usuario con el ID `user-2` en el grupo con el ID `group-2` mediante la siguiente solicitud de suscripción:

```
onGroupMessageCreated(userId : "user-2", groupId: :"group-2"){...}
```

AWS AppSync ejecuta el solucionador de suscripciones, que genera filtros de suscripción e invalidación. Para el cliente B, los filtros de suscripción solo permiten enviar datos a `group-2`, y los filtros de invalidación están definidos tanto para `user-2` como para `group-2`.

A continuación, supongamos que se crea un nuevo mensaje de grupo con el ID `message-1` mediante una solicitud de mutación, como en el ejemplo siguiente:

```
createGroupMessage(id: "message-1", groupId :
      "group-1", message: "test message"){...}
```

Los clientes suscritos que coincidan con los filtros definidos reciben automáticamente la siguiente carga útil de datos a través de: WebSockets

```
{
  "data": {
    "onGroupMessageCreated": {
      "id": "message-1",
      "groupId": "group-1",
      "message": "test message",
    }
  }
}
```

El cliente A recibe el mensaje porque los criterios de filtrado coinciden con el filtro de suscripción definido. Sin embargo, el cliente B no recibe el mensaje porque el usuario no forma pertenece a `group-1`. Además, la solicitud no coincide con el filtro de suscripción definido en el solucionador de suscripciones.

Por último, supongamos que `user-1` se ha eliminado de `group-1` con la siguiente solicitud de mutación:

```
removeUserFromGroup(userId: "user-1", groupId : "group-1"){...}
```

La mutación provoca la invalidación de la suscripción, tal y como se define en el código del controlador de respuestas del `extensions.invalidateSubscriptions()` solucionador. AWS AppSync a continuación, cancela la suscripción del cliente A y cierra su conexión. WebSocket El cliente B no se ve afectado, ya que la carga de invalidación definida en la mutación no coincide con su usuario o grupo.

Cuando se AWS AppSync invalida una conexión, el cliente recibe un mensaje confirmando que se ha dado de baja:

```
{
  "message": "Subscription complete."
}
```

## Uso de variables de contexto en los filtros de invalidación de suscripciones
<a name="aws-appsync-real-time-invalidation-context"></a>

Al igual que con los filtros de suscripción mejorados, puede utilizar la [variable `context`](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html) de la extensión del filtro de invalidación de suscripciones para acceder a determinados datos.

Por ejemplo, puede configurar una dirección de correo electrónico como carga útil de invalidación en la mutación y, a continuación, vincularle una correspondencia con el atributo de correo electrónico o la solicitud de un usuario suscrito autorizado con los grupos de usuarios de Amazon Cognito o con OpenID Connect. El filtro de invalidación definido en el invalidador de suscripciones `extensions.setSubscriptionInvalidationFilter()` comprueba si la dirección de correo electrónico establecida por la carga útil `extensions.invalidateSubscriptions()` de la mutación coincide con la dirección de correo electrónico recuperada del token JWT del usuario en `context.identity.claims.email`, iniciándose así la invalidación.

# Crear un cliente en tiempo real en WebSocket AWS AppSync
<a name="real-time-websocket-client"></a>

**importante**  
A partir del 13 de marzo de 2025, podrás crear una PubSub API en tiempo real con la WebSockets tecnología de AWS AppSync Events. Para obtener más información, consulta [Publicar eventos WebSocket en](https://docs.aws.amazon.com/appsync/latest/eventapi/publish-websocket.html) la *Guía para desarrolladores de AWS AppSync eventos*.

AWS AppSyncEl WebSocket cliente en tiempo real permite las suscripciones a GraphQL mediante un proceso de varios pasos. El cliente primero establece una WebSocket conexión con el punto final AWS AppSync en tiempo real, envía un mensaje de inicialización de la conexión y espera el reconocimiento. Tras una conexión correcta, el cliente registra las suscripciones enviando mensajes de inicio con consultas únicas IDs y de GraphQL. AWS AppSync confirma que las suscripciones se han realizado correctamente con mensajes de confirmación. A continuación, el cliente escucha los eventos de suscripción, que se activan con las mutaciones correspondientes. Para mantener la conexión, AWS AppSync envía mensajes de mantenimiento periódicos. Al finalizar, el cliente cancela el registro de las suscripciones mediante el envío de mensajes de suspensión. Este sistema admite varias suscripciones en una sola WebSocket conexión y admite varios modos de autorización, incluidas las claves de API, los grupos de usuarios de Amazon Cognito, IAM y Lambda.

## Implementación de WebSocket clientes en tiempo real para suscripciones a GraphQL
<a name="appsynclong-real-time-websocket-client-implementation-guide-for-graphql-subscriptions"></a>

El siguiente diagrama de secuencia y los pasos siguientes muestran el flujo de trabajo de suscripciones en tiempo real entre el WebSocket cliente, el cliente HTTP y AWS AppSync.

![\[Sequence diagram showing WebSocket client, AppSync endpoints, and HTTP client interactions for real-time subscriptions.\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/realtime-client-flow.png)


1. El cliente establece una WebSocket conexión con el punto final AWS AppSync en tiempo real. Si hay un error de red, el cliente debe hacer un retardo exponencial con fluctuaciones. Para obtener más información, consulte [Retroceso y fluctuación exponenciales](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/) en el AWS blog de arquitectura.

1. (Opcional) Tras establecer correctamente la WebSocket conexión, el cliente envía un mensaje. `connection_init`

1. Si `connection_init` se envía, el cliente espera un `connection_ack` mensaje de AWS AppSync. Este mensaje incluye un parámetro `connectionTimeoutMs`, que es el tiempo de espera máximo en milisegundos para un mensaje `"ka"` (keep-alive).

1. AWS AppSync envía `"ka"` mensajes periódicamente. El cliente realiza un seguimiento de la hora en que recibió cada mensaje `"ka"`. Si el cliente no recibe un mensaje `"ka"` en cuestión de milisegundos `connectionTimeoutMs`, debe cerrar la conexión.

1. El cliente registra la suscripción enviando un mensaje de suscripción `start`. Una sola WebSocket conexión admite múltiples suscripciones, incluso si están en modos de autorización diferentes.

1. El cliente espera a que se envíen `start_ack` mensajes AWS AppSync para confirmar que las suscripciones se han realizado correctamente. Si hay un error, AWS AppSync devuelve un `"type": "error"` mensaje.

1. El cliente escucha los eventos de suscripción, que se envían después de llamar a la mutación correspondiente. Las consultas y las mutaciones suelen enviarse `https://` al punto final de AWS AppSync GraphQL. Las suscripciones fluyen a través del punto final AWS AppSync en tiempo real mediante secure WebSocket (`wss://`).

1. El cliente anula el registro de la suscripción enviando un mensaje de suscripción `stop`.

1. Tras anular el registro de todas las suscripciones y comprobar que no se están transfiriendo mensajes a través del WebSocket, el cliente puede desconectarse de la WebSocket conexión.

## Detalles del apretón de manos para establecer la conexión WebSocket
<a name="handshake-details-to-establish-the-websocket-connection"></a>

Para conectarse e iniciar un apretón de manos exitoso AWS AppSync, el WebSocket cliente necesita lo siguiente:
+ El punto final AWS AppSync en tiempo real
+ Encabezados: contienen información relevante sobre el AWS AppSync punto final y la autorización. AWS AppSync admite los tres métodos siguientes para proporcionar encabezados: 
  + Encabezados mediante cadena de consulta
    + La información del encabezado está codificada en forma de cadena base64 a partir de un objeto JSON encadenado. Este objeto JSON contiene detalles relacionados con el AWS AppSync punto final y la autorización. El contenido del objeto JSON varía en función del modo de autorización.
  + Encabezados mediante `Sec-WebSocket-Protocol`
    + Una cadena codificada en una URL en base64 del objeto JSON en cadena que contiene información relevante sobre el AWS AppSync punto final y la autorización se transmite como protocolo en el encabezado. `Sec-WebSocket-Protocol` El contenido del objeto JSON varía en función del modo de autorización.
  + Encabezados mediante encabezados HTTP estándar:
    + Los encabezados se pueden pasar como encabezados HTTP estándar en la solicitud de conexión, de forma similar a como se pasan los encabezados para las consultas y mutaciones de GraphQL. AWS AppSync Sin embargo, no es posible pasar encabezados a través de encabezados HTTP estándar en las solicitudes de conexión de API privadas.
+  `payload`: cadena codificada en Base64 de `payload`. La carga útil solo es necesaria si los encabezados se proporcionan mediante una cadena de consulta.

Con estos requisitos, un WebSocket cliente puede conectarse a la URL, que contiene el punto final en tiempo real con la cadena de consulta, utilizando `graphql-ws` como protocolo. WebSocket 

### Descubrir el punto de enlace de en tiempo real desde el punto de enlace de GraphQL
<a name="discovering-the-appsync-real-time-endpoint-from-the-appsync-graphql-endpoint"></a>

El punto final de AWS AppSync GraphQL y el punto final AWS AppSync en tiempo real son ligeramente diferentes en protocolo y dominio. Puedes recuperar el punto final de GraphQL mediante el comando AWS Command Line Interface (AWS CLI). `aws appsync get-graphql-api`

****AWS AppSync Punto final de GraphQL:****  
 `https://example1234567890000.appsync-api.us-east-1.amazonaws.com/graphql`

****AWS AppSync punto final en tiempo real:****  
 `wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql`

Las aplicaciones pueden conectarse al punto final de AWS AppSync GraphQL (`https://`) mediante cualquier cliente HTTP para consultas y mutaciones. Las aplicaciones se pueden conectar al punto final AWS AppSync en tiempo real (`wss://`) mediante cualquier WebSocket cliente para las suscripciones.

Con los nombres de dominio personalizados, puede interactuar con ambos puntos de conexión mediante un único dominio. Por ejemplo, si lo configuras `api.example.com` como tu dominio personalizado, puedes interactuar con tus puntos de conexión GraphQL y en tiempo real de la siguiente manera: URLs

**AWS AppSync punto final GraphQL de dominio personalizado:**  
`https://api.example.com/graphql`

**AWS AppSync punto final en tiempo real de dominio personalizado:**  
`wss://api.example.com/graphql/realtime`

## Formato de parámetros de encabezado basado en el modo AWS AppSync de autorización de la API
<a name="header-parameter-format-based-on-appsync-api-authorization-mode"></a>

El formato del `header` objeto utilizado en la cadena de consulta de conexión varía en función del modo de autorización de la AWS AppSync API. El `host` campo del objeto hace referencia al punto final de AWS AppSync GraphQL, que se utiliza para validar la conexión incluso si la `wss://` llamada se realiza en el punto final en tiempo real. Para iniciar el protocolo de enlace y establecer la conexión autorizada, `payload` debe ser un objeto JSON vacío. La carga útil solo es necesaria si los encabezados se pasan a través de una cadena de consulta.

En las siguientes secciones se muestran los formatos de encabezado para cada modo de autorización.

### Clave de API
<a name="api-key"></a>

#### Encabezado de clave API
<a name="api-key-list"></a>

**Contenido del encabezado**
+  `"host": <string>`: el host del punto final de AWS AppSync GraphQL o tu nombre de dominio personalizado.
+  `"x-api-key": <string>`: la clave de API configurada para la AWS AppSync API.

**Ejemplo**

```
{
    "host":"example1234567890000.appsync-api.us-east-1.amazonaws.com",
    "x-api-key":"da2-12345678901234567890123456"
}
```

**Encabezados mediante cadena de consulta**

En primer lugar, un objeto JSON que contiene el `host` y la `x-api-key` se convierte en una cadena. A continuación, esta cadena se codifica mediante la codificación base64. La cadena codificada en base64 resultante se agrega como un parámetro de consulta con el nombre `header` de la WebSocket URL para establecer la conexión con el AWS AppSync punto final en tiempo real. La URL de solicitud resultante tiene el siguiente formato:

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=eyJob3N0IjoiZXhhbXBsZTEyMzQ1Njc4OTAwMDAuYXBwc3luYy1hcGkudXMtZWFzdC0xLmFtYXpvbmF3cy5jb20iLCJ4LWFtei1kYXRlIjoiMjAyMDA0MDFUMDAxMDEwWiIsIngtYXBpLWtleSI6ImRhMi16NHc0NHZoczV6Z2MzZHRqNXNranJsbGxqaSJ9&payload=e30=
```

Es importante tener en cuenta que, además del objeto de encabezado codificado en base64, un objeto JSON vacío \$1\$1 también está codificado en base64 y se incluye como un parámetro de consulta independiente denominado en la URL. `payload` WebSocket

**Encabezados mediante `Sec-WebSocket-Protocol`**

Un objeto JSON que contiene el `host` y la `x-api-key` se convierte en una cadena y, a continuación, se codifica mediante la codificación base64Url. La cadena codificada en base64Url resultante lleva el prefijo `header-`. Esta cadena con prefijo se utiliza luego como un nuevo subprotocolo, además de en el `Sec-WebSocket-Protocol` encabezado, al establecer la conexión con el `graphql-ws` punto final en tiempo real. WebSocket AWS AppSync 

La URL de solicitud resultante tiene el siguiente formato:

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

El encabezado `Sec-WebSocket-Protocol` contiene el siguiente valor:

```
"sec-websocket-protocol" : ["graphql-ws", "header-ewogICAgImhvc3QiOiJleGFtcGxlMTIzNDU2Nzg5MDAwMC5hcHBzeW5jLWFwaS51cy1lYXN0LTEuYW1hem9uYXdzLmNvbSIsCiAgICAieC1hcGkta2V5IjoiZGEyLTEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Igp9"]
```

**Encabezados mediante encabezados HTTP estándar**

En este método, la información clave del host y de la API se transmite mediante encabezados HTTP estándar al establecer la WebSocket conexión con el AWS AppSync punto final en tiempo real. La URL de solicitud resultante tiene el siguiente formato:

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

Los encabezados de solicitud incluirían lo siguiente:

```
"sec-websocket-protocol" : ["graphql-ws"]
"host":"example1234567890000.appsync-api.us-east-1.amazonaws.com",
"x-api-key":"da2-12345678901234567890123456"
```

### Grupos de usuarios de Amazon Cognito y OpenID Connect (OIDC)
<a name="amazon-cognito-user-pools-and-openid-connect-oidc"></a>

#### Amazon Cognito y encabezado OIDC
<a name="amazon-cognito-user-pools-and-openid-connect-oidc-list"></a>

Contenido del encabezado:
+  `"Authorization": <string>`: un token de ID de JWT. El encabezado puede usar un [esquema Bearer](https://datatracker.ietf.org/doc/html/rfc6750#section-2.1).
+  `"host": <string>`: el host del punto final de AWS AppSync GraphQL o tu nombre de dominio personalizado.

Ejemplo:

```
{
    "Authorization":"eyEXAMPLEiJjbG5xb3A5eW5MK09QYXIrMTJHWEFLSXBieU5WNHhsQjEXAMPLEnM2WldvPSIsImFsZyI6IlEXAMPLEn0.eyEXAMPLEiJhNmNmMjcwNy0xNjgxLTQ1NDItOWYxOC1lNjY0MTg2NjlkMzYiLCJldmVudF9pZCI6ImVkMzM5MmNkLWNjYTMtNGM2OC1hNDYyLTJlZGI3ZTNmY2FjZiIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE1Njk0NTc3MTgsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC5hcC1zb3V0aGVhc3QtMi5hbWF6b25hd3MuY29tXC9hcC1zb3V0aGVhc3QtMl83OHY0SVZibVAiLCJleHAiOjE1Njk0NjEzMjAsImlhdCI6MTU2OTQ1NzcyMCwianRpIjoiNTgzZjhmYmMtMzk2MS00YzA4LWJhZTAtYzQyY2IxMTM5NDY5IiwiY2xpZW50X2lkIjoiM3FlajVlMXZmMzd1N3RoZWw0dG91dDJkMWwiLCJ1c2VybmFtZSI6ImVsb3EXAMPLEn0.B4EXAMPLEFNpJ6ikVp7e6DRee95V6Qi-zEE2DJH7sHOl2zxYi7f-SmEGoh2AD8emxQRYajByz-rE4Jh0QOymN2Ys-ZIkMpVBTPgu-TMWDyOHhDUmUj2OP82yeZ3wlZAtr_gM4LzjXUXmI_K2yGjuXfXTaa1mvQEBG0mQfVd7SfwXB-jcv4RYVi6j25qgow9Ew52ufurPqaK-3WAKG32KpV8J4-Wejq8t0c-yA7sb8EnB551b7TU93uKRiVVK3E55Nk5ADPoam_WYE45i3s5qVAP_-InW75NUoOCGTsS8YWMfb6ecHYJ-1j-bzA27zaT9VjctXn9byNFZmEXAMPLExw",
    "host":"example1234567890000.appsync-api.us-east-1.amazonaws.com"
}
```

**Encabezados mediante cadena de consulta**

En primer lugar, un objeto JSON que contiene el `host` y la `Authorization` se convierte en una cadena. A continuación, esta cadena se codifica mediante la codificación base64. La cadena codificada en base64 resultante se agrega como un parámetro de consulta con el nombre de la WebSocket URL `header` para establecer la conexión con el punto final en tiempo real. AWS AppSync La URL de solicitud resultante tiene el siguiente formato:

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=eyJBdXRob3JpemF0aW9uIjoiZXlKcmFXUWlPaUpqYkc1eGIzQTVlVzVNSzA5UVlYSXJNVEpIV0VGTFNYQmllVTVXTkhoc1FqaFBWVzlZTW5NMldsZHZQU0lzSW1Gc1p5STZJbEpUTWpVMkluMC5leUp6ZFdJaU9pSmhObU5tTWpjd055MHhOamd4TFRRMU5ESXRPV1l4T0MxbE5qWTBNVGcyTmpsa016WWlMQ0psZG1WdWRGOXBaQ0k2SW1Wa016TTVNbU5rTFdOallUTXROR00yT0MxaE5EWXlMVEpsWkdJM1pUTm1ZMkZqWmlJc0luUnZhMlZ1WDNWelpTSTZJbUZqWTJWemN5SXNJbk5qYjNCbElqb2lZWGR6TG1OdloyNXBkRzh1YzJsbmJtbHVMblZ6WlhJdVlXUnRhVzRpTENKaGRYUm9YM1JwYldVaU9qRTFOamswTlRjM01UZ3NJbWx6Y3lJNkltaDBkSEJ6T2x3dlhDOWpiMmR1YVhSdkxXbGtjQzVoY0MxemIzVjBhR1ZoYzNRdE1pNWhiV0Y2YjI1aGQzTXVZMjl0WEM5aGNDMXpiM1YwYUdWaGMzUXRNbDgzT0hZMFNWWmliVkFpTENKbGVIQWlPakUxTmprME5qRXpNakFzSW1saGRDSTZNVFUyT1RRMU56Y3lNQ3dpYW5ScElqb2lOVGd6WmpobVltTXRNemsyTVMwMFl6QTRMV0poWlRBdFl6UXlZMkl4TVRNNU5EWTVJaXdpWTJ4cFpXNTBYMmxrSWpvaU0zRmxhalZsTVhabU16ZDFOM1JvWld3MGRHOTFkREprTVd3aUxDSjFjMlZ5Ym1GdFpTSTZJbVZzYjNKNllXWmxJbjAuQjRjZEp0aDNLRk5wSjZpa1ZwN2U2RFJlZTk1VjZRaS16RUUyREpIN3NIT2wyenhZaTdmLVNtRUdvaDJBRDhlbXhRUllhakJ5ei1yRTRKaDBRT3ltTjJZcy1aSWtNcFZCVFBndS1UTVdEeU9IaERVbVVqMk9QODJ5ZVozd2xaQXRyX2dNNEx6alhVWG1JX0syeUdqdVhmWFRhYTFtdlFFQkcwbVFmVmQ3U2Z3WEItamN2NFJZVmk2ajI1cWdvdzlFdzUydWZ1clBxYUstM1dBS0czMktwVjhKNC1XZWpxOHQwYy15QTdzYjhFbkI1NTFiN1RVOTN1S1JpVlZLM0U1NU5rNUFEUG9hbV9XWUU0NWkzczVxVkFQXy1Jblc3NU5Vb09DR1RzUzhZV01mYjZlY0hZSi0xai1iekEyN3phVDlWamN0WG45YnlORlptS0xwQTJMY3h3IiwiaG9zdCI6ImV4YW1wbGUxMjM0NTY3ODkwMDAwLmFwcHN5bmMtYXBpLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tIn0=&payload=e30=
```

Es importante tener en cuenta que, además del objeto de encabezado codificado en base64, un objeto JSON vacío \$1\$1 también está codificado en base64 y se incluye como un parámetro de consulta independiente denominado en la URL. `payload` WebSocket

**Encabezados mediante `Sec-WebSocket-Protocol`**

Un objeto JSON que contiene el `host` y la `Authorization` se convierte en una cadena y, a continuación, se codifica mediante la codificación base64Url. La cadena codificada en base64Url resultante lleva el prefijo `header-`. Esta cadena con prefijo se utiliza luego como un nuevo subprotocolo, además de en el `Sec-WebSocket-Protocol` encabezado, al establecer la conexión con el `graphql-ws` punto final en tiempo real. WebSocket AWS AppSync 

La URL de solicitud resultante tiene el siguiente formato:

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

El encabezado `Sec-WebSocket-Protocol` contiene el siguiente valor:

```
"sec-websocket-protocol" : ["graphql-ws", "header-ewogICAgImhvc3QiOiJleGFtcGxlMTIzNDU2Nzg5MDAwMC5hcHBzeW5jLWFwaS51cy1lYXN0LTEuYW1hem9uYXdzLmNvbSIsCiAgICAieC1hcGkta2V5IjoiZGEyLTEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Igp9"]
```

**Encabezados mediante encabezados HTTP estándar**

En este método, la información del host y de la autorización se transmite mediante encabezados HTTP estándar al establecer la WebSocket conexión con el AWS AppSync punto final en tiempo real. La URL de solicitud resultante tiene el siguiente formato:

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

Los encabezados de solicitud incluirían lo siguiente:

```
"sec-websocket-protocol" : ["graphql-ws"]
"Authorization":"eyEXAMPLEiJjbG5xb3A5eW5MK09QYXIrMTJHWEFLSXBieU5WNHhsQjEXAMPLEnM2WldvPSIsImFsZyI6IlEXAMPLEn0.eyEXAMPLEiJhNmNmMjcwNy0xNjgxLTQ1NDItOWYxOC1lNjY0MTg2NjlkMzYiLCJldmVudF9pZCI6ImVkMzM5MmNkLWNjYTMtNGM2OC1hNDYyLTJlZGI3ZTNmY2FjZiIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE1Njk0NTc3MTgsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC5hcC1zb3V0aGVhc3QtMi5hbWF6b25hd3MuY29tXC9hcC1zb3V0aGVhc3QtMl83OHY0SVZibVAiLCJleHAiOjE1Njk0NjEzMjAsImlhdCI6MTU2OTQ1NzcyMCwianRpIjoiNTgzZjhmYmMtMzk2MS00YzA4LWJhZTAtYzQyY2IxMTM5NDY5IiwiY2xpZW50X2lkIjoiM3FlajVlMXZmMzd1N3RoZWw0dG91dDJkMWwiLCJ1c2VybmFtZSI6ImVsb3EXAMPLEn0.B4EXAMPLEFNpJ6ikVp7e6DRee95V6Qi-zEE2DJH7sHOl2zxYi7f-SmEGoh2AD8emxQRYajByz-rE4Jh0QOymN2Ys-ZIkMpVBTPgu-TMWDyOHhDUmUj2OP82yeZ3wlZAtr_gM4LzjXUXmI_K2yGjuXfXTaa1mvQEBG0mQfVd7SfwXB-jcv4RYVi6j25qgow9Ew52ufurPqaK-3WAKG32KpV8J4-Wejq8t0c-yA7sb8EnB551b7TU93uKRiVVK3E55Nk5ADPoam_WYE45i3s5qVAP_-InW75NUoOCGTsS8YWMfb6ecHYJ-1j-bzA27zaT9VjctXn9byNFZmEXAMPLExw",
"host":"example1234567890000.appsync-api.us-east-1.amazonaws.com"
```

### IAM
<a name="iam"></a>

#### Encabezado de IAM
<a name="iam-list"></a>

**Contenido del encabezado**
+  `"accept": "application/json, text/javascript"`: un parámetro `<string>` constante.
+  `"content-encoding": "amz-1.0"`: un parámetro `<string>` constante.
+  `"content-type": "application/json; charset=UTF-8"`: un parámetro `<string>` constante.
+  `"host": <string>`: Este es el host del punto final de AWS AppSync GraphQL.
  + `"x-amz-date": <string>`: la marca de tiempo debe estar en UTC y en el formato ISO 8601 siguiente: AAAAMMDD'T'HHMMSS'Z'. Por ejemplo, 20150830T123600Z es una marca de tiempo válida. No incluya milisegundos en la marca de tiempo. Para obtener más información, consulte [Control de fechas en Signature Version 4](https://docs.aws.amazon.com/general/latest/gr/sigv4-date-handling.html) en la *Referencia general de AWS*.
  +  `"X-Amz-Security-Token": <string>`: El token de AWS sesión, que se requiere cuando se utilizan credenciales de seguridad temporales. Para obtener más información, consulte [Uso de credenciales temporales con  AWS](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_credentials_temp_use-resources.html) en la *Guía del usuario de IAM*.
  +  `"Authorization": <string>`: información de firma de la versión 4 (SigV4) para firmar el AWS AppSync punto final. Para obtener más información sobre el proceso de firma, consulte [Tarea 4: Añadir la firma a la solicitud HTTP](https://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html) en la *Referencia general de AWS*.

La solicitud HTTP de firma SigV4 incluye una URL canónica, que es el punto de enlace de AWS AppSync GraphQL con `/connect` anexado. La AWS región del punto final del servicio es la misma región en la que usas la AWS AppSync API y el nombre del servicio es «appsync». La solicitud HTTP para firmar es la siguiente:

```
{
  url: "https://example1234567890000.appsync-api.us-east-1.amazonaws.com/graphql/connect",
  data: "{}",
  method: "POST",
  headers: {
    "accept": "application/json, text/javascript",
    "content-encoding": "amz-1.0",
    "content-type": "application/json; charset=UTF-8",
  }
}
```

**Ejemplo**

```
{
  "accept": "application/json, text/javascript",
  "content-encoding": "amz-1.0",
  "content-type": "application/json; charset=UTF-8",
  "host": "example1234567890000.appsync-api.us-east-1.amazonaws.com",
  "x-amz-date": "20200401T001010Z",
  "X-Amz-Security-Token": "AgEXAMPLEZ2luX2VjEAoaDmFwLXNvdXRoZWFEXAMPLEcwRQIgAh97Cljq7wOPL8KsxP3YtDuyc/9hAj8PhJ7Fvf38SgoCIQDhJEXAMPLEPspioOztj++pEagWCveZUjKEn0zyUhBEXAMPLEjj//////////8BEXAMPLExODk2NDgyNzg1NSIMo1mWnpESWUoYw4BkKqEFSrm3DXuL8w+ZbVc4JKjDP4vUCKNR6Le9C9pZp9PsW0NoFy3vLBUdAXEXAMPLEOVG8feXfiEEA+1khgFK/wEtwR+9zF7NaMMMse07wN2gG2tH0eKMEXAMPLEQX+sMbytQo8iepP9PZOzlZsSFb/dP5Q8hk6YEXAMPLEYcKZsTkDAq2uKFQ8mYUVA9EtQnNRiFLEY83aKvG/tqLWNnGlSNVx7SMcfovkFDqQamm+88y1OwwAEYK7qcoceX6Z7GGcaYuIfGpaX2MCCELeQvZ+8WxEgOnIfz7GYvsYNjLZSaRnV4G+ILY1F0QNW64S9Nvj+BwDg3ht2CrNvpwjVYlj9U3nmxE0UG5ne83LL5hhqMpm25kmL7enVgw2kQzmU2id4IKu0C/WaoDRuO2F5zE63vJbxN8AYs7338+4B4HBb6BZ6OUgg96Q15RA41/gIqxaVPxyTpDfTU5GfSLxocdYeniqqpFMtZG2n9d0u7GsQNcFkNcG3qDZm4tDo8tZbuym0a2VcF2E5hFEgXBa+XLJCfXi/77OqAEjP0x7Qdk3B43p8KG/BaioP5RsV8zBGvH1zAgyPha2rN70/tT13yrmPd5QYEfwzexjKrV4mWIuRg8NTHYSZJUaeyCwTom80VFUJXG+GYTUyv5W22aBcnoRGiCiKEYTLOkgXecdKFTHmcIAejQ9Welr0a196Kq87w5KNMCkcCGFnwBNFLmfnbpNqT6rUBxxs3X5ntX9d8HVtSYINTsGXXMZCJ7fnbWajhg/aox0FtHX21eF6qIGT8j1z+l2opU+ggwUgkhUUgCH2TfqBj+MLMVVvpgqJsPKt582caFKArIFIvO+9QupxLnEH2hz04TMTfnU6bQC6z1buVe7h+tOLnh1YPFsLQ88anib/7TTC8k9DsBTq0ASe8R2GbSEsmO9qbbMwgEaYUhOKtGeyQsSJdhSk6XxXThrWL9EnwBCXDkICMqdntAxyyM9nWsZ4bL9JHqExgWUmfWChzPFAqn3F4y896UqHTZxlq3WGypn5HHcem2Hqf3IVxKH1inhqdVtkryEiTWrI7ZdjbqnqRbl+WgtPtKOOweDlCaRs3R2qXcbNgVhleMk4IWnF8D1695AenU1LwHjOJLkCjxgNFiWAFEPH9aEXAMPLExA==",
  "Authorization": "AWS4-HMAC-SHA256 Credential=XXXXXXXXXXXXXXXXXXX/20200401/us-east-1/appsync/aws4_request, SignedHeaders=accept;content-encoding;content-type;host;x-amz-date;x-amz-security-token, Signature=83EXAMPLEbcc1fe3ee69f75cd5ebbf4cb4f150e4f99cec869f149c5EXAMPLEdc"
}
```

**Encabezados mediante cadena de consulta**

En primer lugar, un objeto JSON que contiene el `host` (punto final de AWS AppSync GraphQL) y los demás encabezados de autorización se convierte en una cadena. A continuación, esta cadena se codifica mediante la codificación base64. La cadena resultante codificada en base64 se añade a la WebSocket URL con un nombre para el parámetro de consulta. `header` La URL de solicitud resultante tiene el siguiente formato:

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=eyJBdXRob3JpemF0aW9uIjoiZXlKcmFXUWlPaUpqYkc1eGIzQTVlVzVNSzA5UVlYSXJNVEpIV0VGTFNYQmllVTVXTkhoc1FqaFBWVzlZTW5NMldsZHZQU0lzSW1Gc1p5STZJbEpUTWpVMkluMC5leUp6ZFdJaU9pSmhObU5tTWpjd055MHhOamd4TFRRMU5ESXRPV1l4T0MxbE5qWTBNVGcyTmpsa016WWlMQ0psZG1WdWRGOXBaQ0k2SW1Wa016TTVNbU5rTFdOallUTXROR00yT0MxaE5EWXlMVEpsWkdJM1pUTm1ZMkZqWmlJc0luUnZhMlZ1WDNWelpTSTZJbUZqWTJWemN5SXNJbk5qYjNCbElqb2lZWGR6TG1OdloyNXBkRzh1YzJsbmJtbHVMblZ6WlhJdVlXUnRhVzRpTENKaGRYUm9YM1JwYldVaU9qRTFOamswTlRjM01UZ3NJbWx6Y3lJNkltaDBkSEJ6T2x3dlhDOWpiMmR1YVhSdkxXbGtjQzVoY0MxemIzVjBhR1ZoYzNRdE1pNWhiV0Y2YjI1aGQzTXVZMjl0WEM5aGNDMXpiM1YwYUdWaGMzUXRNbDgzT0hZMFNWWmliVkFpTENKbGVIQWlPakUxTmprME5qRXpNakFzSW1saGRDSTZNVFUyT1RRMU56Y3lNQ3dpYW5ScElqb2lOVGd6WmpobVltTXRNemsyTVMwMFl6QTRMV0poWlRBdFl6UXlZMkl4TVRNNU5EWTVJaXdpWTJ4cFpXNTBYMmxrSWpvaU0zRmxhalZsTVhabU16ZDFOM1JvWld3MGRHOTFkREprTVd3aUxDSjFjMlZ5Ym1GdFpTSTZJbVZzYjNKNllXWmxJbjAuQjRjZEp0aDNLRk5wSjZpa1ZwN2U2RFJlZTk1VjZRaS16RUUyREpIN3NIT2wyenhZaTdmLVNtRUdvaDJBRDhlbXhRUllhakJ5ei1yRTRKaDBRT3ltTjJZcy1aSWtNcFZCVFBndS1UTVdEeU9IaERVbVVqMk9QODJ5ZVozd2xaQXRyX2dNNEx6alhVWG1JX0syeUdqdVhmWFRhYTFtdlFFQkcwbVFmVmQ3U2Z3WEItamN2NFJZVmk2ajI1cWdvdzlFdzUydWZ1clBxYUstM1dBS0czMktwVjhKNC1XZWpxOHQwYy15QTdzYjhFbkI1NTFiN1RVOTN1S1JpVlZLM0U1NU5rNUFEUG9hbV9XWUU0NWkzczVxVkFQXy1Jblc3NU5Vb09DR1RzUzhZV01mYjZlY0hZSi0xai1iekEyN3phVDlWamN0WG45YnlORlptS0xwQTJMY3h3IiwiaG9zdCI6ImV4YW1wbGUxMjM0NTY3ODkwMDAwLmFwcHN5bmMtYXBpLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tIn0=&payload=e30=
```

Es importante tener en cuenta que, además del objeto de encabezado codificado en base64, un objeto JSON vacío \$1\$1 también está codificado en base64 y se incluye como un parámetro de consulta independiente denominado en la URL. `payload` WebSocket

**Encabezados mediante `Sec-WebSocket-Protocol`**

Un objeto JSON que contiene el `host` y los otros encabezados de autorización se convierte en una cadena y, a continuación, se codifica mediante la codificación base64Url. La cadena codificada en base64Url resultante lleva el prefijo `header-`. Esta cadena con prefijo se utiliza luego como un nuevo subprotocolo, además de en el `Sec-WebSocket-Protocol` encabezado, al establecer la conexión con el `graphql-ws` punto final en tiempo real. WebSocket AWS AppSync 

La URL de solicitud resultante tiene el siguiente formato:

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

El encabezado `Sec-WebSocket-Protocol` contiene el siguiente valor:

```
"sec-websocket-protocol" : ["graphql-ws", "header-ew0KICAiYWNjZXB0IjogImFwcGxpY2F0aW9uL2pzb24sIHRleHQvamF2YXNjcmlwdCIsDQogICJjb250ZW50LWVuY29kaW5nIjogImFtei0xLjAiLA0KICAiY29udGVudC10eXBlIjogImFwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9VVRGLTgiLA0KICAiaG9zdCI6ICJleGFtcGxlMTIzNDU2Nzg5MDAwMC5hcHBzeW5jLWFwaS51cy1lYXN0LTEuYW1hem9uYXdzLmNvbSIsDQogICJ4LWFtei1kYXRlIjogIjIwMjAwNDAxVDAwMTAxMFoiLA0KICAiWC1BbXotU2VjdXJpdHktVG9rZW4iOiAiQWdFWEFNUExFWjJsdVgyVmpFQW9hRG1Gd0xYTnZkWFJvWldGRVhBTVBMRWN3UlFJZ0FoOTdDbGpxN3dPUEw4S3N4UDNZdER1eWMvOWhBajhQaEo3RnZmMzhTZ29DSVFEaEpFWEFNUExFUHNwaW9PenRqKytwRWFnV0N2ZVpVaktFbjB6eVVoQkVYQU1QTEVqai8vLy8vLy8vLy84QkVYQU1QTEV4T0RrMk5EZ3lOemcxTlNJTW8xbVducEVTV1VvWXc0QmtLcUVGU3JtM0RYdUw4dytaYlZjNEpLakRQNHZVQ0tOUjZMZTlDOXBacDlQc1cwTm9GeTN2TEJVZEFYRVhBTVBMRU9WRzhmZVhmaUVFQSsxa2hnRksvd0V0d1IrOXpGN05hTU1Nc2UwN3dOMmdHMnRIMGVLTUVYQU1QTEVRWCtzTWJ5dFFvOGllcFA5UFpPemxac1NGYi9kUDVROGhrNllFWEFNUExFWWNLWnNUa0RBcTJ1S0ZROG1ZVVZBOUV0UW5OUmlGTEVZODNhS3ZHL3RxTFdObkdsU05WeDdTTWNmb3ZrRkRxUWFtbSs4OHkxT3d3QUVZSzdxY29jZVg2WjdHR2NhWXVJZkdwYVgyTUNDRUxlUXZaKzhXeEVnT25JZno3R1l2c1lOakxaU2FSblY0RytJTFkxRjBRTlc2NFM5TnZqK0J3RGczaHQyQ3JOdnB3alZZbGo5VTNubXhFMFVHNW5lODNMTDVoaHFNcG0yNWttTDdlblZndzJrUXptVTJpZDRJS3UwQy9XYW9EUnVPMkY1ekU2M3ZKYnhOOEFZczczMzgrNEI0SEJiNkJaNk9VZ2c5NlExNVJBNDEvZ0lxeGFWUHh5VHBEZlRVNUdmU0x4b2NkWWVuaXFxcEZNdFpHMm45ZDB1N0dzUU5jRmtOY0czcURabTR0RG84dFpidXltMGEyVmNGMkU1aEZFZ1hCYStYTEpDZlhpLzc3T3FBRWpQMHg3UWRrM0I0M3A4S0cvQmFpb1A1UnNWOHpCR3ZIMXpBZ3lQaGEyck43MC90VDEzeXJtUGQ1UVlFZnd6ZXhqS3JWNG1XSXVSZzhOVEhZU1pKVWFleUN3VG9tODBWRlVKWEcrR1lUVXl2NVcyMmFCY25vUkdpQ2lLRVlUTE9rZ1hlY2RLRlRIbWNJQWVqUTlXZWxyMGExOTZLcTg3dzVLTk1Da2NDR0Zud0JORkxtZm5icE5xVDZyVUJ4eHMzWDVudFg5ZDhIVnRTWUlOVHNHWFhNWkNKN2ZuYldhamhnL2FveDBGdEhYMjFlRjZxSUdUOGoxeitsMm9wVStnZ3dVZ2toVVVnQ0gyVGZxQmorTUxNVlZ2cGdxSnNQS3Q1ODJjYUZLQXJJRkl2Tys5UXVweExuRUgyaHowNFRNVGZuVTZiUUM2ejFidVZlN2grdE9MbmgxWVBGc0xRODhhbmliLzdUVEM4azlEc0JUcTBBU2U4UjJHYlNFc21POXFiYk13Z0VhWVVoT0t0R2V5UXNTSmRoU2s2WHhYVGhyV0w5RW53QkNYRGtJQ01xZG50QXh5eU05bldzWjRiTDlKSHFFeGdXVW1mV0NoelBGQXFuM0Y0eTg5NlVxSFRaeGxxM1dHeXBuNUhIY2VtMkhxZjNJVnhLSDFpbmhxZFZ0a3J5RWlUV3JJN1pkamJxbnFSYmwrV2d0UHRLT093ZURsQ2FSczNSMnFYY2JOZ1ZobGVNazRJV25GOEQxNjk1QWVuVTFMd0hqT0pMa0NqeGdORmlXQUZFUEg5YUVYQU1QTEV4QT09IiwNCiAgIkF1dGhvcml6YXRpb24iOiAiQVdTNC1ITUFDLVNIQTI1NiBDcmVkZW50aWFsPVhYWFhYWFhYWFhYWFhYWFhYWFgvMjAyMDA0MDEvdXMtZWFzdC0xL2FwcHN5bmMvYXdzNF9yZXF1ZXN0LCBTaWduZWRIZWFkZXJzPWFjY2VwdDtjb250ZW50LWVuY29kaW5nO2NvbnRlbnQtdHlwZTtob3N0O3gtYW16LWRhdGU7eC1hbXotc2VjdXJpdHktdG9rZW4sIFNpZ25hdHVyZT04M0VYQU1QTEViY2MxZmUzZWU2OWY3NWNkNWViYmY0Y2I0ZjE1MGU0Zjk5Y2VjODY5ZjE0OWM1RVhBTVBMRWRjIg0KfQ"]
```

**Encabezados mediante encabezados HTTP estándar**

En este método, el host y el resto de la información de autorización se transmiten mediante encabezados HTTP estándar al establecer la WebSocket conexión con el AWS AppSync punto final en tiempo real. La URL de solicitud resultante tiene el siguiente formato:

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

Los encabezados de solicitud incluirían lo siguiente:

```
"sec-websocket-protocol" : ["graphql-ws"]
"accept": "application/json, text/javascript",
"content-encoding": "amz-1.0",
"content-type": "application/json; charset=UTF-8",
"host": "example1234567890000.appsync-api.us-east-1.amazonaws.com",
"x-amz-date": "20200401T001010Z",
"X-Amz-Security-Token": "AgEXAMPLEZ2luX2VjEAoaDmFwLXNvdXRoZWFEXAMPLEcwRQIgAh97Cljq7wOPL8KsxP3YtDuyc/9hAj8PhJ7Fvf38SgoCIQDhJEXAMPLEPspioOztj++pEagWCveZUjKEn0zyUhBEXAMPLEjj//////////8BEXAMPLExODk2NDgyNzg1NSIMo1mWnpESWUoYw4BkKqEFSrm3DXuL8w+ZbVc4JKjDP4vUCKNR6Le9C9pZp9PsW0NoFy3vLBUdAXEXAMPLEOVG8feXfiEEA+1khgFK/wEtwR+9zF7NaMMMse07wN2gG2tH0eKMEXAMPLEQX+sMbytQo8iepP9PZOzlZsSFb/dP5Q8hk6YEXAMPLEYcKZsTkDAq2uKFQ8mYUVA9EtQnNRiFLEY83aKvG/tqLWNnGlSNVx7SMcfovkFDqQamm+88y1OwwAEYK7qcoceX6Z7GGcaYuIfGpaX2MCCELeQvZ+8WxEgOnIfz7GYvsYNjLZSaRnV4G+ILY1F0QNW64S9Nvj+BwDg3ht2CrNvpwjVYlj9U3nmxE0UG5ne83LL5hhqMpm25kmL7enVgw2kQzmU2id4IKu0C/WaoDRuO2F5zE63vJbxN8AYs7338+4B4HBb6BZ6OUgg96Q15RA41/gIqxaVPxyTpDfTU5GfSLxocdYeniqqpFMtZG2n9d0u7GsQNcFkNcG3qDZm4tDo8tZbuym0a2VcF2E5hFEgXBa+XLJCfXi/77OqAEjP0x7Qdk3B43p8KG/BaioP5RsV8zBGvH1zAgyPha2rN70/tT13yrmPd5QYEfwzexjKrV4mWIuRg8NTHYSZJUaeyCwTom80VFUJXG+GYTUyv5W22aBcnoRGiCiKEYTLOkgXecdKFTHmcIAejQ9Welr0a196Kq87w5KNMCkcCGFnwBNFLmfnbpNqT6rUBxxs3X5ntX9d8HVtSYINTsGXXMZCJ7fnbWajhg/aox0FtHX21eF6qIGT8j1z+l2opU+ggwUgkhUUgCH2TfqBj+MLMVVvpgqJsPKt582caFKArIFIvO+9QupxLnEH2hz04TMTfnU6bQC6z1buVe7h+tOLnh1YPFsLQ88anib/7TTC8k9DsBTq0ASe8R2GbSEsmO9qbbMwgEaYUhOKtGeyQsSJdhSk6XxXThrWL9EnwBCXDkICMqdntAxyyM9nWsZ4bL9JHqExgWUmfWChzPFAqn3F4y896UqHTZxlq3WGypn5HHcem2Hqf3IVxKH1inhqdVtkryEiTWrI7ZdjbqnqRbl+WgtPtKOOweDlCaRs3R2qXcbNgVhleMk4IWnF8D1695AenU1LwHjOJLkCjxgNFiWAFEPH9aEXAMPLExA==",
"Authorization": "AWS4-HMAC-SHA256 Credential=XXXXXXXXXXXXXXXXXXX/20200401/us-east-1/appsync/aws4_request, SignedHeaders=accept;content-encoding;content-type;host;x-amz-date;x-amz-security-token, Signature=83EXAMPLEbcc1fe3ee69f75cd5ebbf4cb4f150e4f99cec869f149c5EXAMPLEdc"
```

Para firmar la solicitud con un dominio personalizado:

```
{
  url: "https://api.example.com/graphql/connect",
  data: "{}",
  method: "POST",
  headers: {
    "accept": "application/json, text/javascript",
    "content-encoding": "amz-1.0",
    "content-type": "application/json; charset=UTF-8",
  }
}
```

**Ejemplo**

```
{
  "accept": "application/json, text/javascript",
  "content-encoding": "amz-1.0",
  "content-type": "application/json; charset=UTF-8",
  "host": "api.example.com",
  "x-amz-date": "20200401T001010Z",
  "X-Amz-Security-Token": "AgEXAMPLEZ2luX2VjEAoaDmFwLXNvdXRoZWFEXAMPLEcwRQIgAh97Cljq7wOPL8KsxP3YtDuyc/9hAj8PhJ7Fvf38SgoCIQDhJEXAMPLEPspioOztj++pEagWCveZUjKEn0zyUhBEXAMPLEjj//////////8BEXAMPLExODk2NDgyNzg1NSIMo1mWnpESWUoYw4BkKqEFSrm3DXuL8w+ZbVc4JKjDP4vUCKNR6Le9C9pZp9PsW0NoFy3vLBUdAXEXAMPLEOVG8feXfiEEA+1khgFK/wEtwR+9zF7NaMMMse07wN2gG2tH0eKMEXAMPLEQX+sMbytQo8iepP9PZOzlZsSFb/dP5Q8hk6YEXAMPLEYcKZsTkDAq2uKFQ8mYUVA9EtQnNRiFLEY83aKvG/tqLWNnGlSNVx7SMcfovkFDqQamm+88y1OwwAEYK7qcoceX6Z7GGcaYuIfGpaX2MCCELeQvZ+8WxEgOnIfz7GYvsYNjLZSaRnV4G+ILY1F0QNW64S9Nvj+BwDg3ht2CrNvpwjVYlj9U3nmxE0UG5ne83LL5hhqMpm25kmL7enVgw2kQzmU2id4IKu0C/WaoDRuO2F5zE63vJbxN8AYs7338+4B4HBb6BZ6OUgg96Q15RA41/gIqxaVPxyTpDfTU5GfSLxocdYeniqqpFMtZG2n9d0u7GsQNcFkNcG3qDZm4tDo8tZbuym0a2VcF2E5hFEgXBa+XLJCfXi/77OqAEjP0x7Qdk3B43p8KG/BaioP5RsV8zBGvH1zAgyPha2rN70/tT13yrmPd5QYEfwzexjKrV4mWIuRg8NTHYSZJUaeyCwTom80VFUJXG+GYTUyv5W22aBcnoRGiCiKEYTLOkgXecdKFTHmcIAejQ9Welr0a196Kq87w5KNMCkcCGFnwBNFLmfnbpNqT6rUBxxs3X5ntX9d8HVtSYINTsGXXMZCJ7fnbWajhg/aox0FtHX21eF6qIGT8j1z+l2opU+ggwUgkhUUgCH2TfqBj+MLMVVvpgqJsPKt582caFKArIFIvO+9QupxLnEH2hz04TMTfnU6bQC6z1buVe7h+tOLnh1YPFsLQ88anib/7TTC8k9DsBTq0ASe8R2GbSEsmO9qbbMwgEaYUhOKtGeyQsSJdhSk6XxXThrWL9EnwBCXDkICMqdntAxyyM9nWsZ4bL9JHqExgWUmfWChzPFAqn3F4y896UqHTZxlq3WGypn5HHcem2Hqf3IVxKH1inhqdVtkryEiTWrI7ZdjbqnqRbl+WgtPtKOOweDlCaRs3R2qXcbNgVhleMk4IWnF8D1695AenU1LwHjOJLkCjxgNFiWAFEPH9aEXAMPLExA==",
  "Authorization": "AWS4-HMAC-SHA256 Credential=XXXXXXXXXXXXXXXXXXX/20200401/us-east-1/appsync/aws4_request, SignedHeaders=accept;content-encoding;content-type;host;x-amz-date;x-amz-security-token, Signature=83EXAMPLEbcc1fe3ee69f75cd5ebbf4cb4f150e4f99cec869f149c5EXAMPLEdc"
}
```

**URL de solicitud con cadena de consulta**

```
wss://api.example.com/graphql?header=eyEXAMPLEHQiOiJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L2phdmFEXAMPLEQiLCJjb250ZW50LWVuY29kaW5nIjoEXAMPLEEuMCIsImNvbnRlbnQtdHlwZSI6ImFwcGxpY2F0aW9EXAMPLE47IGNoYXJzZXQ9VVRGLTgiLCJob3N0IjoiZXhhbXBsZEXAMPLENjc4OTAwMDAuYXBwc3luYy1hcGkudXMtZWFzdC0xLmFtYEXAMPLEcy5jb20iLCJ4LWFtei1kYXRlIjoiMjAyMDA0MDFUMDAxMDEwWiIsIlgtEXAMPLElY3VyaXR5LVRva2VuIjoiQWdvSmIzSnBaMmx1WDJWakVBb2FEbUZ3TFhOdmRYUm9aV0Z6ZEMweUlrY3dSUUlnQWg5N0NsanE3d09QTDhLc3hQM1l0RHV5Yy85aEFqOFBoSjdGdmYzOFNnb0NJUURoSllKYkpsbmpQc3Bpb096dGorK3BFYWdXQ3ZlWlVqS0VuMHp5VWhCbXhpck5CUWpqLy8vLy8vLy8vLzhCRUFBYUREY3hPRGsyTkRneU56ZzFOU0lNbzFtV25wRVNXVW9ZdzRCa0txRUZTcm0zRFh1TDh3K1piVmM0SktqRFA0dlVDS05SNkxlOUM5cFpwOVBzVzBOb0Z5M3ZMQlVkQVh3dDZQSld1T1ZHOGZlWGZpRUVBKzFraGdGSy93RXR3Uis5ekY3TmFNTU1zZTA3d04yZ0cydEgwZUtNVFhuOEF3QVFYK3NNYnl0UW84aWVwUDlQWk96bFpzU0ZiL2RQNVE4aGs2WWpHVGFMMWVZY0tac1RrREFxMnVLRlE4bVlVVkE5RXRRbk5SaUZMRVk4M2FLdkcvdHFMV05uR2xTTlZ4N1NNY2ZvdmtGRHFRYW1tKzg4eTFPd3dBRVlLN3Fjb2NlWDZaN0dHY2FZdUlmR3BhWDJNQ0NFTGVRdlorOFd4RWdPbklmejdHWXZzWU5qTFpTYVJuVjRHK0lMWTFGMFFOVzY0UzlOdmorQndEZzNodDJDck52cHdqVllsajlVM25teEUwVUc1bmU4M0xMNWhocU1wbTI1a21MN2VuVmd3MmtRem1VMmlkNElLdTBDL1dhb0RSdU8yRjV6RTYzdkpieE44QVlzNzMzOCs0QjRIQmI2Qlo2T1VnZzk2UTE1UkE0MS9nSXF4YVZQeHlUcERmVFU1R2ZTTHhvY2RZZW5pcXFwRk10WkcybjlkMHU3R3NRTmNGa05jRzNxRFptNHREbzh0WmJ1eW0wYTJWY0YyRTVoRkVnWEJhK1hMSkNmWGkvNzdPcUFFalAweDdRZGszQjQzcDhLRy9CYWlvUDVSc1Y4ekJHdkgxekFneVBoYTJyTjcwL3RUMTN5cm1QZDVRWUVmd3pleGpLclY0bVdJdVJnOE5USFlTWkpVYWV5Q3dUb204MFZGVUpYRytHWVRVeXY1VzIyYUJjbm9SR2lDaUtFWVRMT2tnWGVjZEtGVEhtY0lBZWpROVdlbHIwYTE5NktxODd3NUtOTUNrY0NHRm53Qk5GTG1mbmJwTnFUNnJVQnh4czNYNW50WDlkOEhWdFNZSU5Uc0dYWE1aQ0o3Zm5iV2FqaGcvYW94MEZ0SFgyMWVGNnFJR1Q4ajF6K2wyb3BVK2dnd1Vna2hVVWdDSDJUZnFCaitNTE1WVnZwZ3FKc1BLdDU4MmNhRktBcklGSXZPKzlRdXB4TG5FSDJoejA0VE1UZm5VNmJRQzZ6MWJ1VmU3aCt0T0xuaDFZUEZzTFE4OGFuaWIvN1RUQzhrOURzQlRxMEFTZThSMkdiU0VzbU85cWJiTXdnRWFZVWhPS3RHZXlRc1NKZGhTazZYeFhUaHJXTDlFbndCQ1hEa0lDTXFkbnRBeHl5TTluV3NaNGJMOUpIcUV4Z1dVbWZXQ2h6UEZBcW4zRjR5ODk2VXFIVFp4bHEzV0d5cG41SEhjZW0ySHFmM0lWeEtIMWluaHFkVnRrcnlFaVRXckk3WmRqYnFucVJibCtXZ3RQdEtPT3dlRGxDYVJzM1IycVhjYk5nVmhsZU1rNElXbkY4RDE2OTVBZW5VMUx3SGpPSkxrQ2p4Z05GaVdBRkVQSDlhTklhcXMvWnhBPT0iLCJBdXRob3JpemF0aW9uIjoiQVdTNC1ITUFDLVNIQTI1NiBDcmVkZW50aWFsPVhYWFhYWFhYWFhYWFhYWFhYWFgvMjAxOTEwMDIvdXMtZWFzdC0xEXAMPLE5bmMvYXdzNF9yZXF1ZXN0LCBTaWduZWRIZWFkZXJzPWFjY2VwdDtjb250ZWEXAMPLE29kaW5nO2NvbnRlbnQtdHlwZTtob3EXAMPLEW16LWRhdGU7eC1hbXotc2VjdXJpdHktdG9rZW4sIFNpZ25hdHVyZT04MzE4EXAMPLEiY2MxZmUzZWU2OWY3NWNkEXAMPLE0Y2I0ZjE1MGU0Zjk5Y2VjODY5ZjE0OWM1ZDAzNDEXAMPLEn0=&payload=e30=
```

**nota**  
Una WebSocket conexión puede tener varias suscripciones (incluso con distintos modos de autenticación). Una forma de implementarlo consiste en crear una WebSocket conexión para la primera suscripción y, a continuación, cerrarla cuando se anule el registro de la última suscripción. Puedes optimizarlo esperando unos segundos antes de cerrar la WebSocket conexión, en caso de que la aplicación se suscriba inmediatamente después de anular el registro de la última suscripción. Para un ejemplo de aplicación móvil, al cambiar de una pantalla a otra, al *desmontar* un evento, se detiene una suscripción y al *montar* un evento, se inicia una suscripción distinta.

### Autorización Lambda
<a name="lambda-auth"></a>

#### Encabezado de autorización Lambda
<a name="lambda-auth-list"></a>

**Contenido del encabezado**
+  `"Authorization": <string>`: el valor por el que se pasa como `authorizationToken`.
+  `"host": <string>`: el host del punto final de AWS AppSync GraphQL o tu nombre de dominio personalizado.

**Ejemplo**

```
{
    "Authorization":"M0UzQzM1MkQtMkI0Ni00OTZCLUI1NkQtMUM0MTQ0QjVBRTczCkI1REEzRTIxLTk5NzItNDJENi1BQjMwLTFCNjRFNzQ2NzlCNQo=",
    "host":"example1234567890000.appsync-api.us-east-1.amazonaws.com"
}
```

**Encabezados mediante cadena de consulta**

En primer lugar, un objeto JSON que contiene el `host` y la `Authorization` se convierte en una cadena. A continuación, esta cadena se codifica mediante la codificación base64. La cadena codificada en base64 resultante se agrega como un parámetro de consulta con el nombre de la WebSocket URL `header` para establecer la conexión con el punto final en tiempo real. AWS AppSync La URL de solicitud resultante tiene el siguiente formato:

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=eyJBdXRob3JpemF0aW9uIjoiZXlKcmFXUWlPaUpqYkc1eGIzQTVlVzVNSzA5UVlYSXJNVEpIV0VGTFNYQmllVTVXTkhoc1FqaFBWVzlZTW5NMldsZHZQU0lzSW1Gc1p5STZJbEpUTWpVMkluMC5leUp6ZFdJaU9pSmhObU5tTWpjd055MHhOamd4TFRRMU5ESXRPV1l4T0MxbE5qWTBNVGcyTmpsa016WWlMQ0psZG1WdWRGOXBaQ0k2SW1Wa016TTVNbU5rTFdOallUTXROR00yT0MxaE5EWXlMVEpsWkdJM1pUTm1ZMkZqWmlJc0luUnZhMlZ1WDNWelpTSTZJbUZqWTJWemN5SXNJbk5qYjNCbElqb2lZWGR6TG1OdloyNXBkRzh1YzJsbmJtbHVMblZ6WlhJdVlXUnRhVzRpTENKaGRYUm9YM1JwYldVaU9qRTFOamswTlRjM01UZ3NJbWx6Y3lJNkltaDBkSEJ6T2x3dlhDOWpiMmR1YVhSdkxXbGtjQzVoY0MxemIzVjBhR1ZoYzNRdE1pNWhiV0Y2YjI1aGQzTXVZMjl0WEM5aGNDMXpiM1YwYUdWaGMzUXRNbDgzT0hZMFNWWmliVkFpTENKbGVIQWlPakUxTmprME5qRXpNakFzSW1saGRDSTZNVFUyT1RRMU56Y3lNQ3dpYW5ScElqb2lOVGd6WmpobVltTXRNemsyTVMwMFl6QTRMV0poWlRBdFl6UXlZMkl4TVRNNU5EWTVJaXdpWTJ4cFpXNTBYMmxrSWpvaU0zRmxhalZsTVhabU16ZDFOM1JvWld3MGRHOTFkREprTVd3aUxDSjFjMlZ5Ym1GdFpTSTZJbVZzYjNKNllXWmxJbjAuQjRjZEp0aDNLRk5wSjZpa1ZwN2U2RFJlZTk1VjZRaS16RUUyREpIN3NIT2wyenhZaTdmLVNtRUdvaDJBRDhlbXhRUllhakJ5ei1yRTRKaDBRT3ltTjJZcy1aSWtNcFZCVFBndS1UTVdEeU9IaERVbVVqMk9QODJ5ZVozd2xaQXRyX2dNNEx6alhVWG1JX0syeUdqdVhmWFRhYTFtdlFFQkcwbVFmVmQ3U2Z3WEItamN2NFJZVmk2ajI1cWdvdzlFdzUydWZ1clBxYUstM1dBS0czMktwVjhKNC1XZWpxOHQwYy15QTdzYjhFbkI1NTFiN1RVOTN1S1JpVlZLM0U1NU5rNUFEUG9hbV9XWUU0NWkzczVxVkFQXy1Jblc3NU5Vb09DR1RzUzhZV01mYjZlY0hZSi0xai1iekEyN3phVDlWamN0WG45YnlORlptS0xwQTJMY3h3IiwiaG9zdCI6ImV4YW1wbGUxMjM0NTY3ODkwMDAwLmFwcHN5bmMtYXBpLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tIn0=&payload=e30=
```

Es importante tener en cuenta que, además del objeto de encabezado codificado en base64, un objeto JSON vacío \$1\$1 también está codificado en base64 y se incluye como un parámetro de consulta independiente denominado en la URL. `payload` WebSocket

**Encabezados mediante `Sec-WebSocket-Protocol`**

Un objeto JSON que contiene el `host` y la `Authorization` se convierte en una cadena y, a continuación, se codifica mediante la codificación base64Url. La cadena codificada en base64Url resultante lleva el prefijo `header-`. Esta cadena con prefijo se utiliza luego como un nuevo subprotocolo, además de en el `Sec-WebSocket-Protocol` encabezado, al establecer la conexión con el `graphql-ws` punto final en tiempo real. WebSocket AWS AppSync 

La URL de solicitud resultante tiene el siguiente formato:

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

El encabezado `Sec-WebSocket-Protocol` contiene el siguiente valor:

```
"sec-websocket-protocol" : ["graphql-ws", "header-ewogICAgImhvc3QiOiJleGFtcGxlMTIzNDU2Nzg5MDAwMC5hcHBzeW5jLWFwaS51cy1lYXN0LTEuYW1hem9uYXdzLmNvbSIsCiAgICAieC1hcGkta2V5IjoiZGEyLTEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Igp9"]
```

**Encabezados mediante encabezados HTTP estándar**

En este método, la información del host y de la autorización se transmite mediante encabezados HTTP estándar al establecer la WebSocket conexión con el AWS AppSync punto final en tiempo real. La URL de solicitud resultante tiene el siguiente formato:

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

Los encabezados de solicitud incluirían lo siguiente:

```
"sec-websocket-protocol" : ["graphql-ws"]
"Authorization":"eyEXAMPLEiJjbG5xb3A5eW5MK09QYXIrMTJHWEFLSXBieU5WNHhsQjEXAMPLEnM2WldvPSIsImFsZyI6IlEXAMPLEn0.eyEXAMPLEiJhNmNmMjcwNy0xNjgxLTQ1NDItOWYxOC1lNjY0MTg2NjlkMzYiLCJldmVudF9pZCI6ImVkMzM5MmNkLWNjYTMtNGM2OC1hNDYyLTJlZGI3ZTNmY2FjZiIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE1Njk0NTc3MTgsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC5hcC1zb3V0aGVhc3QtMi5hbWF6b25hd3MuY29tXC9hcC1zb3V0aGVhc3QtMl83OHY0SVZibVAiLCJleHAiOjE1Njk0NjEzMjAsImlhdCI6MTU2OTQ1NzcyMCwianRpIjoiNTgzZjhmYmMtMzk2MS00YzA4LWJhZTAtYzQyY2IxMTM5NDY5IiwiY2xpZW50X2lkIjoiM3FlajVlMXZmMzd1N3RoZWw0dG91dDJkMWwiLCJ1c2VybmFtZSI6ImVsb3EXAMPLEn0.B4EXAMPLEFNpJ6ikVp7e6DRee95V6Qi-zEE2DJH7sHOl2zxYi7f-SmEGoh2AD8emxQRYajByz-rE4Jh0QOymN2Ys-ZIkMpVBTPgu-TMWDyOHhDUmUj2OP82yeZ3wlZAtr_gM4LzjXUXmI_K2yGjuXfXTaa1mvQEBG0mQfVd7SfwXB-jcv4RYVi6j25qgow9Ew52ufurPqaK-3WAKG32KpV8J4-Wejq8t0c-yA7sb8EnB551b7TU93uKRiVVK3E55Nk5ADPoam_WYE45i3s5qVAP_-InW75NUoOCGTsS8YWMfb6ecHYJ-1j-bzA27zaT9VjctXn9byNFZmEXAMPLExw",
"host":"example1234567890000.appsync-api.us-east-1.amazonaws.com"
```

## Funcionamiento en tiempo real WebSocket
<a name="real-time-websocket-operation"></a>

Tras iniciar un WebSocket apretón de manos exitoso AWS AppSync, el cliente debe enviar un mensaje posterior al que conectarse AWS AppSync para realizar diferentes operaciones. Estos mensajes requieren los siguientes datos:
+  `type`: el tipo de operación.
+  `id`: un identificador único para la suscripción. Recomendamos usar un UUID para este fin.
+  `payload`: la carga útil asociada según el tipo de operación.

El campo `type` es el único campo obligatorio; los campos `id` y `payload` son opcionales.

### Secuencia de eventos
<a name="sequence-of-events"></a>

Para iniciar, establecer, registrar y procesar correctamente la solicitud de suscripción, el cliente debe pasar por la siguiente secuencia:

1. Inicializar conexión (`connection_init`)

1. Reconocimiento de conexión (`connection_ack`)

1. Registro de suscripción (`start`)

1. Reconocimiento de suscripción (`start_ack`)

1. Procesamiento de suscripción (`data`)

1. Anulación del registro de suscripción (`stop`)

## Mensaje connection init
<a name="connection-init-message"></a>

(Opcional) Tras un apretón de manos exitoso, el cliente puede enviar el `connection_init` mensaje para empezar a comunicarse con el AWS AppSync terminal en tiempo real. El mensaje es una cadena obtenida mediante la representación en forma de cadena del objeto JSON como se indica a continuación:

```
{ "type": "connection_init" }
```

## Mensaje de confirmación de conexión
<a name="connection-acknowledge-message"></a>

Después de enviar el mensaje `connection_init`, el cliente debe esperar el mensaje `connection_ack`. Todos los mensajes enviados antes de recibir `connection_ack` se omitirán. El mensaje debería decir lo siguiente:

```
{
  "type": "connection_ack",
  "payload": {
    // Time in milliseconds waiting for ka message before the client should terminate the WebSocket connection
    "connectionTimeoutMs": 300000
  }
}
```

## Mensaje Keep-alive
<a name="keep-alive-message"></a>

Además del mensaje de confirmación de conexión, el cliente recibe periódicamente mensajes keep-alive. Si el cliente no recibe un mensaje de mantenimiento activo dentro del período de espera de la conexión, debe cerrar la conexión. AWS AppSync sigue enviando estos mensajes y gestionando las suscripciones registradas hasta que cierra la conexión automáticamente (después de 24 horas). Los mensajes keep-alive son latidos y no necesitan reconocimiento por parte del cliente.

```
{ "type": "ka" }
```

## Mensaje de registro de suscripción
<a name="subscription-registration-message"></a>

Una vez que el cliente reciba un `connection_ack` mensaje, podrá enviar los mensajes de registro de la suscripción a AWS AppSync. Este tipo de mensaje es un objeto JSON representado en forma de cadena que contiene los siguientes campos:
+  `"id": <string>`: el ID de la suscripción. Este ID debe ser único para cada suscripción; de lo contrario, el servidor devuelve un error que indica que el ID de suscripción está duplicado.
+  `"type": "start"`: un parámetro `<string>` constante.
+  `"payload": <Object>`: un objeto que contiene la información relevante para la suscripción.
  +  `"data": <string>`: un objeto JSON representado en forma de cadena que contiene una consulta de GraphQL y variables.
    +  `"query": <string>`: operación de GraphQL.
    +  `"variables": <Object>`: un objeto que contiene las variables para la consulta.
  +  `"extensions": <Object>`: un objeto que contiene un objeto de autorización.
+  `"authorization": <Object>`: un objeto que contiene los campos necesarios para la autorización.

### Objeto de autorización para el registro de suscripción
<a name="authorization-object-for-subscription-registration"></a>

Las mismas reglas de la sección [Formato de parámetros de encabezado basado en el modo AWS AppSync de autorización de la API](#header-parameter-format-based-on-appsync-api-authorization-mode) se aplican al objeto de autorización. La única excepción es para IAM, donde la información de la firma SigV4 es ligeramente diferente. Para obtener más información, consulte el ejemplo de IAM.

Ejemplo de uso de grupos de usuarios de Amazon Cognito:

```
{
  "id": "ee849ef0-cf23-4cb8-9fcb-152ae4fd1e69",
  "payload": {
    "data": "{\"query\":\"subscription onCreateMessage {\\n onCreateMessage {\\n __typename\\n message\\n }\\n }\",\"variables\":{}}",
      "extensions": {
        "authorization": {
          "Authorization": "eyEXAMPLEiJjbG5xb3A5eW5MK09QYXIrMTJEXAMPLEBieU5WNHhsQjhPVW9YMnM2WldvPSIsImFsZyI6IlEXAMPLEn0.eyJzdWIiOiJhNmNmMjcwNy0xNjgxLTQ1NDItEXAMPLENjY0MTg2NjlkMzYiLCJldmVudF9pZCI6ImU3YWVmMzEyLWUEXAMPLEY0Zi04YjlhLTRjMWY5M2Q5ZTQ2OCIsInRva2VuX3VzZSI6ImFjY2VzcyIsIEXAMPLEIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE1Njk2MTgzMzgsImlzcyI6Imh0dEXAMPLEXC9jb2duaXRvLWlkcC5hcC1zb3V0aGVhc3QtMi5hbWF6b25hd3MuY29tXC9hcC1zbEXAMPLEc3QtMl83OHY0SVZibVAiLCJleHAiOjE1NzAyNTQ3NTUsImlhdCI6MTU3MDI1MTE1NSwianRpIjoiMmIEXAMPLEktZTVkMi00ZDhkLWJiYjItNjA0YWI4MDEwOTg3IiwiY2xpZW50X2lkIjoiM3FlajVlMXZmMzd1EXAMPLE0dG91dDJkMWwiLCJ1c2VybmFtZSI6ImVsb3J6YWZlIn0.CT-qTCtrYeboUJ4luRSTPXaNewNeEXAMPLE14C6sfg05tO0fOMpiUwj9k19gtNCCMqoSsjtQoUweFnH4JYa5EXAMPLEVxOyQEQ4G7jQrt5Ks6STn53vuseR3zRW9snWgwz7t3ZmQU-RWvW7yQU3sNQRLEXAMPLEcd0yufBiCYs3dfQxTTdvR1B6Wz6CD78lfNeKqfzzUn2beMoup2h6EXAMPLE4ow8cUPUPvG0DzRtHNMbWskjPanu7OuoZ8iFO_Eot9kTtAlVKYoNbWkZhkD8dxutyoU4RSH5JoLAnrGF5c8iKgv0B2dfEXAMPLEIihxaZVJ9w9w48S4EXAMPLEcA",
          "host": "example1234567890000.appsync-api.us-east-1.amazonaws.com"
         }
      }
  },
  "type": "start"
}
```

Ejemplo de uso de IAM:

```
{
  "id": "eEXAMPLE-cf23-1234-5678-152EXAMPLE69",
  "payload": {
    "data": "{\"query\":\"subscription onCreateMessage {\\n onCreateMessage {\\n __typename\\n message\\n }\\n }\",\"variables\":{}}",
    "extensions": {
      "authorization": {
        "accept": "application/json, text/javascript",
        "content-type": "application/json; charset=UTF-8",
        "X-Amz-Security-Token": "AgEXAMPLEZ2luX2VjEAoaDmFwLXNvdXRoZWFEXAMPLEcwRQIgAh97Cljq7wOPL8KsxP3YtDuyc/9hAj8PhJ7Fvf38SgoCIQDhJEXAMPLEPspioOztj++pEagWCveZUjKEn0zyUhBEXAMPLEjj//////////8BEXAMPLExODk2NDgyNzg1NSIMo1mWnpESWUoYw4BkKqEFSrm3DXuL8w+ZbVc4JKjDP4vUCKNR6Le9C9pZp9PsW0NoFy3vLBUdAXEXAMPLEOVG8feXfiEEA+1khgFK/wEtwR+9zF7NaMMMse07wN2gG2tH0eKMEXAMPLEQX+sMbytQo8iepP9PZOzlZsSFb/dP5Q8hk6YEXAMPLEYcKZsTkDAq2uKFQ8mYUVA9EtQnNRiFLEY83aKvG/tqLWNnGlSNVx7SMcfovkFDqQamm+88y1OwwAEYK7qcoceX6Z7GGcaYuIfGpaX2MCCELeQvZ+8WxEgOnIfz7GYvsYNjLZSaRnV4G+ILY1F0QNW64S9Nvj+BwDg3ht2CrNvpwjVYlj9U3nmxE0UG5ne83LL5hhqMpm25kmL7enVgw2kQzmU2id4IKu0C/WaoDRuO2F5zE63vJbxN8AYs7338+4B4HBb6BZ6OUgg96Q15RA41/gIqxaVPxyTpDfTU5GfSLxocdYeniqqpFMtZG2n9d0u7GsQNcFkNcG3qDZm4tDo8tZbuym0a2VcF2E5hFEgXBa+XLJCfXi/77OqAEjP0x7Qdk3B43p8KG/BaioP5RsV8zBGvH1zAgyPha2rN70/tT13yrmPd5QYEfwzexjKrV4mWIuRg8NTHYSZJUaeyCwTom80VFUJXG+GYTUyv5W22aBcnoRGiCiKEYTLOkgXecdKFTHmcIAejQ9Welr0a196Kq87w5KNMCkcCGFnwBNFLmfnbpNqT6rUBxxs3X5ntX9d8HVtSYINTsGXXMZCJ7fnbWajhg/aox0FtHX21eF6qIGT8j1z+l2opU+ggwUgkhUUgCH2TfqBj+MLMVVvpgqJsPKt582caFKArIFIvO+9QupxLnEH2hz04TMTfnU6bQC6z1buVe7h+tOLnh1YPFsLQ88anib/7TTC8k9DsBTq0ASe8R2GbSEsmO9qbbMwgEaYUhOKtGeyQsSJdhSk6XxXThrWL9EnwBCXDkICMqdntAxyyM9nWsZ4bL9JHqExgWUmfWChzPFAqn3F4y896UqHTZxlq3WGypn5HHcem2Hqf3IVxKH1inhqdVtkryEiTWrI7ZdjbqnqRbl+WgtPtKOOweDlCaRs3R2qXcbNgVhleMk4IWnF8D1695AenU1LwHjOJLkCjxgNFiWAFEPH9aEXAMPLExA==",
        "Authorization": "AWS4-HMAC-SHA256 Credential=XXXXXXXXXXXXXXXXXXXX/20200401/us-east-1/appsync/aws4_request, SignedHeaders=accept;content-encoding;content-type;host;x-amz-date;x-amz-security-token, Signature=b90131a61a7c4318e1c35ead5dbfdeb46339a7585bbdbeceeaff51f4022eb1fd",
        "content-encoding": "amz-1.0",
        "host": "example1234567890000.appsync-api.us-east-1.amazonaws.com",
        "x-amz-date": "20200401T001010Z"
      }
    }
  },
  "type": "start"
}
```

Ejemplo de uso de un nombre de dominio personalizado:

```
{
  "id": "key-cf23-4cb8-9fcb-152ae4fd1e69",
  "payload": {
    "data": "{\"query\":\"subscription onCreateMessage {\\n onCreateMessage {\\n __typename\\n message\\n }\\n }\",\"variables\":{}}",
      "extensions": {
        "authorization": {
          "x-api-key": "da2-12345678901234567890123456",
          "host": "api.example.com"
         }
      }
  },
  "type": "start"
}
```

La firma SigV4 no necesita que se anexe `/connect` a la URL y la operación de GraphQL representada en forma de cadena JSON reemplaza a `data`. A continuación, se muestra un ejemplo de una solicitud de firma SigV4:

```
{
  url: "https://example1234567890000.appsync-api.us-east-1.amazonaws.com/graphql",
  data: "{\"query\":\"subscription onCreateMessage {\\n onCreateMessage {\\n __typename\\n message\\n }\\n }\",\"variables\":{}}",
  method: "POST",
  headers: {
    "accept": "application/json, text/javascript",
    "content-encoding": "amz-1.0",
    "content-type": "application/json; charset=UTF-8",
  }
}
```

## Mensaje de confirmación de suscripción
<a name="subscription-acknowledge-message"></a>

Tras enviar el mensaje de inicio de la suscripción, el cliente debe esperar AWS AppSync a que se envíe el `start_ack` mensaje. El mensaje `start_ack` indica que la suscripción se ha realizado correctamente.

Ejemplo de reconocimiento de suscripción:

```
{
  "type": "start_ack",
  "id": "eEXAMPLE-cf23-1234-5678-152EXAMPLE69"
}
```

## Mensaje de error
<a name="error-message"></a>

Si se produce un error en el registro de suscripción o el inicio de la suscripción, o bien si se termina una suscripción desde el servidor, el servidor envía un mensaje de error al cliente. Si el error se produce durante el tiempo de inicio de la conexión, el servidor cerrará la conexión.
+  `"type": "error"`: un parámetro `<string>` constante.
+  `"id": <string>`: el ID de la suscripción registrada correspondiente, si procede.
+  `"payload" <Object>`: un objeto que contiene la información de error correspondiente.

Ejemplo:

```
{
  "type": "error",
  "payload": {
    "errors": [
      {
        "errorType": "LimitExceededError",
        "message": "Rate limit exceeded"
      }
    ]
  }
}
```

## Procesamiento de mensajes de datos
<a name="processing-data-messages"></a>

Cuando un cliente envía una mutación, AWS AppSync identifica a todos los suscriptores interesados en ella y envía un `"type":"data"` mensaje a cada uno de ellos utilizando la suscripción correspondiente a la operación `id` de `"start"` suscripción. Se espera que el cliente realice un seguimiento del `id` de suscripción que envía para que cuando se reciba un mensaje de datos, el cliente pueda asociarlo con la suscripción correspondiente.
+  `"type": "data"`: un parámetro `<string>` constante.
+  `"id": <string>`: el ID de la suscripción registrada correspondiente.
+  `"payload" <Object>`: un objeto que contiene la información relevante para la suscripción.

Ejemplo:

```
{
  "type": "data",
  "id": "ee849ef0-cf23-4cb8-9fcb-152ae4fd1e69",
  "payload": {
    "data": {
      "onCreateMessage": {
        "__typename": "Message",
        "message": "test"
      }
    }
  }
}
```

## Mensaje de anulación de registro de suscripción
<a name="subscription-unregistration-message"></a>

Cuando la aplicación quiere dejar de escuchar los eventos de suscripción, el cliente debe enviar un mensaje con el siguiente objeto JSON representado en forma de cadena:
+  `"type": "stop"`: un parámetro `<string>` constante.
+  `"id": <string>`: el ID de la suscripción cuyo registro se va a cancelar.

Ejemplo:

```
{
  "type":"stop",
  "id":"ee849ef0-cf23-4cb8-9fcb-152ae4fd1e69"
}
```

AWS AppSync devuelve un mensaje de confirmación con el siguiente objeto JSON en cadena:
+  `"type": "complete"`: un parámetro `<string>` constante.
+  `"id": <string>`: el ID de la suscripción cuyo registro se anuló.

Una vez que el cliente reciba el mensaje de confirmación, no recibirá más mensajes para esta suscripción en particular.

Ejemplo:

```
{
  "type":"complete",
  "id":"eEXAMPLE-cf23-1234-5678-152EXAMPLE69"
}
```

## Desconectando el WebSocket
<a name="disconnecting-the-websocket"></a>

Antes de desconectarse, para evitar la pérdida de datos, el cliente debe disponer de la lógica necesaria para comprobar que actualmente no se está realizando ninguna operación a través de la WebSocket conexión. Se debe anular el registro de todas las suscripciones antes de desconectarse de. WebSocket

# Fusión en APIs AWS AppSync
<a name="merged-api"></a>

A medida que el uso de GraphQL se expande dentro de una organización, pueden surgir compensaciones entre la API ease-of-use y la velocidad de desarrollo de la API. Por un lado, las organizaciones adoptan AWS AppSync GraphQL para simplificar el desarrollo de aplicaciones. Esto proporciona a los desarrolladores una API flexible que pueden usar para acceder, manipular y combinar de forma segura los datos de uno o más dominios de datos con una sola llamada a la red. Por otro lado, los equipos de una organización que son responsables de los diferentes dominios de datos combinados en un único punto final de la API de GraphQL pueden querer tener la capacidad de crear, administrar e implementar actualizaciones de API independientes unas de otras. Esto aumenta sus velocidades de desarrollo. 

Para resolver esta tensión, la APIs función AWS AppSync Merged permite a los equipos de diferentes dominios de datos crear e implementar de forma independiente AWS AppSync APIs (por ejemplo, esquemas, resolutores, fuentes de datos y funciones de GraphQL), que luego se pueden combinar en una única API fusionada. De este modo, las organizaciones pueden mantener una API multidominio fácil de usar y los diferentes equipos que colaboran en esa API pueden aplicar actualizaciones de la API de forma rápida e independiente.

El siguiente diagrama muestra el flujo de trabajo de la API combinada:

![\[Diagrama que muestra el flujo de trabajo de la API combinada con varias fuentes APIs que se combinan en un único punto final de la API combinada\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/images/merged-api-workflow.png)


Con Merged APIs, las organizaciones pueden importar los recursos de varias fuentes independientes AWS AppSync APIs a un único punto final de la API AWS AppSync Merged. Para ello, AWS AppSync permite crear una lista de fuentes y AWS AppSync APIs, a continuación, combinar todos los metadatos asociados a la fuente, APIs incluidos el esquema, los tipos, las fuentes de datos, los resolutores y las funciones, en una nueva AWS AppSync API combinada.

Durante las fusiones, pueden producirse conflictos de fusión debido a incoherencias en el contenido de los datos de la API de origen, como conflictos en la nomenclatura de los tipos cuando se combinan varios esquemas. Para los casos de uso sencillos en los que no haya APIs conflictos entre las definiciones de la fuente, no es necesario modificar los esquemas de la API de origen. La API combinada resultante simplemente importa todos los tipos, resolutores, fuentes de datos y funciones de la fuente original. AWS AppSync APIs Para los casos de uso complejos en los que surjan conflictos, users/teams deberán resolverlos por varios medios. AWS AppSync proporciona a los usuarios varias herramientas y ejemplos que pueden reducir los conflictos de fusión. 

Las fusiones posteriores que se configuren en AWS AppSync propagarán los cambios realizados en la fuente APIs a la API Merged asociada.

## Fusión y federación APIs
<a name="merged-api-federation"></a>

Existen muchas soluciones y patrones en la comunidad de GraphQL para combinar esquemas de GraphQL y permitir la colaboración en equipo a través de un gráfico compartido. AWS AppSync Para la composición de los esquemas, Merged APIs adopta un enfoque basado en el *tiempo de creación*, en el APIs que las fuentes se combinan en una API fusionada independiente. Un enfoque alternativo consiste en colocar un router en *tiempo de ejecución* en varias fuentes APIs o subgráficos. En este enfoque, el router recibe una solicitud, hace referencia a un esquema combinado que mantiene como metadatos, crea un plan de solicitudes y, a continuación, distribuye los elementos de la solicitud entre sus subgráficos/servidores subyacentes. En la siguiente tabla, se compara el enfoque de tiempo de compilación de la API AWS AppSync combinada con los enfoques en tiempo de ejecución y basados en enrutadores para la composición de esquemas de GraphQL:


|  |  |  | 
| --- |--- |--- |
| Característica | AppSync API fusionada | Soluciones basadas en enrutadores | 
| Los subgráficos se administran de forma independiente | Sí | Sí | 
| Subgráficos direccionables de forma independiente | Sí | Sí | 
| Composición de esquemas automatizada | Sí | Sí | 
| Detección automatizada de conflictos | Sí | Sí | 
| Resolución de conflictos mediante directivas de esquema | Sí | Sí | 
| Servidores de subgráficos compatibles | AWS AppSync\$1 | Varía | 
| Complejidad de red | Una sola API fusionada significa que no hay saltos de red adicionales. | La arquitectura multicapa requiere planificación y delegación de consultas, análisis de subconsultas y serialización/deserialización, y resolutores de referencia en subgráficos para realizar las uniones. | 
| Soporte de observabilidad | Supervisión, registro y rastreo integrados. Un único servidor de API fusionado significa una depuración simplificada. | Build-your-own observabilidad en el router y en todos los servidores de subgráficos asociados. Depuración compleja en todo el sistema distribuido. | 
| Soporte de autorización | Soporte integrado para múltiples modos de autorización. | Build-your-own reglas de autorización. | 
| Seguridad entre cuentas | Soporte integrado para asociaciones de cuentas entre AWS nubes. | Build-your-own modelo de seguridad. | 
| Soporte de suscripciones | Sí | No | 

\$1 AWS AppSync La combinación solo se APIs puede asociar a la AWS AppSync fuente APIs. Si necesita soporte para la composición de esquemas entre gráficos AWS AppSync y sin AWS AppSync subgráficos, puede conectar uno o más AWS AppSync and/or GraphQL Merged a una solución basada en APIs enrutadores. Por ejemplo, consulte el blog de referencia para añadir AWS AppSync APIs como subgráfico utilizando una arquitectura basada en enrutadores con Apollo Federation v2: Apollo [GraphQL](https://aws.amazon.com/blogs/mobile/federation-appsync-subgraph/) Federation with. AWS AppSync

**Topics**
+ [Fusión y federación APIs](#merged-api-federation)
+ [Resolución de conflictos de la API fusionada](#merged-api-conflict-resolution)
+ [Configuración de esquemas](#configuring-schemas-merged-api)
+ [Configuración de modos de autorización](#configuring-authorization-merged-api)
+ [Configuración de roles de ejecución](#execution-roles-merged-api)
+ [Configuración de varias cuentas: Merged usando APIs AWS RAM](#cross-account-merged-api)
+ [Fusión](#merges)
+ [Soporte adicional para Merged APIs](#merge-api-additional-support)
+ [Limitaciones de las API fusionadas](#merged-api-limits)
+ [Consideraciones sobre la API fusionada](#merged-api-considerations)
+ [Creación de Merged APIs](#creating-merged-api)

## Resolución de conflictos de la API fusionada
<a name="merged-api-conflict-resolution"></a>

En caso de que surja un conflicto de fusión, AWS AppSync proporciona a los usuarios varias herramientas y ejemplos para ayudar a solucionar los problemas.

### Directivas de esquema de la API fusionada
<a name="merged-api-schema-directive"></a>

 AWS AppSync ha introducido varias directivas de GraphQL que se pueden utilizar para reducir o resolver conflictos entre fuentes: APIs
+ *@canonical*: esta directiva establece la prioridad de los tipos o campos con nombres y datos similares. Si dos o más fuentes APIs tienen el mismo tipo o campo de GraphQL, una de ellas APIs puede anotar su tipo o campo como *canónico*, lo que se priorizará durante la fusión. Los conflictos types/fields que no estén anotados con esta directiva en otra fuente se ignoran al fusionarse. APIs 
+ *@hidden*: Esta directiva encapsula ciertos elementos types/fields para eliminarla del proceso de fusión. Los equipos tal vez deseen eliminar u ocultar tipos u operaciones específicos en la API de origen para que solo los clientes internos puedan acceder a datos de tipos específicos. Con esta directiva adjunta, los tipos o campos no se fusionan en la API fusionada. 
+ *@renamed*: Esta directiva cambia los nombres de types/fields para reducir los conflictos de nombres. Hay situaciones en las APIs que diferentes tienen el mismo tipo o nombre de campo. Sin embargo, todas deben estar disponibles en el esquema fusionado. Una forma sencilla de incluirlos todos en la API fusionada consiste en cambiar el nombre del campo por uno similar, pero no idéntico. 

Para mostrar el esquema de utilidades que proporcionan las directivas, observe el siguiente ejemplo:

En este ejemplo, supongamos que queremos fusionar dos fuentes APIs. Tenemos dos esquemas que crean y recuperan publicaciones (p. ej., publicaciones en la sección de comentarios o en las redes sociales). Suponiendo que los tipos y los campos sean muy similares, la probabilidad de que surjan conflictos durante una operación de fusión es muy elevada. Los fragmentos siguientes muestran los tipos y campos de cada esquema.

El primer archivo, denominado *Source1.graphql*, es un esquema de GraphQL que permite al usuario crear `Posts` utilizando la mutación `putPost`. Cada `Post` contiene un título y un ID. El ID se utiliza para hacer referencia al `User`, o a la información del autor de la publicación (correo electrónico y dirección), y al `Message`, o la carga útil (contenido). El tipo de `User` se anota con la etiqueta *@canonical*.

```
# This snippet represents a file called Source1.graphql

type Mutation {
    putPost(id: ID!, title: String!): Post
}

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

type Message {
   id: ID!
   content: String
}

type User @canonical {
   id: ID!
   email: String!
   address: String!
}

type Query {
    singlePost(id: ID!): Post
    getMessage(id: ID!): Message
}
```

El segundo archivo, llamado *Source2.graphql*, es un esquema GraphQL con funciones muy similares a las de *Source1.graphQL*. Sin embargo, tenga en cuenta que los campos de cada tipo son diferentes. Al fusionar estos dos esquemas, se producirán conflictos de fusión debido a estas diferencias. 

Observe también que *Source2.graphql* también contiene varias directivas para reducir estos conflictos. El tipo `Post` tiene anotada una etiqueta *@hidden* para ocultarse durante la operación de fusión. El tipo `Message` tiene anotada la etiqueta *@renamed* para cambiar el nombre del tipo a `ChatMessage` en caso de conflicto de nomenclatura con otro tipo `Message`.

```
# This snippet represents a file called Source2.graphql

type Post @hidden  {
    id: ID!
    title: String!
    internalSecret: String!
}

type Message @renamed(to: "ChatMessage") {
   id: ID!
   chatId: ID!
   from: User!
   to: User!
}

# Stub user so that we can link the canonical definition from Source1
type User {
   id: ID!
}

type Query {
    getPost(id: ID!): Post
    getMessage(id: ID!): Message @renamed(to: "getChatMessage")
}
```

Cuando se produzca la fusión, el resultado generará el archivo `MergedSchema.graphql`:

```
# This snippet represents a file called MergedSchema.graphql

type Mutation {
    putPost(id: ID!, title: String!): Post
}

# Post from Source2 was hidden so only uses the Source1 definition. 
type Post {
    id: ID!
    title: String!
}

# Renamed from Message to resolve the conflict
type ChatMessage {
   id: ID!
   chatId: ID!
   from: User!
   to: User!
}

type Message {
   id: ID!
   content: String
}

# Canonical definition from Source1
type User {
   id: ID!
   email: String!
   address: String!
}

type Query {
    singlePost(id: ID!): Post
    getMessage(id: ID!): Message
    
    # Renamed from getMessage
    getChatMessage(id: ID!): ChatMessage
}
```

En la fusión ocurrieron varias cosas:
+ Se priorizó el tipo `User` de *Source1.graphql* con respecto al `User` de *Source2.graphql* debido a la anotación *@canonical*.
+ El tipo `Message` de *Source1.graphql* se incluyó en la fusión. Sin embargo, había un conflicto de nombres en el `Message` de *Source2.graphql*. Al tener la anotación *@renamed*, también se incluyó en la fusión, pero con el nombre alternativo `ChatMessage`.
+ Se incluyó el tipo `Post` de *Source1.graphql*, pero no el tipo `Post` de *Source2.graphql*. Normalmente, habría un conflicto con este tipo, pero el tipo `Post` de *Source2.graphql* tenía una anotación *@hidden*, por lo que sus datos estaban ocultos y no se incluyeron en la fusión. Por tanto, no hubo conflicto.
+ El tipo `Query` se actualizó para incluir el contenido de ambos archivos. Sin embargo, la directiva hizo que se cambiara el nombre de una consulta de `GetMessage` a `GetChatMessage`. Así se resolvió el conflicto de nomenclatura entre las dos consultas con el mismo nombre.

También puede ocurrir que no se agreguen directivas a un tipo con conflictos. En este caso, el tipo fusionado incluirá la unión de todos los campos de todas las definiciones de origen de ese tipo. Por ejemplo, observe el siguiente caso:

Este esquema, denominado *Source1.graphql*, permite crear y recuperar `Posts`. La configuración es similar a la del ejemplo anterior, pero con menos información.

```
# This snippet represents a file called Source1.graphql

type Mutation {
    putPost(id: ID!, title: String!): Post
}

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

type Query {
    getPost(id: ID!): Post
}
```

Este esquema, denominado *Source2.graphql*, permite crear y recuperar `Reviews` (p. ej., valoraciones de películas o reseñas de restaurantes). Las `Reviews` están asociadas a la `Post` con el mismo valor de ID. En conjunto, contienen el título, el ID de la publicación y el mensaje de carga útil de la publicación de la reseña completa.

Al fusionarse, habrá un conflicto entre los dos tipos `Post`. Como no hay anotaciones para resolver este problema, se lleva a cabo, de manera predeterminada, una operación de unión de los tipos en conflicto.

```
# This snippet represents a file called Source2.graphql

type Mutation {
    putReview(id: ID!, postId: ID!, comment: String!): Review
}

type Post  {
    id: ID!
    reviews: [Review]
}

type Review {
   id: ID!
   postId: ID!
   comment: String!
}

type Query {
    getReview(id: ID!): Review
}
```

Cuando se produzca la fusión, el resultado generará el archivo `MergedSchema.graphql`:

```
# This snippet represents a file called MergedSchema.graphql

type Mutation {
    putReview(id: ID!, postId: ID!, comment: String!): Review
    putPost(id: ID!, title: String!): Post
}

type Post  {
    id: ID!
    title: String!
    reviews: [Review]
}

type Review {
   id: ID!
   postId: ID!
   comment: String!
}

type Query {
    getPost(id: ID!): Post
    getReview(id: ID!): Review
}
```

En la fusión ocurrieron varias cosas:
+ Con el tipo `Mutation` no se produjo ningún conflicto y este se fusionó.
+ Los campos del tipo `Post` se combinaron con una operación de unión. Observe que la unión entre los dos generó un único `id`, un `title` y una única `reviews`.
+ Con el tipo `Review` no se produjo ningún conflicto y este se fusionó.
+ Con el tipo `Query` no se produjo ningún conflicto y este se fusionó.

### Administración de solucionadores en tipos compartidos
<a name="resolvers-shared-types-merged-api"></a>

En el ejemplo anterior, consideremos el caso en el que *Source1.graphql* ha configurado un solucionador de unidades en `Query.getPost`, que utiliza un origen de datos de DynamoDB denominado `PostDatasource`. Este solucionador devolverá el `id` y el `title` de un tipo `Post`. Ahora, consideremos que *Source2.graphql* ha configurado un solucionador de canalización en `Post.reviews` que ejecuta dos funciones. `Function1` tiene un origen de datos `None` adjunto para realizar comprobaciones de autorización personalizadas. `Function2` tiene un origen de datos de DynamoDB asociado para consultar la tabla `reviews`.

```
query GetPostQuery {
    getPost(id: "1") {
        id,
        title,
        reviews
    }
}
```

Cuando un cliente ejecuta la consulta anterior en el punto final de la API Merged, el AWS AppSync servicio ejecuta primero la unidad de resolución for `Query.getPost` from`Source1`, que llama a DynamoDB `PostDatasource` y devuelve los datos de DynamoDB. A continuación, ejecuta el solucionador de canalizaciones de `Post.reviews`, en el cual `Function1` ejecuta una lógica de autorización personalizada y `Function2` devuelve las revisiones en función del `id` encontrado en `$context.source`. El servicio procesa la solicitud como una sola ejecución de GraphQL, y esta solicitud sencilla requiere un único token de solicitud.

### Gestión de conflictos de solucionadores en tipos compartidos
<a name="resolver-conflict-shared-type-merged-api"></a>

Veamos el caso siguiente, en el que también implementamos un solucionador en `Query.getPost` para proporcionar varios campos a la vez además del solucionador de campo en `Source2`. *Source1.graphql* sería parecido a esto:

```
# This snippet represents a file called Source1.graphql

type Post  {
    id: ID!
    title: String!
    date: AWSDateTime!
}

type Query {
    getPost(id: ID!): Post
}
```

*Source2.graphql* sería parecido a esto:

```
# This snippet represents a file called Source2.graphql

type Post  {
  id: ID!
  content: String!
  contentHash: String! 
  author: String! 
}

type Query {
    getPost(id: ID!): Post
}
```

Si se intenta combinar estos dos esquemas, se generará un error de combinación, ya que AWS AppSync Merged APIs no permite adjuntar varias resoluciones de origen al mismo campo. Para resolver este conflicto, puede implementar un patrón de solucionador de campo que obligaría a *Source2.graphql* a agregar un tipo diferente que defina los campos del tipo `Post` que le pertenecen. En el siguiente ejemplo, agregamos un tipo denominado `PostInfo`, que contiene los campos de contenido y de autor que resolverá *Source2.graphql*. *Source1.graphql* implementará el solucionador asociado a `Query.getPost`, mientras que *Source2.graphql* asociará ahora un solucionador a `Post.postInfo` para garantizar que todos los datos se puedan recuperar correctamente:

```
type Post  {
  id: ID!
  postInfo: PostInfo
}

type PostInfo {
   content: String!
   contentHash: String!
   author: String!
}

type Query {
    getPost(id: ID!): Post
}
```

Si bien la resolución de este tipo de conflicto requiere que se reescriban los esquemas de las API de origen y, posiblemente, que los clientes cambien sus consultas, la ventaja de este enfoque es que la propiedad de los solucionadores fusionados queda clara entre los equipos de origen.

## Configuración de esquemas
<a name="configuring-schemas-merged-api"></a>

Hay dos partes responsables de configurar los esquemas para crear una API fusionada:
+ **Propietarios de las API fusionadas**: los propietarios de las API fusionadas deben configurar la lógica de autorización de la API fusionada y los ajustes avanzados, como el registro, el seguimiento, el almacenamiento en caché y la compatibilidad con el WAF.
+ **Propietarios de las API de origen asociadas**: los propietarios de las API asociadas deben configurar los esquemas, los solucionadores y los orígenes de datos que componen la API fusionada.

**Como el esquema de la API combinada se crea a partir de los esquemas de la fuente asociada APIs, es de solo lectura.** Esto significa que los cambios en el esquema deben iniciarse en tu fuente APIs. En la AWS AppSync consola, puedes cambiar entre el esquema combinado y los esquemas individuales de la fuente APIs incluida en la API combinada mediante la lista desplegable situada encima de la ventana del **esquema**.

## Configuración de modos de autorización
<a name="configuring-authorization-merged-api"></a>

Hay varios modos de autorización disponibles para proteger su API fusionada. Para obtener más información sobre los modos de autorización AWS AppSync, consulta [Autorización y autenticación](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html).

Los siguientes modos de autorización están disponibles para su uso con Merged APIs:
+  **Clave de la API**: la estrategia de autorización más sencilla. Todas las solicitudes deben incluir una clave de la API en el encabezado de la solicitud `x-api-key`. Las claves de la API vencidas se conservan durante 60 días después de la fecha de vencimiento. 
+  **AWS Identity and Access Management (IAM): la** **estrategia de autorización de AWS IAM autoriza todas las solicitudes firmadas mediante sigv4.** 
+  **Grupos de usuarios de Amazon Cognito**: autorice a sus usuarios a través de los grupos de usuarios de Amazon Cognito para lograr un control más detallado. 
+  **AWS Autorizadores Lambda**: función sin servidor que permite autenticar y autorizar el acceso a la API mediante una lógica personalizada AWS AppSync .
+ **OpenID Connect**: este tipo de autorización aplica tókenes de OpenID Connect (OIDC) proporcionados por un servicio compatible con OIDC. Su aplicación puede aprovechar los usuarios y los privilegios definidos por su proveedor OIDC para controlar el acceso.

Los modos de autorización de una API fusionada los configura el propietario de la API fusionada. Al llevar a cabo una operación de fusión, la API fusionada debe incluir el modo de autorización principal configurado en una API de origen, ya sea como su propio modo de autorización principal o como modo de autorización secundario. De lo contrario, será incompatible, la operación de fusión producirá un error y se generará un conflicto. Cuando se utilizan directivas de autenticación múltiple en la fuente APIs, el proceso de fusión puede combinar automáticamente estas directivas en el punto final unificado. Si el modo de autorización principal de la API de origen no coincide con el modo de autorización principal de la API fusionada, este agregará automáticamente estas directivas de autorización para garantizar que el modo de autorización de los tipos de la API de origen sea coherente.

## Configuración de roles de ejecución
<a name="execution-roles-merged-api"></a>

Al crear una API fusionada, es necesario definir un rol de servicio. Un rol de AWS servicio es un rol de AWS Identity and Access Management (IAM) que utilizan los AWS servicios para realizar tareas en su nombre.

En este contexto, es necesario que la API combinada ejecute resolutores que accedan a los datos de las fuentes de datos configuradas en la fuente. APIs El rol de servicio necesario para ello es el`mergedApiExecutionRole`, y debe tener acceso explícito para ejecutar las solicitudes en la fuente APIs incluida en la API fusionada mediante el permiso de `appsync:SourceGraphQL` IAM. Durante la ejecución de una solicitud de GraphQL, el AWS AppSync servicio asumirá este rol de servicio y lo autorizará a realizar la `appsync:SourceGraphQL` acción.

AWS AppSync permite permitir o denegar este permiso en campos específicos de nivel superior de la solicitud, por ejemplo, cómo funciona el modo de autorización de IAM para IAM. APIs Para non-top-level los campos, AWS AppSync requiere que definas el permiso en el propio ARN de la API de origen. Para restringir el acceso a non-top-level campos específicos de la API fusionada, te recomendamos implementar una lógica personalizada en tu Lambda u ocultar los campos de la API de origen de la API fusionada mediante la directiva *@hidden*. Si quiere permitir que el rol realice todas las operaciones de datos dentro de una API de origen, puede agregar la política que se indica a continuación. Tenga en cuenta que la primera entrada de recursos permite el acceso a todos los campos de nivel superior y la segunda incluye los solucionadores secundarios que autorizan en el propio recurso de la API de origen: 

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [{
        "Effect": "Allow", 
        "Action": [ "appsync:SourceGraphQL"], 
        "Resource": [ 
            "arn:aws:appsync:us-west-2:123456789012:apis/YourSourceGraphQLApiId/*", 
            "arn:aws:appsync:us-west-2:123456789012:apis/YourSourceGraphQLApiId"] 
    }] 
}
```

------

Si quiere limitar el acceso únicamente a un campo de nivel superior específico, puede usar una política como esta:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [{
        "Effect": "Allow", 
        "Action": [ "appsync:SourceGraphQL"], 
        "Resource": [ 
            "arn:aws:appsync:us-west-2:123456789012:apis/YourSourceGraphQLApiId/types/Query/fields/<Field-1>",
            "arn:aws:appsync:us-west-2:123456789012:apis/YourSourceGraphQLApiId"] 
    }] 
}
```

------

También puedes usar el asistente de creación de la API de la AWS AppSync consola para generar un rol de servicio que permita a la API fusionada acceder a los recursos configurados en la fuente APIs que se encuentran en la misma cuenta que la API fusionada. En el caso de que su fuente no APIs esté en la misma cuenta que la API fusionada, primero debe compartir sus recursos mediante AWS Resource Access Manager (AWS RAM). 

## Configuración de varias cuentas: Merged usando APIs AWS RAM
<a name="cross-account-merged-api"></a>

Al crear una API combinada, si lo desea, puede asociar la fuente APIs de otras cuentas que se hayan compartido mediante AWS Resource Access Manager (AWS RAM). AWS RAM le ayuda a compartir sus recursos de forma segura entre AWS las cuentas, dentro de su organización o unidades organizativas (OUs) y con los roles y usuarios de IAM.

AWS AppSync se integra con AWS RAM para permitir la configuración y el acceso a la fuente APIs en varias cuentas desde una única API fusionada. AWS RAM permite crear un recurso compartido o un contenedor de recursos y los conjuntos de permisos que se compartirán para cada uno de ellos. Puede añadir recursos AWS AppSync APIs a un recurso compartido en AWS RAM. Dentro de un recurso compartido, AWS AppSync proporciona tres conjuntos de permisos diferentes que se pueden asociar a una AWS AppSync API en la RAM:

1. `AWSRAMPermissionAppSyncSourceApiOperationAccess`: el conjunto de permisos predeterminado que se añade al compartir una AWS AppSync API AWS RAM si no se especifica ningún otro permiso. Este conjunto de permisos se utiliza para compartir una AWS AppSync API de origen con el propietario de una API fusionada. Este conjunto de permisos incluye el permiso `appsync:AssociateMergedGraphqlApi` en la API de origen, así como el permiso `appsync:SourceGraphQL` necesario para acceder a los recursos de la API de origen en tiempo de ejecución.

1. `AWSRAMPermissionAppSyncMergedApiOperationAccess`: este conjunto de permisos debe configurarse al compartir una API fusionada con el propietario de una API de origen. Este conjunto de permisos permitirá a la API de origen configurar la API fusionada, incluida la posibilidad de asociar cualquier fuente que sea APIs propiedad del principal de destino a la API fusionada y de leer y actualizar las asociaciones de la API de origen de la API fusionada.

1. `AWSRAMPermissionAppSyncAllowSourceGraphQLAccess`: Este conjunto de permisos permite utilizar el `appsync:SourceGraphQL` permiso con una AWS AppSync API. La finalidad prevista de este permiso es la de compartir una API de origen con el propietario de una API fusionada. A diferencia del conjunto de permisos predeterminado para el acceso a las operaciones de la API de origen, este conjunto de permisos solo incluye el permiso de tiempo de ejecución `appsync:SourceGraphQL`. Si un usuario opta por compartir el acceso a la operación de la API fusionada con el propietario de la API de origen, también tendrá que compartir este permiso de la API de origen con el propietario de la API fusionada para tener acceso en tiempo de ejecución a través del punto de conexión de la API fusionada.

AWS AppSync también es compatible con los permisos gestionados por el cliente. Si uno de los permisos AWS administrados proporcionados no funciona, puedes crear tu propio permiso administrado por el cliente. Los permisos gestionados por el cliente son permisos gestionados que usted crea y mantiene especificando con precisión qué acciones se pueden realizar y en qué condiciones con los recursos que se comparten. AWS RAM AWS AppSync le permite elegir entre las siguientes acciones al crear su propio permiso:

1. `appsync:AssociateSourceGraphqlApi`

1. `appsync:AssociateMergedGraphqlApi`

1. `appsync:GetSourceApiAssociation`

1. `appsync:UpdateSourceApiAssociation`

1. `appsync:StartSchemaMerge`

1. `appsync:ListTypesByAssociation`

1. `appsync:SourceGraphQL`

Una vez que hayas compartido correctamente una API de origen o una API fusionada AWS RAM y, si es necesario, hayas aceptado la invitación a compartir recursos, estará visible en la AWS AppSync consola cuando crees o actualices las asociaciones de API de origen en tu API fusionada. También puedes hacer una lista de todas las AWS AppSync APIs que se han compartido AWS RAM con tu cuenta, independientemente del permiso establecido, llamando a la `ListGraphqlApis` operación proporcionada por el propietario AWS AppSync y utilizando el filtro `OTHER_ACCOUNTS` propietario. 

**nota**  
Para compartir a AWS RAM través de ella, la persona AWS RAM que llama debe tener permiso para realizar la `appsync:PutResourcePolicy` acción en cualquier API que se esté compartiendo. 

## Fusión
<a name="merges"></a>

### Administración de fusiones
<a name="managing-merges"></a>

El objetivo de APIs las fusiones es facilitar la colaboración en equipo en un AWS AppSync punto final unificado. Los equipos pueden desarrollar de forma independiente su propio GraphQL de origen aislado APIs en el backend, mientras que el AWS AppSync servicio gestiona la integración de los recursos en el único punto final de la API combinada para reducir la fricción en la colaboración y reducir los plazos de desarrollo.

### Fusiones automáticas
<a name="auto-merge"></a>

La fuente APIs asociada a tu API AWS AppSync fusionada se puede configurar para que se fusione automáticamente (se fusione automáticamente) en la API fusionada después de realizar cualquier cambio en la API de origen. Esto garantiza que los cambios en la API de origen siempre se propaguen al punto de conexión de la API fusionada en segundo plano. Cualquier cambio en el esquema de la API de origen se actualizará en la API fusionada siempre y cuando no genere un conflicto de fusión con una definición existente en la API fusionada. Si la actualización de la API de origen actualiza un solucionador, un origen de datos o una función, también se actualizará el recurso importado. Cuando se introduce un nuevo conflicto que no se puede resolver automáticamente (resolución automática), se rechaza la actualización del esquema de la API fusionada debido a un conflicto no admitido durante la operación de fusión. El mensaje de error está disponible en la consola para cada asociación de la API de origen cuyo estado sea `MERGE_FAILED`. También puedes inspeccionar el mensaje de error llamando a la `GetSourceApiAssociation` operación de una asociación de API de origen determinada mediante el AWS SDK o la AWS CLI de la siguiente manera:

```
aws appsync get-source-api-association --merged-api-identifier <Merged API ARN> --association-id <SourceApiAssociation id>
```

Esto generará un resultado con el formato siguiente:

```
{
    "sourceApiAssociation": {
        "associationId": "<association id>",
        "associationArn": "<association arn>",
        "sourceApiId": "<source api id>",
        "sourceApiArn": "<source api arn>",
        "mergedApiArn": "<merged api arn>",
        "mergedApiId": "<merged api id>",
        "sourceApiAssociationConfig": {
            "mergeType": "MANUAL_MERGE"
        },
        "sourceApiAssociationStatus": "MERGE_FAILED",
        "sourceApiAssociationStatusDetail": "Unable to resolve conflict on object with name title: Merging is not supported for fields with different types."
    }
}
```

### Fusiones manuales
<a name="manual-merges"></a>

La configuración predeterminada de una API de origen es una fusión manual. Para combinar cualquier cambio que se haya producido en la fuente APIs desde la última actualización de la API combinada, el propietario de la API de origen puede invocar una fusión manual desde la AWS AppSync consola o mediante la `StartSchemaMerge` operación disponible en el AWS SDK y la AWS CLI.

## Soporte adicional para Merged APIs
<a name="merge-api-additional-support"></a>

### Configuración de suscripciones
<a name="config-subscription"></a>

A diferencia de los enfoques basados en enrutadores para la composición de esquemas de GraphQL, AWS AppSync Merged APIs proporciona soporte integrado para las suscripciones de GraphQL. Todas las operaciones de suscripción definidas en la fuente asociada se APIs fusionarán automáticamente y funcionarán en la API fusionada sin necesidad de modificarlas. Para obtener más información sobre cómo se AWS AppSync admiten las suscripciones mediante una WebSockets conexión sin servidor, consulta [Datos en tiempo real](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-data.html).

### Configuración de la observabilidad
<a name="config-observability"></a>

AWS AppSync APIs Los fusionados proporcionan registros, monitoreo y métricas integrados a través de [Amazon CloudWatch](https://docs.aws.amazon.com/appsync/latest/devguide/monitoring.html). AWS AppSync también proporciona soporte integrado para el rastreo mediante [AWS X-Ray](https://docs.aws.amazon.com/appsync/latest/devguide/x-ray-tracing.html). 

### Configuración de dominios personalizados
<a name="config-custom-domain"></a>

AWS AppSync Merged APIs proporciona soporte integrado para el uso de dominios personalizados con los puntos de enlace [GraphQL y Real-Time](https://docs.aws.amazon.com/appsync/latest/devguide/custom-domain-name.html) de su API Merged. 

### Configuración del almacenamiento en caché
<a name="config-caching"></a>

AWS AppSync Merged APIs ofrece soporte integrado para almacenar en caché, de forma opcional, las respuestas a nivel de solicitud o a nivel de resolución, así como para la compresión de respuestas. Para obtener más información, consulte [Almacenamiento en caché y compresión](https://docs.aws.amazon.com/appsync/latest/devguide/enabling-caching.html). 

### Configuración privada APIs
<a name="config-private-api"></a>

AWS AppSync Merged APIs proporciona compatibilidad integrada con Private, APIs que limita el acceso a los puntos de enlace GraphQL y en tiempo real de la API combinada al tráfico que se origina en los puntos de enlace de la [VPC que puede configurar.](https://docs.aws.amazon.com/appsync/latest/devguide/using-private-apis.html) 

### Configuración de reglas de firewall
<a name="config-firewall"></a>

AWS AppSync Merged APIs ofrece soporte integrado para AWS WAF, lo que te permite proteger tus aplicaciones APIs mediante la definición de reglas de firewall para aplicaciones [web](https://docs.aws.amazon.com/appsync/latest/devguide/WAF-Integration.html). 

### Configuración de registros de auditoría
<a name="config-audit"></a>

AWS AppSync Merged APIs ofrece soporte integrado para AWS CloudTrail, lo que le permite [configurar y gestionar los registros de auditoría](https://docs.aws.amazon.com/appsync/latest/devguide/cloudtrail-logging.html). 

## Limitaciones de las API fusionadas
<a name="merged-api-limits"></a>

Al desarrollar Merged APIs, tenga en cuenta las siguientes reglas:

1. Una API fusionada no puede ser una API de origen para otra API fusionada.

1. Una API de origen no se puede asociar a más de una API fusionada.

1. El límite de tamaño predeterminado para un documento de esquema de API fusionada es de 10 MB.

1. El número predeterminado de fuentes APIs que se pueden asociar a una API fusionada es 10. Sin embargo, puedes solicitar un aumento del límite si necesitas más de 10 fuentes APIs en tu API fusionada.

## Consideraciones sobre la API fusionada
<a name="merged-api-considerations"></a>

Al diseñar e implementar Merged APIs, tenga en cuenta lo siguiente:

La fusión de varias fuentes APIs en un único punto final puede aumentar el tamaño y la complejidad del esquema y las consultas de GraphQL. A medida que el esquema fusionado crezca, es posible que las consultas deban pasar por varios solucionadores para cumplir con una sola solicitud, lo que puede añadir latencia al tiempo total de solicitud. Por ejemplo, una consulta que accede AWS AppSync a campos de varias fuentes APIs puede requerir ejecutar los resolutores desde cada API de origen de forma secuencial, y cada resolución se suma al tiempo total de respuesta.

Le recomendamos encarecidamente que pruebe APIs minuciosamente su Merged durante el desarrollo y en condiciones de carga realistas para asegurarse de que cumple con los requisitos de su empresa. Presta especial atención a:
+ La profundidad y la complejidad del esquema combinado, en particular las consultas que acceden a campos de varias fuentes APIs.
+ La cantidad de resolutores que se deben ejecutar para cumplir con los patrones de consulta comunes.
+ Las características de rendimiento de las fuentes de datos y los resolutores en condiciones de carga esperadas.
+ El impacto de la latencia de la red al acceder a los recursos de varias fuentes APIs.

Considere implementar optimizaciones de rendimiento, como el almacenamiento en caché, la agrupación por lotes de las solicitudes de fuentes de datos y el diseño de sus esquemas de API de origen para minimizar la cantidad de ejecuciones de resolución necesarias para las operaciones comunes.

## Creación de Merged APIs
<a name="creating-merged-api"></a>

**Para crear una API fusionada en la consola**

1. Inicie sesión en la [AWS AppSync consola Consola de administración de AWS y ábrala](https://console.aws.amazon.com/appsync/).

   1. En el **Panel**, elija **Crear API**.

1. Seleccione **API fusionada** y, a continuación, **Siguiente**.

1. En la página **Especificar los detalles de la API**, introduzca la información siguiente: 

   1. En **Detalles de API**, escriba la información siguiente:

      1. Especifique el **Nombre de API** de su API fusionada. Este campo es una forma de etiquetar tu API de GraphQL para distinguirla cómodamente de otras aplicaciones de GraphQL. APIs 

      1. Especifique los **Datos de contacto**. Este campo es opcional y adjunta un nombre o grupo a la API de GraphQL. No está vinculado a otros recursos ni es generado por ellos, y funciona de forma muy parecida al campo de nombre de la API. 

   1. En **Función de servicio**, debes asignar una función de ejecución de IAM a la API fusionada para poder importar y utilizar tus recursos de forma segura en tiempo de ejecución. AWS AppSync Puede optar por **crear y usar un nuevo rol de servicio**, lo que le permitirá especificar las políticas y los recursos que AWS AppSync utilizará. También puede importar un rol de IAM existente seleccionando **Usar un rol de servicio existente** y, a continuación, seleccionando el rol en la lista desplegable. 

   1. En **Configuración de API privada**, puede optar por habilitar las características de API privadas. Tenga en cuenta que esta opción no se puede cambiar después de crear la API fusionada. Para obtener más información acerca de lo privado APIs, consulte [Uso de lo AWS AppSync privado APIs](https://docs.aws.amazon.com/appsync/latest/devguide/using-private-apis.html). 

      Cuando haya terminado, elija **Siguiente**. 

1. A continuación, debes añadir el GraphQL APIs que se utilizará como base para la API fusionada. En la APIs página **Seleccionar fuente**, introduce la siguiente información: 

   1. En la tabla **APIs de su AWS cuenta**, seleccione **Añadir fuente APIs**. En la lista de GraphQL APIs, cada entrada contendrá los siguientes datos:

      1. **Nombre**: el campo de **nombre de la API** de la API de GraphQL. 

      1. **ID de la API**: el valor de ID único de la API de GraphQL.

      1. **Modo de autorización principal**: el modo de autorización predeterminado para la API de GraphQL. Para obtener más información sobre los modos de autorización en AWS AppSync, consulte [Autorización y autenticación](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html). 

      1. **Modos de autorización adicionales**: los modos de autorización secundarios que se configuraron en la API de GraphQL.

      1. Selecciona la APIs que utilizarás en la API fusionada. Para ello, selecciona la casilla de verificación situada junto al campo **Nombre** de la API. A continuación, selecciona **Añadir fuente APIs**. El GraphQL seleccionado APIs aparecerá en la tabla **APIs de tus AWS cuentas**.

   1. En la tabla **APIs de otras AWS cuentas**, selecciona **Añadir fuente APIs**. Los GraphQL APIs de esta lista provienen de otras cuentas que comparten sus recursos con la tuya a través de AWS Resource Access Manager ()AWS RAM. El proceso para seleccionar GraphQL APIs en esta tabla es el mismo que en la sección anterior. Para obtener más información sobre cómo compartir recursos AWS RAM, consulte [¿Qué es? AWS Resource Access Manager](https://docs.aws.amazon.com/ram/latest/userguide/what-is.html) .

      Cuando haya terminado, elija **Siguiente**.

   1. Agregue su modo de autenticación principal. Para obtener más información, consulte [Autorización y autenticación](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html). Seleccione **Siguiente**.

   1. Revise la información indicada y, a continuación, seleccione **Crear API**.

# Creación de GraphQL APIs con introspección de RDS
<a name="rds-introspection"></a>

Su utilidad de introspección de AWS AppSync puede descubrir modelos a partir de tablas de bases de datos y proponer tipos de GraphQL. El asistente de creación de API de la AWS AppSync consola puede generar instantáneamente una API a partir de una base de datos Aurora MySQL o PostgreSQL. Crea automáticamente tipos y JavaScript resolutores para leer y escribir datos.

AWS AppSync proporciona una integración directa con las bases de datos de Amazon Aurora a través de la API de datos de Amazon RDS. En lugar de requerir una conexión de base de datos persistente, la API de datos de Amazon RDS ofrece un punto de enlace HTTP seguro al que AWS AppSync se conecta para ejecutar SQL sentencias. Puede utilizarlo para crear una API de base de datos relacional para sus cargas de trabajo de MySQL y PostgreSQL en Aurora.

La creación de una API para su base de datos relacional AWS AppSync tiene varias ventajas:
+ Su base de datos no está expuesta directamente a los clientes, lo que desacopla el punto de acceso de la propia base de datos. 
+ Puede crear aplicaciones diseñadas específicamente para APIs adaptarse a las necesidades de las diferentes aplicaciones, lo que elimina la necesidad de una lógica empresarial personalizada en las interfaces de usuario. Esto se alinea con el patrón Backend-For-Frontend (BFF). 
+ La autorización y el control de acceso se pueden implementar en la AWS AppSync capa utilizando varios modos de autorización para controlar el acceso. No se requieren recursos informáticos adicionales para conectarse a la base de datos, como alojar un servidor web o establecer conexiones mediante proxy. 
+ Las capacidades en tiempo real se pueden añadir mediante suscripciones, y las mutaciones de datos AppSync se envían automáticamente a los clientes conectados. 
+ Los clientes pueden conectarse a la API a través de HTTPS mediante puertos comunes, como el 443.

AWS AppSync facilita la creación APIs a partir de bases de datos relacionales existentes. Su utilidad de introspección puede descubrir modelos a partir de tablas de bases de datos y proponer tipos de GraphQL. El asistente *Creación de API* de la consola de AWS AppSync puede generar una API al instante a partir de una base de datos Aurora MySQL o PostgreSQL. Crea automáticamente tipos y JavaScript resolutores para leer y escribir datos. 

AWS AppSync proporciona JavaScript utilidades integradas para simplificar la escritura de sentencias SQL en los resolutores. Puede utilizar las plantillas AWS AppSync de `sql` etiquetas para sentencias estáticas con valores dinámicos o las utilidades del `rds` módulo para crear sentencias mediante programación. Para obtener más información, consulte los orígenes de datos [Referencia a la función de solucionador para RDS](https://docs.aws.amazon.com//appsync/latest/devguide/resolver-reference-rds-js.html) y los [módulos integrados](https://docs.aws.amazon.com//appsync/latest/devguide/built-in-modules-js.html#built-in-rds-modules). 

## Uso de la característica de introspección (consola)
<a name="using-introspection-console"></a>

Para ver un tutorial detallado y una guía de introducción, consulte [Tutorial: Aurora PostgreSQL sin servidor con API de datos](https://docs.aws.amazon.com//appsync/latest/devguide/aurora-serverless-tutorial-js.html). 

La AWS AppSync consola le permite crear una API AWS AppSync GraphQL a partir de su base de datos Aurora existente configurada con la API de datos en solo unos minutos. Esto genera rápidamente un esquema operativo basado en la configuración de la base de datos. Puede usar la API tal cual o desarrollarla para añadir características. 

1. Inicie sesión en la [AppSyncconsola Consola de administración de AWS](https://console.aws.amazon.com/appsync/) y ábrala.

   1. En el **Panel**, elija **Crear API**.

1. **En **Opciones de API**, selecciona **GraphQL APIs**, **Comience con un clúster de Amazon Aurora** y, a continuación, Siguiente.**

   1. Escriba un **Nombre de API**. Se utilizará como identificador de la API en la consola.

   1. Para obtener **los detalles de contacto**, puede introducir un punto de contacto para identificar al administrador de la API. Se trata de un campo opcional.

   1. En **Configuración de API privada**, puede habilitar las características de API privadas. Solo se puede acceder a una API privada desde un punto de conexión de VPC (VPCE) configurado. Para obtener más información, consulte [Privado APIs](https://docs.aws.amazon.com//appsync/latest/devguide/using-private-apis.html).

      No le recomendamos habilitar esta característica para este ejemplo. Seleccione **Siguiente** después de revisar sus entradas.

1. En la página **Base de datos**, elija **Seleccionar base de datos**.

   1. Es necesario elegir la base de datos de su clúster. El primer paso es elegir la **región** en la que se encuentra el clúster.

   1. Elija el **clúster de Aurora** en la lista desplegable. Tenga en cuenta que debe haber creado y [habilitado](https://docs.aws.amazon.com//AmazonRDS/latest/AuroraUserGuide/data-api.html#data-api.enabling) la API de datos correspondiente antes de utilizar el recurso.

   1. A continuación, debe añadir las credenciales de la base de datos al servicio. Esto se hace principalmente usando AWS Secrets Manager. Elija la **región** en la que se encuentra su secreto. Para obtener más información sobre cómo recuperar información del secreto, consulte [Buscar secretos](https://docs.aws.amazon.com//secretsmanager/latest/userguide/manage_search-secret.html) o [Recuperar secretos](https://docs.aws.amazon.com//secretsmanager/latest/userguide/retrieving-secrets.html).

   1. Añada su secreto en la lista desplegable. Tenga en cuenta que el usuario debe tener [permisos de lectura](https://docs.aws.amazon.com//AmazonRDS/latest/UserGuide/security_iam_id-based-policy-examples.html#security_iam_id-based-policy-examples-console) para su base de datos.

1. Seleccione **Importar**.

   AWS AppSync empezará a inspeccionar su base de datos, descubriendo tablas, columnas, claves principales e índices. Comprueba que las tablas descubiertas se pueden admitir en una API de GraphQL. Tenga en cuenta que para permitir la creación de nuevas filas, las tablas necesitan una clave principal, que puede utilizar varias columnas. AWS AppSync asigna las columnas de la tabla a los campos de texto de la siguiente manera:     
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/es_es/appsync/latest/devguide/rds-introspection.html)

1. Una vez que se haya completado la detección de tablas, la sección **Base de datos** se rellenará con su información. En la nueva sección **Tablas de base de datos**, es posible que los datos de la tabla ya estén rellenados y convertidos a un tipo para su esquema. Si no ve algunos de los datos necesarios, puede comprobarlos. Para ello, seleccione **Añadir tablas**, haga clic en las casillas de verificación de esos tipos en el modal que aparece y, a continuación, seleccione **Añadir**. 

   Para eliminar un tipo de la sección **Tablas de bases de datos**, haga clic en la casilla de verificación situada junto al tipo que desea eliminar y, a continuación, seleccione **Eliminar**. Los tipos eliminados se colocarán en el modal **Añadir tablas** si desea volver a añadirlos más adelante.

   Tenga en cuenta que AWS AppSync utiliza los nombres de las tablas como nombres de tipos, pero puede cambiarles el nombre, por ejemplo, cambiando un nombre de tabla plural por el nombre *Movie* del tipo. *movies* Para cambiar el nombre de un tipo en la sección **Tablas de bases de datos**, haga clic en la casilla de verificación del tipo al que desee cambiar el nombre y, a continuación, haga clic en el icono del *lápiz* en la columna **Nombre del tipo**.

   Para obtener una vista previa del contenido del esquema en función de sus selecciones, elija **Vista previa del esquema**. Tenga en cuenta que este esquema no puede estar vacío, por lo que tendrá al menos una tabla convertida en un tipo. Además, este esquema no puede tener un tamaño superior a 1 MB.

   1. En **Rol de servicio**, elija si desea crear un nuevo rol de servicio específicamente para esta importación o utilizar un rol existente.

1. Elija **Siguiente**.

1. A continuación, elija si desea crear una API de solo lectura (solo consultas) o una API para leer y escribir datos (con consultas y mutaciones). Esta última también admite suscripciones en tiempo real activadas por mutaciones. 

1. Elija **Siguiente**.

1. Revise sus opciones y, a continuación, seleccione **Crear API**. AWS AppSync creará la API y adjuntará los solucionadores a las consultas y mutaciones. La API generada es totalmente operativa y se puede ampliar según sea necesario. 

## Uso de la característica de introspección (API)
<a name="using-introspection-api"></a>

Puede usar la API de introspección `StartDataSourceIntrospection` para descubrir modelos en su base de datos mediante programación. Para obtener más información sobre el comando, consulte el uso de la API [https://docs.aws.amazon.com//appsync/latest/APIReference/API_StartDataSourceIntrospection.html](https://docs.aws.amazon.com//appsync/latest/APIReference/API_StartDataSourceIntrospection.html). 

Para usarlo`StartDataSourceIntrospection`, proporcione el nombre de recurso de Amazon (ARN), el nombre de la base de datos y AWS Secrets Manager el ARN secreto del clúster Aurora. El comando inicia el proceso de introspección. Puede recuperar los resultados con el comando `GetDataSourceIntrospection`. Puede especificar si el comando debe devolver la cadena de lenguaje de definición de almacenamiento (SDL) de los modelos descubiertos. Esto resulta útil para generar una definición de esquema de SDL directamente a partir de los modelos descubiertos.

 Por ejemplo, si tiene la siguiente instrucción de lenguaje de definición de datos (DDL) para una tabla `Todos` sencilla:

```
create table if not exists public.todos  
(  
id serial constraint todos_pk primary key,  
description text,  
due timestamp,  
"createdAt" timestamp default now()  
);
```

Comience la introspección con lo siguiente.

```
aws appsync start-data-source-introspection \ 
  --rds-data-api-config resourceArn=<cluster-arn>,secretArn=<secret-arn>,databaseName=database
```

A continuación, utilice el comando `GetDataSourceIntrospection` para recuperar el resultado.

```
aws appsync get-data-source-introspection \
  --introspection-id a1234567-8910-abcd-efgh-identifier \
  --include-models-sdl
```

Esto devuelve el resultado siguiente.

```
{
    "introspectionId": "a1234567-8910-abcd-efgh-identifier",
    "introspectionStatus": "SUCCESS",
    "introspectionStatusDetail": null,
    "introspectionResult": {
        "models": [
            {
                "name": "todos",
                "fields": [
                    {
                        "name": "description",
                        "type": {
                            "kind": "Scalar",
                            "name": "String",
                            "type": null,
                            "values": null
                        },
                        "length": 0
                    },
                    {
                        "name": "due",
                        "type": {
                            "kind": "Scalar",
                            "name": "AWSDateTime",
                            "type": null,
                            "values": null
                        },
                        "length": 0
                    },
                    {
                        "name": "id",
                        "type": {
                            "kind": "NonNull",
                            "name": null,
                            "type": {
                                "kind": "Scalar",
                                "name": "Int",
                                "type": null,
                                "values": null
                            },
                            "values": null
                        },
                        "length": 0
                    },
                    {
                        "name": "createdAt",
                        "type": {
                            "kind": "Scalar",
                            "name": "AWSDateTime",
                            "type": null,
                            "values": null
                        },
                        "length": 0
                    }
                ],
                "primaryKey": {
                    "name": "PRIMARY_KEY",
                    "fields": [
                        "id"
                    ]
                },
                "indexes": [],
                "sdl": "type todos\n{\ndescription: String\n\ndue: AWSDateTime\n\nid: Int!\n\ncreatedAt: AW
SDateTime\n}\n"
            }
        ],
        "nextToken": null
    }
}
```