• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

Migrando koa-graphql para grahpql-http

Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,481
Баллы
155
Recentemente eu desenvolvi o desafio da Woovi com Koa.js e GraphQL (

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

). Uma das especificações opcionais era o uso do graphql-http, substituto do koa-graphql, que está presente no

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

disponibilizado. No entanto, me deparei com alguns problemas iniciais: diversas funcionalidades não estavam presentes no graphql-http, visto que ele é apenas uma

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

, isto é, é simples e minimalista.

Introdução - Por quê? E alguns problemas


Primeiro, por quê? Bom, principalmente, porque koa-graphql foi

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

e graphql-http deve ser utilizado ao invés disso. Tomei esta decisão baseada em uma

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

que inclusive recomendava o uso do yoga, uma alternativa mais completa para servidores graphql, no entanto, eu vi que seria completamente capaz de resolver apenas com graphql-http. Caso queira uma opção mais robusta, tente o

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

.

Vamos aos problemas. Eu utilizava algumas funcionalidades interessantes já presentes no koa-graphql, como:

  • o uso de uma customErrorFn para retornar erros do servidor de uma maneira específica, além de logar no console em ambientes de teste e desenvolvimento
  • graphiql: um playground GraphQL para fazer queries e mutations de maneira intuitiva pelo navegador
  • alterar o context da requisição, já que o projeto armazenava o usuário caso estivesse logado (por meio de token JWT)
Migrando para o graphql-http


A primeira coisa a ser feita é remover koa-graphql completamente.


pnpm un koa-graphql

E adicionar graphql-http:


pnpm i graphql-http

Com isso, é começar a adaptar as funcionalidades.

Criando o handler


Seguindo o snippet que está presente no próprio README do graphql-http, para criar o handler é bem simples, é só importar o createHandler para o koa e criar passar o schema e o context:


import { createHandler } from 'graphql-http/lib/use/koa';

const graphqlHandler = createHandler({
schema,
context: async (ctx) => {
const { user } = await getUser(ctx);
return getContext({ ctx, user });
},
});

Ok, o schema é a parte mais fácil, apenas passei o schema definido anteriormente. No entanto, tive alguns problemas com os tipos do context, especialmente porque a forma de conseguir as informações do header pode ser diferentes.

Adaptando os tipos do context


No get-context.ts, criei o tipo que deveria receber para o contexto:


import type { Request } from 'graphql-http';
import type { IncomingMessage } from 'node:http';
import type { RequestContext } from 'graphql-http/lib/use/koa';

export type RequestGraphQLContext = Request<IncomingMessage, RequestContext>;

Agora para o get-user.ts, antes eu simplesmente pegava o valor de context.headers.authorization, mas agora a tipagem para o headers é completamente diferente:

  • é preciso utilizar context.headers.get
  • get pode ser uma função, uma string, ou conter array no seu valor

Portanto, criei uma função para validar corretamente, o get-graphql-http-headers.ts:


import { Request } from 'graphql-http';
import { RequestContext } from 'graphql-http/lib/use/koa';
import { IncomingMessage } from 'node:http';

type HeaderKeyType = 'authorization';

export function getGraphQLHttpHeaders(
ctx: Request<IncomingMessage, RequestContext>,
headerKey: HeaderKeyType
) {
if (typeof ctx.headers.get === 'function') {
return ctx.headers.get(headerKey);
}

if (typeof ctx.headers === 'object') {
const header = (
ctx.headers as Record<string, string | string[] | undefined>
)[headerKey];
if (Array.isArray(header)) {
return header[0] ?? null;
} else if (typeof header === 'string') {
return header;
}
}

return null;
}

Agora, para conseguir o authToken, basta utilizar a função criada:


const authHeader = getGraphQLHttpHeaders(ctx, 'authorization');

Schema e Context prontos! Agora faltam as funcionalidades: graphiql e tratamento de erros.

Tratamento de erros


Agora ficou ainda mais simples! Não precisamos passar uma função para o handler novo, basta apenas adicionar um middleware!


// graphql error handling middleware
app.use(async (ctx, next) => {
try {
await next();
} catch (error) {
if (error instanceof GraphQLError) {
if (logEnvironments.includes(config.NODE_ENV)) {
console.log(error.message);
console.log(error.locations);
console.log(error.stack);
}

ctx.body = {
errors: [
{
message: error.message,
locations: error.locations,
stack: config.NODE_ENV === 'development' ? error.stack : undefined,
},
],
};
} else {
throw error;
}
}
});
GraphiQL - playground


Aqui eu mudei um pouco a forma que o playground é acessado. Como ele é utilizado apenas em ambiente de desenvolvimento, resolvi utilizar o

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

e adicionar um script no package.json do server para acessá-lo. Para isto, ele pede que o pacote ruru seja instalado, este inclusive pode ser utilizado em qualquer endpoint graphql disponível!


npx ruru -SP -p 3001 -e

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.


  • -p especifica a porta do playground
  • -e especifica a rota para o servidr graphql
Concluindo


Acabou! Com isso, poupei alguns KBs:


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



E, principalmente, atualizei para uma lib mais atualizada.

No meu projeto no

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

você pode visualizar exatamente como foi minha linha de pensamento visualizando a

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

e o

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

. E outra: tem um bônus onde eu configurei o graphiql em um app react-router v7 (antigo Remix), vale a pena dar uma olhada!

Caso tenha alguma dúvida, não hesite em comentar ou me chamar em qualquer um dos meus

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Referencias


Foto de

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

na

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.




Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу