graphql-nexus / nexus

Code-First, Type-Safe, GraphQL Schema Construction
https://nexusjs.org
MIT License
3.4k stars 274 forks source link

Add example for integrating with Nestjs #386

Open tl-jarvis-prestidge opened 4 years ago

tl-jarvis-prestidge commented 4 years ago

Context

Nestjs is a popular framework for architecting Nodejs backend services. I enjoy working with Nest, just as I do with Nexus / Prisma.

Issue

There's currently no community consensus or integration example for how to use nexus with Nest's flavor of structuring projects.

Nestjs has examples using other code-first approaches in the form of type-graphql.

I would love for the Nexus contributors to tune in a work towards an example or even a first class integration with Nestjs.

kazazes commented 4 years ago

+1, but using Nuxt on the frontend here. The two are in a monorepo. While sharing node_module-stored typings is fine while developing, things get tricky when deploying components separately. Adding a common module would be acceptable, technically, but is still a pain.

Enabling multiple output destinations for type generation would be great.

ZenSoftware commented 4 years ago

I have been digging into how to best go about this myself and have been scratching my head. The best thing I have found thus far is @EndyKaufman / typegraphql-prisma-nestjs. Unfortunately, the repository has not had any commits for the last 4 months, so it is only working with Prisma v2 beta.

I think the largest difference in feature parity between Prisma v1 and Prisma v2 is that Prisma v2 does not support GraphQL schema delegation and prisma-binding anymore. With the last variant of the Nest - Prisma v1 recipe, it leveraged a lot off of the TypeScript code generated prisma-labs/prisma-binding. You could very easily implement schema delegations to the Prisma v1 server from Nest GraphQL. Nest would simply act as a sort of thin gateway layer between your client application and the Prisma v1 server. By simply forwarding the Nest @Args() and @Info() parameters of a GraphQL request to the prisma-binding endpoints, you could get a whole lot of features for free. See the sample code below.

With Prisma v1 schema delegation and prisma-binding you would get the following GraphQL features for free:

import { UseGuards } from '@nestjs/common';
import { Query, Mutation, Subscription, Resolver, Args, Info } from '@nestjs/graphql';
import { merge } from 'lodash';
import { Roles, GqlGuard, GqlUser, RequestUser } from '../../auth';
import { PrismaService } from '../../prisma';
import { EventTrainerCreateInput, EventTrainerWhereInput, EventTrainerSubscriptionWhereInput } from '../../prisma/binding';

@Resolver('EventTrainer')
@UseGuards(GqlGuard)
@Roles('ADMIN')
export class EventTrainerResolver {
  constructor(private readonly prisma: PrismaService) {}

  @Query()
  @Roles('REGISTERED')
  async eventTrainer(@Args() args, @Info() info) {
    return await this.prisma.binding.query.eventTrainer(args, info);
  }

  @Query()
  @Roles('REGISTERED')
  async eventTrainers(
    @Args() args: { where: EventTrainerWhereInput },
    @Info() info,
    @GqlUser() user: RequestUser
  ) {
    args.where.user = { id: user.id };
    return await this.prisma.binding.query.eventTrainers(args, info);
  }

  @Query()
  @Roles('REGISTERED')
  async eventTrainersConnection(@Args() args, @Info() info) {
    return await this.prisma.binding.query.eventTrainersConnection(args, info);
  }

  @Mutation()
  @Roles('REGISTERED')
  async createEventTrainer(
    @Args() args: { data: EventTrainerCreateInput },
    @Info() info,
    @GqlUser() user: RequestUser
  ) {
    args.data.user = { connect: { id: user.id } };
    return await this.prisma.binding.mutation.createEventTrainer(args, info);
  }

  @Mutation()
  async updateEventTrainer(@Args() args, @Info() info) {
    return await this.prisma.binding.mutation.updateEventTrainer(args, info);
  }

  @Mutation()
  async updateManyEventTrainers(@Args() args, @Info() info) {
    return await this.prisma.binding.mutation.updateManyEventTrainers(args, info);
  }

  @Mutation()
  async upsertEventTrainer(@Args() args, @Info() info) {
    return await this.prisma.binding.mutation.upsertEventTrainer(args, info);
  }

