1665997323
One of the nice things with GraphQL for API design is that it enforces type-safety in the schema that we define. But alas, these types are embedded as part of our schema and that type safety is lost for our resolvers, resolver variables, consuming clients and so on, requiring us to recreate the type system. It’d be so much easier if we could leverage our schema type system in our application.
This sounds like a job for type generation, but how do we do that? We’ll take a look at a tool that can generate you TypeScript type definitions, then implement our backend using them before looking at how they can plug into the front end with React (or Angular or Vue or Svelte or whatever is the framework of the month!).
We’ll cap off by learning how to model our storage platform effectively, using a separate type system for storage and combine them with the GraphQL schema types, producing a rich, strongly types, end-to-end development model.
#graphql #typescript #security
1654588030
TypeScript Deep Dive
I've been looking at the issues that turn up commonly when people start using TypeScript. This is based on the lessons from Stack Overflow / DefinitelyTyped and general engagement with the TypeScript community. You can follow for updates and don't forget to ★ on GitHub 🌹
If you are here to read the book online get started.
Book is completely free so you can copy paste whatever you want without requiring permission. If you have a translation you want me to link here. Send a PR.
You can also download one of the Epub, Mobi, or PDF formats from the actions tab by clicking on the latest build run. You will find the files in the artifacts section.
All the amazing contributors 🌹
Share URL: https://basarat.gitbook.io/typescript/
Author: Basarat
Source Code: https://github.com/basarat/typescript-book/
License: View license
1651813200
Why use this package over the other available Elm GraphQL packages? This is the only one that generates type-safe code for your entire schema. Check out this blog post, Type-Safe & Composable GraphQL in Elm, to learn more about the motivation for this library. (It's also the only type-safe library with Elm 0.18 or 0.19 support, see this discourse thread).
I built this package because I wanted to have something that:
See an example in action on Ellie. See more end-to-end example code in the examples/
folder.
dillonkearns/elm-graphql
is an Elm package and accompanying command-line code generator that creates type-safe Elm code for your GraphQL endpoint. You don't write any decoders for your API with dillonkearns/elm-graphql
, instead you simply select which fields you would like, similar to a standard GraphQL query but in Elm. For example, this GraphQL query
query {
human(id: "1001") {
name
homePlanet
}
}
would look like this in dillonkearns/elm-graphql
(the code in this example that is prefixed with StarWars
is auto-generated)
import Graphql.Operation exposing (RootQuery)
import Graphql.SelectionSet as SelectionSet exposing (SelectionSet)
import StarWars.Object
import StarWars.Object.Human as Human
import StarWars.Query as Query
import StarWars.Scalar exposing (Id(..))
query : SelectionSet (Maybe HumanData) RootQuery
query =
Query.human { id = Id "1001" } humanSelection
type alias HumanData =
{ name : String
, homePlanet : Maybe String
}
humanSelection : SelectionSet HumanData StarWars.Object.Human
humanSelection =
SelectionSet.map2 HumanData
Human.name
Human.homePlanet
GraphQL and Elm are a perfect match because GraphQL is used to enforce the types that your API takes as inputs and outputs, much like Elm's type system does within Elm. elm-graphql
simply bridges this gap by making your Elm code aware of your GraphQL server's schema. If you are new to GraphQL, graphql.org/learn/ is an excellent way to learn the basics.
After following the installation instructions to install the @dillonkearns/elm-graphql
NPM package and the proper Elm packages (see the Setup section for details). Once you've installed everything, running the elm-graphql
code generation tool is as simple as this:
npx elm-graphql https://elm-graphql.herokuapp.com --base StarWars --output examples/src
If headers are required, such as a Bearer Token, the --header
flag can be supplied.
npx elm-graphql https://elm-graphql.herokuapp.com --base StarWars --output examples/src --header 'headerKey: header value'
There is a thorough tutorial in the SelectionSet
docs. SelectionSet
s are the core concept in this library, so I recommend reading through the whole page (it's not very long!).
The examples/
folder is another great place to start.
If you want to learn more GraphQL basics, this is a great tutorial, and a short read: graphql.org/learn/
My Elm Conf 2018 talk goes into the philosophy behind dillonkearns/elm-graphql
(Skip to 13:06 to go straight to the dillonkearns/elm-graphql
demo).
elm-graphql
using the Scalar Codecs feature. If you're wondering why code is generated a certain way, you're likely to find an answer in the Frequently Asked Questions (FAQ).
There's a very helpful group of people in the #graphql channel in the Elm Slack. Don't hesitate to ask any questions about getting started, best practices, or just general GraphQL in there!
dillonkearns/elm-graphql
generates Elm code that allows you to build up type-safe GraphQL requests. Here are the steps to setup dillonkearns/elm-graphql
.
Add the dillonkearns/elm-graphql
elm package as a dependency in your elm.json
. You will also need to make sure that elm/json
is a dependency of your project since the generated code has lots of JSON decoders in it.
elm install dillonkearns/elm-graphql
elm install elm/json
Install the @dillonkearns/elm-graphql
command line tool through npm. This is what you will use to generate Elm code for your API. It is recommended that you save the @dillonkearns/elm-graphql
command line tool as a dev dependency so that everyone on your project is using the same version.
npm install --save-dev @dillonkearns/elm-graphql
# you can now run it locally using `npx elm-graphql`,
# or by calling it through an npm script as in this project's package.json
Run the @dillonkearns/elm-graphql
command line tool installed above to generate your code. If you used the --save-dev
method above, you can simply create a script in your package.json like the following:
{
"name": "star-wars-elm-graphql-project",
"version": "1.0.0",
"scripts": {
"api": "elm-graphql https://elm-graphql.herokuapp.com/api --base StarWars"
}
With the above in your package.json
, running npm run api
will generate dillonkearns/elm-graphql
code for you to call in ./src/StarWars/
. You can now use the generated code as in this Ellie example or in the examples
folder.
You can do real-time APIs using GraphQL Subscriptions and dillonkearns/elm-graphql
. Just wire in the framework-specific JavaScript code for opening the WebSocket connection through a port. Here's a live demo and its source code. The demo server is running Elixir/Absinthe.
Thank you Mario Martinez (martimatix) for all your feedback, the elm-format PR, and for the incredible logo design!
Thank you Mike Stock (mikeastock) for setting up Travis CI!
Thanks for the reserved words pull request @madsflensted!
A huge thanks to @xtian for doing the vast majority of the 0.19 upgrade work! :tada:
Thank you Josh Adams (@knewter) for the code example for Subscriptions with Elixir/Absinthe wired up through Elm ports!
Thank you Romario for adding OptionalArgument.map
!
Thank you Aaron White for your pull request to improve the performance and stability of the elm-format
step! 🎉
All core features are supported. That is, you can build any query or mutation with your dillonkearns/elm-graphql
-generated code, and it is guaranteed to be valid according to your server's schema.
dillonkearns/elm-graphql
will generate code for you to generate subscriptions and decode the responses, but it doesn't deal with the low-level details for how to send them over web sockets. To do that, you will need to use custom code or a package that knows how to communicate over websockets (or whichever protocol) to setup a subscription with your particular framework. See this discussion for why those details are not handled by this library directly.
I would love to hear feedback if you are using GraphQL Subscriptions. In particular, I'd love to see live code examples to drive any improvements to the Subscriptions design. Please ping me on Slack, drop a message in the #graphql channel, or open up a Github issue to discuss!
I would like to investigate generating helpers to make pagination simpler for Connections (based on the Relay Cursor Connections Specification). If you have ideas on this chime in on this thread.
See the full roadmap on Trello.
Author: dillonkearns
Source Code: https://github.com/dillonkearns/elm-graphql
License: View license
1654313220
In this article, you will build a full-stack app using GraphQL and Node.js in the backend. Meanwhile, our frontend will use the graphql-request
library to perform network operations on our backend.
Whenever developers build a GraphQL server using Apollo, the library generates a “frontend” which looks like so:
This interface allows users to make query or mutation requests to the server via code. However, let’s address the elephant in the room: it doesn’t look very user friendly. Since the frontend doesn’t feature any buttons or any helpful interface elements, it might be hard for many users to navigate around your app. Consequently, this shrinks your user base. So how do we solve this problem?
This is where graphql-request
comes in. It is an open source library which lets users perform queries on a GraphQL server. It boasts the following features:
graphql-request
is one of many libraries which allows for TypeScript. One major advantage of Typescript is that it allows for stable and predictable codeFor example, look at the following program:
let myNumber = 9; //here, myNumber is an integer
myNumber = 'hello'; //now it is a string.
myNumber = myNumber + 10; //even though we are adding a string to an integer,
//JavaScript won't return an error. In the real world, it might bring unexpected outputs.
//However, in Typescript, we can tell the compiler..
//what data types we need to choose.
let myNumber:number = 39; //tell TS that we want to declare an integer.
myNumber = 9+'hello'; //returns an error. Therefore, it's easier to debug the program
//this promises stability and security.
In this article, we will build a full-stack app using GraphQL and TypeScript. Here, we will use the apollo-server-express
package to build a backend server. Furthermore, for the frontend, we will use Next and graphql-request
to consume our GraphQL API.
To initialize a blank Node.js project, run these terminal commands:
mkdir graphql-ts-tutorial #create project folder
cd graphql-ts-tutorial
npm init -y #initialize the app
When that’s done, we now have to tell Node that we need to use TypeScript in our codebase:
#configure our Typescript:
npx tsc --init --rootDir app --outDir dist --esModuleInterop --resolveJsonModule --lib es6 --module commonjs --allowJs true --noImplicitAny true
mkdir app #our main code folder
mkdir dist #Typescript will use this folder to compile our program.
Next, install these dependencies:
#development dependencies. Will tell Node that we will use Typescript
npm install -d ts-node @types/node typescript @types/express nodemon
#Installing Apollo Server and its associated modules. Will help us build our GraphQL
#server
npm install apollo-server-express apollo-server-core express graphql
After this step, navigate to your app
folder. Here, create the following files:
index.ts
: Our main file. This will execute and run our Express GraphQL serverdataset.ts
: This will serve as our database, which will be served to the clientResolvers.ts
: This module will handle user commands. We will learn about resolvers later in this articleSchema.ts
: As the name suggests, this file will store the schematics needed to send data to the clientIn the end, your folder structure should look like so:
In this section, we will create a dummy database which will be used to send requested data. To do so, go to app/dataset.ts
and write the following code:
let people: { id: number; name: string }[] = [
{ id: 1, name: "Cassie" },
{ id: 2, name: "Rue" },
{ id: 3, name: "Lexi" },
];
export default people;
people
id
of type number
, and name
of type string
Here, we will now create a schema for our GraphQL server.
To put it simply, a GraphQL schema is a description of the dataset that clients can request from an API. This concept is similar to that of the Mongoose library.
To build a schema, navigate to the app/Schema.ts
file. There, write the following code:
import { gql } from "apollo-server-express"; //will create a schema
const Schema = gql`
type Person {
id: ID!
name: String
}
#handle user commands
type Query {
getAllPeople: [Person] #will return multiple Person instances
getPerson(id: Int): Person #has an argument of 'id` of type Integer.
}
`;
export default Schema;
//export this Schema so we can use it in our project
Let’s break down this code piece by piece:
Schema
variable contains our GraphQL schemaPerson
schema. It will have two fields: id
of type ID
and name
of type String
getAllPeople
command, the server will return an array of Person
objectsgetPerson
command, GraphQL will return a single Person
instanceNow that we have coded our schema, our next step is to define our resolvers.
In simple terms, a resolver is a group of functions that generate response for a GraphQL query. In other words, a resolver serves as a GraphQL query handler.
In Resolvers.ts
, write the following code:
import people from "./dataset"; //get all of the available data from our database.
const Resolvers = {
Query: {
getAllPeople: () => people, //if the user runs the getAllPeople command
//if the user runs the getPerson command:
getPerson: (_: any, args: any) => {
console.log(args);
//get the object that contains the specified ID.
return people.find((person) => person.id === args.id);
},
},
};
export default Resolvers;
Query
object that handles all the incoming queries going to the servergetAllPeople
command, the program will return all the objects present in our databasegetPerson
command requires an argument id
. This will return a Person
instance with the matching IDWe’re almost done! Now that we have built both our schema and resolver, our next step is to link them together.
In index.js
, write this block of code:
import { ApolloServer } from "apollo-server-express";
import Schema from "./Schema";
import Resolvers from "./Resolvers";
import express from "express";
import { ApolloServerPluginDrainHttpServer } from "apollo-server-core";
import http from "http";
async function startApolloServer(schema: any, resolvers: any) {
const app = express();
const httpServer = http.createServer(app);
const server = new ApolloServer({
typeDefs: schema,
resolvers,
//tell Express to attach GraphQL functionality to the server
plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
}) as any;
await server.start(); //start the GraphQL server.
server.applyMiddleware({ app });
await new Promise<void>((resolve) =>
httpServer.listen({ port: 4000 }, resolve) //run the server on port 4000
);
console.log(`Server ready at http://localhost:4000${server.graphqlPath}`);
}
//in the end, run the server and pass in our Schema and Resolver.
startApolloServer(Schema, Resolvers);
Let’s test it out! To run the code, use this Bash command:
npx nodemon app/index.ts
This will create a server at the localhost:4000/graphql
URL.
Here, you can see your available schemas within the UI:
This means that our code works!
All of our GraphQL queries will go within the Operation panel. To see it in action, type this snippet within this box:
#make a query:
query {
#get all of the people available in the server
getAllPeople {
#procure their IDs and names.
id
name
}
}
To see the result, click on the Run button:
We can even search for a specific entity via the getPerson
query:
query ($getPersonId: Int) { #the argument will be of type Integer
getPerson(id: 1) {
#get the person with the ID of 1
name
id
}
}
In the GraphQL world, mutations are commands that perform side effects on the database. Common examples of this include:
To handle mutations, go to your Schema.ts
module. Here, within the Schema
variable, add the following lines of code:
const Schema = gql`
#other code..
type Mutation {
#the addPerson commmand will accept an argument of type String.
#it will return a 'Person' instance.
addPerson(name: String): Person
}
`;
Our next step is to create a resolver to handle this mutation. To do so, within the Resolvers.ts
file, add this block of code:
const Resolvers = {
Query: {
//..further code..
},
//code to add:
//all our mutations go here.
Mutation: {
//create our mutation:
addPerson: (_: any, args: any) => {
const newPerson = {
id: people.length + 1, //id field
name: args.name, //name field
};
people.push(newPerson);
return newPerson; //return the new object's result
},
},
};
addPerson
mutation accepts a name
argumentname
is passed, the program will create a new object with a matching name
keypush
method to add this object to the people
datasetThat’s it! To test it out, run this code within the Operations window:
#perform a mutation on the server
mutation($name: String) {
addPerson(name:"Hussain") { #add a new person with the name "Hussain"
#if the execution succeeds, return its 'id' and 'name` to the user.
id
name
}
}
Let’s verify if GraphQL has added the new entry to the database:
query {
getAllPeople { #get all the results within the 'people' database.
#return only their names
name
}
}
We have successfully built our server. In this section, we will build a client app using Next that will listen to the server and render data to the UI.
As a first step, initialize a blank Next.js app like so:
npx create-next-app@latest graphql-client --ts
touch constants.tsx #our query variables go here.
To perform GraphQL operations, we will use the graphql-request library. This is a minimal, open source module that will help us make mutations and queries on our server:
npm install graphql-request graphql
npm install react-hook-form #to capture user input
In this section, we will code our queries and mutations to help us make GraphQL operations. To do so, go to constants.tsx
and add the following code:
import { gql } from "graphql-request";
//create our query
const getAllPeopleQuery = gql`
query {
getAllPeople { #run the getAllPeople command
id
name
}
}
`;
//Next, declare a mutation
const addPersonMutation = gql`
mutation addPeople($name: String!) {
addPerson(name: $name) { #add a new entry. Argument will be 'name'
id
name
}
}
`;
export { getAllPeopleQuery, addPersonMutation };
getAllPeopleQuery
variable. When the user runs this query, the program will instruct the server to get all the entries present in the databaseaddPerson
mutation tells GraphQL to add a new entry with its respected name
fieldexport
keyword to link our variables with the rest of the projectIn pages/index.ts
, write the following code:
import type { NextPage, GetStaticProps, InferGetStaticPropsType } from "next";
import { request } from "graphql-request"; //allows us to perform a request on our server
import { getAllPeopleQuery } from "../constants";
import Link from "next/link";
const Home: NextPage = ({
result, //extract the 'result' prop
}: InferGetStaticPropsType<typeof getStaticProps>) => {
return (
<div className={styles.container}>
{result.map((item: any) => { //render the 'result' array to the UI
return <p key={item.id}>{item.name}</p>;
})}
<Link href="/addpage">Add a new entry </Link>
</div>
);
};
//fetch data from the server
export const getStaticProps: GetStaticProps = async () => {
//the first argument is the URL of our GraphQL server
const res = await request("http://localhost:4000/graphql", getAllPeopleQuery);
const result = res.getAllPeople;
return {
props: {
result,
}, // will be passed to the page component as props
};
};
export default Home;
Here is a breakdown of this code piece by piece:
getStaticProps
method, we instructed Next to run the getAllPeople
command on our GraphQL serverHome
functional component. This means that we can now render the result to the UImap
method to render all of the results of the getAllPeople
command to the UI. Each paragraph element will display the name
fields of each entryLink
component to redirect the user to the addpage
route. This will allow the user to add a new Person
instance to the tableTo test out the code, run the following terminal command:
npm run dev
This will be the result:
Our GraphQL server even updates in real time.
Now that we have successfully performed a query, we can even perform mutations via the graphql-request
library.
Within your pages
folder, create a new file called addpage.tsx
. As the name suggests, this component will allow the user to add a new entry to the database. Here, start by writing the following block of code:
import type { NextPage, GetStaticProps, InferGetStaticPropsType } from "next";
import { request } from "graphql-request";
import { addPersonMutation } from "../constants";
const AddPage: NextPage = () => {
return (
<div>
<p>We will add a new entry here. </p>
</div>
);
};
export default AddPage;
In this piece of code, we are creating a blank page with a piece of text. We are doing this to ensure whether our URL routing system works.
This means that we used routing successfully! Next, write this snippet in your addpage.tsx
file:
import { useForm } from "react-hook-form";
const { register, handleSubmit } = useForm();
//if the user submits the form, then the program will output the value of their input.
const onSubmit = (data: any) => console.log(data);
return (
<div>
<form onSubmit={handleSubmit(onSubmit)}> {/*Bind our handler to this form.*/}
{/* The user's input will be saved within the 'name' property */}
<input defaultValue="test" {...register("name")} />
<input type="submit" />
</form>
</div>
);
This will be the output:
Now that we have successfully captured the user’s input, our last step is to add their entry to the server.
To do so, change the onSubmit
handler located in pages/addpage.tsx
file like so:
const onSubmit = async (data: any) => {
const response = await request(
"http://localhost:4000/graphql",
addPersonMutation,
data
);
console.log(response);
};
request
functionaddPerson
mutation command to our request header. This will tell GraphQL to perform the addMutation
action on our serverThis will be the result:
And we’re done!
Here is the full source code of this project.
In this article, you learned how to create a full-stack app using GraphQL and TypeScript. They both are extremely crucial skills within the programming world since they are in high demand nowadays.
If you encountered any difficulty in this code, I advise you to deconstruct the code and play with it so that you can fully grasp this concept.
Thank you so much for reading! Happy coding!
This story was originally published at https://blog.logrocket.com/build-graphql-app-node-js-typescript-graphql-request/
1654310400
En este artículo, creará una aplicación de pila completa utilizando GraphQL y Node.js en el backend. Mientras tanto, nuestro frontend usará la graphql-request
biblioteca para realizar operaciones de red en nuestro backend.
Cada vez que los desarrolladores construyen un servidor GraphQL usando Apollo, la biblioteca genera una "interfaz" que se ve así:
Esta interfaz permite a los usuarios realizar consultas o solicitudes de mutación al servidor a través de un código. Sin embargo, hablemos del elefante en la habitación: no parece muy fácil de usar. Dado que la interfaz no presenta ningún botón ni ningún elemento de interfaz útil, puede ser difícil para muchos usuarios navegar por su aplicación. En consecuencia, esto reduce su base de usuarios. Entonces, ¿cómo resolvemos este problema?
Aquí es donde graphql-request
entra en juego. Es una biblioteca de código abierto que permite a los usuarios realizar consultas en un servidor GraphQL. Cuenta con las siguientes características:
graphql-request
es una de las muchas bibliotecas que permite TypeScript. Una de las principales ventajas de Typescript es que permite un código estable y predecible.Por ejemplo, mira el siguiente programa:
let myNumber = 9; //here, myNumber is an integer
myNumber = 'hello'; //now it is a string.
myNumber = myNumber + 10; //even though we are adding a string to an integer,
//JavaScript won't return an error. In the real world, it might bring unexpected outputs.
//However, in Typescript, we can tell the compiler..
//what data types we need to choose.
let myNumber:number = 39; //tell TS that we want to declare an integer.
myNumber = 9+'hello'; //returns an error. Therefore, it's easier to debug the program
//this promises stability and security.
En este artículo, crearemos una aplicación de pila completa utilizando GraphQL y TypeScript. Aquí, usaremos el apollo-server-express
paquete para construir un servidor backend. Además, para la interfaz, usaremos Next y graphql-request
consumiremos nuestra API GraphQL.
Para inicializar un proyecto Node.js en blanco, ejecute estos comandos de terminal:
mkdir graphql-ts-tutorial #create project folder
cd graphql-ts-tutorial
npm init -y #initialize the app
Cuando termine, ahora tenemos que decirle a Node que necesitamos usar TypeScript en nuestra base de código:
#configure our Typescript:
npx tsc --init --rootDir app --outDir dist --esModuleInterop --resolveJsonModule --lib es6 --module commonjs --allowJs true --noImplicitAny true
mkdir app #our main code folder
mkdir dist #Typescript will use this folder to compile our program.
A continuación, instale estas dependencias:
#development dependencies. Will tell Node that we will use Typescript
npm install -d ts-node @types/node typescript @types/express nodemon
#Installing Apollo Server and its associated modules. Will help us build our GraphQL
#server
npm install apollo-server-express apollo-server-core express graphql
Después de este paso, navegue a su app
carpeta. Aquí, crea los siguientes archivos:
index.ts
: Nuestro archivo principal. Esto ejecutará y ejecutará nuestro servidor Express GraphQLdataset.ts
: Esto servirá como nuestra base de datos, que se servirá al clienteResolvers.ts
: Este módulo manejará los comandos del usuario. Aprenderemos sobre los resolutores más adelante en este artículo.Schema.ts
: como sugiere el nombre, este archivo almacenará los esquemas necesarios para enviar datos al clienteAl final, la estructura de carpetas debería verse así:
En esta sección, crearemos una base de datos ficticia que se utilizará para enviar los datos solicitados. Para hacerlo, vaya a app/dataset.ts
y escriba el siguiente código:
let people: { id: number; name: string }[] = [
{ id: 1, name: "Cassie" },
{ id: 2, name: "Rue" },
{ id: 3, name: "Lexi" },
];
export default people;
people
id
de tipo number
y name
de tipostring
Aquí, ahora crearemos un esquema para nuestro servidor GraphQL.
En pocas palabras, un esquema de GraphQL es una descripción del conjunto de datos que los clientes pueden solicitar desde una API. Este concepto es similar al de la biblioteca Mongoose .
Para crear un esquema, vaya al app/Schema.ts
archivo. Allí escribe el siguiente código:
import { gql } from "apollo-server-express"; //will create a schema
const Schema = gql`
type Person {
id: ID!
name: String
}
#handle user commands
type Query {
getAllPeople: [Person] #will return multiple Person instances
getPerson(id: Int): Person #has an argument of 'id` of type Integer.
}
`;
export default Schema;
//export this Schema so we can use it in our project
Desglosemos este código pieza por pieza:
Schema
variable contiene nuestro esquema GraphQLPerson
esquema. Tendrá dos campos: id
de tipo ID
y name
de tipoString
getAllPeople
comando, el servidor devolverá una matriz de Person
objetosgetPerson
comando, GraphQL devolverá una sola Person
instanciaAhora que hemos codificado nuestro esquema, nuestro siguiente paso es definir nuestros resolutores.
En términos simples, un resolver es un grupo de funciones que generan una respuesta para una consulta de GraphQL. En otras palabras, un resolver sirve como un controlador de consultas GraphQL.
En Resolvers.ts
, escribe el siguiente código:
import people from "./dataset"; //get all of the available data from our database.
const Resolvers = {
Query: {
getAllPeople: () => people, //if the user runs the getAllPeople command
//if the user runs the getPerson command:
getPerson: (_: any, args: any) => {
console.log(args);
//get the object that contains the specified ID.
return people.find((person) => person.id === args.id);
},
},
};
export default Resolvers;
Query
objeto que maneja todas las consultas entrantes que van al servidorgetAllPeople
comando, el programa devolverá todos los objetos presentes en nuestra base de datosgetPerson
comando requiere un argumento id
. Esto devolverá una Person
instancia con el ID coincidente¡Ya casi hemos terminado! Ahora que hemos creado tanto nuestro esquema como nuestro resolutor, nuestro siguiente paso es vincularlos.
En index.js
, escribe este bloque de código:
import { ApolloServer } from "apollo-server-express";
import Schema from "./Schema";
import Resolvers from "./Resolvers";
import express from "express";
import { ApolloServerPluginDrainHttpServer } from "apollo-server-core";
import http from "http";
async function startApolloServer(schema: any, resolvers: any) {
const app = express();
const httpServer = http.createServer(app);
const server = new ApolloServer({
typeDefs: schema,
resolvers,
//tell Express to attach GraphQL functionality to the server
plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
}) as any;
await server.start(); //start the GraphQL server.
server.applyMiddleware({ app });
await new Promise<void>((resolve) =>
httpServer.listen({ port: 4000 }, resolve) //run the server on port 4000
);
console.log(`Server ready at http://localhost:4000${server.graphqlPath}`);
}
//in the end, run the server and pass in our Schema and Resolver.
startApolloServer(Schema, Resolvers);
¡Vamos a probarlo! Para ejecutar el código, use este comando Bash:
npx nodemon app/index.ts
Esto creará un servidor en la localhost:4000/graphql
URL.
Aquí puede ver sus esquemas disponibles dentro de la interfaz de usuario:
¡Esto significa que nuestro código funciona!
Todas nuestras consultas de GraphQL irán dentro del panel de Operación . Para verlo en acción, escriba este fragmento dentro de este cuadro:
#make a query:
query {
#get all of the people available in the server
getAllPeople {
#procure their IDs and names.
id
name
}
}
Para ver el resultado, haga clic en el botón Ejecutar :
Incluso podemos buscar una entidad específica a través de la getPerson
consulta:
query ($getPersonId: Int) { #the argument will be of type Integer
getPerson(id: 1) {
#get the person with the ID of 1
name
id
}
}
En el mundo de GraphQL, las mutaciones son comandos que tienen efectos secundarios en la base de datos. Ejemplos comunes de esto incluyen:
Para manejar mutaciones, vaya a su Schema.ts
módulo. Aquí, dentro de la Schema
variable, agregue las siguientes líneas de código:
const Schema = gql`
#other code..
type Mutation {
#the addPerson commmand will accept an argument of type String.
#it will return a 'Person' instance.
addPerson(name: String): Person
}
`;
Nuestro próximo paso es crear un resolver para manejar esta mutación. Para hacerlo, dentro del Resolvers.ts
archivo, agregue este bloque de código:
const Resolvers = {
Query: {
//..further code..
},
//code to add:
//all our mutations go here.
Mutation: {
//create our mutation:
addPerson: (_: any, args: any) => {
const newPerson = {
id: people.length + 1, //id field
name: args.name, //name field
};
people.push(newPerson);
return newPerson; //return the new object's result
},
},
};
addPerson
mutación acepta un name
argumento.name
se pasa a, el programa creará un nuevo objeto con una name
clave coincidentepush
método para agregar este objeto al conjunto de people
datos .¡Eso es todo! Para probarlo, ejecute este código dentro de la ventana Operaciones :
#perform a mutation on the server
mutation($name: String) {
addPerson(name:"Hussain") { #add a new person with the name "Hussain"
#if the execution succeeds, return its 'id' and 'name` to the user.
id
name
}
}
Verifiquemos si GraphQL ha agregado la nueva entrada a la base de datos:
query {
getAllPeople { #get all the results within the 'people' database.
#return only their names
name
}
}
Hemos construido con éxito nuestro servidor. En esta sección, crearemos una aplicación cliente usando Next que escuchará al servidor y procesará datos en la interfaz de usuario.
Como primer paso, inicialice una aplicación Next.js en blanco así:
npx create-next-app@latest graphql-client --ts
touch constants.tsx #our query variables go here.
Para realizar operaciones GraphQL, utilizaremos la biblioteca graphql-request . Este es un módulo mínimo y de código abierto que nos ayudará a realizar mutaciones y consultas en nuestro servidor:
npm install graphql-request graphql
npm install react-hook-form #to capture user input
En esta sección, codificaremos nuestras consultas y mutaciones para ayudarnos a realizar operaciones GraphQL. Para hacerlo, vaya a constants.tsx
y agregue el siguiente código:
import { gql } from "graphql-request";
//create our query
const getAllPeopleQuery = gql`
query {
getAllPeople { #run the getAllPeople command
id
name
}
}
`;
//Next, declare a mutation
const addPersonMutation = gql`
mutation addPeople($name: String!) {
addPerson(name: $name) { #add a new entry. Argument will be 'name'
id
name
}
}
`;
export { getAllPeopleQuery, addPersonMutation };
getAllPeopleQuery
variable. Cuando el usuario ejecuta esta consulta, el programa le indicará al servidor que obtenga todas las entradas presentes en la base de datos.addPerson
mutación le dice a GraphQL que agregue una nueva entrada con su name
campo respectivoexport
palabra clave para vincular nuestras variables con el resto del proyecto.En pages/index.ts
, escribe el siguiente código:
import type { NextPage, GetStaticProps, InferGetStaticPropsType } from "next";
import { request } from "graphql-request"; //allows us to perform a request on our server
import { getAllPeopleQuery } from "../constants";
import Link from "next/link";
const Home: NextPage = ({
result, //extract the 'result' prop
}: InferGetStaticPropsType<typeof getStaticProps>) => {
return (
<div className={styles.container}>
{result.map((item: any) => { //render the 'result' array to the UI
return <p key={item.id}>{item.name}</p>;
})}
<Link href="/addpage">Add a new entry </Link>
</div>
);
};
//fetch data from the server
export const getStaticProps: GetStaticProps = async () => {
//the first argument is the URL of our GraphQL server
const res = await request("http://localhost:4000/graphql", getAllPeopleQuery);
const result = res.getAllPeople;
return {
props: {
result,
}, // will be passed to the page component as props
};
};
export default Home;
Aquí hay un desglose de este código pieza por pieza:
getStaticProps
método, le indicamos a Next que ejecute el getAllPeople
comando en nuestro servidor GraphQLHome
componente funcional. Esto significa que ahora podemos mostrar el resultado en la interfaz de usuario.map
método para representar todos los resultados del getAllPeople
comando en la interfaz de usuario. Cada elemento de párrafo mostrará los name
campos de cada entradaLink
componente para redirigir al usuario a la addpage
ruta. Esto permitirá al usuario agregar una nueva Person
instancia a la tabla .Para probar el código, ejecute el siguiente comando de terminal:
npm run dev
Este será el resultado:
Nuestro servidor GraphQL incluso se actualiza en tiempo real.
Ahora que hemos realizado con éxito una consulta, incluso podemos realizar mutaciones a través de la graphql-request
biblioteca.
Dentro de su pages
carpeta, cree un nuevo archivo llamado addpage.tsx
. Como sugiere el nombre, este componente permitirá al usuario agregar una nueva entrada a la base de datos. Aquí, comience escribiendo el siguiente bloque de código:
import type { NextPage, GetStaticProps, InferGetStaticPropsType } from "next";
import { request } from "graphql-request";
import { addPersonMutation } from "../constants";
const AddPage: NextPage = () => {
return (
<div>
<p>We will add a new entry here. </p>
</div>
);
};
export default AddPage;
En este fragmento de código, estamos creando una página en blanco con un fragmento de texto. Estamos haciendo esto para asegurarnos de que nuestro sistema de enrutamiento de URL funcione.
¡Esto significa que usamos el enrutamiento con éxito! A continuación, escribe este fragmento en tu addpage.tsx
archivo:
import { useForm } from "react-hook-form";
const { register, handleSubmit } = useForm();
//if the user submits the form, then the program will output the value of their input.
const onSubmit = (data: any) => console.log(data);
return (
<div>
<form onSubmit={handleSubmit(onSubmit)}> {/*Bind our handler to this form.*/}
{/* The user's input will be saved within the 'name' property */}
<input defaultValue="test" {...register("name")} />
<input type="submit" />
</form>
</div>
);
Esta será la salida:
Ahora que hemos capturado con éxito la entrada del usuario, nuestro último paso es agregar su entrada al servidor.
Para hacerlo, cambie el onSubmit
controlador ubicado en pages/addpage.tsx
el archivo de esta manera:
const onSubmit = async (data: any) => {
const response = await request(
"http://localhost:4000/graphql",
addPersonMutation,
data
);
console.log(response);
};
request
funciónaddPerson
comando de mutación a nuestro encabezado de solicitud. Esto le indicará a GraphQL que realice la addMutation
acción en nuestro servidorEste será el resultado:
¡Y hemos terminado!
Aquí está el código fuente completo de este proyecto.
En este artículo, aprendió a crear una aplicación completa con GraphQL y TypeScript. Ambas son habilidades extremadamente cruciales dentro del mundo de la programación, ya que tienen una gran demanda en la actualidad.
Si encontró alguna dificultad en este código, le aconsejo que deconstruya el código y juegue con él para que pueda comprender completamente este concepto.
Muchas Gracias Por Leer! ¡Feliz codificación!
Esta historia se publicó originalmente en https://blog.logrocket.com/build-graphql-app-node-js-typescript-graphql-request/
1625988288
When building with GraphQL you define the schema up front and this can be really handy go use when it comes to writing the queries, resolvers, etc., especially if it’s in TypeScript. So, how do you go about doing the type generation? We’ll take a look at a tool that can generate you the TypeScript types, then implement our backend using them before looking at how they can plug into the front end with React Hooks. We’ll cap off by learning how to model our storage platform effectively using its own types and combine them with the GraphQL schema types.
#graphql #typescript