This document details how Lerna manages the NestJS multi-package repository, including coordinated versioning, release workflows, and package interdependencies. For information about the individual packages themselves and their purposes, see Core Package Ecosystem. For sample application structure, see Sample Applications Guide.
The NestJS repository is organized as a Lerna-managed monorepo containing 10+ npm packages that are developed, versioned, and published together. Lerna (version 9.0.4) provides tooling for managing multiple packages within a single repository, enabling coordinated releases and simplified dependency management across packages.
The repository follows a fixed versioning strategy where all packages share the same version number and are released simultaneously, ensuring version compatibility across the entire framework.
Sources: package.json1-242
The monorepo contains two primary categories of packages:
| Category | Location | Purpose | Example Packages |
|---|---|---|---|
| Framework Packages | packages/ | Core NestJS functionality | @nestjs/core, @nestjs/common, @nestjs/platform-express |
| Sample Applications | sample/ | Demonstration applications | 06-mongoose, 22-graphql-prisma, 23-graphql-code-first |
Sources: package.json1-3 package.json147-148 sample/06-mongoose/package.json22-24 sample/22-graphql-prisma/package.json25-27 sample/23-graphql-code-first/package.json24-26
The NestJS monorepo uses Lerna's fixed mode (also called "locked mode"), where all packages share a single version number. This approach ensures:
The root package.json declares version 11.1.10, while sample applications reference NestJS packages at version 11.1.13, demonstrating the coordinated versioning across releases.
Sources: package.json3 sample/06-mongoose/package.json22-24 sample/22-graphql-prisma/package.json25-27
The publish script uses the --exact flag to ensure packages specify exact dependency versions rather than version ranges:
This prevents version drift and ensures predictable dependency resolution.
Sources: package.json45
The repository defines multiple publication workflows for different release channels:
| Script | NPM Tag | Git Commit | Force Publish | Use Case |
|---|---|---|---|---|
publish | latest | ✓ | ✓ | Stable releases |
publish:beta | beta | ✓ | ✗ | Beta testing |
publish:next | next | ✗ | ✗ | Canary builds |
publish:rc | rc | ✓ | ✗ | Release candidates |
publish:test | test | ✗ | ✓ | Testing releases |
Sources: package.json44-50
Sources: package.json44-45
Before publication, the prerelease script executes Gulp tasks to prepare distribution artifacts:
"prerelease": "gulp copy-misc"
This copies essential files (package.json, README, LICENSE) into the distribution directories for each package.
Sources: package.json44
The --force-publish flag ensures all packages are published regardless of whether Lerna detects changes. This is used for:
publish script)publish:test script)This guarantees version consistency across the entire framework even when some packages haven't changed.
Sources: package.json45 package.json50
The build process uses TypeScript project references to compile all packages efficiently:
"build": "tsc -b -v packages"
"build:prod": "tsc -b -v packages"
The -b flag enables build mode with project references, compiling packages in topological order based on their dependencies.
Sources: package.json17 package.json21
After compilation, the repository moves node_modules to the appropriate package directories:
"postbuild": "npm run move:node_modules"
"move:node_modules": "gulp move:node_modules"
Sources: package.json18 package.json25
The repository uses lerna-changelog (version 2.2.0) to automatically generate changelogs from Git commit history:
"changelog": "lerna-changelog"
The prepublishOnly hook automatically copies the generated changelog to the clipboard before publishing:
"prepublishOnly": "npm run changelog | pbcopy"
Sources: package.json22 package.json46 package.json148
The changelog generation is configured with semantic labels that categorize commits:
This configuration maps GitHub labels to changelog sections, organizing changes by type for better readability.
Sources: package.json184-193
Sample applications maintain synchronized dependency versions with the framework packages. For example:
06-mongoose Sample: sample/06-mongoose/package.json22-24
22-graphql-prisma Sample: sample/22-graphql-prisma/package.json25-27
23-graphql-code-first Sample: sample/23-graphql-code-first/package.json24-26
All samples consistently reference 11.1.13 for core framework packages, demonstrating the coordinated versioning strategy.
Sources: sample/06-mongoose/package.json22-24 sample/22-graphql-prisma/package.json25-27 sample/23-graphql-code-first/package.json24-26
The repository provides scripts for building and testing all sample applications:
"build:samples": "gulp install:samples && npm run build && npm run move:samples && gulp build:samples && gulp test:samples && gulp test:e2e:samples"
This comprehensive workflow:
gulp install:samples)npm run build)npm run move:samples)gulp build:samples)gulp test:samples)gulp test:e2e:samples)Sources: package.json26
The repository uses Lerna version 9.0.4, specified in devDependencies:
This version provides modern features including:
Sources: package.json147
Additional tools work alongside Lerna:
The lerna-changelog package generates formatted changelogs from GitHub pull request metadata and commit messages.
Sources: package.json147-148
The NestJS monorepo leverages Lerna 9.0.4 to manage a complex multi-package ecosystem with:
This architecture enables the NestJS team to maintain a large framework codebase while ensuring version compatibility and coordinated releases across all packages.
Sources: package.json1-242 sample/06-mongoose/package.json1-72 sample/22-graphql-prisma/package.json1-67
Refresh this wiki