  @Mutation()
  async deleteEventTrainer(@Args() args, @Info() info) {
    return await this.prisma.binding.mutation.deleteEventTrainer(args, info);
  }

  @Mutation()
  async deleteManyEventTrainers(@Args() args, @Info() info) {
    return await this.prisma.binding.mutation.deleteManyEventTrainers(args, info);
  }

  @Subscription('eventTrainer')
  @Roles('REGISTERED')
  async eventTrainerSubscription(
    @Args() args: { where: EventTrainerSubscriptionWhereInput },
    @Info() info,
    @GqlUser() user: RequestUser
  ) {
    merge(args, {
      where: {
        node: {
          user: { id: user.id }
        },
      },
    });

    return this.prisma.binding.subscription.eventTrainer(args, info);
  }
}

Prisma v1 would almost be perfect if it supported case-insensitive text search. It's the only feature for me that would make Prisma v1 the complete GraphQL solution I was hoping it would turn out to be. I am a little sad that the team moved so abruptly to Prisma v2.

Though, at any rate! I was thinking what could be done to achieve something similar is to use a sort of micro-service architecture between Nest and a Nexus+Prisma server. What could be done is you could spin up a Nexus+Prisma server that acts as a standalone GraphQL service, and use Nest as the authentication gateway to forward GraphQL requests to the Nexus+Prisma server, as a sort of replacement to the prisma-binding approach. Since there wont to be any official support for a Nest + Nexus integration, I would really like to hear if anyone has had any success integrating Prisma v2 with Nest.

EndyKaufman commented 4 years ago

@ZenSoftware I update fork and example :smirk:

dvins commented 3 years ago

@ZenSoftware Did you ever manage to get the three to play well together, that is Prisma 2 + Nexus + NestJs? I noticed Nest have published an updated Prisma recipe which uses Prisma 2 and addresses REST.

ZenSoftware commented 3 years ago

@dvins Sorry, I was unable to find a way to integrate Nexus non-trivially with Nest. So in my struggles to find a solution to integrate Prisma with Nest, I ended up writing a solution for myself. Nest GraphQL uses Apollo Server under the hood, so it seems to be a much more elegant solution to just code generate the Apollo GraphQL SDL Prisma bindings using Pal.js written by @AhmedElywa. If you don't want to go through the process of manually integrating Apollo GraphQL SDL Prisma bindings into your stack yourself, you can use my starter kit in the link below that has everything pre-integrated. The starter kit code generates everything from the schema.prisma file. It code generates the Nest GraphQL endpoints to hook into Prisma Client, and also the Apollo Angular services for type safe access to the Nest GraphQL API. At minimum, it should give you an idea of how to create a Nest GraphQL gateway to Prisma Client.

🎐 Cheers my friend. ^_^

⛩ Zen ⛩ Nest + Prisma + Angular 🏮 Full Stack Starter Kit

djedlajn commented 3 years ago

@dvins Sorry, I was unable to find a way to integrate Nexus non-trivially with Nest. So in my struggles to find a solution to integrate Prisma with Nest, I ended up writing a solution for myself. Nest GraphQL uses Apollo Server under the hood, so it seems to be a much more elegant solution to just code generate the Apollo GraphQL SDL Prisma bindings using Pal.js written by @AhmedElywa. If you don't want to go through the process of manually integrating Apollo GraphQL SDL Prisma bindings into your stack yourself, you can use my starter kit in the link below that has everything pre-integrated. The starter kit code generates everything from the schema.prisma file. It code generates the Nest GraphQL endpoints to hook into Prisma Client, and also the Apollo Angular services for type safe access to the Nest GraphQL API. At minimum, it should give you an idea of how to create a Nest GraphQL gateway to Prisma Client.

🎐 Cheers my friend. ^_^

⛩ Zen ⛩ Nest + Prisma + Angular 🏮 Full Stack Starter Kit

Well done awesome, repo.

ceefour commented 3 years ago

shinto_shrine Zen shinto_shrine Nest + Prisma + Angular izakaya_lantern Full Stack Starter Kit

Thank you @ZenSoftware , this is very interesting approach.