

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.

# Referencia de tipos de GraphQL
<a name="type-reference"></a>

Los tipos escalares de GraphQL representan valores de hoja primitivos en un esquema de GraphQL. Estos son los tipos de datos más básicos que se resuelven en un solo valor. A diferencia de los tipos de objetos, los tipos escalares no pueden tener subcampos. GraphQL incluye un conjunto de tipos escalares predeterminados: 
+ **Int**: un entero con signo de 32 bits. 
+ **Float**: un valor de punto flotante de doble precisión con signo. 
+ **String**: una secuencia de caracteres en UTF-8. 
+ **Boolean**: valor “true” o “false”.
+ **ID**: un identificador único, que se suele utilizar como clave de una caché o para referirse a un objeto.

Estos tipos escalares sirven como componentes para los tipos más complejos del esquema. Se utilizan para definir campos que contienen valores simples y singulares. Además de estos escalares integrados, AWS AppSync proporciona escalares adicionales para distintos casos de uso. 

Las interfaces y uniones en GraphQL son tipos abstractos que permiten diseñar esquemas de forma flexible y extensible. Proporcionan mecanismos para agrupar tipos relacionados y permitir consultas polimórficas. Una interfaz en GraphQL es un tipo abstracto que define un conjunto de campos que un tipo debe incluir para implementar la interfaz. Sirve como un contrato para los objetos al especificar un conjunto común de campos que deben tener los tipos de implementación. Las interfaces son útiles cuando se desea devolver un objeto o campo que puede ser de varios tipos diferentes, pero que aún tiene algunos campos garantizados. Por el contrario, una unión en GraphQL representa un tipo que podría ser uno de varios tipos de objetos, pero no define ningún campo común entre esos tipos. Las uniones son útiles cuando se necesita devolver un campo que puede ser de varios tipos, y estos tipos no comparten necesariamente campos comunes. Tanto las interfaces como las uniones son especialmente útiles en situaciones en las que un campo podría devolver diferentes tipos de datos, lo que permite a los clientes consultar campos específicos en función del tipo que se devuelva. 

Esta sección se utiliza como referencia de los tipos de esquemas.

