

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.

# AWS AppSync referencia de plantilla de mapeo de resolución para Lambda
<a name="resolver-mapping-template-reference-lambda"></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/resolver-reference-js-version.html).

Puede usar AWS AppSync funciones y resolutores para invocar las funciones de Lambda ubicadas en su cuenta. Puede configurar las cargas útiles de sus solicitudes y la respuesta de sus funciones de Lambda antes de devolverlas a sus clientes. También puede utilizar plantillas de mapeo para dar pistas AWS AppSync sobre la naturaleza de la operación que se va a invocar. En esta sección se describen las distintas plantillas de mapeo para las operaciones de Lambda admitidas.

## Plantilla de mapeo de solicitudes
<a name="request-mapping-template"></a>

La plantilla de mapeo de solicitudes de Lambda gestiona los campos relacionados con la función de Lambda:

```
{
  "version": string,
  "operation": Invoke|BatchInvoke,
  "payload": any type,
  "invocationType": RequestResponse|Event
}
```

A continuación, se muestra un ejemplo de esquema JSON de la plantilla de mapeo de solicitudes de Lambda una vez resuelta:

```
{
  "definitions": {},
  "$schema": "https://json-schema.org/draft-06/schema#",
  "$id": "https://aws.amazon.com/appsync/request-mapping-template.json",
  "type": "object",
  "properties": {
    "version": {
      "$id": "/properties/version",
      "type": "string",
      "enum": [
        "2018-05-29"
      ],
      "title": "The Mapping template version.",
      "default": "2018-05-29"
    },
    "operation": {
      "$id": "/properties/operation",
      "type": "string",
      "enum": [
        "Invoke",
        "BatchInvoke"
      ],
      "title": "The Mapping template operation.",
      "description": "What operation to execute.",
      "default": "Invoke"
    },
    "payload": {},
    "invocationType": {
      "$id": "/properties/invocationType",
      "type": "string",
      "enum": [
        "RequestResponse",
        "Event"
      ],
      "title": "The Mapping template invocation type.",
      "description": "What invocation type to execute.",
      "default": "RequestResponse"
    }
  },
  "required": [
    "version",
    "operation"
  ],
  "additionalProperties": false
}
```

A continuación, se muestra un ejemplo en el que se usa una operación `invoke` cuyos datos de carga útil son el campo `getPost` de un esquema de GraphQL junto con sus argumentos del contexto:

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
  "payload": {
    "field": "getPost",
    "arguments": $util.toJson($context.arguments)
  }
}
```

Todo el documento de mapeo se transfiere como la entrada a la función de Lambda, de modo que el ejemplo anterior tendría ahora el siguiente aspecto:

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
  "payload": {
    "field": "getPost",
    "arguments": {
      "id": "postId1"
    }
  }
}
```

### Versión
<a name="version"></a>

El campo `version` es común a todas las plantillas de mapeo de solicitudes y define la versión que utiliza la plantilla. El campo `version` es obligatorio y tiene asociado un valor estático:

```
"version": "2018-05-29"
```

### Operación
<a name="operation"></a>

El origen de datos de Lambda permite definir dos operaciones en el campo `operation`: `Invoke` y `BatchInvoke`. La `Invoke` operación permite llamar a AWS AppSync la función Lambda para cada solucionador de campos de GraphQL. `BatchInvoke`indica AWS AppSync que se agrupen las solicitudes para el campo GraphQL actual. El campo `operation` es obligatorio.

Para `Invoke`, la plantilla de mapeo de solicitudes resuelta coincide con la carga útil de entrada de la función de Lambda. Modifiquemos el ejemplo anterior:

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
    "payload": {
      "arguments": $util.toJson($context.arguments)
    }
}
```

Esto se resuelve y se transfiere a la función de Lambda, que podría tener un aspecto similar al siguiente:

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
    "payload": {
      "arguments": {
        "id": "postId1"
      }
    }
}
```

Para `BatchInvoke`, la plantilla de mapeo se aplica a cada solucionador de campo del lote. Para mayor concisión, AWS AppSync fusiona todos los `payload` valores de la plantilla de mapeo resueltos en una lista bajo un único objeto que coincida con la plantilla de mapeo. La siguiente plantilla de ejemplo muestra esta combinación:

```
{
  "version": "2018-05-29",
  "operation": "BatchInvoke",
  "payload": $util.toJson($context)
}
```

Esta plantilla se resuelve para dar el siguiente documento de mapeo:

