Header Ads Widget

Ticker

6/recent/ticker-posts

Creación de API GraphQL sin servidor y fullstack en la nube

 


GraphQL , un potente lenguaje de consulta para API, ha sido apreciado durante mucho tiempo por sus capacidades de integración de datos. GraphQL permite a los desarrolladores extraer datos pertinentes de sus API sin complicaciones adicionales. A su vez, las aplicaciones pueden controlar con precisión qué datos obtienen. Mientras que las configuraciones RESTful tradicionales se basan en las solicitudes del servidor, GraphQL asume el control de la recuperación de datos. Ese control granular es sumamente beneficioso tanto para los desarrolladores como para los usuarios finales. Esto mantiene las aplicaciones en funcionamiento, estables y escalables a medida que crecen las bases de datos.

William Lyon , desarrollador de software de Neo4j , ayuda regularmente a los desarrolladores a crear aplicaciones GraphQL de pila completa. Con el uso adecuado de herramientas y visualización de datos, esta vía de desarrollo tiene una inmensa promesa para aplicaciones exigentes. Empresas como Facebook, GitHub, Pinterest e Intuit incorporan GraphQL en toda la plataforma. Por el contrario, incluso los equipos pequeños pueden aprovechar el lenguaje para crear API capaces. Durante su presentación en nuestra Cumbre de API de Austin 2019 , William describió cómo los desarrolladores pueden hacer precisamente eso.

Vea a William Lyon de Neo4j presente en el Austin API Summit 2019:

Descripción general y herramientas de desarrollo de GraphQL

Lyon comienza con un breve resumen de herramientas de desarrollo útiles para la implementación de API GraphQL. Estos servicios incluyen GraphQL , React , Apollo y Neo4j Database . Cada uno juega un papel clave en el proceso de construcción. Juntos, forman un solo marco GraphQL llamado GRANDstack . Para comenzar, proporcionemos una descripción general de Neo4j , la capa de datos para este proyecto:

Neo4j utiliza gráficos para modelos de datos, a diferencia de tablas o documentos. La plataforma también usa Cypher , que Lyon compara con SQL especializado para GraphQL. Como se muestra arriba, Cypher se basa bastante en la coincidencia de patrones dentro de su lógica. Las bases de datos de gráficos junto con Neo4j son útiles para las siguientes aplicaciones:

  • Gráficos de conocimiento
  • Recomendaciones personalizadas
  • Gestión de datos maestros
  • Gestión de redes y TI
  • Detección de fraudes
  • Analítica
  • Gestión de identidades y accesos
  • Privacidad y cumplimiento
  • Logística y enrutamiento
  • Búsqueda basada en gráficos

Ya podemos observar cierta superposición con los casos de uso de REST, aunque GraphQL se acerca a estos fines utilizando diferentes medios. La gestión de redes y TI tiene su lugar dentro de ambas metodologías. Un paralelo interesante radica en la identidad y el control de acceso. A menudo pensamos en cosas como el control de acceso basado en roles (RBAC) , que hemos mencionado en un artículo sobre las mejores prácticas de API REST. Estos servicios son ubicuos independientemente del enfoque de creación de API, lo que otorga a GraphQL un inmenso potencial empresarial.

Los fundamentos de GraphQL

Pero, ¿cómo está compuesto el idioma? GraphQL utiliza definiciones de tipos que definen colecciones de estructuras de datos. Estas agrupaciones se denominan esquemas. Aquellos con experiencia en SQL deberían encontrarlos familiares. Para los propósitos de nuestra API GraphQL, estos comprenden el lenguaje de definición de esquemas (SDL) . A partir de aquí, evaluamos los diversos datos y campos disponibles. Estos formarán las especificaciones para nuestra API GraphQL. El cliente puede usar esos esquemas para construir consultas, los componentes básicos de GraphQL, que forman sus llamadas a la API. Los resultados de esas consultas coincidirán con los campos que solicita el cliente.

GraphQL es único porque interpreta los datos de su aplicación como un gráfico, como sugiere su homónimo. Los consumidores y clientes deben interpretar los datos de esta manera fundamental. Cada nodo de datos está interconectado de alguna manera. Esas relaciones hacen posible un proceso llamado introspección . Esto permite a los desarrolladores consultar esquemas y ver cómo se conectan los tipos y campos. La información de esas consultas ayuda a formar la documentación de nuestras API. Herramientas como GraphiQL y GraphQL Playground nos permiten visualizar estas estructuras de tipos, dando a la documentación una mayor claridad.

