The schema-first approach helps you design your data and API structure first using a clear schema. This makes it easy to understand and share how your API works before writing code.
Schema-first approach in NestJS
type Query { hello: String } type Mutation { setMessage(message: String): String }
type Query {
greet(name: String): String
}type Mutation {
updateAge(age: Int): Boolean
}This NestJS module sets up GraphQL with a schema-first approach by generating the schema file automatically. The resolver defines the Query and Mutation fields matching the schema. The hello query returns a message, and setMessage mutation updates it.
import { Module } from '@nestjs/common'; import { GraphQLModule } from '@nestjs/graphql'; import { join } from 'path'; import { Resolver, Query, Mutation, Args } from '@nestjs/graphql'; // Resolver implementing schema fields @Resolver() export class AppResolver { private message = 'Hello World!'; @Query(() => String) hello() { return this.message; } @Mutation(() => String) setMessage(@Args('message') message: string) { this.message = message; return this.message; } } @Module({ imports: [ GraphQLModule.forRoot({ autoSchemaFile: join(process.cwd(), 'src/schema.gql'), // Using schema-first means you can also provide a schema file here }), ], providers: [AppResolver], }) export class AppModule {}
Schema-first means you start by writing the GraphQL schema, then write resolvers to match it.
You can generate the schema file automatically or write it manually and load it.
This approach helps teams agree on API design early.
Schema-first approach means designing your API schema before coding.
It uses GraphQL SDL to define types, queries, and mutations.
Resolvers implement the schema fields in NestJS.
Practice
Schema-first approach in NestJS GraphQL?Solution
Step 1: Understand Schema-first approach concept
Schema-first means you write the GraphQL schema (types, queries, mutations) before coding the logic.Step 2: Match resolvers to schema
Resolvers are then implemented to fulfill the schema's fields and operations.Final Answer:
Define the GraphQL schema first, then write resolvers to match it -> Option CQuick Check:
Schema-first = Define schema first [OK]
- Thinking resolvers come before schema
- Confusing schema-first with code-first
- Assuming REST is involved
- Skipping schema definition
Solution
Step 1: Recognize GraphQL SDL syntax
GraphQL SDL defines types with the keywordtypefollowed by fields and their types.Step 2: Check each option
type User { id: ID! name: String! } uses correct SDL syntax. Options B and C use TypeScript syntax, and A uses invalid keywordschemafor type definition.Final Answer:
type User { id: ID! name: String! } -> Option AQuick Check:
SDL type syntax = type User { id: ID! name: String! } [OK]
- Using TypeScript syntax instead of SDL
- Confusing 'schema' keyword with 'type'
- Omitting exclamation marks for required fields
type Query { hello: String! }And this resolver in NestJS:
@Resolver('Query')
export class HelloResolver {
@Query()
hello() {
return 'Hi there!';
}
}What will be the result of querying
{ hello }?Solution
Step 1: Match schema and resolver
The schema defines a Query fieldhelloreturning a non-null String. The resolver implements a methodhello()returning 'Hi there!'.Step 2: Query execution result
When querying{ hello }, the resolver returns 'Hi there!', so the response is the string "Hi there!".Final Answer:
"Hi there!" -> Option AQuick Check:
Schema and resolver match = returns 'Hi there!' [OK]
- Not matching resolver method name to schema field
- Returning undefined or null in resolver
- Missing @Query decorator
@Resolver('Query')
export class UserResolver {
@Query()
user(id: string) {
return { id, name: 'Alice' };
}
}Assuming the schema defines
user(id: ID!): User.Solution
Step 1: Check resolver method parameters
The resolver methoduserexpects an argumentid. In NestJS schema-first, arguments must be decorated with@Args()to map schema args.Step 2: Identify missing decorator
The code misses@Args('id')before theidparameter, so NestJS won't pass the argument correctly.Final Answer:
Missing @Args decorator for the id parameter -> Option BQuick Check:
Arguments need @Args decorator [OK]
- Forgetting @Args decorator on parameters
- Wrong resolver class naming (not required)
- Returning wrong types
- Thinking schema can't have arguments
type Mutation {
updateUser(id: ID!, name: String): User
}
type User {
id: ID!
name: String!
}Which resolver implementation correctly updates the user name and returns the updated user in NestJS?
Solution
Step 1: Match resolver signature to schema
The schema definesupdateUser(id: ID!, name: String): User. The resolver must use@Args('id')and optional@Args('name')parameters.Step 2: Check update logic and return
@Mutation() updateUser(@Args('id') id: string, @Args('name') name?: string) { const user = users.find(u => u.id === id); if (user && name) user.name = name; return user; } finds the user by id, updates name only if provided, and returns the user object, matching schema and logic.Step 3: Analyze other options
@Mutation() updateUser(id: string, name: string) { const user = users.find(u => u.id === id); user.name = name; return user; } misses @Args decorators, so arguments won't map. @Mutation() updateUser(@Args() args) { const user = users.find(u => u.id === args.id); user.name = args.name; return user; } uses @Args() args but does not check if user exists before setting user.name, causing runtime error if user not found. @Mutation() updateUser(@Args('id') id: string, @Args('name') name: string) { return { id, name }; } returns a new object without updating the stored user.Final Answer:
The resolver using @Args('id') id: string, @Args('name') name?: string with conditional update logic -> Option DQuick Check:
Use @Args and update logic correctly [OK]
- Missing @Args decorators
- Not checking if user exists before update
- Returning new object without updating data
- Using @Args() without destructuring
Ready to prove it?
Pass the test and this pattern moves unknown
