Files
What you'll learn
- Recognise the four files every Nest application starts from and what each declares
- Register a provider in a module so Nest can inject it into a controller
- Read Nest's dependency error and its boot log to see what was and was not wired
First Steps
Nest is a framework for building backends in TypeScript on top of Node. Underneath it uses Express, the same library that answers most Node web requests, but it adds the thing Express leaves to you: structure. Every Nest application is a graph of classes, each with one job, and Nest builds the graph for you from the decorators on those classes. This course teaches that graph, one piece per lesson, in a real Nest application running in your browser.
The four files
main.ts is the entry point. It creates the application from a root module and starts listening:
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
NestFactory.create reads the root module and wires up everything the module declares, recursively. app.listen starts the HTTP server. In this browser runtime the port is a formality, but the call is still required: it is what tells the grader your application is ready.
app.module.ts is the root module. A module is a class with an @Module() decorator listing what belongs together:
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
controllershandle incoming requests.providersare the classes Nest can inject into other classes: services, repositories, helpers.importsbrings in other modules. You will meet it in lesson 4.
app.controller.ts maps routes to methods. @Controller() with no argument means "the root path", and @Get() on a method means "GET on that path":
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello() {
return { message: this.appService.getHello() };
}
}
app.service.ts holds the logic. @Injectable() marks the class as something Nest may construct and hand to whoever asks for it.
How the service reaches the controller
Look at the controller's constructor: constructor(private readonly appService: AppService). That parameter is a request. When Nest creates AppController it reads the parameter's type, finds a provider registered for AppService, and passes the instance in. Nobody writes new AppService(). This is dependency injection, and it is the idea the rest of this course builds on: classes declare what they need, and the module decides what they get.
It only works if the provider is registered somewhere Nest can see. Leave AppService out of providers and Nest refuses to start:
Nest can't resolve dependencies of the AppController (?).
Please make sure that the argument AppService at index [0] is available in the AppModule context.
Read that error closely once, because you will meet it for the rest of your Nest career. AppController is the class being built. (?) stands in for the argument Nest could not find, and "at index [0]" says it is the first constructor parameter. "Available in the AppModule context" names the module whose providers array needs the entry.
Returning JSON
A route handler that returns an object or an array sends it as JSON, with Content-Type: application/json. A handler that returns a string sends it as plain text. Real APIs return objects, so this course does too.
Reading the console
Press Run tests and Nest prints the same lines nest start prints on your machine: [NestFactory] Starting Nest application..., one [InstanceLoader] line per module it initialises, one [RouterExplorer] Mapped {/, GET} route line per route it finds, and [NestApplication] Nest application successfully started. Then the grader calls your endpoints and reports each one. When something does not work, the console is where the answer is: a route that is not mapped is a route Nest never saw.
Your task
Two things are missing from the starter code:
AppModuledoes not registerAppService, so the controller cannot be built.AppController.getHello()returns a placeholder instead of the service's greeting.
Fix both and run. Run once after fixing only the first, and compare what the console prints with the error above.
When it fails
Nest can't resolve dependencies of the AppController (?): the provider is not in the module'sprovidersarray.- The route answers
{"message":"TODO"}: the handler still returns the placeholder. The grader prints what it got next to what it expected. - A red line naming a file and a line number is a TypeScript error. Nest never starts an application that does not compile, and neither does this editor.
Remember
- A module lists the classes that belong together: controllers answer requests, providers do the work.
- A constructor parameter with a class type is a request to Nest, and Nest fulfils it from the module's providers.
- Return an object and Nest sends JSON.
Stuck? Show a hint
AppController asks for AppService in its constructor, so AppService has to be in the module's providers array. Then getHello() should return whatever the service's getHello() gives, inside { message }.
Press Run tests to start the app. Its log appears here.Graded endpoints
Returns the greeting from AppService as JSON