```
{
  "version": "2018-05-29",
  "operation": "BatchInvoke",
  "payload": [
    {...}, // context for batch item 1
    {...}, // context for batch item 2
    {...}  // context for batch item 3
  ]
}
```

Cada elemento de la lista `payload` se corresponde con cada elemento individual del lote. También se espera que la función de Lambda devuelva una respuesta en forma de lista que coincida con el orden de los elementos enviados en la solicitud:

```
[
  { "data": {...}, "errorMessage": null, "errorType": null }, // result for batch item 1
  { "data": {...}, "errorMessage": null, "errorType": null }, // result for batch item 2
  { "data": {...}, "errorMessage": null, "errorType": null }  // result for batch item 3
]
```

### Carga útil
<a name="payload"></a>

El campo `payload` es un contenedor que se utiliza para transferir cualquier formato JSON correcto a la función de Lambda. Si el `operation` campo está establecido en`BatchInvoke`, AWS AppSync agrupa los `payload` valores existentes en una lista. El campo `payload` es opcional.

### Tipos de invocación
<a name="async-invocation-type"></a>

El origen de datos de Lambda permite definir dos tipos de invocación: `RequestResponse` y `Event`. Los tipos de invocación son sinónimos de los tipos de invocación definidos en la [API de Lambda](https://docs.aws.amazon.com//lambda/latest/api/API_Invoke.html). El tipo `RequestResponse` de invocación permite AWS AppSync llamar a la función Lambda de forma sincrónica para esperar una respuesta. La invocación `Event` permite invocar su función de Lambda de forma asíncrona. Para obtener más información sobre cómo Lambda gestiona las solicitudes de tipo de invocación `Event`, consulte [Invocación asíncrona](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html). El campo `invocationType` es opcional. Si este campo no está incluido en la solicitud, AWS AppSync será el tipo de invocación predeterminado. `RequestResponse`

Para cualquier campo `invocationType`, la solicitud resuelta coincide con la carga útil de entrada de la función de Lambda. Modifiquemos el ejemplo anterior:

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
  "invocationType": "Event"
  "payload": {
    "arguments": $util.toJson($context.arguments)
  }
}
```

Esto se resuelve y se transfiere a la función de Lambda, que podría tener un aspecto similar al siguiente:

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
  "invocationType": "Event",
  "payload": {
    "arguments": {
      "id": "postId1"
    }
  }
}
```

Cuando la `BatchInvoke` operación se usa junto con el campo de tipo de `Event` invocación, AWS AppSync fusiona el solucionador de campos de la misma manera que se mencionó anteriormente y la solicitud se pasa a la función Lambda como un evento asíncrono, siendo una lista de valores. `payload` Le recomendamos que deshabilite el almacenamiento en caché de los solucionadores para los solucionadores de tipo de invocación `Event`, ya que estos no se enviarían a Lambda si hubiera un acierto de caché.

## Plantilla de mapeo de respuestas
<a name="response-mapping-template"></a>

Al igual que con otras fuentes de datos, la función Lambda envía una respuesta AWS AppSync que debe convertirse a un tipo GraphQL.

El resultado de la función de Lambda se define con el objeto `context` que está disponible a través de la propiedad `$context.result` de Velocity Template Language (VTL).

Si la forma de la respuesta de la función Lambda coincide exactamente con la forma del tipo de GraphQL, puede reenviar la respuesta mediante la siguiente plantilla de mapeo de respuesta:

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

No hay campos obligatorios ni restricciones de forma aplicables a la plantilla de mapeo de respuesta. Sin embargo, dado que los tipos de GraphQL son estrictos, la plantilla de mapeo resuelta debe coincidir con el tipo de GraphQL previsto.

## Repuesta de la función de Lambda en lotes
<a name="aws-appsync-resolver-mapping-template-reference-lambda-batched-response"></a>

Si el campo `operation` tiene el valor `BatchInvoke`, AWS AppSync espera que la función Lambda le devuelva una lista de elementos. Para volver AWS AppSync a asignar cada resultado al elemento de solicitud original, la lista de respuestas debe coincidir en tamaño y orden. Se pueden tener elementos `null` en la lista de respuestas; `$ctx.result` se establece en *null* en consecuencia.

## Solucionadores de Lambda directos
<a name="direct-lambda-resolvers"></a>

