install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/codex/nestjs-graphql-integration" ~/.claude/skills/intense-visions-harness-engineering-nestjs-graphql-integration-38d086 && rm -rf "$T"
manifest:
agents/skills/codex/nestjs-graphql-integration/SKILL.mdsource content
NestJS GraphQL Integration
Build GraphQL APIs with GraphQLModule, @Resolver, @Query/@Mutation, @ObjectType, and DataLoader
When to Use
- You are building an API that needs flexible field selection to avoid over/under-fetching
- You have a complex domain with many interrelated entities and nested queries
- Your frontend needs real-time subscriptions alongside standard queries
- You want a strongly-typed schema generated from TypeScript classes (code-first approach)
Instructions
- Install and configure:
npm install @nestjs/graphql @nestjs/apollo @apollo/server graphql
@Module({ imports: [ GraphQLModule.forRoot<ApolloDriverConfig>({ driver: ApolloDriver, autoSchemaFile: join(process.cwd(), 'src/schema.gql'), sortSchema: true, playground: true, }), ], }) export class AppModule {}
- Define object types:
@ObjectType() export class User { @Field(() => ID) id: string; @Field() email: string; @Field({ nullable: true }) displayName?: string; @Field(() => [Post]) posts: Post[]; }
- Create a resolver:
@Resolver(() => User) export class UsersResolver { constructor( private usersService: UsersService, private postsService: PostsService ) {} @Query(() => User, { nullable: true }) user(@Args('id', { type: () => ID }) id: string): Promise<User | null> { return this.usersService.findOne(id); } @Query(() => [User]) users(): Promise<User[]> { return this.usersService.findAll(); } @Mutation(() => User) createUser(@Args('input') input: CreateUserInput): Promise<User> { return this.usersService.create(input); } @ResolveField(() => [Post]) posts(@Parent() user: User): Promise<Post[]> { return this.postsService.findByUser(user.id); } }
- Input types for mutations:
@InputType() export class CreateUserInput { @Field() @IsEmail() email: string; @Field() @MinLength(8) password: string; }
- DataLoader for N+1 prevention:
@Injectable({ scope: Scope.REQUEST }) export class PostsLoader { constructor(private postsService: PostsService) {} readonly loader = new DataLoader<string, Post[]>(async (userIds) => { const posts = await this.postsService.findByUserIds([...userIds]); return userIds.map((id) => posts.filter((p) => p.userId === id)); }); }
Details
Code-first vs schema-first: Code-first (above) generates the SDL from TypeScript decorators. Schema-first starts from a
.graphql file and maps resolvers to it. Code-first is preferred for TypeScript teams because types are unified.
explicit types: When TypeScript reflection cannot determine the type (arrays, enums, circular references), the explicit arrow function syntax is required. For nullable fields: @Field(() => Type)
@Field({ nullable: true }).
Auth on resolvers: Apply guards with
@UseGuards(JwtAuthGuard) on the class or individual query/mutation. Access the current user via @Context() ctx: GqlContext where ctx.req.user is populated by the guard.
Subscriptions: Add
installSubscriptionHandlers: true and use @Subscription(() => Post) with pubSub.asyncIterator('postCreated') for real-time updates via WebSocket.
Complexity and depth limiting: In production, configure
validationRules: [depthLimit(5), createComplexityRule(...)] to prevent expensive queries from exhausting server resources.
Source
https://docs.nestjs.com/graphql/quick-start
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.