**Temas**
+ [Tipos escalares en GraphQL](https://docs.aws.amazon.com/appsync/latest/devguide/scalars.html)
+ [Interfaces y uniones en GraphQL](https://docs.aws.amazon.com/appsync/latest/devguide/interfaces-and-unions.html)

# Tipos escalares en GraphQL
<a name="scalars"></a>

Un tipo de objeto de GraphQL tiene un nombre y campos, y esos campos pueden tener subcampos. En última instancia, los campos de un tipo de objeto deben resolverse en tipos *escalares*, que representan las hojas de la consulta. Para obtener más información sobre los tipos de objetos y los escalares, consulte [Schemas and types](https://graphql.org/learn/schema/) en el sitio web de GraphQL.

Además del conjunto predeterminado de escalares de GraphQL, AWS AppSync también le permite usar escalares **definidos por el servicio** que comienzan con el prefijo *AWS*. AWS AppSync no admite la creación de escalares **definidos por el usuario** (personalizados). Debe usar los escalares predeterminados o de *AWS*. 

No puede utilizar *AWS* como prefijo para tipos de objetos personalizados.

La siguiente sección es una referencia para de los tipos de esquemas.

## Escalares predeterminados
<a name="graph-ql-base-scalars"></a>

GraphQL define los siguientes escalares predeterminados:

### Lista de escalares predeterminados
<a name="graph-ql-base-scalars-list"></a>

`ID`  
Identificador único de un objeto. Este escalar está serializado como una `String` pero no está destinado a ser legible por humanos.

`String`  
Secuencia de caracteres UTF-8.

`Int`  
Valor entero entre -(231) y 231-1.

`Float`  
Valor de coma flotante según la norma IEEE 754.

`Boolean`  
Un valor booleano, ya sea `true` o `false`.

## Escalares AWS AppSync
<a name="graph-ql-aws-appsync-scalars"></a>

AWS AppSync define los siguientes escalares:

### Lista de escalares de AWS AppSync
<a name="graph-ql-aws-appsync-scalars-list"></a>

`AWSDate`  
Cadena de [fecha ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Calendar_dates) extendida en el formato `YYYY-MM-DD`.

`AWSTime`  
Cadena de [hora ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Times) extendida en el formato `hh:mm:ss.sss`.

`AWSDateTime`  
Cadena de [fecha y hora ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations) extendida en el formato `YYYY-MM-DDThh:mm:ss.sssZ`.

**nota**  
Los escalares `AWSDate`, `AWSTime` y `AWSDateTime` pueden incluir opcionalmente un [desfase de zona horaria](https://en.wikipedia.org/wiki/ISO_8601#Time_zone_designators). Por ejemplo, los valores `1970-01-01Z`, `1970-01-01-07:00` y `1970-01-01+05:30` son todos válidos para `AWSDate`. El desfase de zona horaria debe ser `Z` (UTC) o un desfase en horas y minutos (y, opcionalmente, en segundos). Por ejemplo, `±hh:mm:ss`. El campo de segundos del desfase horario se considera válido aunque no forme parte de la norma ISO 8601.

`AWSTimestamp`  
Valor entero que representa el número de segundos anteriores o posteriores a `1970-01-01-T00:00Z`.

`AWSEmail`  
Dirección de correo electrónico con el formato `local-part@domain-part` definido en el [RFC 822](https://tools.ietf.org/html/rfc822).

`AWSJSON`  
Cadena JSON. Cualquier construcción JSON válida se analiza y carga automáticamente en el código de resolución como mapas, listas o valores escalares en lugar de como cadenas de entrada de literales. Las cadenas sin comillas o un JSON no válido provocan un error de validación de GraphQL.

`AWSPhone`  
Número de teléfono. Este valor se almacena como una cadena. Los números de teléfono pueden contener espacios o guiones para separar grupos de dígitos. Se supone que los números de teléfono sin código de país son números de Estados Unidos o Norteamérica que cumplen el [plan de numeración de Norteamérica (NANP)](https://en.wikipedia.org/wiki/North_American_Numbering_Plan).

`AWSURL`  
URL tal como se define en el [RFC 1738](https://tools.ietf.org/html/rfc1738). Por ejemplo, `https://www.amazon.com/dp/B000NZW3KC/` o `mailto:example@example.com`. Las direcciones URL deben contener un esquema (`http`, `mailto`) y no pueden contener dos barras diagonales (`//`) en la parte de la ruta.

`AWSIPAddress`  
Dirección IPv4 o IPv6 válida. Las direcciones IPv4 se esperan en la notación de puntos cuádruples (`123.12.34.56`). Se espera que las direcciones IPv6 estén en un formato sin corchetes y separadas por dos puntos (`1a2b:3c4b::1234:4567`). Puede incluir un sufijo CIDR opcional (`123.45.67.89/16`) para indicar la máscara de subred.

## Ejemplo de uso de esquema
<a name="example-schema-usage"></a>

En el siguiente ejemplo de esquema, GraphQL utiliza todos los escalares personalizados como un "objeto" y muestra las plantillas de solicitud y respuesta del solucionador para las operaciones básicas put, get y list. Por último, en el ejemplo se muestra cómo se puede utilizar esta información al ejecutar consultas y mutaciones.

```
type Mutation {
    putObject(
        email: AWSEmail,
        json: AWSJSON,
        date: AWSDate,
        time: AWSTime,
        datetime: AWSDateTime,
        timestamp: AWSTimestamp,
        url: AWSURL,
        phoneno: AWSPhone,
        ip: AWSIPAddress
    ): Object
}

type Object {
    id: ID!
    email: AWSEmail
    json: AWSJSON
    date: AWSDate
    time: AWSTime
    datetime: AWSDateTime
    timestamp: AWSTimestamp
    url: AWSURL
    phoneno: AWSPhone
    ip: AWSIPAddress
}

type Query {
    getObject(id: ID!): Object
    listObjects: [Object]
}

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

Este es el aspecto que podría tener una plantilla de solicitud de `putObject`. Un `putObject` utiliza una operación `PutItem` para crear o actualizar un elemento en la tabla de Amazon DynamoDB. Tenga en cuenta que este fragmento de código no tiene una tabla de Amazon DynamoDB configurada como origen de datos. Se utiliza únicamente como ejemplo:

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

La plantilla de respuesta para `putObject` devuelve los resultados:

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

Este es el aspecto que podría tener una plantilla de solicitud de `getObject`. Un `getObject` utiliza una operación `GetItem` para devolver un conjunto de atributos del elemento dada la clave principal. Tenga en cuenta que este fragmento de código no tiene una tabla de Amazon DynamoDB configurada como origen de datos. Se utiliza únicamente como ejemplo:

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

La plantilla de respuesta para `getObject` devuelve los resultados:

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

Este es el aspecto que podría tener una plantilla de solicitud de `listObjects`. Un `listObjects` utiliza una operación `Scan` para devolver uno o más elementos y atributos. Tenga en cuenta que este fragmento de código no tiene una tabla de Amazon DynamoDB configurada como origen de datos. Se utiliza únicamente como ejemplo:

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

La plantilla de respuesta para `listObjects` devuelve los resultados:

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

Estos son algunos ejemplos de uso de este esquema con consultas de GraphQL:

```
mutation CreateObject {
    putObject(email: "example@example.com"
        json: "{\"a\":1, \"b\":3, \"string\": 234}"
        date: "1970-01-01Z"
        time: "12:00:34."
        datetime: "1930-01-01T16:00:00-07:00"
        timestamp: -123123
        url:"https://amazon.com"
        phoneno: "+1 555 764 4377"
        ip: "127.0.0.1/8"
    ) {
        id
        email
        json
        date
        time
        datetime
        url
        timestamp
        phoneno
        ip
    }
}

query getObject {
    getObject(id:"0d97daf0-48e6-4ffc-8d48-0537e8a843d2"){
        email
        url
        timestamp
        phoneno
        ip
    }
}

query listObjects {
    listObjects {
        json
        date
        time
        datetime
    }
}
```

# Interfaces y uniones en GraphQL
<a name="interfaces-and-unions"></a>

El sistema de tipos de GraphQL admite las [interfaces](https://graphql.org/learn/schema/#interfaces). Una interfaz expone un determinado conjunto de campos que un tipo debe incluir para implementar la interfaz. 

El sistema de tipos GraphQL también admite las [uniones](https://graphql.org/learn/schema/#union-types). Las uniones son idénticas a las interfaces, con la excepción de que no definen un conjunto de campos común. En general, las uniones suelen ser la opción preferida frente a las interfaces cuando los tipos posibles no comparten una jerarquía lógica.

La siguiente sección es una referencia de los tipos de esquemas.

## Ejemplos de interfaces
<a name="interfaces"></a>

Podríamos representar una interfaz `Event` que represente cualquier tipo de actividad o reunión de personas. Algunos tipos de eventos posibles son `Concert`, `Conference` y `Festival`. Todos estos tipos comparten características comunes, incluidos un nombre, un lugar donde se celebra el evento, así como una fecha de inicio y de fin. Pero también tienen diferencias. Por ejemplo, una `Conference` incluye una lista de ponentes y talleres mientras que un `Concert` incluye una banda.

En el lenguaje de definición de esquema (SDL), la interfaz `Event` se define de la manera siguiente:

```
interface Event {
        id: ID!
        name : String!
        startsAt: String
        endsAt: String
        venue: Venue
        minAgeRestriction: Int
}
```

Y cada tipo implementa la interfaz `Event` del modo siguiente:

```
type Concert implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performingBand: String
}

type Festival implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performers: [String]
}

type Conference implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    speakers: [String]
    workshops: [String]
}
```

Las interfaces son útiles para representar elementos, que pueden ser de varios tipos. Por ejemplo, podríamos buscar todos los eventos que ocurran en una ubicación específica. Agreguemos un campo `findEventsByVenue` al esquema de la siguiente manera:

```
schema {
    query: Query
}

type Query {
    # Retrieve Events at a specific Venue
    findEventsAtVenue(venueId: ID!): [Event]
}

type Venue {
    id: ID!
    name: String
    address: String
    maxOccupancy: Int
}

type Concert implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performingBand: String
}

interface Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
}

type Festival implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performers: [String]
}

type Conference implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    speakers: [String]
    workshops: [String]
}
```

`findEventsByVenue` devuelve una lista de `Event`. Puesto que los campos de la interfaz GraphQL son comunes a todos los tipos de implementación, se puede seleccionar cualquier campo en la interfaz (`Event`, `id`, `name`, `startsAt`, `endsAt`, `venue` y `minAgeRestriction`). Además, puede obtener acceso a los campos en cualquier tipo de implementación utilizando [fragmentos](https://graphql.org/learn/queries/#fragments) de GraphQL, siempre que especifique el tipo.

Observemos un ejemplo de consulta de GraphQL que utiliza la interfaz.

```
query {
  findEventsAtVenue(venueId: "Madison Square Garden") {
    id
    name
    minAgeRestriction
    startsAt

    ... on Festival {
      performers
    }

    ... on Concert {
      performingBand
    }

    ... on Conference {
      speakers
      workshops
    }
  }
}
```

La consulta anterior da una sola lista de resultados y el servidor podría ordenar los eventos por fecha de inicio de forma predeterminada.

```
{
  "data": {
    "findEventsAtVenue": [
      {
        "id": "Festival-2",
        "name": "Festival 2",
        "minAgeRestriction": 21,
        "startsAt": "2018-10-05T14:48:00.000Z",
        "performers": [
          "The Singers",
          "The Screamers"
        ]
      },
      {
        "id": "Concert-3",
        "name": "Concert 3",
        "minAgeRestriction": 18,
        "startsAt": "2018-10-07T14:48:00.000Z",
        "performingBand": "The Jumpers"
      },
      {
        "id": "Conference-4",
        "name": "Conference 4",
        "minAgeRestriction": null,
        "startsAt": "2018-10-09T14:48:00.000Z",
        "speakers": [
          "The Storytellers"
        ],
        "workshops": [
          "Writing",
          "Reading"
        ]
      }
    ]
  }
}
```

Dado que los resultados se devuelven como un conjunto único de eventos, el uso de interfaces para representar características comunes resulta muy útil para ordenar los resultados.

## Ejemplos de uniones
<a name="unions"></a>

Como se indicó anteriormente, las uniones no definen conjuntos de campos comunes. Un resultado de búsqueda puede representar muchos tipos diferentes. Con el esquema `Event`, puede definir una unión `SearchResult` de la siguiente manera:

```
type Query {
    # Retrieve Events at a specific Venue
    findEventsAtVenue(venueId: ID!): [Event]
    # Search across all content
    search(query: String!): [SearchResult]
}