Si desea evitar por completo el uso de plantillas de mapeo, AWS AppSync puede proporcionar una carga útil predeterminada a su función Lambda y una respuesta de función Lambda predeterminada a un tipo GraphQL. Puedes elegir entre proporcionar una plantilla de solicitud, una plantilla de respuesta o ninguna de las dos, y gestionarla en consecuencia. AWS AppSync 

### Plantilla de mapeo de la solicitud Lambda directa
<a name="lambda-mapping-template-bypass-request"></a>

Si no se proporciona la plantilla de mapeo de solicitudes, AWS AppSync enviará el `Context` objeto directamente a la función Lambda como una `Invoke` operación. Para obtener más información sobre la estructura del objeto `Context`, consulte [AWS AppSync referencia de contexto de plantilla de mapeo de resolución](resolver-context-reference.md).

### Plantilla de mapeo de la respuesta de Lambda directa
<a name="lambda-mapping-template-bypass-response"></a>

Cuando no se proporciona la plantilla de mapeo de respuestas, AWS AppSync realiza una de estas dos acciones al recibir la respuesta de la función Lambda. Si no ha proporcionado una plantilla de mapeo de solicitudes o si ha proporcionado una plantilla de mapeo de solicitudes con la versión `2018-05-29`, respuesta será equivalente a la siguiente plantilla de mapeo de respuestas:

```
#if($ctx.error)
     $util.error($ctx.error.message, $ctx.error.type, $ctx.result)
 #end
 $util.toJson($ctx.result)
```

Si ha proporcionado una plantilla con la versión `2017-02-28`, la lógica de respuesta funcionará de manera equivalente a la siguiente plantilla de mapeo de respuestas:

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

Superficialmente, la omisión de plantillas de mapeo funciona de manera similar a utilizar ciertas plantillas de mapeo, como se muestra en los ejemplos anteriores. Sin embargo, entre bastidores, se elude por completo la evaluación de las plantillas de mapeo. Al omitirse el paso de evaluación de la plantilla, las aplicaciones podrían experimentar en algunas situaciones menos sobrecarga y latencia durante la respuesta en comparación con una función de Lambda con una plantilla de mapeo de respuestas que debe evaluarse. 

### Gestión de errores personalizada en las respuestas de solucionador de Lambda directo
<a name="lambda-mapping-template-bypass-errors"></a>

Puede personalizar las respuestas de error de las funciones de Lambda que invocan los solucionadores de Lambda directos mostrando una excepción personalizada. El siguiente ejemplo muestra cómo crear una excepción personalizada mediante JavaScript:

```
class CustomException extends Error {
  constructor(message) {
    super(message);
    this.name = "CustomException";
  }
}
 
throw new CustomException("Custom message");
```

Cuando se muestran excepciones, `errorType` y `errorMessage` son el `name` y `message`, respectivamente, del error personalizado que se produce.

Si `errorType` es `UnauthorizedException` así, AWS AppSync devuelve el mensaje predeterminado (`"You are not authorized to make this call."`) en lugar de un mensaje personalizado.

El siguiente fragmento es un ejemplo de respuesta de GraphQL que muestra un `errorType` personalizado:

```
{
  "data": {
    "query": null
  },
  "errors": [
    {
      "path": [
        "query"
      ],
      "data": null,
      "errorType": "CustomException",
      "errorInfo": null,
      "locations": [
        {
          "line": 5,
          "column": 10,
          "sourceName": null
        }
      ],
      "message": "Custom Message"
    }
  ]
}
```

### Solucionadores de Lambda directos: agrupación en lotes habilitada
<a name="lambda-resolvers-batching"></a>

Puede habilitar la agrupación en lotes para el solucionador de Lambda directo mediante la configuración del `maxBatchSize` en el solucionador. Cuando `maxBatchSize` se establece en un valor superior `0` al de un solucionador de Direct Lambda, AWS AppSync envía las solicitudes en lotes a la función Lambda en tamaños de hasta. `maxBatchSize` 

Si `maxBatchSize` se establece en `0` en un solucionador de Lambda directo, se desactivará la agrupación en lotes.

