plugins/src/nestjs/skills/nestjs-graphql/SKILL.md
Comprehensive guide for NestJS GraphQL development using Apollo and code-first approach. This skill should be used when writing GraphQL resolvers, mutations, queries, types, subscriptions, or implementing advanced features like field middleware, complexity limits, and custom scalars. Also covers project-specific patterns including zero-trust auth decorators and DataLoader integration.
npx skillsauth add codyswanngt/lisa nestjs-graphqlInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill provides comprehensive guidance for building GraphQL APIs with NestJS using Apollo Server and the code-first approach. It covers official NestJS GraphQL patterns plus project-specific implementations for authentication, authorization, and data loading.
| Decorator | Purpose | Import |
|-----------|---------|--------|
| @Resolver() | Define resolver class | @nestjs/graphql |
| @Query() | Define query operation | @nestjs/graphql |
| @Mutation() | Define mutation operation | @nestjs/graphql |
| @Args() | Extract arguments | @nestjs/graphql |
| @Context() | Access GraphQL context | @nestjs/graphql |
| @Parent() | Access parent in field resolver | @nestjs/graphql |
| @ResolveField() | Define field resolver | @nestjs/graphql |
| @ObjectType() | Define GraphQL object type | @nestjs/graphql |
| @InputType() | Define GraphQL input type | @nestjs/graphql |
| @Field() | Define field on type | @nestjs/graphql |
| @Extensions() | Attach metadata to fields | @nestjs/graphql |
| Decorator | GraphQL Type | TypeScript Type |
|-----------|-------------|-----------------|
| @Field(() => String) | "String!" | string |
| @Field(() => Int) | "Int!" | number |
| @Field(() => Float) | "Float!" | number |
| @Field(() => Boolean) | "Boolean!" | boolean |
| @Field(() => ID) | "ID!" | string |
| @Field(() => [String]) | "[String!]!" | string[] |
| @Field({ nullable: true }) | String | string \| null |
import { Args, Context, Mutation, Query, Resolver } from "@nestjs/graphql";
import { Public, Authed } from "../auth";
@Resolver(() => Entity)
export class EntityResolver {
constructor(private readonly entityService: EntityService) {}
@Query(() => Entity, { description: "Retrieve entity by ID" })
@Authed()
async entity(@Args("id", { type: () => ID }) id: string): Promise<Entity> {
return this.entityService.findById(id);
}
@Mutation(() => Entity, { description: "Create new entity" })
@Authed()
async createEntity(
@Args("input") input: CreateEntityInput,
@Context() { req }: GraphQLContext
): Promise<Entity> {
return this.entityService.create(input, req.user.id);
}
}
import { Field, ID, ObjectType } from "@nestjs/graphql";
@ObjectType({ description: "Represents a user in the system" })
export class User {
@Field(() => ID, { description: "Unique identifier" })
id: string;
@Field(() => String, { description: "User's email address" })
email: string;
@Field(() => String, { nullable: true, description: "Display name" })
displayName?: string;
@Field(() => Date, { description: "Account creation timestamp" })
createdAt: Date;
}
import { Field, InputType } from "@nestjs/graphql";
@InputType({ description: "Input for creating a new user" })
export class CreateUserInput {
@Field(() => String, { description: "User's email address" })
email: string;
@Field(() => String, { description: "User's password" })
password: string;
@Field(() => String, { nullable: true, description: "Optional display name" })
displayName?: string;
}
This skill includes detailed reference files for specific topics:
Setup and configuration for NestJS GraphQL with Apollo driver, module configuration, and code-first vs schema-first approaches.
Comprehensive guide to writing resolvers, queries, mutations, field resolvers, and using decorators like @Args, @Context, @Parent.
Creating object types, input types, enums, interfaces, unions, and custom scalars. Includes mapped types (PartialType, PickType, etc.).
Field middleware, query complexity, plugins, subscriptions, and extensions.
Project-specific patterns including zero-trust auth decorators (@Public, @Authed, @Owner, @Groups), DataLoader integration, and GraphQL documentation standards.
@Query() decorator@Public(), @Authed(), or @Groups())@Query(() => ReturnType)@Query(() => ReturnType, { description: "..." })@Args() for parameters with descriptions@Mutation() decorator@Authed())@Context() { req }: GraphQLContext@ResolveField(() => [Comment], { description: "Entity's comments" })
async comments(
@Parent() entity: Entity,
@Context() { loaders }: GraphQLContext
): Promise<Comment[]> {
return loaders.commentsLoader.load(entity.id);
}
getByIds(ids: string[]): Promise<Entity[]>IDataLoaders interfaceDataLoaderService.getLoaders()loaders.entityLoader.load(id)See references/project-patterns.md for detailed DataLoader patterns.
documentation
Onboard a user to the project via its LLM Wiki. Interviews the user about themselves in relation to the project, captures that to project-scoped memory only, then gives a guided tour of what the project is and sample questions they can ask. Use when someone is new to the project or asks to be onboarded. Read-mostly — it does not open PRs or write PII into the wiki.
documentation
Migrate an existing, hand-rolled wiki implementation onto the lisa-wiki kernel — phased and compatibility-first, with a strict no-loss guarantee. Use when adopting lisa-wiki in a repo that already has its own wiki/, ingest skills, docs, or roles. Renaming things into the canonical shape is fine; losing functionality or data is not. Ends by running /doctor.
development
Health-check the LLM Wiki. Reports orphan pages, contradictions, stale claims, broken internal links, missing index/log coverage, structure-manifest violations, and secret/tenant leaks. Use periodically or before hardening a wiki. Read-only — it reports findings, it does not fix them.
testing
Ingest source material into the LLM Wiki. With an argument (URL, file path, or prompt) it ingests that one source; with no argument it runs a full ingest across every enabled non-external-write source. Routes to the right connector, then runs the ordered pipeline (source note → synthesis → index → log → verify → state → commit/PR). Use whenever new knowledge should enter the wiki.