Crie sua própria API usando essas tecnologias populares da Web.

GraphQL e NestJS formam uma excelente parceria, oferecendo a você uma base sólida para suas APIs e uma estrutura fácil de usar para criar aplicativos da Web escaláveis. A combinação é perfeita para criar aplicativos prontos para produção e ambas são ferramentas muito relevantes no ecossistema tecnológico atual.

Saiba mais sobre como você pode criar uma API usando os dois produtos.

O que é GraphQL?

GraphQL é uma linguagem de consulta e manipulação de dados você pode usar para criar APIs de maneira mais precisa e concisa. O GraphQL fornece uma descrição completa e adequada dos dados existentes em uma API e dá poder ao cliente para obter os dados exatos necessários.

O GraphQL fornece muitos recursos que faltam nas APIs REST, variando de consultas de dados precisas a melhores ferramentas de desenvolvedor, como o gráfico editor. Ele também permite consultar vários recursos por meio de uma única solicitação.

O que é NestJS?

NestJS é uma estrutura Node.js progressiva que você pode usar para criar aplicativos escalonáveis ​​e eficientes do lado do servidor. O NestJS fornece muitos plug-ins, juntamente com ferramentas para desenvolvimento rápido e fácil, incluindo suporte a GraphQL, GRPC, WebSockets, etc.

instagram viewer

O NestJS é conhecido no ecossistema por sua estrutura de projeto otimizada usando módulos, controladores, serviços e esquemas. Sua CLI integrada permite que você crie uma arquitetura de API estruturada. Você pode usar princípios de injeção de dependência para controlar como as partes de um aplicativo se comunicam entre si.

Implementando GraphQL com NestJS e MongoDB

Antes de criar uma API com NestJS e GraphQL, você precisará ter as dependências certas disponíveis. Você precisa para instalar o Node.js e NestJS, que você pode instalar executando npm i -g @nestjs/cli.

O exemplo a seguir é um aplicativo simples que armazena informações sobre livros. Execute o seguinte comando em seu terminal para criar um novo aplicativo NestJS:

ninho novo 

Navegue até o diretório do aplicativo gerado () e instale suas dependências com o seguinte comando:

$ npm install --save @nestjs/config @nestjs/graphql graphql-tools graphql \
 @nestjs/apollo apollo-server-express @nestjs/mongoose @types/graphql

Existem duas abordagens principais para a construção de APIs GraphQL, a saber:

  1. Abordagem do primeiro esquema: onde você descreve a API em arquivos de definição de esquema ou SDL, e o NestJS gera definições Typescript com base neles.
  2. Abordagem de código primeiro: onde você define consultas, mutações e outras funcionalidades do GraphQL usando classes e decoradores Typescript, e o NestJS gera arquivos SDL com base neles.

O exemplo a seguir descreve como usar uma abordagem de primeiro código.

Primeiro, você precisa inicializar o GraphQL em seu AppModule e conecte-o a um banco de dados MongoDB:

// app.module.ts
importar { Módulo } de'@nestjs/common';
importar { GraphQLModule como NestGraphQLModule } de'@nestjs/graphql';
importar { ApolloDriver, ApolloDriverConfig } de'@nestjs/apollo';
importar { juntar } de'caminho';
importar { MongooseModule } de'@nestjs/mangusto';
importar { AplicativoControlador } de'./app.controller';
importar { Serviço de Aplicativo } de'./app.service';
importar { ConfigModule, ConfigServiço } de'@nestjs/config';
importar mongodbConfig de'./config/mongodb.config';

@Módulo({
importações: [
ConfigModule.forRoot({
carregar: [mongodbConfig],
éGlobal: verdadeiro
}),
NestGraphQLModule.forRootAsync({
motorista: ApolloDriver,
injetar: [ConfigServiço],
useFábrica: assíncrono (configService: ConfigService) => ({
autoSchemaFile: join (process.cwd(), 'src/schema.gql'),
installSubscriptionHandlers: verdadeiro,
sortSchema: verdadeiro,
Parque infantil: verdadeiro,
depurar: configService.get<boleano>("DEPURAR"),
uploads: falso,
}),
}),
MongooseModule.forRootAsync({
injetar: [ConfigServiço],
useFábrica: assíncrono (configService: ConfigService) => ({
uri: configService.get('MONGO_URI')
})
}),
],
controladores: [AppController],
provedores: [AppService],
})

exportaraula AppModule {}

Este módulo importa o Módulo GraphQLM de @nestjs/graphql e a Módulo Mangusto de @nestjs/mangusto que ajuda a conectar-se ao MongoDB. O autoSchemaFile propriedade especifica a localização do arquivo de esquema gerado e o sortSchema A propriedade garante que ela ordene os campos em ordem alfabética.

Aqui está o que seu MongoDB configuração arquivo deve se parecer com:

importar { registrar Como } de'@nestjs/config';

/**
 * Configuração de conexão do banco de dados Mongo
 */
exportarpadrão registrarAs('mongodb', () => {
const {
MONGO_URI
} = processo.env;

retornar {
uri: `${MONGO_URI}`,
};
});

Definindo o esquema GraphQL

Depois de configurar as conexões GraphQL e MongoDB, você deve definir consultas e mutações GraphQL para gerar um esquema (schema.gql) arquivo.

Escrevendo consultas

No abordagem de código primeiro, você cria um modelo usando o Tipo de objeto decorador. Posteriormente, você transformará esse modelo em um tipo GraphQL.

Por exemplo:

// livro.model.ts
importar { Campo, Tipo de Objeto } de'@nestjs/graphql';
importar { Prop, Schema, SchemaFactory } de'@nestjs/mangusto';
importar { Documento } de'mangusto';

exportartipo LivroDocumento = Livro & Documento;

@Tipo de objeto()
@Esquema()
exportaraula Livro {
@Campo()
título: corda;

@Campo()
autor: corda;

@Campo()
data de publicação: boleano;
}

exportarconst BookSchema = SchemaFactory.createForClass (Livro);

O GraphQL, por padrão, não pode usar os esquemas criados. Para torná-los funcionais, você precisa de um serviço resolvedor que contenha as funções para executar os tipos GraphQL. Você pode fazer isso com o Resolver decorador.

// books.resolver.ts
importar { Resolvedor, Consulta, Mutação, Args, ID } de'@nestjs/graphql';
importar { Livro } de'./livro.modelo';
importar { BookService } de'./books.service';

