0
# @lerna/diff
1
2
@lerna/diff is a Lerna command that provides git diff functionality for monorepo projects. It allows developers to see changes in all packages or a specific package since the last release, integrating seamlessly with Lerna's package graph system and git operations.
3
4
## Package Information
5
6
- **Package Name**: @lerna/diff
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install @lerna/diff` or included with `lerna`
10
11
## Core Imports
12
13
```javascript
14
// Main factory function (default export)
15
const factory = require("@lerna/diff");
16
17
// Access DiffCommand class from factory module
18
const { DiffCommand } = require("@lerna/diff");
19
20
// Command module for yargs integration
21
const command = require("@lerna/diff/command");
22
23
// Utility functions
24
const { getLastCommit } = require("@lerna/diff/lib/get-last-commit");
25
const { hasCommit } = require("@lerna/diff/lib/has-commit");
26
```
27
28
## Basic Usage
29
30
### CLI Usage
31
32
```bash
33
# Diff all packages since last release
34
lerna diff
35
36
# Diff specific package since last release
37
lerna diff my-package
38
39
# Ignore certain file patterns
40
lerna diff --ignore-changes "*.md" "test/**"
41
42
# Include ignored files (overrides lerna.json ignoreChanges configuration)
43
lerna diff --no-ignore-changes
44
```
45
46
### Programmatic Usage
47
48
```javascript
49
const factory = require("@lerna/diff");
50
const { DiffCommand } = require("@lerna/diff");
51
52
// Create command instance using factory
53
const diffCommand = factory(process.argv);
54
55
// Or directly instantiate DiffCommand
56
const command = new DiffCommand(process.argv);
57
await command.runner();
58
```
59
60
## Capabilities
61
62
### Factory Function
63
64
Creates a new DiffCommand instance for programmatic usage.
65
66
```typescript { .api }
67
/**
68
* Factory function to create DiffCommand instance
69
* @param argv - Process arguments array
70
* @returns DiffCommand instance ready for execution
71
*/
72
function factory(argv: NodeJS.Process["argv"]): DiffCommand;
73
```
74
75
### DiffCommand Class
76
77
Main command class that handles git diff operations for Lerna packages.
78
79
```typescript { .api }
80
/**
81
* Lerna command for showing git diff since last release
82
* Extends base Command class with diff-specific functionality
83
*/
84
class DiffCommand extends Command<DiffCommandOptions> {
85
/**
86
* Initialize the diff command
87
* - Validates package name if provided
88
* - Checks repository has commits
89
* - Builds git diff arguments with appropriate filters
90
*/
91
initialize(): void;
92
93
/**
94
* Execute the git diff command
95
* Spawns git diff process with constructed arguments and displays output
96
* @returns Promise that resolves when git diff completes successfully or rejects on error
97
*/
98
execute(): Promise<void>;
99
}
100
101
interface DiffCommandOptions extends CommandConfigOptions {
102
/** Optional package name to filter diff output */
103
pkgName: string;
104
/** Array of glob patterns to ignore in diff output */
105
ignoreChanges: string[];
106
}
107
```
108
109
### Command Definition
110
111
Yargs command module for CLI integration.
112
113
```typescript { .api }
114
/**
115
* Yargs CommandModule for lerna diff command
116
* Defines CLI interface with arguments and options
117
*/
118
const command: CommandModule = {
119
command: "diff [pkgName]";
120
describe: "Diff all packages or a single package since the last release";
121
122
/**
123
* Configure command arguments and options
124
* Configures pkgName positional argument and ignore-changes option
125
* Includes epilogue help text about ignoreChanges configuration
126
* @param yargs - Yargs instance for configuration
127
* @returns Configured yargs instance with positional and options
128
*/
129
builder(yargs: any): any;
130
131
/**
132
* Handle command execution
133
* Calls the factory function with parsed arguments
134
* @param argv - Parsed command arguments
135
* @returns Result from factory function execution
136
*/
137
handler(argv: any): any;
138
};
139
```
140
141
### CLI Configuration Details
142
143
The builder function configures the following options:
144
145
- **pkgName** (positional): Optional package name to filter diff output
146
- **ignore-changes** (option): Array type option to ignore files matched by glob patterns
147
- **epilogue**: Help text explaining `--no-ignore-changes` flag to override lerna.json settings
148
149
### Utility Functions
150
151
#### Get Last Commit
152
153
Determines the reference point for diff comparison.
154
155
```typescript { .api }
156
/**
157
* Get the last commit or tag for diff comparison
158
* Returns latest reachable tag if available, otherwise first commit
159
* @param execOpts - Child process execution options
160
* @returns Commit SHA or tag reference string
161
*/
162
function getLastCommit(execOpts: ExecOpts): string;
163
```
164
165
#### Has Commit
166
167
Validates repository has commit history before running diff.
168
169
```typescript { .api }
170
/**
171
* Check if repository has any commits
172
* Used to validate diff operation is possible
173
* @param opts - Child process execution options
174
* @returns True if repository has commits, false otherwise
175
*/
176
function hasCommit(opts: ExecOpts): boolean;
177
```
178
179
## Types
180
181
```typescript { .api }
182
interface DiffCommandOptions extends CommandConfigOptions {
183
/** Optional package name to filter diff output to single package */
184
pkgName: string;
185
/** Array of glob patterns to exclude from diff output */
186
ignoreChanges: string[];
187
}
188
189
/**
190
* Child process execution options
191
* Based on @lerna/child-process ExecOpts
192
*/
193
interface ExecOpts {
194
/** Working directory for command execution */
195
cwd: string;
196
/** Maximum buffer size for command output */
197
maxBuffer?: number;
198
}
199
```
200
201
## Error Handling
202
203
The command throws specific validation errors during initialization:
204
205
- **ENOPKG**: Thrown when specified package name doesn't exist in the monorepo with message `"Cannot diff, the package '{packageName}' does not exist."`
206
- **ENOCOMMITS**: Thrown when repository has no commit history to diff against with message `"Cannot diff, there are no commits in this repository yet."`
207
208
The execute method handles git diff process errors by:
209
- Catching process spawn errors and re-throwing if exitCode is truthy (non-zero)
210
- Allowing successful exits (exitCode 0 or falsy) to complete normally
211
- Treats quitting the diff viewer as a normal operation, not an error
212
213
```javascript
214
const { ValidationError } = require("@lerna/core");
215
216
// Example error handling
217
try {
218
const command = new DiffCommand(argv);
219
await command.runner();
220
} catch (error) {
221
if (error instanceof ValidationError) {
222
if (error.code === "ENOPKG") {
223
console.error(`Package not found: ${error.message}`);
224
} else if (error.code === "ENOCOMMITS") {
225
console.error("No commits to diff against");
226
}
227
}
228
}
229
```
230
231
## Implementation Details
232
233
### Git Command Construction
234
235
The command constructs git diff arguments as follows:
236
1. Base command: `git diff [lastCommit] --color=auto`
237
2. Target paths: Either specific package location or all package parent directories
238
3. Exclusion patterns: Applied using `:(exclude,glob)pattern` syntax for ignoreChanges
239
240
### Integration Notes
241
242
- Integrates with Lerna's package graph system for package validation
243
- Uses `@lerna/child-process` for git command execution
244
- Supports Lerna project configuration including ignore patterns from `lerna.json`
245
- Compatible with Lerna's execution options and logging systems
246
- Automatically detects latest tag or falls back to first commit for diff baseline
247
- Uses `--color=auto` flag to preserve git's color output in terminals