-
-
Notifications
You must be signed in to change notification settings - Fork 677
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Integration with Nest #135
Comments
HI @stevefan1999 , I am the author of that package, and here is the source https://github.com/MagnusCloudCorp/nestjs-type-graphql, But it's really really basic integration I made for a small project, just a matter to respect NestJs lifecycle. You can easily put the same code inside your app, so you have full control. If you have any question! |
The goal of TypeGraphQL integration with Nest is to create a replacement/substitute for the GraphQL (Apollo) module for Nest, so all the Nest features like pipes or guards would work. This requires a lot of changes in TypeGraphQL core so it will be done later 😞 |
Would love to see it! ❤️ |
I have this working without needing anything fancy import { Injectable, Logger } from '@nestjs/common';
import { GqlOptionsFactory, GqlModuleOptions } from '@nestjs/graphql';
import { buildSchema } from 'type-graphql';
@Injectable()
export class GraphqlConfigService implements GqlOptionsFactory {
async createGqlOptions(): Promise<GqlModuleOptions> {
const schema = await buildSchema({
resolvers: [__dirname + '../**/*.resolver.ts'],
});
return {
debug: true,
playground: true,
schema,
};
}
} And then in the app.module... imports: [
GraphQLModule.forRootAsync({
useClass: GraphqlConfigService,
}),
], |
@Sacro Do you have injects available for TGQL resolvers in runtime? |
I'm not sure I follow. My current repo is at https://gitlab.benwoodward.me.uk/pokedex/backend |
@Sacro In this case, you aren't using NestJS injections at all in resolvers far as I see, you also used Active Record pattern so you evaded the need for a repository. Unfortunately, I was indeed using AR pattern (with But the problem is, NestJS doesn't have a global container, it is re-entrant-able, so instead, the container is attached by an instance context by design. |
@stevefan1999-personal Injecting repositories seems to work fine for me when I build off @Sacro's awesome integration work. Here is one of my resolvers that I moved from @nestjs/graphql to type-graphql along with the original statements. item.resolvers.ts // import { Resolver, Query } from '@nestjs/graphql';
import { Resolver, Query } from 'type-graphql';
import { Item } from './item.entity';
import { ItemService } from './item.service';
// @Resolver('Item')
@Resolver(_of => Item)
export class ItemsResolvers {
constructor(private readonly itemsService: ItemService) {}
// @Query()
@Query(_returns => [Item])
public async getItems(): Promise<Item[]> {
return this.itemsService.findAll();
}
} item.service.ts import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Item } from './item.entity';
@Injectable()
export class ItemService {
constructor(@InjectRepository(Item) private readonly itemRepository: Repository<Item>) {}
public async findAll(): Promise<Item[]> {
return this.itemRepository.find();
}
} |
I just realized that integration could be fairly easy. I'll provide a POC once I find some time :) |
Hello Kamil, do you have any news about this POC ? I'm trying to find the best integration method for type-graphql and Nest.js. |
Hey @kamilmysliwiec I found type-graphql this past weekend, which I spend looking at many possible graphql solutions (from prisma to postgraphile to type-graphql). My opinion, it rocks! Just like NestJS, you can build anything :-) I think it's the most mature and feature complete library out there, and it will be AWESOME if it works smoothly with Nest - we can't wait for So, I've been trying a couple of days to make them work and eventually they did, but with quite a few hacks, for example: The type-graphql So I had to hack it like:
but its not nice or scalable etc. So if we can make this integration happen, it will be really awesome!!! |
Hey @anodynos, you can look at this working solution : src/app/app.module.ts import * as path from 'path';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { Module, CacheModule, CacheInterceptor } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { GraphQLModule } from '@nestjs/graphql';
import { ConfigModule } from 'nestjs-config';
import { TypeOrmConfigService } from './typeorm.config.service';
import { GraphqlConfigService } from './graphql.config.service';
import { PaysModule } from 'pays/pays.module';
@Module({
imports: [
ConfigModule.load(path.resolve(__dirname, 'config/**/*.{ts,js}')),
CacheModule.register(),
TypeOrmModule.forRootAsync({ useClass: TypeOrmConfigService }),
GraphQLModule.forRootAsync({ useClass: GraphqlConfigService }),
PaysModule,
],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: CacheInterceptor,
},
],
})
export class AppModule {
} src/app/graphql.config.service.ts import { Injectable } from '@nestjs/common';
import { GqlOptionsFactory, GqlModuleOptions } from '@nestjs/graphql';
import { ConfigService } from 'nestjs-config';
import { useContainer, buildSchema } from 'type-graphql';
@Injectable()
export class GraphqlConfigService implements GqlOptionsFactory {
constructor(private readonly config: ConfigService) { }
setContainer(container: any) {
useContainer(container);
}
async createGqlOptions(): Promise<GqlModuleOptions> {
const schema = await buildSchema({
resolvers: [ __dirname + '../**/*.resolver.ts' ],
});
return {
debug: this.config._isDev(),
playground: this.config._isDev(),
schema,
};
}
} src/pays/pays.service.ts import { Injectable } from '@nestjs/common';
import { Pays } from './pays.entity';
@Injectable()
export class PaysService {
async findAll(): Promise<Pays[]> {
return Pays.find();
}
} src/pays/pays.resolver.ts import { Injectable } from '@nestjs/common';
import { Resolver, Query, Arg, Int } from 'type-graphql';
import { Pays } from './pays.entity';
import { PaysService } from './pays.service';
@Resolver(of => Pays)
export class PaysResolver {
constructor(private readonly paysService: PaysService) { }
@Query(returns => [Pays])
async pays(): Promise<Pays[]> {
return this.paysService.findAll();
}
} src/main.ts // Nest App
const app = await NestFactory.create(AppModule, server);
const graphQlConfigService = app.get(GraphqlConfigService);
graphQlConfigService.setContainer(app); |
That method still won't use any guards or interceptors that you have setup in NestJS. The only way I've gotten requests to go through those is by using Nest's |
Thank you Christopher @christopherdupont - I had a similar setup at some point, didn't work :-( Basicaly I took code / ideas from @Sacro https://gitlab.benwoodward.me.uk/pokedex/backend @Resolver(of => Pays)
export class PaysResolver {
constructor(private readonly paysService: PaysService) { } // <---- THIS IS CALLED TWICE - 1st time with `paysService` instance (instantiated by NestJS) and second time by type-graphql, with `null`. If your's doesn't have this problem, I 'd like to examine your setup - can you please put a min working example on a repo? @caseyduquettesc Sure, there are a lot of integration points (and pains!!!) still... We're can't wait for |
Thank you @christopherdupont - I had a look and I think it works because you're using
I think if you start using Repository based entities or start using more DI, you'll start facing problems. |
I created a module for NestJs, combining the typegraphql and nestjs decorators, the type graphql will generate the schema from typescript and NestJS will provide the resolvers, so guards, pipes, interceptors, injection is on NestJS but schema generating is by type graphql. |
I have just finished POC integration locally. The biggest issue that I'm encountering frequently so far is an inconsistency between which makes it almost impossible to provide a good developer experience for the end-user (calling |
The problem is that TypeGraphQL heavily depends on
So all you need to do is: const schema = await buildSchema(options);
const schemaString = printSchema(schema); I also have a PoC of building apollo-like |
Actually, I took a look into the source code of these functions already. The problem is that when I have tried to do the exact same thing as you proposed above^ const schema = await buildSchema(options);
const schemaString = printSchema(schema); I was also getting the |
@kamilmysliwiec I will also try to find a way to detect the version of And sorry for the late response 😞 |
Please, can someone look at nestjs/nest#2187, if it is related - my understanding of the topic is too low. Thank You |
I have found a simple workaround to generate an schema using the import { Resolver, Query, Mutation, Args } from '@nestjs/graphql';
import { Ctx, Query as QueryTypeGraphql, Mutation as MutationTypeGraphql, Arg } from 'type-graphql';
@Resolver(of => User)
export class UsersResolver {
/**
* Returns the current logger user
*/
@QueryTypeGraphql(() => User, {
nullable: true,
description: 'Returns the current logged user.'
})
@Query(() => User, {
nullable: true,
description: 'Returns the current logged user.'
})
@UseGuards(UserGuard)
async me(@Ctx() ctx) : Promise<User | undefined> {
// ...
}
/**
* Register a new user
*/
@MutationTypeGraphql((): typeof User => User, {
description: 'Register a new user'
})
@Mutation((): typeof User => User, {
description: 'Register a new user'
})
public async create(
@Args('data')
@Arg('data')
{
email,
name,
username,
password,
}: UserCreateInput): Promise<User> {
// ...
}
} With that the schema can be mocked an then passed to nestjs graphql module. // Generate a base schema from classes and decorators
let baseSchema;
try{
baseSchema = await buildSchema({
resolvers: [ __dirname + "/**/*.resolver.ts"],
});
}catch(e){
console.error(e.details);
throw e;
}
// Extract only types definitions
const schemaString = printSchema(baseSchema);
// Make a GraphQL schema with no resolvers
const schema = makeExecutableSchema({ typeDefs: schemaString });
// Add mocks, modifies schema in place
addMockFunctionsToSchema({ schema });
@Module({
imports: [
ConfigModule,
DatabaseModule,
UsersModule,
AuthModule,
GraphQLModule.forRoot({
debug: true,
playground: true,
introspection: true,
schema: schema,
//... |
I'm trying to integrate NestJs + type-graphql + Prisma 2
The problem that is Nest do not see decorator In playground I see that resolvers from type-graphql affected on schema, but they are returning null. Is it not yet supported? Or I'm doing something wrong... Update: |
@unlight As stated earlier, in the future you gonna be able to use just |
In fact this fork is not using nestjs. All is spinning around type-graphql, prisma and direct usage of ApolloServer. :D |
this repo use nestjs https://github.com/EndyKaufman/typegraphql-prisma-nestjs-example, nestjs need for use guards and pipes from nest world |
Nest v7 broke my nest+graphql+prisma2 app.
Looks like importing decorators from |
@unlight Please check out @EndyKaufman Nest-based fork or create an issue on Nest GraphQL repository with a feature request. Basically, we've returned to the starting point, where we need to revamp the simple integrations like #135 (comment) or nestjs-type-graphql for those people that want to use TypeGraphQL, not a Nest's variant. As stated a year ago, somewhere in the future there will be available fully-fledged integration that will allow to use Nest's guards, interceptors, etc. in the TypeGraphQL resolvers 😉 |
@unlight I do have a PR in @EndyKaufman Nest-based fork to support NestJS 7. |
Support nest 7 and then have a fork that supports nest 6. Just an idea. |
Original Typegraphql inputs and objects can use in frontend, when sharing it with mono repository between backend and frontend, but in nestjs 7 is break it, now I try add support this feature for nestjs 7 |
If use only in backend fork work may work correct, but I use inputs and object not only backend, I use it in frontend on angular |
@EndyKaufman To avoid issues like that my work flow is as follows: Backend:
Frontend:
This means I only ever need to write the Prisma Schema and the GraphQL request and I get type safety on the frontend and backend and my GraphQL request can be as simple or complicated as I want them to be. It also means that the server and client are decoupled in a sense that neither project are importing from the same library but still type safe through code generation. |
@wSedlacek I've been doing the same thing, except I'm using react :) |
I've spend yesterday's afternoon on working on the basic integration of TypeGraphQL with NestJS, and here it is - This integration provides a way to use TypeGraphQL with NestJS modules and dependency injector. For now it doesn't support other NestJS features, so you have to use standard TypeGraphQL equivalents. The "how to use it" instruction and some code examples are available on the repo: Plese check it out and let me know how it works for you guys (or which features are missing, apart from the guards or pipes) 😉 |
That's awesome news! Now I wonder if this makes @nestjs/graphql obsolete? @kamilmysliwiec Will this be the new official way to combine NestJS with TypeGraphQL in the future? |
They have copied and embedded the modified TypeGraphQL source code into |
I'm just about to start a new project. And I did understand that I also read this part in https://www.npmjs.com/package/typegraphql-nestjs#caveats:
But I do not quite understand what the difference is. |
https://trilon.io/blog/announcing-nestjs-7-whats-new#GraphQL-TypeScript |
Hi, @RafaelKr , |
@MichalLytek is there a possible workaround to get pipes, guards working using https://www.npmjs.com/package/typegraphql-nestjs? |
@XBeg9 They use their own |
Will guards and pipes be supported in the future? |
has anyone (@MichalLytek) gotten Nestjs to work with graphql code-first in lambda? |
Are you referring to AWS Lambda Functions? The main difference from a regular NestJS application is the way the entrypoint works. |
Owner note
Scroll to
typegraphql-nestjs
package info ⬇️Original post
I was wondering if there could be more support for Nest.js, in particular, integration with an authorization endpoint is needed. Right now, I'm using this NPM package + TypeORM, following the sample, so far so good but unfortunately the source was nowhere to be found, and so I have to workaround my auth checker which required me to pass the database module into the context but it is very dangerous. So what about an official extension of TypeGraphQL to Nest.JS? This would make it easier to write universal services.
The text was updated successfully, but these errors were encountered: