The npm module manages Node.js packages using npm (Node Package Manager).
Functions
packages
Install, remove, or update npm packages.
from pyinfra.operations import npm
npm.packages(
name = "Install Node.js packages" ,
packages = [ "express" , "lodash" ],
)
List of packages to ensure.
Whether the packages should be present.
Whether to upgrade packages without a specified version.
Directory to manage packages for. Defaults to global installation.
Package versions can be pinned like npm: <pkg>@<version>
Examples
Global Installation
Project Installation
Version Pinning
Latest Versions
from pyinfra.operations import npm
# Install packages globally
npm.packages(
name = "Install global npm packages" ,
packages = [ "typescript" , "nodemon" ],
)
Common Use Cases
Express.js Application Setup
from pyinfra.operations import npm
npm.packages(
name = "Install Express.js dependencies" ,
packages = [
"[email protected] " ,
"body-parser" ,
"cors" ,
"dotenv" ,
"mongoose" ,
],
directory = "/var/www/api" ,
)
React Application
from pyinfra.operations import npm
npm.packages(
name = "Install React dependencies" ,
packages = [
"[email protected] " ,
"[email protected] " ,
"react-router-dom" ,
"axios" ,
],
directory = "/var/www/frontend" ,
)
from pyinfra.operations import npm
npm.packages(
name = "Install global development tools" ,
packages = [
"typescript" ,
"nodemon" ,
"pm2" ,
"eslint" ,
"prettier" ,
],
)
Install from package.json
from pyinfra.operations import server
# Install all dependencies from package.json
server.shell(
name = "Install npm dependencies" ,
commands = [ "cd /app && npm install" ],
)
from pyinfra.operations import npm
npm.packages(
name = "Install build tools" ,
packages = [
"webpack" ,
"webpack-cli" ,
"babel-loader" ,
"@babel/core" ,
"@babel/preset-env" ,
],
directory = "/var/www/myapp" ,
)
Testing Framework
from pyinfra.operations import npm
npm.packages(
name = "Install testing tools" ,
packages = [
"jest" ,
"@testing-library/react" ,
"@testing-library/jest-dom" ,
"supertest" ,
],
directory = "/app" ,
)
npm-Specific Tips
Global packages (no directory parameter):
Installed system-wide
Typically CLI tools
Use npm install -g
Local packages (with directory parameter):
Installed in project’s node_modules
Project dependencies
Use npm install in directory
from pyinfra.operations import npm
# Global: CLI tools
npm.packages(
name = "Install global tools" ,
packages = [ "typescript" , "nodemon" ],
)
# Local: Project dependencies
npm.packages(
name = "Install project dependencies" ,
packages = [ "express" , "mongoose" ],
directory = "/app" ,
)
For full project setups, use package.json: from pyinfra.operations import files, server
# Upload package.json
files.put(
name = "Upload package.json" ,
src = "local/package.json" ,
dest = "/app/package.json" ,
)
# Install all dependencies
server.shell(
name = "Install npm dependencies" ,
commands = [ "cd /app && npm install" ],
)
# For production (skip devDependencies)
server.shell(
name = "Install production dependencies" ,
commands = [ "cd /app && npm install --production" ],
)
Update packages to latest versions: from pyinfra.operations import npm
# Update specific packages
npm.packages(
name = "Update packages" ,
packages = [ "express" , "lodash" ],
latest = True ,
directory = "/app" ,
)
# Or use npm update directly
from pyinfra.operations import server
server.shell(
name = "Update all packages" ,
commands = [ "cd /app && npm update" ],
)
Install scoped packages (organization packages): from pyinfra.operations import npm
npm.packages(
name = "Install scoped packages" ,
packages = [
"@babel/core" ,
"@testing-library/react" ,
"@types/node" ,
],
directory = "/app" ,
)
Perform a clean install (removes node_modules): from pyinfra.operations import server
server.shell(
name = "Clean install dependencies" ,
commands = [
"cd /app" ,
"rm -rf node_modules" ,
"npm ci" , # Clean install from package-lock.json
],
)
Install from private npm registries: from pyinfra.operations import server
# Set registry
server.shell(
name = "Configure private registry" ,
commands = [
"npm config set registry https://registry.company.com" ,
],
)
# Or use .npmrc file
from pyinfra.operations import files
files.put(
name = "Upload .npmrc" ,
src = "local/.npmrc" ,
dest = "/app/.npmrc" ,
)
Best Practices
Always commit and deploy package-lock.json for reproducible builds: from pyinfra.operations import files, server
files.put(
name = "Upload package files" ,
src = "local/package.json" ,
dest = "/app/package.json" ,
)
files.put(
name = "Upload lock file" ,
src = "local/package-lock.json" ,
dest = "/app/package-lock.json" ,
)
server.shell(
name = "Install exact versions" ,
commands = [ "cd /app && npm ci" ],
)
Separate Dev and Production
from pyinfra.operations import server
# Production: skip devDependencies
server.shell(
name = "Install production dependencies" ,
commands = [ "cd /app && npm install --production" ],
)
# Development: install all
server.shell(
name = "Install all dependencies" ,
commands = [ "cd /app && npm install" ],
)
from pyinfra.operations import npm
# Pin major versions for stability
npm.packages(
name = "Install with version constraints" ,
packages = [
"[email protected] " , # Exact version
"lodash@^4.17.21" , # Compatible version
],
directory = "/app" ,
)
Important Notes
When no directory is specified, packages are installed globally using npm install -g.
Global npm installations may require sudo/administrator privileges depending on Node.js installation.
For production deployments, use npm ci instead of npm install for faster, more reliable builds.