Expected Node Version
The `expected-node-version` package provides a utility to programmatically retrieve the expected Node.js version for a project. It prioritizes speed and common configuration practices by checking environment variables (specifically `npm_package_engines_node` which is set by `npm start`), followed by the `.nvmrc` file, and finally the `engines.node` field within the `package.json`. This specific load order ensures that the most direct and often project-specific version is identified quickly. The current stable version is 1.0.2, with recent minor updates indicating active maintenance, though not a rapid release cycle. Its primary use case is for tools or scripts that need to determine the project's intended Node.js runtime without parsing multiple files manually, streamlining environment checks and ensuring compatibility. It simplifies the process of aligning development environments with project requirements.
Common errors
-
TypeError: require is not a function
cause Attempting to use `require` in an ES module (ESM) context without proper configuration for CJS interoperability.fixIf running in an ESM context, consider using a dynamic `import()` for CJS modules, or ensure your `package.json` is configured for CommonJS (e.g., by omitting `"type": "module"` or using `.cjs` extensions). -
TypeError: Cannot read properties of null (reading 'startsWith') (or similar error when operating on the returned version)
cause The `expectedNodeVersion` function returned `null` because no Node.js version was found in the expected locations (environment, `.nvmrc`, `package.json`), and subsequent code tried to operate on `null`.fixImplement a null-check before using the returned value: `const version = expectedNodeVersion(); if (version) { /* proceed with version */ } else { console.warn('No expected Node.js version found.'); }`
Warnings
- gotcha This package is CommonJS-only. In pure ES module (ESM) environments, direct `import` statements for `expected-node-version` will fail at runtime. It can be used in hybrid ESM/CJS projects or by explicitly configuring an ESM loader for CJS interop, but this adds complexity.
- gotcha The utility determines the Node.js version based on a specific load order: `npm_package_engines_node` environment variable, then `.nvmrc` file, and finally `package.json`'s `engines.node` field. Be aware that environment variables take precedence over file-based configurations, which might lead to unexpected results if not understood.
- gotcha The function returns `null` if no expected Node.js version can be found in any of the checked locations. It does not throw an error in this scenario, requiring explicit handling of the `null` return.
Install
-
npm install expected-node-version -
yarn add expected-node-version -
pnpm add expected-node-version
Imports
- expectedNodeVersion
import expectedNodeVersion from 'expected-node-version';
const expectedNodeVersion = require('expected-node-version');
Quickstart
const expectedNodeVersion = require('expected-node-version');
const path = require('path');
const fs = require('fs');
// Create a temporary directory for testing
const tempDir = path.join(__dirname, 'temp_node_version_test');
fs.mkdirSync(tempDir, { recursive: true });
try {
// Scenario 1: .nvmrc file
const nvmrcPath = path.join(tempDir, '.nvmrc');
fs.writeFileSync(nvmrcPath, '18.17.1\n');
const versionFromNvmrc = expectedNodeVersion(tempDir);
console.log(`Version from .nvmrc in '${tempDir}': ${versionFromNvmrc}`); // Expected: 18.17.1
fs.unlinkSync(nvmrcPath);
// Scenario 2: package.json engines.node
const packageJsonPath = path.join(tempDir, 'package.json');
fs.writeFileSync(packageJsonPath, JSON.stringify({
name: 'test-project',
engines: {
node: '>=16.0.0 <20.0.0'
}
}, null, 2));
const versionFromPackageJson = expectedNodeVersion(tempDir);
console.log(`Version from package.json in '${tempDir}': ${versionFromPackageJson}`); // Expected: >=16.0.0 <20.0.0
fs.unlinkSync(packageJsonPath);
// Scenario 3: Environment variable (simulated)
// This is checked globally, so setting it before calling without a path argument
process.env.npm_package_engines_node = '20.x';
const versionFromEnv = expectedNodeVersion(); // No path, checks process.env first
console.log(`Version from environment variable: ${versionFromEnv}`); // Expected: 20.x
delete process.env.npm_package_engines_node; // Clean up env var
// Scenario 4: No version found
const noVersion = expectedNodeVersion(tempDir);
console.log(`Version when no file found in '${tempDir}': ${noVersion || 'Not found'}`); // Expected: Not found
} finally {
// Clean up the temporary directory
fs.rmSync(tempDir, { recursive: true, force: true });
console.log(`Cleaned up temporary directory: ${tempDir}`);
}