union SearchResult = Conference | Festival | Concert | Venue
```

En este caso, para consultar cualquier campo en nuestra unión `SearchResult`, debe utilizar fragmentos.

```
query {
  search(query: "Madison") {
    ... on Venue {
      id
      name
      address
    }

    ... on Festival {
      id
      name
      performers
    }

    ... on Concert {
      id
      name
      performingBand
    }

    ... on Conference {
      speakers
      workshops
    }
  }
}
```

## Escriba la resolución en AWS AppSync
<a name="type-resolution-in-appsynclong"></a>

La resolución Type es el mecanismo por el que el motor GraphQL identifica un valor resuelto como un tipo de objeto determinado.

Volvamos al ejemplo de búsqueda de unión. Siempre y cuando nuestra consulta haya dado resultados, cada elemento de la lista de resultados debe presentarse como uno de los tipos posibles que ha definido la unión `SearchResult` (es decir, `Conference`, `Festival`, `Concert` o `Venue`).

Dado que la lógica para identificar un `Festival` a partir de un `Venue` o una `Conference` depende de los requisitos de la aplicación, debemos darle una pista al motor de GraphQL para que identifique nuestros tipos posibles a partir de los resultados sin procesar.

Con AWS AppSync, esta sugerencia se representa mediante un metacampo denominado`__typename`, cuyo valor corresponde al nombre del tipo de objeto identificado. `__typename`es obligatorio para los tipos de retorno que son interfaces o uniones.

## Ejemplo de resolución Type
<a name="type-resolution-example"></a>

Utilicemos el esquema anterior. Puede seguir el ejemplo navegando a la consola y añadiendo los siguientes datos en la página **Schema (Esquema)**:

```
schema {
    query: Query
}

