How to only expose part of prima generated schema in nestjs - graphql

I'm trying to integrate nestjs with prisma. I followed the tutorial in nestjs document.
Everthing works fine until I want to make some changes so nestjs doesn't expose all the query/mutations schema.
what I did is
1. update app module not let typePath include the generated schema
import { Module } from '#nestjs/common';
import { AppController } from 'app/app.controller';
import { AppService } from 'app/app.service';
import { GraphQLModule } from '#nestjs/graphql';
import { UserModule } from './user/user.module';
#Module({
imports: [
GraphQLModule.forRoot({
typePaths: ['./src/**/*.schema.graphql'],
debug: true,
playground: true,
}),
UserModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
2. Then I created a user.schema.graphql file in user folder:
#import User from "../prisma/generated/prisma.graphql"
type Query {
user(id: ID!): User
}
However, I got some error saying I can't import User:
(node:36277) UnhandledPromiseRejectionWarning: Error: Type "User" not found in document.
at ASTDefinitionBuilder._resolveType (/Users/anx/Projects/axesk/gallery-api/node_modules/graphql/utilities/buildASTSchema.js:100:11)
at ASTDefinitionBuilder.buildType (/Users/anx/Projects/axesk/gallery-api/node_modules/graphql/utilities/buildASTSchema.js:210:79)
at ASTDefinitionBuilder._buildWrappedType (/Users/anx/Projects/axesk/gallery-api/node_modules/graphql/utilities/buildASTSchema.js:229:17)
at ASTDefinitionBuilder.buildField (/Users/anx/Projects/axesk/gallery-api/node_modules/graphql/utilities/buildASTSchema.js:249:18)
at /Users/anx/Projects/axesk/gallery-api/node_modules/graphql/utilities/buildASTSchema.js:332:21
at /Users/anx/Projects/axesk/gallery-api/node_modules/graphql/jsutils/keyValMap.js:36:31
at Array.reduce (<anonymous>)
at keyValMap (/Users/anx/Projects/axesk/gallery-api/node_modules/graphql/jsutils/keyValMap.js:35:15)
at ASTDefinitionBuilder._makeFieldDefMap (/Users/anx/Projects/axesk/gallery-api/node_modules/graphql/utilities/buildASTSchema.js:329:48)
at fields (/Users/anx/Projects/axesk/gallery-api/node_modules/graphql/utilities/buildASTSchema.js:312:22)
(node:36277) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:36277) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I'm new to nestjs and graphql, please help!

