Awesome
nestjs-project-structure
Node.js framework NestJS project structure
Started from this issue: nestjs/nest#2249
Alternatives
If you focus on the performance or features of the module, you can consider:
- Fastify instead of
Express
- Prisma or Sequelize or MikroORM instead of
TypeORM
- SWC instead of
TypeScript compiler
- Vitest instead of
Jest
Check out the nestjs-project-performance repository for examples using this alternative.
Configuration
- Create a
.env
file- Rename the .env.sample file to
.env
to fix it.
- Rename the .env.sample file to
- Edit env config
- Edit the file in the config/envs folder.
default
,development
,production
,test
Installation
# 1. node_modules
npm ci
# 2. When synchronize database from existing entities
npm run entity:sync
# 2-1. When import entities from an existing database
npm run entity:load
If you use multiple databases in entity:load
, modify them.
Development
npm run start:dev
# https://docs.nestjs.com/recipes/repl
npm run start:repl
Test
npm test # exclude e2e
npm run test:e2e
Production
npm run lint
npm run build
# define environment variable yourself.
# NODE_ENV=production PORT=8000 NO_COLOR=true node dist/app
node dist/app
# OR
npm start
Folders
+-- bin // Custom tasks
+-- dist // Source build
+-- public // Static Files
+-- src
| +-- config // Environment Configuration
| +-- entity // TypeORM Entities
| +-- auth // Authentication
| +-- common // Global Nest Module
| | +-- constants // Constant value and Enum
| | +-- controllers // Nest Controllers
| | +-- decorators // Nest Decorators
| | +-- dto // DTO (Data Transfer Object) Schema, Validation
| | +-- filters // Nest Filters
| | +-- guards // Nest Guards
| | +-- interceptors // Nest Interceptors
| | +-- interfaces // TypeScript Interfaces
| | +-- middleware // Nest Middleware
| | +-- pipes // Nest Pipes
| | +-- providers // Nest Providers
| | +-- * // models, repositories, services...
| +-- shared // Shared Nest Modules
| +-- gql // GraphQL Structure
| +-- * // Other Nest Modules, non-global, same as common structure above
+-- test // Jest testing
+-- typings // Modules and global type definitions
// Module structure
// Add folders according to module scale. If it's small, you don't need to add folders.
+-- src/greeter
| +-- * // folders
| +-- greeter.constant.ts
| +-- greeter.controller.ts
| +-- greeter.service.ts
| +-- greeter.module.ts
| +-- greeter.*.ts
| +-- index.ts
This is the most basic structure to start a NestJS project.
You should choose the right architecture<sup>[1]</sup> (Layered, Clean, Onion, Hexagonal ...)<sup>[2]</sup> based on the size of your project.
Implements
- See bootstrap, app.module
- Database, Module Router, Static Files, Validation, Pino Logger
- Global Exception Filter
- Global Logging Context Middleware
- Custom Logger with nestjs-pino
- Custom Decorators Example at Nest level
- Configuration
- Authentication - JWT and Session login with Passport
- Role-based Guard
- Controller Routes
- Auth Login
- Sample Parameter and DTO
- CRUD API Sample
- Database Query Example
- Unit Test
- E2E Test
- Shared Modules Example
- GraphQL Structure Example
Documentation
# APP, Compodoc
npm run doc #> http://localhost:8080
# API, Swagger - src/swagger.ts
npm run doc:api #> http://localhost:8000/api
File Naming for Class
export class PascalCaseSuffix {} //= pascal-case.suffix.ts
// Except for suffix, PascalCase to hyphen-case
class FooBarNaming {} //= foo-bar.naming.ts
class FooController {} //= foo.controller.ts
class BarQueryDto {} //= bar-query.dto.ts
Interface Naming
// https://stackoverflow.com/questions/541912
// https://stackoverflow.com/questions/2814805
interface User {}
interface CustomeUser extends User {}
interface ThirdCustomeUser extends CustomeUser {}
Index Exporting
# It is recommended to place index.ts in each folder and export.
# Unless it's a special case, it is import from a folder instead of directly from a file.
- import { FooController } from './controllers/foo.controller';
- import { BarController } from './controllers/bar.controller';
+ import { FooController, BarController } from './controllers';
# My preferred method is to place only one fileOrFolder name at the end of the path.
- import { UtilService } from '../common/providers/util.service';
+ import { UtilService } from '../common';
Circular dependency
https://docs.nestjs.com/fundamentals/circular-dependency
# Do not use a path that ends with a dot.
- import { FooService } from '.';
- import { BarService } from '..';
+ import { FooService } from './foo.service';
+ import { BarService } from '../providers';
Variables Naming
refer to Naming cheatsheet