¿Cuáles son los componentes individuales de una consulta GraphQL? La API tiene puntos de entrada, que comienzan con un nombre de operación y argumentos asociados. Estos argumentos forman instrucciones para la API, que especifican la parte de la base de datos a la que queremos acceder. Digamos que queremos recuperar datos sobre una película específica, de una base de datos de diferentes películas. Para nuestro argumento, especificaríamos el título de esta película. Una vez que hemos determinado e ingresado eso, agregamos tipos para nuestra consulta. Estos tipos de datos colectivos forman el conjunto de selección.

{
	Movie(tite: "River Runs Through It, A") {
		title	
		actors(first: 2) {
			Name
}
	genres { 
		Name
}
	directors { 
		name
		movies(first: 3) { 
			title
			}
		}
}
}

Los tipos de este conjunto de selección determinan los puntos de datos específicos que devolverá nuestra API. Como se ve en la figura anterior, al consultar la base de datos en busca de “River Runs Through It, A”, se devolverá el título, los dos primeros actores enumerados y sus nombres. También podemos agregar parámetros para géneros, directores o cualquier otro tipo de datos pertinente a la película. Convenientemente, nuestra API no recuperará ninguna información que no solicitemos explícitamente. Ésta es la belleza de GraphQL. Podemos mantener nuestras consultas eficientes y limpias, sin acumular llamadas extrañas a la API. También alivia la necesidad de construir numerosas estructuras elaboradas como lo haríamos en REST.

Los datos se devuelven en formato JSON , utilizando solo los campos que solicitamos. Dicho esto, Lyon enfatiza que GraphQL es un lenguaje de consulta de API en lugar de un lenguaje de consulta de base de datos. En consecuencia, tenemos relativamente poca expresividad dentro de GraphQL. Por ejemplo, las proyecciones, agregaciones y consultas de longitud variable son limitadas.

GraphQL también es independiente de la capa de datos . Podemos usar una API GraphQL para acceder a los datos independientemente de cómo los almacenemos, lo que hace que el lenguaje sea flexible. No es necesaria una base de datos de gráficos. En consecuencia, GraphQL a menudo se basa en datos de múltiples fuentes y los agrupa en una API.

Ventajas y desventajas de GraphQL

Sabemos que GraphQL es increíble para devolver solo los datos específicos que solicitamos. Mientras que otros tipos de API pueden tener problemas con la recuperación excesiva, una API GraphQL no sufre este mismo destino. Esto mantiene la transmisión de datos al mínimo, preservando el ancho de banda y los recursos. En ese mismo sentido, el control granular nos permite evitar la captación insuficiente. Si escribimos una consulta correctamente, podemos contar con campos específicos que regresan sin problemas. Podemos generar vistas de aplicaciones y completar solicitudes de datos con un viaje de ida y vuelta a la API, sin obstruir las cosas.

GraphQL también se basa en conjuntos de especificaciones predefinidas. Las API REST son más abiertas a este respecto, lo que introduce variación y, a menudo, incertidumbre en el proceso de construcción. Estas ambigüedades pueden provocar errores o confusión, especialmente para los desarrolladores más nuevos. Como resultado, GraphQL es más usuario dado su enfoque estructurado para la construcción de API.

Las relaciones de datos se basan en la importancia contextual, de acuerdo con cómo se relacionan los tipos y los campos. Por ejemplo, es fácil mirar una publicación de blog y conectarla con un autor determinado. Abordamos todas las consultas de la misma manera. En REST, vemos los puntos de datos como recursos, que son algo menos cortados y secos. GraphQL se basa en las asociaciones heurísticas y lógicas que ya dibujamos entre elementos. También podemos construir nuestras consultas sobre componentes individuales en nuestras aplicaciones.

Desventajas

Sin embargo, ningún sistema es perfecto y tenemos que aclarar algunas de las deficiencias de GraphQL. Muchas de las mejores prácticas de REST no necesitan aplicarse, separando los dos enfoques. Saltar entre REST y GraphQL puede ser un desafío. Faltan códigos de estado HTTP y, en consecuencia, los códigos de error dan poco contexto. Si bien los desarrolladores de REST pueden proporcionar mensajes de error personalizados para los clientes, las API GraphQL brindan una respuesta universal 200 . El almacenamiento en caché web no es tan efectivo. Sin embargo, si se trata de una API autenticada, el almacenamiento en caché puede no ser una gran preocupación.

Lyon también aborda cuestiones asociadas con la complejidad arbitraria y cómo manejamos esas repercusiones con el cliente. Si el cliente puede producir una consulta que es innecesariamente compleja, ¿cómo podemos mitigar esto? Además, ¿qué implicaciones de rendimiento podría introducir esto?

También hay un n+1problema para las consultas relacionadas con la búsqueda de listas y la comparación de datos. Digamos que recuperamos varias publicaciones de blog o un grupo de películas. ¿Necesitaremos entonces solicitar autores o directores para cada uno de nuestra base de datos? Estos problemas pueden eludirse, aunque se necesita un poco de trabajo para hacerlo.

Finalmente, la limitación de velocidad y complejidad genera incertidumbres. Existen soluciones y mejores prácticas que abordan estos problemas, como la limitación de consultas. En estos casos, los clientes solo pueden crear consultas a partir de una lista predeterminada, bloqueando las solicitudes y mitigando los problemas de rendimiento.

API GraphQL: ejemplo y proceso de compilación

Cuando construya su API por primera vez, usar GraphQL Playground como espacio de trabajo puede ser extremadamente útil. Esto permite realizar pruebas y modificaciones en tiempo real sin introducir cambios en su aplicación en vivo. También le permite desarrollar consultas, tipos, campos y contenido estructurado sin riesgo. Para este ejemplo, estamos echando un vistazo al propio proyecto de William, un foro de discurso basado en blogs y publicaciones de usuarios categorizados.

Cada consulta está conectada a diferentes tipos y campos relevantes para el foro, como autor, nombre de usuario, nombre de pantalla y avatar. Si enviamos una consulta en Playgrounds, podemos ver los resultados de nuestra llamada a la API en el panel de la derecha. Estos retornos se basan en los parámetros que establecemos. En el caso de William, quería recuperar los primeros 10 proyectos de código abierto de la comunidad. Esta consulta también recupera el título, la URL, el nombre del autor y las credenciales de Discourse asociadas para ese autor:

Esta información ayuda a mostrar una vista para los visitantes del foro, representada como información en una página web o aplicación asociada. A medida que la información en la base de datos cambia según sea aplicable a una consulta determinada, estas representaciones cambiarán en consecuencia. Esto significa que una simple actualización de la base de datos enviará nuevos datos al usuario, en caso de que la consulta permanezca activa dentro de la aplicación. Por esta razón, las API GraphQL son buenas para generar contenido que depende de una base de datos. Esto es cierto tanto para contenido estático como dinámico.

Cómo construir un servicio GraphQL

Podemos crear instancias para recopilar datos de la comunidad, esta vez de Neo4j. Cuando un miembro de la comunidad publica contenido nuevo basado en Neo4j, esta información se puede analizar y agregar automáticamente a una base de datos. Desde aquí, las consultas pueden acceder a esquemas dentro de la base de datos a través de nuestra API GraphQL. Los tipos de consulta y mutación ayudan a definir estos puntos de entrada de la API.

Después de definir estas definiciones de tipo, pasamos a crear resolutores GraphQL. Estos contienen lógica de recuperación para nuestras solicitudes GraphQL, que le dicen a la API cómo funcionar correctamente:

const resolvers = { 
	Query: { 
		topCommunityBlogsAndContent: (object, params, context) => {
			// TODO: check auth headers from context
			// TODO: query the database
			// TODO: validate / format response
			// TODO: return results
		}
	}
};

Estos son importantes para la autenticación, validación o cualquier otro proceso que garantice la recuperación adecuada de datos. También permiten utilizar ORM para facilitar la manipulación de objetos. Una vez que solidifiquemos la funcionalidad de recuperación, podemos dictar cómo se formatean estos datos al regresar. Las consultas se pueden realizar en formato cifrado. Esto también nos permite manejar devoluciones de errores en caso de que ocurran.

const driver = neo4j.driver (
	process.env. NEO4J_URI || `bolt://localhost:7867`,
		neo4j.auth.basic(“neo4j”, “neo4j”)
);

Usando Node.js como columna vertebral, el servidor Apollo nos permite servir esquemas (definiciones de tipo y resolutores) creando una conexión de base de datos. Las definiciones de tipo y los resolutores se combinan en un formato ejecutable bajo varios esquemas. Una vez que Apollo está activo, podemos comenzar a ejecutar consultas sobre nuestra capa de datos. Así es como hacemos una API GraphQL de forma estándar. Sin embargo, esté atento a la duplicación de esquemas, el mapeo innecesario, el exceso de código repetitivo y los n+1problemas.