I make it work in sort of hack way.. i will just paste my solution here for anyone who got same problem.
For example i have a user.schema.graphql that import some type from prisma.graphql:
#import User from "../prisma/generated/prisma.graphql"
type Query {
user(id: ID!): User
}
Then i create a main.schema.graphql file that will import every schemas from the project manually.
#import * from "./user/user.schema.graphql"
Finally just import this maim schema to app.module.ts:
import { Module } from '#nestjs/common';
import { AppController } from 'app/app.controller';
import { AppService } from 'app/app.service';
import { GraphQLModule } from '#nestjs/graphql';
import { UserModule } from './user/user.module';
import { importSchema } from 'graphql-import';
#Module({
imports: [
GraphQLModule.forRoot({
resolverValidationOptions: {
requireResolversForResolveType: false,
},
typeDefs: importSchema('./src/main.schema.graphql'),
debug: true,
playground: true,
}),
UserModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Doing this not really ideal. if graphql-import library can import from folders, it makes life easier.
or the #nest/graphql library can use graphql-import instead of merge-graphql-schemas under the hood to build typeDefs will be also great.

Related

Unexpected type error in websockets when compiling nest js project

Below is my code
I tried to set a web socket gateway as below.
events.gateways.ts
import {
MessageBody,
SubscribeMessage,
WebSocketGateway,
WebSocketServer,
} from "#nestjs/websockets";
import { Server } from "socket.io";
#WebSocketGateway({
cors: {
origin: "http://localhost:3000",
},
})
export class EventsGateway {
#WebSocketServer()
server: Server;
#SubscribeMessage("events")
handleEvent(#MessageBody() data: string): string {
return data;
}
}
I set above gateway as a provider to a module.
events.module.ts
import { Module } from "#nestjs/common";
import { EventsGateway } from "./events.gateway";
#Module({
providers: [EventsGateway],
})
export class EventsModule {}
Fianllt, i imported above module to the app.module.ts and now I am getting the error
app.module.ts
import { Module } from "#nestjs/common";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";
import { APP_FILTER } from "#nestjs/core";
import { AllExceptionFilter } from "./all-exception.filter";
import { ConfigModule } from "#nestjs/config";
import { TypeOrmModule } from "#nestjs/typeorm";
import { Student } from "./student/entities/student.entity";
import { EventsModule } from "./events/events.module";
#Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forRoot({
type: "postgres",
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT as string) | 5432,
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
entities: [Student],
synchronize: true,
}),
EventsModule,
],
controllers: [AppController],
providers: [
{
provide: APP_FILTER,
useClass: AllExceptionFilter,
},
AppService,
],
})
export class AppModule {}
This is the error I am keep getting.
TypeError: this.graphInspector.insertEntrypointDefinition is not a function
at /home/Desktop/New Folder/nest_try_1/node_modules/#nestjs/websockets/web-sockets-controller.js:108:33
at Array.forEach (<anonymous>)
at WebSocketsController.inspectEntrypointDefinitions (/home/Desktop/New Folder/nest_try_1/node_modules/#nestjs/websockets/web-sockets-controller.js:106:25)
at WebSocketsController.subscribeToServerEvents (/home/Desktop/New Folder/nest_try_1/node_modules/#nestjs/websockets/web-sockets-controller.js:39:14)
at WebSocketsController.connectGatewayToServer (/home/Desktop/New Folder/nest_try_1/node_modules/#nestjs/websockets/web-sockets-controller.js:30:14)
at SocketModule.connectGatewayToServer (/home/Desktop/New Folder/nest_try_1/node_modules/#nestjs/websockets/socket-module.js:47:35)
at /home/Desktop/New Folder/nest_try_1/node_modules/#nestjs/websockets/socket-module.js:36:38
at IteratorWithOperators.forEach (/home/Desktop/New Folder/nest_try_1/node_modules/iterare/lib/iterate.js:157:13)
at SocketModule.connectAllGateways (/home/Desktop/New Folder/nest_try_1/node_modules/#nestjs/websockets/socket-module.js:36:14)
at /home/Desktop/New Folder/nest_try_1/node_modules/#nestjs/websockets/socket-module.js:31:61
Node.js v19.4.0
I am follwing the documentation and I am keep getting above error.
you should align your dependencies, ie., if you're using #nestjs/websockets v9.3.1, #nestjs/core must be in v9.3.1 as well
Run npx nest info and check that out.
That error is because #nestjs/websockets is invoking a method added in v9.3 which depends on a method added in v9.3 of #nestjs/core as well.
btw there are closed issues on GitHub about that error: https://github.com/nestjs/nest/issues?q=is%3Aissue+sort%3Aupdated-desc+is%3Aclosed+insertEntrypointDefinition

Running Nestjs version 9 with Graphql and apollo server v4 gives Error: Cannot find module 'apollo-server-core'

I am trying to build a nestjs graphql with federation Schema with schema first approach monorepo of two microservices AUTH and LEDGER and a GATEWAY the AUTH microservice appModule.ts looks like this:
import { AuthModule } from './../auth/auth.module';
import { Module } from '#nestjs/common';
import { GraphQLModule } from '#nestjs/graphql';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { join } from 'path';
import { ApolloFederationDriver, ApolloFederationDriverConfig } from '#nestjs/apollo';
#Module({
imports: [
GraphQLModule.forRoot<ApolloFederationDriverConfig>({
driver: ApolloFederationDriver,
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
context: ({ req }) => ({ req }),
useGlobalPrefix: true,
}),
AuthModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
However I keep getting Error: Cannot find module 'apollo-server-core'. Now I am not using apollo-server-core directly I am using apollo/server v4 and V10 of nest/graphql and nest/apollo. I also understand that nestjs v9 may not be updated to apollo/server v4. can anyone shed some light on this?...what is causing this error? is there a workaround?
At this time, nestjs is not compatible with v4. You can check this: https://github.com/nestjs/graphql/issues/2445

Nestjs displays error during production that: "Persisted queries are enabled and are using an unbounded cache."

Nestjs application does not display the error message during development only during production. I found no module where the apollo -server can be configured to cache: "bounded". The Nestjs documentation itself makes no mention of it anywhere.
The complete error message says:
Persisted queries are enabled and are using an unbounded cache. Your server is vulnerable to denial of service attacks via memory exhaustion. Set cache: "bounded" or persistedQueries: false in your ApolloServer constructor, or see https://go.apollo.dev/s/cache-backends for other alternatives.
Here are some dependencies I suspect could be related to it.
"#nestjs/apollo": "10.0.19",
"#nestjs/common": "9.0.5",
"#nestjs/core": "9.0.5",
"#nestjs/graphql": "10.0.20",
A similar issue was opened at github and sadly it was closed without any solution.
This is related to the Apollo module's configuration, by default the cache is "unbounded" and not safe for production (see : https://www.apollographql.com/docs/apollo-server/performance/cache-backends/#ensuring-a-bounded-cache)
You can easily follow their recommendation by adding the optional "cache" configuration inside your GraphQL module.
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
cache: 'bounded', // <--- This option
...
}
Or provide an external caching with KeyvAdapter see: https://github.com/apollographql/apollo-utils/tree/main/packages/keyvAdapter#keyvadapter-class
In the app.module.ts inside the import array,
GraphQLModule.forRootAsync<ApolloDriverConfig>({
driver: ApolloDriver,
useClass: GqlConfigService,
}),
Then in the GqlConfigService I add cache: 'bounded' in the ApolloDriverConfig options.
import { ConfigService } from '#nestjs/config';
import { ApolloDriverConfig } from '#nestjs/apollo';
import { Injectable } from '#nestjs/common';
import { GqlOptionsFactory } from '#nestjs/graphql';
import { GraphqlConfig } from './config.interface';
#Injectable()
export class GqlConfigService implements GqlOptionsFactory {
constructor(private configService: ConfigService) {}
createGqlOptions(): ApolloDriverConfig {
const graphqlConfig = this.configService.get<GraphqlConfig>('graphql');
return {
// schema options
cache: 'bounded', // ! <== Added here
autoSchemaFile: graphqlConfig.schemaDestination || './src/schema.graphql',
sortSchema: graphqlConfig.sortSchema,
buildSchemaOptions: {
numberScalarMode: 'integer',
},
// subscription
installSubscriptionHandlers: true,
debug: graphqlConfig.debug,
playground: graphqlConfig.playgroundEnabled,
context: ({ req }) => ({ req }),
};
}
}

When I run nest.js, I get a Missing "driver" option error

I am using nest.js, prisma, and graphql.
When I run the npm run start:dev command, I get an error.
If anyone knows how to solve this, please let me know.
ERROR [GraphQLModule] Missing
"driver" option. In the latest version of "#nestjs/graphql" package
(v10) a new required configuration property called "driver" has been
introduced. Check out the official documentation for more details on
how to migrate (https://docs.nestjs.com/graphql/migration-guide).
Example:
GraphQLModule.forRoot({
driver: ApolloDriver,
})
app.module.ts
import { Module } from '#nestjs/common';
import { GraphQLModule } from '#nestjs/graphql';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
import { DonationsModule } from './donations/donations.module';
#Module({
imports: [
GraphQLModule.forRoot({
playground: false,
plugins: [ApolloServerPluginLandingPageLocalDefault()],
typePaths: ['./**/*.graphql'],
}),
DonationsModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
generate-typings.ts
import { GraphQLDefinitionsFactory } from '#nestjs/graphql';
import { join } from 'path';
const definitionsFactory = new GraphQLDefinitionsFactory();
definitionsFactory.generate({
typePaths: ['./src/**/*.graphql'],
path: join(process.cwd(), 'src/graphql.ts'),
outputAs: 'class',
watch: true,
});
fix
#Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: true,
plugins: [ApolloServerPluginLandingPageLocalDefault()],
typePaths: ['./**/*.graphql'],
}),
DonationsModule,
],
controllers: [AppController],
providers: [AppService],
})
Checkout the nestjs/graphql documentation page and the other link that you have mentioned. You have to configure your GraphQLModule like this which I don't see in your code.
#Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
}),
],
})
Also don't forget to import
import { ApolloDriverConfig, ApolloDriver } from '#nestjs/apollo';

