I'm submitting a...Bug report
[ ] Regression
[*] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
Current behavior
Hello,
I'm using the graphql example( in the example directory of nest) with the Cat CRUD and i try to use a union type and interface but i didn't find a way to do it.
When i try to request my data with a fragment, i have the following error :
"Abstract type MutationResult must resolve to an Object type at runtime for field Mutation.createCat with value "[object Object]", received "undefined". Either the MutationResult type should provide a "resolveType" function or each possible types should provide an "isTypeOf" function."
There is nothing in the doc explaining how to use union / interface, and there is nothing in the graphql example.
In the apollo documentation, the type resolver ( here "Cat" Resolver") should implement a __resolveType function. I tried to set this function in the @resolver('Cat') class CatsResolvers
but it's not working.
I tried to add it on the cat resolvers class
Expected behavior
The request should return either a Cat item or GraphQLErrorItem from my schema definition.
Minimal reproduction of the problem with instructions
export interface GraphQLError {
readonly message: string;
readonly errorCode: number;
readonly type: string;
}
type GraphQLError {
message: String
errorCode: Int
type: String
}
union MutationResult = Cat | GraphQLError
- change the createCat Mutation in the schema
- createCat(name: String, age: Int): MutationResult
- add the function in cats.resolvers.ts in the CatsResolvers class
__resolveType(obj, context, info): string{
return obj.errorCode ? 'GraphQLError' : 'Cat';
}
What is the motivation / use case for changing the behavior?
Environment
Nest version: 4.5.10 (core)
For Tooling issues:
- Node version: 9.4
- Platform: Mac
Others:
I'm submitting a...
[ ] Regression
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
Current behavior
I cant't figure out how set custom header during a query request.
Header decorator, doesn't work, nor Response decorator.
Let me know if there is another way.
Expected behavior
There should be the ability to use header decorator as for the controller:
@Header('x-custom-header', 'xxxx')
@query('books')
async getBooks() {
....
}
Minimal reproduction of the problem with instructions
What is the motivation / use case for changing the behavior?
Environment
Nest version: X.Y.Z
For Tooling issues:
- Node version: XX
- Platform:
Others:
I have following code:
import {
Module,
MiddlewaresConsumer,
NestModule,
RequestMethod,
} from '@nestjs/common';
import { graphqlExpress } from 'apollo-server-express';
import { GraphQLModule, GraphQLFactory } from '@nestjs/graphql';
import {UsersModule} from './Users/users.module';
@Module({
imports: [GraphQLModule],
modules: [UsersModule],
export class ApplicationModule {
constructor(private readonly graphQLFactory: GraphQLFactory) {}
}
And application exits with following error:
[Nest] 24011 - 2018-2-13 13:06:05 [NestFactory] Starting Nest application...
[Nest] 24011 - 2018-2-13 13:06:05 [ExceptionHandler] Nest can't resolve dependencies of the ApplicationModule (?). Please verify whether [0] argument is available in the current context.
Error: Nest can't resolve dependencies of the ApplicationModule (?). Please verify whether [0] argument is available in the current context.
at Injector.<anonymous> (/home/tymur/Learning/nest/project/node_modules/@nestjs/core/injector/injector.js:160:23)
at Generator.next (<anonymous>)
at fulfilled (/home/tymur/Learning/nest/project/node_modules/@nestjs/core/injector/injector.js:4:58)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:160:7)
at Function.Module.runMain (module.js:703:11)
at startup (bootstrap_node.js:190:16)
at bootstrap_node.js:662:3
1: node::Abort() [node]
2: 0x8c8099 [node]
3: v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) [node]
4: 0xaddc5c [node]
5: v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) [node]
6: 0x3ab9ebd042fd
Aborted (core dumped)
UsersModule is dummy module:
import {Module} from '@nestjs/common';
import {UsersService} from './users.service';
import UsersController from './users.controller';
import {usersProviders} from './users.providers';
import {DatabaseModule} from '../common/database/database.module';
import {LibrariesModule} from '../Libraries/libraries.module';
import {UserResolver} from './user.resolver';
@Module({
// modules: [DatabaseModule, LibrariesModule],
// controllers: [UsersController],
// components: [
// UsersService,
// ...usersProviders,
// UsersResolver,
// ],
// exports: [
// UsersService,
// ],
})
export class UsersModule {}
but if i comment out modules: [UsersModule],
in ApplicationModule, everithing works fine. Same as commenting out constructor in application module. What im doing wrong?
Hi guys,
I started to use the GraphQL module and I must say that it is awesome. However, I had some difficulties to perform POST requests against my GraphQL endpoints (GET requests works out of the box).
I'm using the following packages:
"dependencies": {
"@nestjs/common": "^4.5.4",
"@nestjs/core": "^4.5.4",
"@nestjs/graphql": "^2.0.0",
"@nestjs/microservices": "^4.5.3",
"@nestjs/testing": "^4.5.4",
"@nestjs/websockets": "^4.5.3",
...
"apollo-server-express": "^1.3.2",
"graphql": "^0.11.7",
"graphql-tools": "^2.11.0",
...
}
Here is my GraphQL module implementation, according to the Nestjs documentation:
import {Module, NestModule, MiddlewaresConsumer, RequestMethod} from '@nestjs/common';
import {graphqlExpress, graphiqlExpress} from 'apollo-server-express';
import {GraphQLFactory, GraphQLModule} from '@nestjs/graphql';
import {SnippetResolvers} from "./snippet/snippet.resolvers";
import {SnippetModule} from "../snippet/snippet.module";
@Module({
imports: [
GraphQLModule,
SnippetModule
],
components: [
SnippetResolvers
]
})
export class GQLModule implements NestModule {
constructor(private readonly graphQLFactory: GraphQLFactory) {}
configure(consumer: MiddlewaresConsumer) {
const typeDefs = this.graphQLFactory.mergeTypesByPaths('./**/*.graphql');
const schema = this.graphQLFactory.createSchema({ typeDefs });
consumer
.apply(graphiqlExpress({ endpointURL: '/graphql' }))
.forRoutes({ path: '/graphiql', method: RequestMethod.GET })
.apply(graphqlExpress(req => ({ schema, rootValue: req })))
.forRoutes({ path: '/graphql', method: RequestMethod.ALL });
}
}
With the following request:
POST /graphql HTTP/1.1
Host: localhost:3000
Content-Type: application/graphql
Cache-Control: no-cache
{ snippets {name}}
I get the following response:
HTTP 500
POST body missing. Did you forget use body-parser middleware?
I found the solution reading some Apollo documentation; all I had to do was to add the following middlewares to my endpoint:
import {Module, NestModule, MiddlewaresConsumer, RequestMethod} from '@nestjs/common';
import {graphqlExpress, graphiqlExpress} from 'apollo-server-express';
import {GraphQLFactory, GraphQLModule} from '@nestjs/graphql';
import {SnippetResolvers} from "./snippet/snippet.resolvers";
import {SnippetModule} from "../snippet/snippet.module";
import * as bodyParser from 'body-parser';
@Module({
imports: [
GraphQLModule,
SnippetModule
],
components: [
SnippetResolvers
]
})
export class GQLModule implements NestModule {
constructor(private readonly graphQLFactory: GraphQLFactory) {}
configure(consumer: MiddlewaresConsumer) {
const typeDefs = this.graphQLFactory.mergeTypesByPaths('./**/*.graphql');
const schema = this.graphQLFactory.createSchema({ typeDefs });
consumer
.apply(bodyParser.text({ type: 'application/graphql' }))
.forRoutes({ path: '/graphql', method: RequestMethod.ALL })
.apply((req, res, next) => {
if (req.is('application/graphql')) {
req.body = { query: req.body };
}
next();
})
.forRoutes({ path: '/graphql', method: RequestMethod.ALL })
.apply(graphiqlExpress({ endpointURL: '/graphql' }))
.forRoutes({ path: '/graphiql', method: RequestMethod.GET })
.apply(graphqlExpress(req => ({ schema, rootValue: req })))
.forRoutes({ path: '/graphql', method: RequestMethod.ALL });
}
}
At this point, everything looks like working fine for me and I'm pretty happy with this solution. Could any of you give me some impression on this implementation? Is it the way to go? (if yes, then we should maybe add those details to the documentation)
Thanks for your time 😄
Playing with the graphql sample provided in the samples of nestjs, I was looking for a way to fetch the context in the resolver in order to extract user token in the header of the request to forward it to other backend services.
Unfortunately, it does not seem to be given as parameter despite its presence in the method signature -> findByOneId.
Here follows the context added to each request and expected in the resolver method call (object ->req.headers)...
configure(consumer: MiddlewareConsumer) {
const schema = this.createSchema();
this.subscriptionsService.createSubscriptionServer(schema);
consumer
.apply(
graphiqlExpress({
endpointURL: '/graphql',
subscriptionsEndpoint: `ws://localhost:3001/subscriptions`,
}),
)
.forRoutes('/graphiql')
.apply(graphqlExpress(req => ({ schema, rootValue: req, context: req.headers })))
.forRoutes('/graphql');
}
@Query('cat')
async findOneById(obj, args, context, info): Promise<Cat> {
const { id } = args;
return await this.catsService.findOneById(+id);
}
All parameters are undefined except the args one which contains the id.
Moreover, I figured out other unexpected behaviors when adding decorators to the method:
@Query('cat')
async findOneById(@Req() req, obj, args, context, info): Promise<Cat> {
const { id } = args;
return await this.catsService.findOneById(+id);
}
Here all arguments are undefined except the args one which contains... the context !! (same issue when replacing the @Req()
with @Body()
)
@Query('cat')
async findOneById(@Body() body, @Req() req, obj, args, context, info): Promise<Cat> {
const { id } = args;
return await this.catsService.findOneById(+id);
}
2 decorators allows here to fetch the whole GraphQLOptions
in the args parameter (other param still undefined). Same behavior for the signature async findOneById(args): Promise<Cat>
.
I found an issue regarding guards. Let's take the following example:
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';
import { Reflector } from '@nestjs/core';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const roles = this.reflector.get<string[]>('roles', context.getHandler());
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const user = request.user;
return user && user.role && roles.some((role) => role === user.role));
}
}
Now, in the rest of the framework this works like a charm. But whenever you are in graphql, this doesn't work quite as well. Taking the following .gql
file.
type Bookings implements Node {
id: ID!
...
}
type BookingEdge {
cursor: ID!
node: Booking
}
type BookingConnection {
edges: [BookingEdge]
nodes: [Booking]
pageInfo: PageInfo!
totalCount: Int!
}
type Restaurant implements Node {
id: ID!
orders(first: Int, after: String, last: Int, before: String):OrderConnection
...
}
type Query {
restaurant(id: ID!): Restaurant
}
For the following query, the const request = context.switchToHttp().getRequest();
becomes the user.
query ($id: ID!) {
restaurant(id: $id) {
id
bookings {
nodes {
id
}
}
}
}
So, in this query, request.user
in the guard, becomes undefined
and you have to make a workaround:
canActivate(context: ExecutionContext): boolean | Promise<boolean> {
const roles = this.reflector.get<string[]>('roles', context.getHandler());
const request = context.switchToHttp().getRequest(); //this works only for when querying a parent type
const ctx = context.getArgByIndex(2); // this works for when querying a child.
const user = request.user || ctx.user;
return user && user.role && roles.some((role) => role === user.role));
}
Can you guys check if it happens to you or it's an issue of mine? Thank you.
Here is a good example on how to apply Auth in GraphQL using Directive Resolvers as "resolvers middlewares" -> https://blog.graph.cool/graphql-directive-permissions-authorization-made-easy-54c076b5368e. Currently this module don't support to define directives, even that graphql-tools
allows it.
I don't know how that is handled in combination with Guards/Interceptors of Nest. Using this kind of directives allow the Schema definition to be discovered by the users and depending the role to show or hide specific fields.
I'm submitting a...
[ ] Regression
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
Current behavior
I want to implement two endpoints. For this goal I have two modules: AdminModule and SiteModule. In each module I imported GraphQLModule:
GraphQLModule.forRootAsync({
useFactory: async () => {
return {
typePaths: ['./src/admin/**/*.graphql'],
path: '/admin',
}
},
})
and
GraphQLModule.forRootAsync({
useFactory: async () => {
return {
typePaths: ['./src/site/**/*.graphql'],
path: '/site',
}
},
})
In this case only /admin
is available. When I request /site
it returns 404. From another side I can use forRoot
instead of forFootAsync
. In this case both endpoints work as expected. But I have to use forRootAsync
for have possibility to define allowResolversNotInSchema: true
by the issue described in #19. Without It I get error: Error: "Mutation" defined in resolvers, but not in schema
when in shared module I add some resolver which defined only in one of two schemes.
Expected behavior
Possibility for implement multiple endpoints
Minimal reproduction of the problem with instructions
- Use with example https://github.com/nestjs/nest/tree/master/sample/12-graphql-apollo/src
- Add two modules with configs as described above.
What is the motivation / use case for changing the behavior?
It is very convenient for have possibility for split public and protected API.
Environment
Nest version: 5.3.0
For Tooling issues:
- Node version: 10.1.0
- Platform: Windows
how to test graphql use nestjs
This syntax is not working in the NPM version. Probably a release is pending.
const resolvers = {
UUID: GraphQLUUID
}
const typeDefs = this.graphQLFactory.mergeTypesByPaths('./**/*.graphql');
const schema = this.graphQLFactory.createSchema({ typeDefs, resolvers });
I'm submitting a...
[ ] Regression
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
Current behavior
Using Nestjs with the GraphQLModule as documentation describes, there are a problem with throwing HttpException. The error message that GraphQL returns, contains "[Object Object"] in the message field instead the HttpException message.
The GraphQL.js library is expecting an Error instance, but HttpException not inherit from Error. What is the main reason for HttpException is not extending from Error?
In addition to this any Exception Filter is not working.
Expected behavior
Proper error handling and Exception Filters working with GraphQL.
Minimal reproduction of the problem with instructions
Install @nestjs/graphql and configure it as documentation describes. In any resolver try to throw a HttpException (or a inherited custom one). GraphQL returns an error like this:
{
"data": {
"findOneUserById": null
},
"errors": [
{
"message": "[object Object]",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"findOneUserById"
]
}
]
}
What is the motivation / use case for changing the behavior?
Proper error handling working with GraphQL and documentation for how to deal with this.
Environment
- "@nestjs/common": "^4.5.9",
- "@nestjs/core": "^4.5.10",
- "@nestjs/graphql": "^2.0.0",
- "@nestjs/microservices": "^4.5.8",
- "@nestjs/testing": "^4.5.5",
- "@nestjs/websockets": "^4.5.8",
For Tooling issues:
- Node version: 9.4.0
- Platform: Linux
Others:
- Kubuntu
- WebStorm
- GraphiQL
- npm
Hey, I want know a possibility to send an array of errors using the GraphQL module.
Is it possible with GraphQL module using a mutation? I have no idea how to implement it.
Big thanks.
In @query, we get the parameters (args, context, info) like this
@Query()
user(_, args, context, info) {
And req can be retrieved from context or info
Is it possible to get the req from @ResolveProperty too? I have tried something like this but it does not work.
@ResolveProperty()
userExperience(user: user, @Req() request) {
I'm submitting a...
Current behavior
(Me again! Thanks for the incredibly rapid response to my last two issues - hopefully this is the last for a while ... 😄 )
So in my app I am using the typeDefs
config option and omitting typePaths
because I do some of my own pre-processing of the schema files before handing them off to Nest.
There is an issue currently with this part of the GraphQLModule
code:
|
const typeDefs = this.graphQLFactory.mergeTypesByPaths( |
|
...(this.options.typePaths || []), |
|
); |
|
const apolloOptions = await this.graphQLFactory.mergeOptions({ |
|
...this.options, |
|
typeDefs: extend(typeDefs, this.options.typeDefs), |
|
}); |
When this.options.typePaths
is falsy (undefined in my case), then the call to this.graphQLFactory.mergeTypesByPath()
will return the following string:
When this is later combined with the string I pass as the typeDefs
value, then the resulting schema only contains my Queries, but none of my Mutations.
Expected behavior
Passing typeDefs
and no typePaths
should result in a schema exactly equivalent to that defined by the typeDefs
string.
Minimal reproduction of the problem with instructions
git clone [email protected]:nestjs/nest.git
cd nest/sample/12-graphql-apollo
npm install
- edit app.module.ts to look like:
GraphQLModule.forRootAsync({
useFactory() {
return {
installSubscriptionHandlers: true,
typeDefs: `
type Query {
getCats: [Cat]
cat(id: ID!): Cat
}
type Mutation {
createCat(name: String): Cat
}
type Subscription {
catCreated: Cat
}
type Cat {
id: Int
name: String
age: Int
}
`
};
},
}),
npm run start
When trying to execute the createCat
mutation, you will not get the error: "Schema is not configured for mutations."
Additional note: I noticed when putting together the reproduction that when passing the above config to the .forRoot()
method, the app does not even bootstrap, instead failing with the error:
UnhandledPromiseRejectionWarning: Error: Type "Query" was defined more than once.
at Object.buildASTSchema (C:\Development\temp\nest\sample\12-graphql-apollo\node_modules\graphql\utilities
What is the motivation / use case for changing the behavior?
Sometimes you need to pre-process the typedefs before handing off to Nest. In my case, I use user config to create custom fields at run-time.
Suggested fix
I fixed the issue locally by changing line 100 to:
const typeDefs = this.options.typePaths ? this.graphQLFactory.mergeTypesByPaths(
...(this.options.typePaths || []),
) : '';
Environment
Nest version: 5.3.2, graphql v5.1.1
Recommend Projects
-
-
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
An Open Source Machine Learning Framework for Everyone
-
The Web framework for perfectionists with deadlines.
-
A PHP framework for web artisans
-
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
Some thing interesting about web. New door for the world.
-
A server is a program made to process requests and deliver data to clients.
-
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Some thing interesting about visualization, use data art
-
Some thing interesting about game, make everyone happy.
-
Recommend Org
-
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Open source projects and samples from Microsoft.
-
Google ❤️ Open Source for everyone.
-
Alibaba Open Source for everyone
-
Data-Driven Documents codes.
-
China tencent open source team.
-