Motores GraphQL y GRANDstack Starter

Los motores GraphQL son esencialmente integraciones de bases de datos que simplifican la forma en que trabajamos con GraphQL. Estos son beneficiosos para acortar el tiempo de desarrollo y reducir la curva de aprendizaje asociada con la implementación de API.

Algunos de estos complementos, como PostGraphile y Hasura , nos permiten trabajar con Postgres más fácilmente. AWS AppSync otorga acceso a los recursos de Amazon Web Services . Prisma es una herramienta útil para trabajar con múltiples bases de datos simultáneamente.

Lyons aboga por el motor Neo4j-GraphQL . Su integración viene con algunos objetivos y advertencias, que describiremos aquí:

  • Habilite el primer desarrollo de GraphQL, incluidas las definiciones de tipo y los esquemas
  • Genere Cypher desde GraphQL, mientras se asegura de que una consulta cuente para un solo viaje de ida y vuelta utilizando nuestra API
  • Genere API CRUD basadas en GraphQL
  • Promueva una directiva de esquema Cypher extendiendo la funcionalidad de GraphQL
type Query { 
   sessionsBySubstring(string: String): [Session] @cypher(
	statement: “””MATCH (s:Session)
		          WHERE toLower(s.description) CONTAINS toLower($string)
			    OR toLower(s.name) CONTAINS toLower($string)
		          RETURN s;”””)
}

Estas directivas de esquema Cypher permiten la lógica personalizada y la anotación de campo, que se asignan a una consulta Cypher. El motor viene en versiones de JavaScript y Java, incluido un complemento de base de datos. Las solicitudes son generadas por el cliente, procesadas por el servidor Apollo y luego enviadas a la base de datos de Neo4j. Los datos se obtienen y se devuelven al cliente.

GRANDstack Starter hace que estas implementaciones de código sean aún más fáciles para los desarrolladores. Comenzamos con un esquema y definiciones de tipos. Importamos las bibliotecas necesarias e iniciamos una aplicación rápida, después de lo cual pasamos las definiciones de tipo a una makeAugmentedSchemafunción. Esta función proporciona una API CRUD GraphQL al tiempo que agrega filtrado y paginación.

import { typeDefs } from “./graphql-schema”;
import { ApolloServer } from “apollo-server-express”;
import express from “express”;
import  { v1 as neo4j } from “neo4j-driver”;
import { makeAugmentedSchema } from “neo4j-graphql-js”;
import dotenv from “dotenv”;

// set environment variables from ../.env
dotenv.config();

const app = express();

/*
 * Create an executable GraphQL schema object from GraphQL type definitions
 * including autogenerated queries and mutations.
 * Optionally a config object can be included to specify which types to include
 * in generated queries and/or mutations. Read more in the docs:
 * https://grandstack.io/docs/neo4j-graphql-js-api.html#makeaugmentedschemaoptions-graphqlschema

Desde aquí, creamos una conexión con la base de datos. Este está conectado al servidor Apollo, desde el cual podemos definir varios puntos finales GraphQL. Podemos ejecutar esto y revisar nuestros esquemas, incluidas las mutaciones que puedan estar presentes. Estas mutaciones explican los cambios realizados en la información presente en una base de datos determinada.

Si diseñamos nuestros puntos de entrada correctamente, nos permitirá ejecutar cualquier operación CRUD necesaria con relativa facilidad.

Una vez que tenemos todo en funcionamiento, es posible procesar consultas complejas. Podemos escribir en una plétora de tipos y hacer que nuestra API GraphQL busque los datos relevantes. Esto puede incluir información numérica, texto y más. Volver a nuestro código permite hacer coincidir diferentes parámetros, como usuarios y varias empresas para las que están escribiendo reseñas (por nombrar un ejemplo). Este filtrado nos permite devolver información más relevante para el cliente.

Los beneficios de los motores

Los motores GraphQL son útiles porque nos permiten construir una mayor funcionalidad en nuestras API. Por un lado, podemos lograr esto mediante integraciones declarativas. Esto nos permite definir claramente los procedimientos de obtención de datos mientras incorporamos middleware. Las definiciones de tipos nos permiten definir modelos de bases de datos. Las API GraphQL generadas automáticamente surgen de nuestras definiciones de tipo, que podemos proporcionar para la recuperación de datos. Como parte de eso, también podemos enriquecer nuestros esquemas para presentar información más detallada a nuestros clientes; estos datos a menudo también tienen más importancia contextual.

También podemos crear resolutores automáticamente mientras reducimos la cantidad de código repetitivo necesario para poner en marcha los proyectos. Esto ahorra tiempo y simplifica las cosas, dos características distintivas de la metodología GraphQL.

Entonces, ¿cómo ayudan estos motores a generar consultas a la base de datos? El resolveInfoargumento de resolución contiene información para el árbol de sintaxis abstracta de consultas GraphQL (AST), los objetos de esquema y conjuntos de selección, variables y más para construir consultas de base de datos.

Ir por la ruta sin servidor

Si buscamos adoptar un enfoque de implementación sin servidor, nos dirigimos a muchos servicios que brindan una funcionalidad clave. Éstas incluyen:

Las herramientas creadas sobre estas funciones proporcionan una experiencia de desarrollador única. Podemos combinar la implementación de código de cliente estático con nuestra API sin servidor utilizando estas opciones, lo que facilita el desarrollo. Hay muchos recursos que describen cómo podemos utilizar estos servicios.

Consultar GraphQL para el cliente

GRANDstack usa React para lograr esto. Apollo proporciona integraciones de marcos de front-end, lo que agiliza este proceso. También podemos usar Relay y urql . Los clientes GraphiQL , Playground, fetch y HTTP también están disponibles como alternativas a Apollo. Nuestra elección de cliente HTTP, en caso de que sigamos esa ruta, depende de las características únicas proporcionadas y de cómo se comparan con los objetivos de nuestro proyecto. El almacenamiento en caché y las integraciones son consideraciones cruciales con estas opciones. En el foro de la comunidad de Neo4j, utilizan fetchsolicitudes junto con JavaScript para entregar contenido y devolver datos al cliente.

La integración de React para Apollo es bastante sencilla. Creamos una nueva instancia y la dirigimos a varios puntos finales GraphQL. Las necesidades de autenticación determinarán los requisitos del encabezado. Esta instancia de Apollo se inyecta en el componente React. Esto es similar a la integración de Redux.

import ApolloClient from ‘apollo-boost’;
Import { ApolloProvider } from ‘react-apollo’;

const client = new ApolloClient({
	url: “https://graphconnect-2018-graphql-api.now.sh/”
})

Configuración de Apollo Server para que se integre sin problemas con React.

Nuestro <Query>componente puede tomar una consulta GraphQL, o podemos definir nuestros propios fragmentos (conjuntos de selección únicos para nuestras consultas) y combinarlos con los componentes de React. Esto promueve la compartimentación del código y facilita la administración a largo plazo. Los hijos de eso definen una respuesta y representan tablas, delineando cómo presentamos los datos devueltos.

Autorización en GraphQL

Afortunadamente, GraphQL ofrece una buena cantidad de opciones. Podemos utilizar nuestros solucionadores para lograr estas tareas o crear una lógica empresarial en torno a una capa de acceso a datos. Esto permite un control granular sobre qué clientes pueden recuperar qué datos de nuestras bases de datos. El middleware puede proporcionar una capa adicional de seguridad alrededor de nuestros solucionadores. Las directivas de esquema también son útiles. Tome Cypher, por ejemplo. Anotar nuestras definiciones de tipo y crear reglas proporciona protocolos de autorización rápidos.

Las autorizaciones de resolución son fáciles de implementar y rápidas de crear prototipos. Sin embargo, podemos duplicar nuestra lógica si no tenemos cuidado. Las capas de acceso a datos brindan una gran flexibilidad al procesar solicitudes y permiten una implementación única. Sin embargo, surgen preguntas cuando se trata de resolutores generados, especialmente en relación con las herramientas del motor GraphQL. Los resolutores de envoltura nos permiten definir permisos juntos y unificar reglas de autenticación. Estos permisos deben coincidir con los resolutores, y los resolutores generados pueden dificultar la comparación. Las directivas de esquema son declarativas a través de anotaciones y se combinan armoniosamente con los resolutores generados. Esto funciona bien con los motores GraphQL. Sin embargo, las reglas de autorización se distribuyen en todo el esquema GraphQL.



Publicar un comentario

0 Comentarios