document is not defined when do "tns test android"

I create a login.component.spec.ts for my loginComponent. However, when I run tns test android, the TestBed.createComponent(LoginComponent) failed. The error is below:
NativeScript / 29 (10; Android SDK built for x86) LoginComponent
Should create the app FAILED
Failed: StaticInjectorError(DynamicTestModule)[TestComponentRenderer
-> InjectionToken DocumentToken]:
StaticInjectorError(Platform: core)[TestComponentRenderer ->
InjectionToken DocumentToken]: document is not defined
error properties: Object({ ngTempTokenPath: null, ngTokenPath: [
'TestComponentRenderer', InjectionToken DocumentToken ] }) at Jasmine
I cannot find any result in website about my problem. Thanks for helping.
I tried to include http module since someone said the undefined document may because of http. However, it still does not work.
This is code for login.component.spec.ts:
import "core-js";
import "zone.js/dist/zone";
import "zone.js/dist/proxy";
import "zone.js/dist/sync-test";
import "zone.js/dist/async-test";
import "zone.js/dist/fake-async-test";
import "zone.js/dist/jasmine-patch";
import "zone.js/dist/long-stack-trace-zone";
import { ComponentFixture, async, TestBed} from '#angular/core/testing';
import { By } from '#angular/platform-browser';
import { NO_ERRORS_SCHEMA, DebugElement} from '#angular/core';
import { RouterTestingModule } from '#angular/router/testing';
import { Router } from '#angular/router';
import { ActivatedRoute } from "#angular/router";
import { RouterExtensions } from "nativescript-angular/router";
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting }
from '#angular/platform-browser-dynamic/testing';
import { LoginComponent } from '~/pages/login/login.component';
describe ('LoginComponent', () => {
beforeEach(async( () => {
TestBed.resetTestEnvironment();
TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
providers: [],
declarations: [
LoginComponent
],
schemas: [
NO_ERRORS_SCHEMA]
}).compileComponents();
}));
it('Should create the app', async( () => {
const fixture = TestBed.createComponent(LoginComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
});
You are using the BrowserDynamicTestingModule which is not valid for {N}. You are suppose to use NativeScriptTestingModule form nativescript-angular/testing.

Resources