Skip to content

Commit

Permalink
feat(nestjs): update to NestJS v9/10 and Federation v2
Browse files Browse the repository at this point in the history
  • Loading branch information
MichalLytek committed Jan 11, 2023
1 parent d28a95c commit 3fc0038
Show file tree
Hide file tree
Showing 109 changed files with 4,698 additions and 10,814 deletions.
5 changes: 4 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"arrowParens": "avoid",
"trailingComma": "all"
"trailingComma": "all",
"bracketSameLine": false,
"bracketSpacing": true,
"semi": true
}
31 changes: 15 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { authChecker } from "./auth";
@Module({
imports: [
TypeGraphQLModule.forRoot({
driver: ApolloDriver,
emitSchemaFile: true,
validate: false,
authChecker,
Expand Down Expand Up @@ -112,6 +113,7 @@ Example of using the config service to generate `TypeGraphQLModule` options:
TypeGraphQLModule.forRootAsync({
inject: [ConfigService],
useFactory: async (config: ConfigService) => ({
driver: ApolloDriver,
cors: true,
debug: config.isDevelopmentMode,
playground: !config.isDevelopmentMode,
Expand All @@ -126,13 +128,13 @@ Example of using the config service to generate `TypeGraphQLModule` options:
export default class AppModule {}
```

### `TypeGraphQLFederationModule`
### Apollo Federation

`typegraphql-nestjs` has also support for [Apollo Federation](https://www.apollographql.com/docs/federation/).

However, Apollo Federation requires building a federated GraphQL schema, hence you need to use the `TypeGraphQLFederationModule` module, designed specially for that case.
However, Apollo Federation requires building a federated GraphQL schema, hence you need to adjust your code a bit.

The usage is really similar to the basic `TypeGraphQLModule` - the only different is that `.forFeature()` method has an option to provide `referenceResolvers` object which is needed in some cases of Apollo Federation:
The usage is really similar to the basic case - the only difference is that in `TypeGraphQLModule.forFeature()` method you can provide a `referenceResolvers` option object, which is needed in some cases of Apollo Federation:

```ts
function resolveUserReference(
Expand All @@ -143,7 +145,7 @@ function resolveUserReference(

@Module({
imports: [
TypeGraphQLFederationModule.forFeature({
TypeGraphQLModule.forFeature({
orphanedTypes: [User],
referenceResolvers: {
User: {
Expand All @@ -157,25 +159,22 @@ function resolveUserReference(
export default class AccountModule {}
```

The `.forRoot()` method has no differences but you should provide the `skipCheck: true` option as federated schema can violate the standard GraphQL schema rules like at least one query defined:
For the `.forRoot()` method there's no differences - just need to provide `driver: ApolloFederationDriver` option in order to build a subgraph schema, same as with `GraphQLModule` from `@nestjs/graphql` described in the [NestJS docs](https://docs.nestjs.com/graphql/federation). However, you also need to explicitly setup federation version, by using `federationVersion` option:

```ts
@Module({
imports: [
TypeGraphQLFederationModule.forRoot({
validate: false,
skipCheck: true,
TypeGraphQLModule.forRoot({
driver: ApolloFederationDriver,
federationVersion: 2,
}),
AccountModule,
],
})
export default class AppModule {}
```

> Be aware that you cannot mix `TypeGraphQLFederationModule.forRoot()` with the base `TypeGraphQLModule.forFeature()` one.
> You need to consistently use only `TypeGraphQLFederationModule` across all modules.
Then, for exposing the federated schema using Apollo Gateway, you should use the standard NestJS [GraphQLGatewayModule](https://docs.nestjs.com/graphql/federation#federated-example-gateway).
Then, for exposing the federated schema using Apollo Gateway, you should use the standard [NestJS `ApolloGatewayDriver` solution](https://docs.nestjs.com/graphql/federation#federated-example-gateway).

## Caveats

Expand All @@ -201,13 +200,13 @@ You can see some examples of the integration in this repo:

Usage of request scoped dependencies - retrieving fresh instances of resolver and service classes on every request (query/mutation)

1. [Apollo Federation](https://github.com/MichalLytek/typegraphql-nestjs/tree/master/examples/4-federation)
1. [Middlewares](https://github.com/MichalLytek/typegraphql-nestjs/tree/master/examples/4-middlewares)

Showcase of Apollo Federation approach, using the `TypeGraphQLFederationModule` and `GraphQLGatewayModule`.
Usage of class-based middlewares - modules, providers and schema options

1. [Middlewares](https://github.com/MichalLytek/typegraphql-nestjs/tree/master/examples/5-middlewares)
1. [Apollo Federation](https://github.com/MichalLytek/typegraphql-nestjs/tree/master/examples/5-federation)

Usage of class-based middlewares - modules, providers and schema options
Showcase of Apollo Federation approach

You can run them by using `ts-node`, like `npx ts-node ./examples/1-basics/index.ts`.

Expand Down
5 changes: 4 additions & 1 deletion examples/1-basics/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { ApolloDriver, ApolloDriverConfig } from "@nestjs/apollo";
import { Module } from "@nestjs/common";
import { TypeGraphQLModule } from "../../src";

import RecipeModule from "./recipe/module";

@Module({
imports: [
// TypeGraphQLModule.forRoot<ApolloDriverConfig>({
TypeGraphQLModule.forRoot({
driver: ApolloDriver,
emitSchemaFile: true,
validate: false,
}),
RecipeModule,
],
})
export default class AppModule {}
export default class AppModule { }
10 changes: 5 additions & 5 deletions examples/1-basics/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import "reflect-metadata";
import { NestFactory } from "@nestjs/core";
import {
NestFastifyApplication,
FastifyAdapter,
} from "@nestjs/platform-fastify";
NestExpressApplication,
ExpressAdapter,
} from "@nestjs/platform-express";

import AppModule from "./app.module";

async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(
const app = await NestFactory.create<NestExpressApplication>(
AppModule,
new FastifyAdapter(),
new ExpressAdapter(),
);

await app.listen(3000);
Expand Down
2 changes: 1 addition & 1 deletion examples/1-basics/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ type Recipe {
input RecipeInput {
description: String
title: String!
}
}
2 changes: 1 addition & 1 deletion examples/2-multiple-servers/first-schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ type SuperRecipe {
description: String
isSuperRecipe: Boolean!
title: String!
}
}
4 changes: 3 additions & 1 deletion examples/2-multiple-servers/first.module.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ApolloDriver } from "@nestjs/apollo";
import { Module } from "@nestjs/common";
import path from "path";
import { TypeGraphQLModule } from "../../src";
Expand All @@ -7,10 +8,11 @@ import RecipeModule from "./recipe/module";
@Module({
imports: [
TypeGraphQLModule.forRoot({
driver: ApolloDriver,
emitSchemaFile: path.resolve(__dirname, "first-schema.graphql"),
validate: false,
}),
RecipeModule,
],
})
export default class FirstAppModule {}
export default class FirstAppModule { }
14 changes: 7 additions & 7 deletions examples/2-multiple-servers/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import "reflect-metadata";
import { NestFactory } from "@nestjs/core";
import {
NestFastifyApplication,
FastifyAdapter,
} from "@nestjs/platform-fastify";
NestExpressApplication,
ExpressAdapter,
} from "@nestjs/platform-express";

import FirstAppModule from "./first.module";
import SecondAppModule from "./second.module";

async function bootstrap() {
const firstApp = await NestFactory.create<NestFastifyApplication>(
const firstApp = await NestFactory.create<NestExpressApplication>(
FirstAppModule,
new FastifyAdapter(),
new ExpressAdapter(),
);
const secondApp = await NestFactory.create<NestFastifyApplication>(
const secondApp = await NestFactory.create<NestExpressApplication>(
SecondAppModule,
new FastifyAdapter(),
new ExpressAdapter(),
);

await firstApp.listen(3001);
Expand Down
2 changes: 1 addition & 1 deletion examples/2-multiple-servers/second-schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ type SuperAnimal {
isSuperHero: Boolean!
name: String!
weight: Int!
}
}
4 changes: 3 additions & 1 deletion examples/2-multiple-servers/second.module.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ApolloDriver } from "@nestjs/apollo";
import { Module } from "@nestjs/common";
import path from "path";
import { TypeGraphQLModule } from "../../src";
Expand All @@ -7,10 +8,11 @@ import AnimalModule from "./animal/module";
@Module({
imports: [
TypeGraphQLModule.forRoot({
driver: ApolloDriver,
emitSchemaFile: path.resolve(__dirname, "second-schema.graphql"),
validate: false,
}),
AnimalModule,
],
})
export default class SecondAppModule {}
export default class SecondAppModule { }
4 changes: 3 additions & 1 deletion examples/3-request-scoped/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ApolloDriver } from "@nestjs/apollo";
import { Module } from "@nestjs/common";
import { TypeGraphQLModule } from "../../src";

Expand All @@ -6,10 +7,11 @@ import RecipeModule from "./recipe/module";
@Module({
imports: [
TypeGraphQLModule.forRoot({
driver: ApolloDriver,
emitSchemaFile: true,
validate: false,
}),
RecipeModule,
],
})
export default class AppModule {}
export default class AppModule { }
10 changes: 5 additions & 5 deletions examples/3-request-scoped/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import "reflect-metadata";
import { NestFactory } from "@nestjs/core";
import {
NestFastifyApplication,
FastifyAdapter,
} from "@nestjs/platform-fastify";
NestExpressApplication,
ExpressAdapter,
} from "@nestjs/platform-express";

import AppModule from "./app.module";

async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(
const app = await NestFactory.create<NestExpressApplication>(
AppModule,
new FastifyAdapter(),
new ExpressAdapter(),
);

await app.listen(3000);
Expand Down
2 changes: 1 addition & 1 deletion examples/3-request-scoped/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ type Recipe {
input RecipeInput {
description: String
title: String!
}
}
16 changes: 0 additions & 16 deletions examples/4-federation/Readme.md

This file was deleted.

24 changes: 0 additions & 24 deletions examples/4-federation/app.module.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Module } from "@nestjs/common";
import { ApolloDriver } from "@nestjs/apollo";
import { TypeGraphQLModule } from "../../src";
import { LoggingMiddleware } from "./logging/middleware";

Expand All @@ -8,6 +9,7 @@ import LoggingModule from "./logging/module";
@Module({
imports: [
TypeGraphQLModule.forRoot({
driver: ApolloDriver,
emitSchemaFile: true,
validate: false,
// register middlewares in settings
Expand All @@ -18,4 +20,4 @@ import LoggingModule from "./logging/module";
LoggingModule,
],
})
export default class AppModule {}
export default class AppModule { }
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import "reflect-metadata";
import { NestFactory } from "@nestjs/core";
import {
NestFastifyApplication,
FastifyAdapter,
} from "@nestjs/platform-fastify";
NestExpressApplication,
ExpressAdapter,
} from "@nestjs/platform-express";

import AppModule from "./app.module";

async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(
const app = await NestFactory.create<NestExpressApplication>(
AppModule,
new FastifyAdapter(),
new ExpressAdapter(),
);

await app.listen(3000);
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ type Recipe {
input RecipeInput {
description: String
title: String!
}
}
16 changes: 16 additions & 0 deletions examples/5-federation/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## Apollo Federation

Showcase of Apollo Federation approach, using the `ApolloGatewayDriver`.

### How to run?

This example is a bit more complex than the other ones.

Apart from running the main `index.ts` file by e.g. `npx ts-node ./examples/6-federation-2/index.ts`, you also need to run all the other services first:

- `npx ts-node ./examples/6-federation-2/accounts/index.ts`
- `npx ts-node ./examples/6-federation-2/inventory/index.ts`
- `npx ts-node ./examples/6-federation-2/products/index.ts`
- `npx ts-node ./examples/6-federation-2/reviews/index.ts`

They will be listening on ports 3001-3004 and the main script on port 3000.
Loading

0 comments on commit 3fc0038

Please sign in to comment.