Lerna project configuration management for monorepos with package discovery and workspace handling
npx @tessl/cli install tessl/npm-lerna--project@6.4.00
# Lerna Project
1
2
Lerna project configuration management for monorepos, providing package discovery, workspace handling, and configuration resolution for Lerna-managed multi-package repositories.
3
4
## Package Information
5
6
- **Package Name**: @lerna/project
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install @lerna/project`
10
11
## Core Imports
12
13
```javascript
14
const { Project } = require("@lerna/project");
15
const { getPackages, getPackagesSync } = require("@lerna/project");
16
```
17
18
For ES modules:
19
20
```javascript
21
import { Project, getPackages, getPackagesSync } from "@lerna/project";
22
```
23
24
## Basic Usage
25
26
```javascript
27
const { Project } = require("@lerna/project");
28
29
// Create a project instance from current working directory
30
const project = new Project();
31
32
// Get packages asynchronously
33
const packages = await project.getPackages();
34
console.log(packages.length); // Number of packages found
35
36
// Access project configuration
37
console.log(project.config.version); // Project version
38
console.log(project.rootPath); // Project root directory
39
40
// Static methods for convenience
41
const packages2 = await Project.getPackages("/path/to/monorepo");
42
const packagesSync = Project.getPackagesSync("/path/to/monorepo");
43
```
44
45
## Architecture
46
47
The @lerna/project package is built around several key components:
48
49
- **Project Class**: Central class representing a Lerna project with configuration and package discovery
50
- **Configuration System**: Resolves lerna.json and package.json configurations with inheritance support
51
- **Package Discovery**: Locates packages using glob patterns, supporting npm/yarn/pnpm workspaces
52
- **File System Integration**: Handles file operations, license detection, and configuration persistence
53
- **Utility Functions**: Configuration merging, deprecation handling, and file finding capabilities
54
55
## Capabilities
56
57
### Project Class
58
59
Core class representing a Lerna project and its configuration, providing access to packages, configuration, and project metadata.
60
61
```javascript { .api }
62
/**
63
* A representation of the entire project managed by Lerna
64
* @param {string} [cwd] - Working directory (defaults to process.cwd())
65
*/
66
class Project {
67
constructor(cwd?: string);
68
69
// Static convenience methods
70
static getPackages(cwd?: string): Promise<Package[]>;
71
static getPackagesSync(cwd?: string): Package[];
72
73
// Instance properties
74
config: ProjectConfig;
75
configNotFound: boolean;
76
rootConfigLocation: string;
77
rootPath: string;
78
version: string;
79
packageConfigs: string[];
80
packageParentDirs: string[];
81
manifest: Package;
82
pnpmWorkspaceConfig: PnpmWorkspaceConfig;
83
licensePath: string;
84
fileFinder: FileFinder;
85
86
// Instance methods
87
getPackages(): Promise<Package[]>;
88
getPackagesSync(): Package[];
89
getPackageLicensePaths(): Promise<string[]>;
90
isIndependent(): boolean;
91
serializeConfig(): Promise<string>;
92
93
// Static constants
94
static PACKAGE_GLOB: string; // "packages/*"
95
static LICENSE_GLOB: string; // "LICEN{S,C}E{,.*}"
96
}
97
```
98
99
### Standalone Functions
100
101
Convenience functions providing direct access to package discovery without instantiating the Project class.
102
103
```javascript { .api }
104
/**
105
* Get packages for a project directory
106
* @param {string} [cwd] - Working directory (defaults to process.cwd())
107
* @returns {Promise<Package[]>} Array of Package instances
108
*/
109
function getPackages(cwd?: string): Promise<Package[]>;
110
111
/**
112
* Synchronously get packages for a project directory
113
* @param {string} [cwd] - Working directory (defaults to process.cwd())
114
* @returns {Package[]} Array of Package instances
115
*/
116
function getPackagesSync(cwd?: string): Package[];
117
```
118
119
### Package Discovery
120
121
Methods for discovering and enumerating packages within the monorepo.
122
123
```javascript { .api }
124
/**
125
* Asynchronously discover packages in the project
126
* @returns {Promise<Package[]>} Array of Package instances
127
*/
128
Project.prototype.getPackages(): Promise<Package[]>;
129
130
/**
131
* Synchronously discover packages in the project
132
* @returns {Package[]} Array of Package instances
133
*/
134
Project.prototype.getPackagesSync(): Package[];
135
```
136
137
**Usage Examples:**
138
139
```javascript
140
const { Project } = require("@lerna/project");
141
142
// Async package discovery
143
const project = new Project();
144
const packages = await project.getPackages();
145
packages.forEach(pkg => {
146
console.log(`${pkg.name}@${pkg.version} at ${pkg.location}`);
147
});
148
149
// Sync package discovery
150
const packagesSync = project.getPackagesSync();
151
console.log(`Found ${packagesSync.length} packages`);
152
153
// Static methods
154
const allPackages = await Project.getPackages("/path/to/monorepo");
155
```
156
157
### Configuration Management
158
159
Access and manage project configuration from lerna.json and package.json.
160
161
```javascript { .api }
162
/**
163
* Project version getter/setter
164
*/
165
get version(): string;
166
set version(val: string): void;
167
168
/**
169
* Write configuration back to file system
170
* @returns {Promise<string>} Path to written config file
171
*/
172
serializeConfig(): Promise<string>;
173
174
/**
175
* Check if project uses independent versioning
176
* @returns {boolean} True if independent versioning is enabled
177
*/
178
isIndependent(): boolean;
179
```
180
181
**Usage Examples:**
182
183
```javascript
184
const project = new Project();
185
186
// Access configuration
187
console.log(project.config.version); // Current version
188
console.log(project.config.packages); // Package patterns
189
console.log(project.config.useWorkspaces); // Workspace usage
190
191
// Modify and save configuration
192
project.version = "2.0.0";
193
await project.serializeConfig();
194
195
// Check versioning mode
196
if (project.isIndependent()) {
197
console.log("Using independent versioning");
198
}
199
```
200
201
### Configuration Inheritance
202
203
Support for extending configurations from other modules using the `extends` property.
204
205
```javascript { .api }
206
/**
207
* Configuration can extend from locally-resolvable modules
208
* Supports inheritance chains with circular reference detection
209
*/
210
interface ProjectConfig {
211
extends?: string; // Path to module to extend from
212
// ... other properties
213
}
214
```
215
216
**Usage Examples:**
217
218
```javascript
219
// lerna.json
220
{
221
"extends": "@my/lerna-config",
222
"version": "1.0.0"
223
}
224
225
// The @my/lerna-config module exports:
226
module.exports = {
227
"npmClient": "yarn",
228
"useWorkspaces": true,
229
"command": {
230
"publish": {
231
"conventionalCommits": true
232
}
233
}
234
};
235
236
// Resulting merged configuration:
237
const project = new Project();
238
console.log(project.config);
239
// {
240
// "version": "1.0.0",
241
// "npmClient": "yarn",
242
// "useWorkspaces": true,
243
// "command": { "publish": { "conventionalCommits": true } }
244
// }
245
```
246
247
### Workspace Integration
248
249
Support for npm, yarn, and pnpm workspace configurations.
250
251
```javascript { .api }
252
/**
253
* Get package configuration patterns
254
* Resolves from pnpm-workspace.yaml, package.json workspaces, or lerna.json
255
*/
256
get packageConfigs(): string[];
257
258
/**
259
* Get PNPM workspace configuration
260
*/
261
get pnpmWorkspaceConfig(): PnpmWorkspaceConfig;
262
263
/**
264
* Get package parent directories
265
*/
266
get packageParentDirs(): string[];
267
```
268
269
**Usage Examples:**
270
271
```javascript
272
const project = new Project();
273
274
// Get package patterns
275
const patterns = project.packageConfigs;
276
console.log(patterns); // ["packages/*", "tools/*"]
277
278
// Check workspace configuration
279
if (project.config.useWorkspaces) {
280
const workspaces = project.manifest.get("workspaces");
281
console.log("Using workspaces:", workspaces);
282
}
283
284
// PNPM-specific configuration
285
if (project.config.npmClient === "pnpm") {
286
const pnpmConfig = project.pnpmWorkspaceConfig;
287
console.log("PNPM packages:", pnpmConfig.packages);
288
}
289
```
290
291
### File System Operations
292
293
File finding, license detection, and project metadata access.
294
295
```javascript { .api }
296
/**
297
* Get project root package.json as Package instance
298
*/
299
get manifest(): Package;
300
301
/**
302
* Get path to project license file
303
*/
304
get licensePath(): string;
305
306
/**
307
* Get file finder function for locating files in packages
308
*/
309
get fileFinder(): FileFinder;
310
311
/**
312
* Get paths to package license files
313
* @returns {Promise<string[]>} Array of license file paths
314
*/
315
getPackageLicensePaths(): Promise<string[]>;
316
```
317
318
**Usage Examples:**
319
320
```javascript
321
const project = new Project();
322
323
// Access root package.json
324
const rootPackage = project.manifest;
325
console.log(rootPackage.name); // Root package name
326
console.log(rootPackage.get("scripts")); // Root scripts
327
328
// Find license files
329
const licensePath = project.licensePath;
330
const packageLicenses = await project.getPackageLicensePaths();
331
332
// Use file finder to locate files across packages
333
const fileFinder = project.fileFinder;
334
const readmeFiles = await fileFinder("README.md");
335
const testFiles = await fileFinder("*.test.js");
336
```
337
338
339
## Types
340
341
```javascript { .api }
342
/**
343
* Project configuration object
344
*/
345
interface ProjectConfig {
346
version: string;
347
packages?: string[];
348
useNx?: boolean;
349
useWorkspaces?: boolean;
350
npmClient?: string;
351
command?: {
352
[commandName: string]: Record<string, any>;
353
};
354
extends?: string;
355
[key: string]: any; // Allow additional configuration properties
356
}
357
358
/**
359
* PNPM workspace configuration from pnpm-workspace.yaml
360
*/
361
interface PnpmWorkspaceConfig {
362
packages: string[];
363
}
364
365
/**
366
* File finder function for locating files in packages
367
* @param fileName - File name or glob pattern to search for
368
* @param fileMapper - Optional function to transform file paths or file path arrays
369
* @param customGlobOpts - Optional glob options to override defaults
370
* @returns Promise resolving to array of file paths, or transformed results if fileMapper is provided
371
*/
372
type FileFinder = <T = string>(
373
fileName: string,
374
fileMapper?: (filePaths: string[]) => T[] | Promise<T[]>,
375
customGlobOpts?: object
376
) => Promise<T[]>;
377
378
/**
379
* Package class from @lerna/package
380
*/
381
class Package {
382
name: string;
383
version: string;
384
location: string;
385
private: boolean;
386
get(key: string): any;
387
set(key: string, value: any): this;
388
toJSON(): object;
389
}
390
```
391
392
## Error Handling
393
394
The package throws `ValidationError` instances for configuration-related issues:
395
396
- **EWORKSPACES**: Missing or invalid workspace configuration (npm/yarn workspaces or pnpm-workspace.yaml)
397
- **JSONError**: Invalid JSON syntax in configuration files (lerna.json or package.json)
398
- **EPKGCONFIG**: Invalid package configuration (e.g., node_modules pattern with globstars)
399
- **ERESOLVED**: Configuration extends path cannot be resolved
400
- **ECIRCULAR**: Circular extends references in configuration inheritance
401
- **ENOENT**: Missing pnpm-workspace.yaml when using pnpm client
402
403
Example error handling:
404
405
```javascript
406
const { Project } = require("@lerna/project");
407
const { ValidationError } = require("@lerna/validation-error");
408
409
try {
410
const project = new Project();
411
const packages = await project.getPackages();
412
} catch (error) {
413
if (error instanceof ValidationError) {
414
console.error("Configuration error:", error.message);
415
} else {
416
console.error("Unexpected error:", error);
417
}
418
}
419
```