Building a GraphQL API with NestJS Code-First Approach
📖 Scenario: You are creating a simple GraphQL API for a bookstore. You want to define your data models and GraphQL schema using code, not schema files.
🎯 Goal: Build a NestJS GraphQL API using the code-first approach. You will create a book model, configure GraphQL, write a resolver to fetch books, and complete the module setup.
📋 What You'll Learn
Create a Book class with id, title, and author fields using GraphQL decorators
Add a configuration variable books as an array of book objects
Write a resolver method getBooks that returns the books array
Complete the AppModule to import GraphQLModule with code-first setup and register the resolver
💡 Why This Matters
🌍 Real World
Many modern APIs use GraphQL to allow clients to request exactly the data they need. NestJS's code-first approach lets developers define GraphQL schemas using familiar TypeScript classes and decorators.
💼 Career
Understanding how to build GraphQL APIs with NestJS is valuable for backend developers working on scalable and flexible APIs in Node.js environments.
Progress0 / 4 steps
1
Create the Book model with GraphQL decorators
Create a class called Book with fields id (number), title (string), and author (string). Use @ObjectType() on the class and @Field() on each field from @nestjs/graphql.
NestJS
Hint
Use @ObjectType() above the class and @Field() above each property. For id, specify the type as Int.
2
Add a books array with sample data
Create a constant array called books with two book objects. Each object should have id, title, and author matching the Book class fields.
NestJS
Hint
Define books as an array of objects matching the Book structure.
3
Create a resolver with a query to get books
Create a class called BooksResolver. Use @Resolver(() => Book) on the class. Add a method getBooks decorated with @Query(() => [Book]) that returns the books array.
NestJS
Hint
Use @Resolver(() => Book) on the class and @Query(() => [Book]) on the method returning books.
4
Complete AppModule with GraphQLModule and resolver
In AppModule, import GraphQLModule from @nestjs/graphql and configure it with autoSchemaFile: true. Add BooksResolver to the providers array.
NestJS
Hint
Use GraphQLModule.forRoot({ autoSchemaFile: true }) in imports and add BooksResolver to providers.
Practice
(1/5)
1. What does the code-first approach in NestJS GraphQL primarily involve?
easy
A. Manually writing GraphQL schema files before coding
B. Using REST endpoints instead of GraphQL
C. Writing TypeScript classes and decorators to define GraphQL schema
D. Generating code from existing GraphQL schema files
Solution
Step 1: Understand code-first approach basics
The code-first approach means you write your GraphQL types and resolvers directly in TypeScript code using classes and decorators.
Step 2: Compare with other approaches
Unlike schema-first, you do not write schema files manually; instead, the schema is generated automatically from your code.
Final Answer:
Writing TypeScript classes and decorators to define GraphQL schema -> Option C
Quick Check:
Code-first = Define schema in code [OK]
Hint: Code-first means schema comes from your TypeScript classes [OK]
Common Mistakes:
Confusing code-first with schema-first approach
Thinking schema files must be manually written
Assuming REST is involved in code-first GraphQL
2. Which decorator is used in NestJS code-first approach to mark a class as a GraphQL object type?
easy
A. @ObjectType()
B. @Resolver()
C. @Query()
D. @Injectable()
Solution
Step 1: Identify decorator for GraphQL object type
In code-first, @ObjectType() marks a class as a GraphQL object type to generate schema.
Step 2: Differentiate from other decorators
@Resolver() marks resolver classes, @Query() marks query methods, and @Injectable() is for dependency injection, not schema types.
Final Answer:
@ObjectType() -> Option A
Quick Check:
@ObjectType = GraphQL type class [OK]
Hint: Use @ObjectType() for GraphQL types, not @Resolver() [OK]
Common Mistakes:
Using @Resolver() instead of @ObjectType() for types
Confusing @Query() with type decorators
Thinking @Injectable() defines GraphQL schema
3. Given this code-first resolver snippet, what will be the GraphQL query result for hello()?
The method hello() returns the string 'Hello, NestJS!'. The @Query decorator specifies the return type as String.
Step 2: Understand GraphQL query result
When queried, the hello field returns the string value wrapped in quotes as a valid GraphQL string response.
Final Answer:
"Hello, NestJS!" -> Option A
Quick Check:
hello() returns string 'Hello, NestJS!' [OK]
Hint: Resolver method return matches GraphQL query result [OK]
Common Mistakes:
Expecting null or undefined instead of returned string
Thinking missing return type causes runtime error
Confusing resolver method with schema definition
4. Identify the error in this code-first resolver snippet:
import { Query, Resolver } from '@nestjs/graphql';
@Resolver()
export class SampleResolver {
@Query()
sample() {
return 123;
}
}
medium
A. Method sample() should be async
B. Missing return type in @Query decorator
C. Resolver class missing @ObjectType decorator
D. Return value 123 is invalid in GraphQL
Solution
Step 1: Check @Query decorator usage
The @Query decorator requires a return type function, e.g., @Query(() => Int) or @Query(() => String).
Step 2: Identify missing return type
Here, @Query() is missing the return type, which causes schema generation errors.
Final Answer:
Missing return type in @Query decorator -> Option B
Quick Check:
@Query needs return type function [OK]
Hint: Always specify return type in @Query(() => Type) [OK]
Common Mistakes:
Omitting return type in @Query decorator
Adding @ObjectType to resolver class incorrectly
Assuming async is mandatory for resolver methods
5. You want to create a GraphQL object type with a field that is optional and nullable using the code-first approach. Which is the correct way to define the field in your class?
import { Field, ObjectType } from '@nestjs/graphql';
@ObjectType()
export class User {
@Field(() => String, { nullable: true })
nickname?: string;
}
What does this code do?
hard
A. Ignores the nickname field in the generated schema
B. Causes a schema error because optional fields are not allowed
C. Makes nickname required and non-nullable in the schema
D. Defines a User type with an optional nullable nickname field in GraphQL schema
Solution
Step 1: Understand @Field decorator options
The @Field decorator with { nullable: true } marks the field as nullable in GraphQL schema, allowing null values.
Step 2: Check TypeScript optional property
Using ? in nickname?: string means the property is optional in TypeScript, matching nullable in GraphQL.
Step 3: Confirm schema generation behavior
This combination correctly generates a GraphQL field that can be omitted or set to null without errors.
Final Answer:
Defines a User type with an optional nullable nickname field in GraphQL schema -> Option D
Quick Check:
nullable + optional = optional nullable field [OK]
Hint: Use @Field({ nullable: true }) and ? for optional nullable fields [OK]
Common Mistakes:
Omitting nullable option for optional fields
Confusing optional in TypeScript with required in GraphQL
Expecting errors for optional nullable fields
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.