Para obtener más información sobre el funcionamiento de la agrupación en lotes con solucionadores de Lambda, consulte [Caso de uso avanzado: agrupación en lotes](tutorial-lambda-resolvers.md#advanced-use-case-batching).

#### Plantilla de mapeo de solicitudes
<a name="lambda-resolvers-batching-request-template"></a>

Cuando el procesamiento por lotes está activado y no se proporciona la plantilla de mapeo de solicitudes, AWS AppSync envía una lista de `Context` objetos como una `BatchInvoke` operación directamente a la función Lambda.

#### Plantilla de mapeo de respuestas
<a name="lambda-resolvers-batching-response-template"></a>

Si la agrupación en lotes está habilitada y no se proporciona la plantilla de mapeo de respuestas, la lógica de respuesta es equivalente a la siguiente plantilla de mapeo de respuestas:

```
#if( $context.result && $context.result.errorMessage )
      $utils.error($context.result.errorMessage, $context.result.errorType,
      $context.result.data)
#else
      $utils.toJson($context.result.data)
#end
```

La función de Lambda debe devolver una lista de resultados en el mismo orden que la lista de objetos `Context` que se han enviado. Puede devolver errores individuales proporcionando un `errorMessage` y `errorType` para un resultado específico. Cada resultado de la lista se indica con el formato siguiente:

```
{
   "data" : { ... }, // your data
   "errorMessage" : { ... }, // optional, if included an error entry is added to the "errors" object in the AppSync response 
   "errorType" : { ... } // optional, the error type
}
```

**nota**  
Actualmente, se ignoran otros campos del objeto de resultado.

#### Gestión de errores de Lambda
<a name="lambda-resolvers-batching-error-handling"></a>

Puede devolver un error para todos los resultados produciendo una excepción o un error en la función de Lambda. Si el tamaño de respuesta o solicitud de carga de la solicitud por lote es demasiado grande, Lambda devolverá un error. En ese caso, debería considerar la posibilidad de reducir el `maxBatchSize` o el tamaño de la carga de la respuesta.

Para obtener información sobre la gestión de errores individuales, consulte [Devolución de errores individuales](tutorial-lambda-resolvers.md#returning-individual-errors).

#### Funciones de Lambda de ejemplo
<a name="sample-lambda-function"></a>

Con el siguiente esquema, puede crear un solucionador de Lambda directo para el solucionador de campo `Post.relatedPosts` y habilitar la agrupación en lotes al establecer `maxBatchSize` por encima de `0`:

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

type Query {
    getPost(id:ID!): Post
    allPosts: [Post]
}

type Mutation {
    addPost(id: ID!, author: String!, title: String, content: String, url: String): Post!
}

type Post {
    id: ID!
    author: String!
    title: String
    content: String
    url: String
    ups: Int
    downs: Int
    relatedPosts: [Post]
}
```

En la siguiente consulta, se llamará a la función de Lambda con lotes de solicitudes para resolver `relatedPosts`:

```
query getAllPosts {
  allPosts {
    id
    relatedPosts {
      id
    }
  }
}
```

A continuación, se proporciona una implementación sencilla de una función de Lambda:

```
const posts = {
  1: {
    id: '1',
    title: 'First book',
    author: 'Author1',
    url: 'https://amazon.com/',
    content:
      'SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1',
    ups: '100',
    downs: '10',
  },
  2: {
    id: '2',
    title: 'Second book',
    author: 'Author2',
    url: 'https://amazon.com',
    content: 'SAMPLE TEXT AUTHOR 2 SAMPLE TEXT AUTHOR 2 SAMPLE TEXT',
    ups: '100',
    downs: '10',
  },
  3: { id: '3', title: 'Third book', author: 'Author3', url: null, content: null, ups: null, downs: null },
  4: {
    id: '4',
    title: 'Fourth book',
    author: 'Author4',
    url: 'https://www.amazon.com/',
    content:
      'SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4',
    ups: '1000',
    downs: '0',
  },
  5: {
    id: '5',
    title: 'Fifth book',
    author: 'Author5',
    url: 'https://www.amazon.com/',
    content: 'SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT',
    ups: '50',
    downs: '0',
  },
}

const relatedPosts = {
  1: [posts['4']],
  2: [posts['3'], posts['5']],
  3: [posts['2'], posts['1']],
  4: [posts['2'], posts['1']],
  5: [],
}
exports.handler = async (event) => {
  console.log('event ->', event)
  // retrieve the ID of each post
  const ids = event.map((context) => context.source.id)
  // fetch the related posts for each post id
  const related = ids.map((id) => relatedPosts[id])

  // return the related posts; or an error if none were found
  return related.map((r) => {
    if (r.length > 0) {
      return { data: r }
    } else {
      return { data: null, errorMessage: 'Not found', errorType: 'ERROR' }
    }
  })
}
```