Series Navigation
Player Subgraph (Node.js)
Now, let's create the Nest.js subgraph
nx add @nx/nest
nx g @nx/nest:app apps/player-service
Let's add some dependencies:
pnpm i @nestjs/graphql graphql graphql-yoga @graphql-yoga/nestjs-federation
We're going to be using the GraphQL Yoga server here, because NestJS's federated Apollo configuration doesn't allow for subscriptions -- fun fact (mainly because Apollo charges for federated subscriptions, and we can get that for free if we use Hive Gateway over the Apollo Router).
If you need higher throughput on your router, Wundergraph's Router is free and it's in Golang. I've used it before, but my use-case only required Hive Gateway -- for now.
Anyhow, here's how we set up our src/app.module.ts
with the GraphQL module configured for graphql-yoga
:
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import {
YogaFederationDriver,
YogaFederationDriverConfig,
} from '@graphql-yoga/nestjs-federation';
import { PlayerModule } from './player/player.module';
@Module({
imports: [
GraphQLModule.forRoot<YogaFederationDriverConfig>({
driver: YogaFederationDriver,
autoSchemaFile: {
federation: {
version: 2,
// required for federated subscriptions
importUrl: 'https://specs.apollo.dev/federation/v2.4',
},
},
subscriptions: true,
}),
PlayerModule,
],
})
export class AppModule {}
For our player
module, we need our resolver in src/player/player.resolver.ts
:
import { Args, Mutation, Resolver, Subscription } from '@nestjs/graphql';
import { Player } from './player.model';
import { createPubSub, Repeater } from 'graphql-yoga';
const pubSub = createPubSub();
@Resolver(() => Player)
export class PlayerResolver {
@Mutation(() => Player)
enterArea(
@Args('playerId') playerId: string,
@Args('area') area: string
): Player {
pubSub.publish(`${area}`, { id: playerId });
return { id: playerId };
}
@Subscription(() => Player, {
nullable: true,
resolve: (value: Player) => value,
})
nearbyPlayers(@Args('area') area: string): Repeater<Player> {
return pubSub.subscribe(`${area}`);
}
}
Now, we need our entity that we're resolving in src/player/player.model.ts
:
import { Field, ID, ObjectType } from '@nestjs/graphql';
@ObjectType()
export class Player {
@Field(() => ID)
id: string;
}
Let's tie it together in src/player/player.module.ts
:
import { Module } from '@nestjs/common';
import { PlayerResolver } from './player.resolver';
@Module({
providers: [PlayerResolver],
})
export class PlayerModule {}
As with the above services, you'll boot this up and migrate to the proper URL and test it out with multiple browser tabs open:
subscription NearbyPlayers {
nearbyPlayers(area: "forest") {
id
}
}
mutation {
enterArea(playerId: "1243", area: "forest"){
id
}
}
Now, let's move onto the final part: tying it all together with Hive Gateway in part 4!
Top comments (0)