or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

executors.mdgenerators.mdindex.mdpackage-management.mdplugin-development.mdproject-graph.mdtree-operations.mdutilities.mdworkspace-configuration.md

package-management.mddocs/

0

# Package Management

1

2

Package management utilities for adding dependencies, managing package.json files, and ensuring required packages are available across npm, yarn, and pnpm.

3

4

## Capabilities

5

6

### Dependency Management

7

8

Add and remove dependencies from package.json with intelligent version resolution and conflict handling.

9

10

```typescript { .api }

11

/**

12

* Add dependencies and devDependencies to package.json

13

* Handles version conflicts and prevents duplicate dependencies

14

* @param tree - File system tree

15

* @param dependencies - Production dependencies to add

16

* @param devDependencies - Development dependencies to add

17

* @param packageJsonPath - Path to package.json (defaults to root)

18

* @param keepExistingVersions - Prevent upgrading existing packages

19

* @returns Callback to install packages

20

*/

21

function addDependenciesToPackageJson(

22

tree: Tree,

23

dependencies: Record<string, string>,

24

devDependencies: Record<string, string>,

25

packageJsonPath?: string,

26

keepExistingVersions?: boolean

27

): GeneratorCallback;

28

29

/**

30

* Remove dependencies from package.json

31

* @param tree - File system tree

32

* @param dependencies - Production dependencies to remove

33

* @param devDependencies - Development dependencies to remove

34

* @param packageJsonPath - Path to package.json (defaults to root)

35

* @returns Callback to run package manager operations

36

*/

37

function removeDependenciesFromPackageJson(

38

tree: Tree,

39

dependencies: string[],

40

devDependencies: string[],

41

packageJsonPath?: string

42

): GeneratorCallback;

43

```

44

45

**Usage Examples:**

46

47

```typescript

48

import {

49

Tree,

50

addDependenciesToPackageJson,

51

removeDependenciesFromPackageJson,

52

GeneratorCallback

53

} from "@nx/devkit";

54

55

export default function myGenerator(tree: Tree): GeneratorCallback {

56

// Add React dependencies

57

const addDepsTask = addDependenciesToPackageJson(

58

tree,

59

{

60

"react": "^18.2.0",

61

"react-dom": "^18.2.0"

62

},

63

{

64

"@types/react": "^18.0.15",

65

"@types/react-dom": "^18.0.6",

66

"@testing-library/react": "^13.3.0"

67

}

68

);

69

70

// Remove old dependencies

71

const removeDepsTask = removeDependenciesFromPackageJson(

72

tree,

73

["lodash"], // Remove from dependencies

74

["@types/lodash"] // Remove from devDependencies

75

);

76

77

// Return combined task

78

return async () => {

79

await addDepsTask();

80

await removeDepsTask();

81

};

82

}

83

```

84

85

### Package Installation

86

87

Manage package installation tasks and ensure required packages are available.

88

89

```typescript { .api }

90

/**

91

* Create a task to install packages using the detected package manager

92

* @param tree - File system tree

93

* @param alwaysRun - Force installation even if no changes detected

94

* @param cwd - Working directory for installation

95

* @param packageManager - Specific package manager to use

96

*/

97

function installPackagesTask(

98

tree: Tree,

99

alwaysRun?: boolean,

100

cwd?: string,

101

packageManager?: PackageManager

102

): void;

103

104

/**

105

* Ensure a package is installed and available for use

106

* Installs the package temporarily if not found

107

* @param pkg - Package name to ensure

108

* @param version - Version to install if missing

109

* @returns The required package module or null for ESM packages

110

*/

111

function ensurePackage<T = any>(pkg: string, version: string): T;

112

113

/**

114

* Current version of Nx being used

115

*/

116

const NX_VERSION: string;

117

```

118

119

**Usage Examples:**

120

121

```typescript

122

import {

123

Tree,

124

installPackagesTask,

125

ensurePackage,

126

NX_VERSION

127

} from "@nx/devkit";

128

129

export default function myGenerator(tree: Tree) {

130

// Schedule package installation

131

installPackagesTask(tree);

132

133

// Ensure a specific package is available

134

try {

135

const chalk = ensurePackage("chalk", "^4.1.0");

136

console.log(chalk.green("Package is available!"));

137

} catch (error) {

138

console.error("Failed to ensure package:", error.message);

139

}

140

141

// Use current Nx version

142

console.log(`Using Nx version: ${NX_VERSION}`);

143

}

144

```

145

146

### Package Manager Detection

147

148

Detect and work with different package managers (npm, yarn, pnpm).

149

150

```typescript { .api }

151

/**

152

* Detect which package manager is being used in the workspace

153

* @param dir - Directory to check (defaults to workspace root)

154

* @returns Detected package manager

155

*/

156

function detectPackageManager(dir?: string): PackageManager;

157

158

/**

159

* Get commands for the specified package manager

160

* @param packageManager - Package manager to get commands for

161

* @returns Object with package manager commands

162

*/

163

function getPackageManagerCommand(packageManager?: PackageManager): {

164

install: string;

165

add: string;

166

addDev: string;

167

rm: string;

168

exec: string;

169

dlx: string;

170

list: string;

171

run: (script: string, args?: string) => string;

172

preInstall?: string;

173

};

174

175

/**

176

* Get version of the specified package manager

177

* @param packageManager - Package manager to check

178

* @returns Version string

179

*/

180

function getPackageManagerVersion(packageManager?: PackageManager): string;

181

182

/**

183

* Check if workspaces are enabled for the package manager

184

* @param packageManager - Package manager to check

185

* @param root - Workspace root directory

186

* @returns Whether workspaces are enabled

187

*/

188

function isWorkspacesEnabled(

189

packageManager: PackageManager,

190

root: string

191

): boolean;

192

193

/**

194

* Supported package managers

195

*/

196

type PackageManager = "npm" | "yarn" | "pnpm";

197

```