@Resolver(() => Livro)
exportaraula BookResolver {
construtor(privado somente leitura bookService: BookService) { }

@Consulta(() => [Livro])
assíncrono livros(): Promessa {
retornaresse.bookService.findAll();
}

@Consulta(() => Livro)
assíncrono livro(@Args('eu ia', { tipo: () => Eu fiz: corda): Promessa {
retornaresse.bookService.findOne (id);
}
}

Você pode implementar o BookService, importado acima, como segue:

// books.service.ts
importar { Injetável } de'@nestjs/common';
importar {InjectModel} de'@nestjs/mangusto';
importar { Modelo } de'mangusto';
importar { Livro, LivroDocumento } de'./livro.modelo';

@Injetável()
exportaraula BookService {
construtor(@InjectModel(Livro.nome) privado bookModel: Model) { }

assíncrono encontrar tudo(): Promessa {
retornaresse.bookModel.find().exec();
}

assíncrono encontrarUm (id: corda): Promessa {
retornaresse.bookModel.findById (id).exec();
}
}

Você também precisa adicionar o BookResolver à lista de provedores em livros.module.ts.

importar { Módulo } de"@nestjs/common";
importar { MongooseModule } de"@nestjs/mangusto";
importar { BookService } de'./books.service';
importar { BookResolver } de'./livros.resolvedor';
importar { Livro, Esquema do Livro } de'./livro.modelo';

@Módulo({
provedores: [
BookService,
BookResolver
],
importações: [MongooseModule.forFeature([
{
nome: Book.name,
esquema: BookSchema,
},
]),
],
})

exportaraula Módulo Livros {}

Trabalhando com Mutações

Enquanto você usa uma consulta para recuperar dados no GraphQL, mutações criam ou atualizam dados no banco de dados. Para criar mutações, você precisa aceitar os dados dos usuários. O Tipo de entrada decorador, que transforma uma classe em um tipo de entrada GraphQL, é útil aqui.

// livro.input.ts
importar { Tipo de entrada, Campo } de'@nestjs/graphql';

@Tipo de entrada()
exportaraula BookInput {
@Campo()
título: corda;

@Campo()
autor: corda;

@Campo()
data de publicação: boleano
}

Agora você pode atualizar livros.resolvedor.ts para ficar assim:

importar { Resolvedor, Consulta, Mutação, Args, ID } de'@nestjs/graphql';
importar { Livro } de'./livro.modelo';
importar { BookService } de'./books.service';
importar { BookInput } de'./book.input';

@Resolver(() => Livro)
exportaraula BookResolver {
construtor(privado somente leitura bookService: BookService) { }

@Mutação(() => Livro)
assíncrono criarLivro(@Args('entrada') input: BookInput): Promessa {
retornaresse.bookService.create (entrada);
}

@Mutação(() => Livro)
assíncrono updateBook(
@Args('eu ia', { tipo: () => Eu fiz: corda,
@Args('entrada') entrada: BookInput,
): Promessa {
retornaresse.bookService.update (id, entrada);
}

@Mutação(() => Livro)
assíncrono deletarLivro(@Args('eu ia', { tipo: () => Eu fiz: corda): Promessa {
retornaresse.bookService.delete (id);
}
}

E livros.serviço.ts assim:

importar { Injetável } de'@nestjs/common';
importar {InjectModel} de'@nestjs/mangusto';
importar { Modelo } de'mangusto';
importar { Livro, LivroDocumento } de'./livro.modelo';

@Injetável()
exportaraula BookService {
construtor(@InjectModel(Livro.nome) privado bookModel: Model) { }

assíncrono criar (livro: Livro): Promessa {
const novoLivro = novoesse.bookModel (livro);
retornar novoLivro.save();
}

assíncrono atualizar (id: corda, livro livro): Promessa {
retornaresse.bookModel.findByIdAndUpdate (id, livro, { novo: verdadeiro }).exec();
}

assíncronoexcluir(eu ia: corda): Promessa {
retornaresse.bookModel.findByIdAndDelete (id).exec();
}
}

O @Mutação decorator marca uma função como um tipo de mutação e o @Args decorator pega todas as entradas passadas para a função.

Finalmente, você deve importar o Módulo Livros em AppModule para torná-lo funcional. Você também deve passar o Módulo Livros para forRootAsync como visto abaixo.

importar { Módulo Livros } de'./books/books.module';
/**
 * outras importações
*/

@Módulo({
importações: [
ConfigModule.forRoot({
carregar: [mongodbConfig],
éGlobal: verdadeiro
}),
NestGraphQLModule.forRootAsync({
motorista: ApolloDriver,
injetar: [ConfigServiço],
useFábrica: assíncrono (configService: ConfigService) => ({
autoSchemaFile: join (process.cwd(), 'src/schema.gql'),
installSubscriptionHandlers: verdadeiro,
sortSchema: verdadeiro,
Parque infantil: verdadeiro,
depurar: configService.get<boleano>("DEPURAR"),
uploads: falso,
}),
}),
MongooseModule.forRootAsync({
injetar: [ConfigServiço],
useFábrica: assíncrono (configService: ConfigService) => ({
uri: configService.get('MONGO_URI')
})
}),
Módulo Livros,
],
controladores: [AppController],
provedores: [AppService],
})

exportaraula AppModule {}

Você pode testar o código executando npm run start: dev em seu terminal, e seu aplicativo deve iniciar com sucesso na porta 3000.

Abrir host local: 3000/graphql no seu navegador para mostrar o gráfico interface onde você pode testar consultas e mutações. Aqui está um exemplo que mostra uma consulta:

E aqui está um exemplo de uma mutação:

Crie APIs eficientes com NestJS e GraphQL

Construir uma API GraphQL em NestJS com MongoDB usando Mongoose envolve definir um esquema para a API GraphQL, um esquema para o modelo Mongoose, um serviço para interagir com o banco de dados e um resolvedor para mapear as operações do GraphQL para o serviço métodos.

O NestJS possui funcionalidade integrada para criar APIs, incluindo decoradores para definir rotas, guardas para protegê-los e middlewares para lidar com solicitações e respostas. Ele também suporta outros bancos de dados como PostgreSQL, MySQL e SQLite, bem como outras bibliotecas GraphQL como Apollo e TypeGraphQL.