type Query {
    # Retrieve Events at a specific Venue
    findEventsAtVenue(venueId: ID!): [Event]
    # Search across all content
    search(query: String!): [SearchResult]
}

union SearchResult = Conference | Festival | Concert | Venue

type Venue {
    id: ID!
    name: String!
    address: String
    maxOccupancy: Int
}

interface Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
}

type Festival implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performers: [String]
}

type Conference implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    speakers: [String]
    workshops: [String]
}

type Concert implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performingBand: String
}
```

A continuación, asociaremos un solucionador al campo `Query.search`. En la `Resolvers` sección, elija **Adjuntar**, cree una nueva **fuente de datos** de tipo *NONE* y, a continuación, asígnele un nombre *StubDataSource*. En este ejemplo, vamos a imaginar que hemos tomado los resultados de una fuente externa y que hemos codificado los resultados obtenidos en la plantilla de mapeo de solicitud.

En el panel de la plantilla de mapeo de solicitud, escriba lo siguiente:

```
{
    "version" : "2018-05-29",
    "payload":
    ## We are effectively mocking our search results for this example
    [
        {
            "id": "Venue-1",
            "name": "Venue 1",
            "address": "2121 7th Ave, Seattle, WA 98121",
            "maxOccupancy": 1000
        },
        {
            "id": "Festival-2",
            "name": "Festival 2",
            "performers": ["The Singers", "The Screamers"]
        },
        {
            "id": "Concert-3",
            "name": "Concert 3",
            "performingBand": "The Jumpers"
        },
        {
            "id": "Conference-4",
            "name": "Conference 4",
            "speakers": ["The Storytellers"],
            "workshops": ["Writing", "Reading"]
        }
    ]
}
```

Si la aplicación devuelve el nombre del tipo como parte del campo `id`, la lógica de resolución de tipos debe analizar el campo `id` para extraer el nombre del tipo y, a continuación, añadir el campo `__typename` a cada uno de los resultados. Puede aplicar dicha lógica en la plantilla de mapeo de respuesta de la siguiente manera:

**nota**  
También puede realizar esta tarea como parte de su función de Lambda, si usa el origen de datos de Lambda.

```
#foreach ($result in $context.result)
    ## Extract type name from the id field.
    #set( $typeName = $result.id.split("-")[0] )
    #set( $ignore = $result.put("__typename", $typeName))
#end
$util.toJson($context.result)
```

Ejecute la siguiente consulta:

```
query {
  search(query: "Madison") {
    ... on Venue {
      id
      name
      address
    }

    ... on Festival {
        id
      name
      performers
    }

    ... on Concert {
      id
      name
      performingBand
    }

    ... on Conference {
      speakers
      workshops
    }
  }
}
```

La consulta genera los siguientes resultados:

```
{
  "data": {
    "search": [
      {
        "id": "Venue-1",
        "name": "Venue 1",
        "address": "2121 7th Ave, Seattle, WA 98121"
      },
      {
        "id": "Festival-2",
        "name": "Festival 2",
        "performers": [
          "The Singers",
          "The Screamers"
        ]
      },
      {
        "id": "Concert-3",
        "name": "Concert 3",
        "performingBand": "The Jumpers"
      },
      {
        "speakers": [
          "The Storytellers"
        ],
        "workshops": [
          "Writing",
          "Reading"
        ]
      }
    ]
  }
}
```

La lógica de la resolución Type varía en función de cada aplicación. Por ejemplo, podría tener una lógica de identificación distinta que compruebe la existencia de determinados campos o incluso una combinación de campos. Es decir, podría detectar la presencia del campo `performers` para identificar un `Festival` o la combinación de los campos `speakers` y `workshops` para identificar una `Conference`. En definitiva, le corresponde a usted definir la lógica que desea usar.