198

199

**Usage Examples:**

200

201

```typescript

202

import {

203

detectPackageManager,

204

getPackageManagerCommand,

205

getPackageManagerVersion,

206

isWorkspacesEnabled,

207

workspaceRoot

208

} from "@nx/devkit";

209

210

function setupPackageManager() {

211

// Detect current package manager

212

const pm = detectPackageManager();

213

console.log(`Using package manager: ${pm}`);

214

215

// Get package manager commands

216

const commands = getPackageManagerCommand(pm);

217

console.log(`Install command: ${commands.install}`);

218

console.log(`Add dev dependency: ${commands.addDev}`);

219

220

// Check version

221

const version = getPackageManagerVersion(pm);

222

console.log(`${pm} version: ${version}`);

223

224

// Check workspace support

225

const workspacesEnabled = isWorkspacesEnabled(pm, workspaceRoot);

226

console.log(`Workspaces enabled: ${workspacesEnabled}`);

227

228

// Run package manager commands

229

const { execSync } = require("child_process");

230

231

// Install dependencies

232

execSync(commands.install, { cwd: workspaceRoot, stdio: "inherit" });

233

234

// Add a new dependency

235

execSync(`${commands.add} lodash@^4.17.21`, {

236

cwd: workspaceRoot,

237

stdio: "inherit"

238

});

239

240

// Run a script

241

const testCommand = commands.run("test", "--coverage");

242

execSync(testCommand, { cwd: workspaceRoot, stdio: "inherit" });

243

}

244

```

245

246

## Advanced Package Management

247

248

### Version Resolution Strategy

249

250

The dependency management functions use intelligent version resolution:

251

252

1. **Conflict Prevention**: Dependencies in devDependencies won't be added to dependencies if they already exist

253

2. **Version Upgrading**: By default, higher versions replace lower versions

254

3. **Version Preservation**: Use `keepExistingVersions: true` to prevent version bumps

255

4. **Semver Handling**: Supports standard semver ranges and special tags like "latest", "next"

256

257

```typescript

258

// Example of complex dependency management

259

export default function myGenerator(tree: Tree) {

260

const addDepsTask = addDependenciesToPackageJson(

261

tree,

262

{

263

"react": "^18.2.0", // Will upgrade from ^17.x.x

264

"lodash": "latest", // Uses latest tag

265

"moment": "~2.29.0" // Patch-level updates only

266

},

267

{

268

"@types/react": "^18.0.15",

269

"typescript": "next" // Uses next tag

270

},

271

"package.json",

272

false // Allow version upgrades

273

);

274

275

return addDepsTask;

276

}

277

```

278

279

### Monorepo Package Management

280

281

Working with packages in monorepo environments:

282

283

```typescript

284

// Add dependencies to a specific project

285

export default function addToProject(tree: Tree, options: { project: string }) {

286

const projectConfig = readProjectConfiguration(tree, options.project);

287

const packageJsonPath = `${projectConfig.root}/package.json`;

288

289

const addDepsTask = addDependenciesToPackageJson(

290

tree,

291

{ "axios": "^1.0.0" },

292

{ "@types/axios": "^1.0.0" },

293

packageJsonPath // Project-specific package.json

294

);

295

296

return addDepsTask;

297

}

298

```

299

300

### Package Manager Configuration

301

302

```typescript

303

// Configure package manager behavior

304

function configurePackageManager(tree: Tree, packageManager: PackageManager) {

305

const nxJson = readNxJson(tree);

306

307

updateNxJson(tree, {

308

...nxJson,

309

cli: {

310

...nxJson?.cli,

311

packageManager: packageManager

312

}

313

});

314

315

// Create package manager specific configuration files

316

switch (packageManager) {

317

case "yarn":

318

if (getPackageManagerVersion("yarn").startsWith("3.")) {

319

tree.write(".yarnrc.yml", "nodeLinker: node-modules\nenableScripts: false");

320

}

321

break;

322

case "pnpm":

323

tree.write(".npmrc", "shamefully-hoist=true");

324

break;

325

}

326

}

327

```

328

329

### Dynamic Package Loading

330

331

```typescript

332

// Dynamically load packages with fallback handling

333

async function loadPackageDynamic<T>(packageName: string, version: string): Promise<T | null> {

334

try {

335

// Try to require the package

336

return require(packageName);

337

} catch (error) {

338

if (error.code === 'MODULE_NOT_FOUND') {

339

// Package not found, ensure it's available

340

const pkg = ensurePackage<T>(packageName, version);

341

return pkg;

342

} else if (error.code === 'ERR_REQUIRE_ESM') {

343

// ESM package, use dynamic import

344

const pkg = await import(packageName);

345

return pkg.default || pkg;

346

}

347

throw error;

348

}

349

}

350

351

// Usage example

352

export default async function myGenerator(tree: Tree) {

353

// Load chalk dynamically

354

const chalk = await loadPackageDynamic("chalk", "^4.1.0");

355

if (chalk) {

356

console.log(chalk.green("Successfully loaded chalk!"));

357

}

358

359

// Load an ESM package

360

const prettier = await loadPackageDynamic("prettier", "^2.8.0");

361

if (prettier) {

362

const formatted = await prettier.format("const x=1;", { parser: "typescript" });

363

console.log("Formatted code:", formatted);

364

}

365

}

366

```