Configuration management for the npm command-line interface with hierarchical layered configuration system.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Configuration-specific error classes for handling invalid authentication and configuration validation failures.
Error class for invalid authentication configuration, typically thrown when authentication credentials are malformed or missing required components.
const { ErrInvalidAuth } = require('@npmcli/config/lib/errors');
/**
* Error thrown when authentication configuration is invalid
* Extends the standard Error class with problem details
*/
class ErrInvalidAuth extends Error {
/**
* Create an invalid authentication error
* @param problems - Array of authentication problems found
*/
constructor(problems: AuthProblem[]);
/** Error message describing the authentication problems */
message: string;
/** Error code, always "ERR_INVALID_AUTH" */
code: string;
/** Array of authentication problems */
problems: AuthProblem[];
/** Error name, always "ErrInvalidAuth" */
name: string;
}
interface AuthProblem {
/** Action required to fix the problem ('delete', 'rename') */
action: 'delete' | 'rename';
/** Configuration key that has the problem */
key?: string;
/** Source key that needs renaming (for 'rename' action) */
from?: string;
/** Target key for renaming (for 'rename' action) */
to?: string;
/** Configuration location where problem exists */
where: string;
}Usage Examples:
const { ErrInvalidAuth } = require('@npmcli/config/lib/errors');
// Catching authentication errors
try {
// This would be called internally by config validation
config.validate();
} catch (error) {
if (error instanceof ErrInvalidAuth) {
console.error('Authentication configuration problems found:');
console.error(error.message);
// Examine specific problems
error.problems.forEach(problem => {
if (problem.action === 'delete') {
console.log(`Remove invalid key '${problem.key}' from ${problem.where} config`);
} else if (problem.action === 'rename') {
console.log(`Rename '${problem.from}' to '${problem.to}' in ${problem.where} config`);
}
});
console.log('Run `npm config fix` to repair your configuration.');
}
}
// Throwing authentication errors in custom validation code
function validateAuthConfig(configData, where) {
const problems = [];
// Check for deprecated auth keys
if (configData['_authtoken']) {
problems.push({
action: 'rename',
from: '_authtoken',
to: '_authToken',
where: where
});
}
// Check for invalid keys in wrong locations
if (where === 'global' && configData['_authToken']) {
problems.push({
action: 'delete',
key: '_authToken',
where: where
});
}
if (problems.length > 0) {
throw new ErrInvalidAuth(problems);
}
}The ErrInvalidAuth error is typically thrown in the following scenarios:
Missing Credentials:
// No authentication provided for private registry
try {
config.getCredentialsByURI('https://private-registry.com/');
} catch (error) {
// ErrInvalidAuth: No authentication credentials found for registry
}Incomplete Credentials:
// Username without password
config.setCredentialsByURI('https://registry.com/', {
username: 'john',
// Missing password
});
// Throws: ErrInvalidAuth: Username provided but password missingInvalid Token Format:
// Malformed authentication token
config.setCredentialsByURI('https://registry.npmjs.org/', {
token: 'invalid-token-format'
});
// Throws: ErrInvalidAuth: Invalid token format for registryConflicting Authentication Methods:
// Both token and username/password provided
config.setCredentialsByURI('https://registry.com/', {
token: 'npm_abc123',
username: 'john',
password: 'secret'
});
// Throws: ErrInvalidAuth: Cannot use both token and username/password authenticationComprehensive Error Handling:
const { ErrInvalidAuth } = require('@npmcli/config/lib/errors');
async function setupAuthentication(config, registry, credentials) {
try {
// Validate credentials before setting
if (!credentials) {
throw new ErrInvalidAuth('No credentials provided', registry);
}
// Set credentials
config.setCredentialsByURI(registry, credentials);
// Save to user configuration
await config.save('user');
console.log(`Authentication configured for ${registry}`);
} catch (error) {
if (error instanceof ErrInvalidAuth) {
console.error(`Authentication Error: ${error.message}`);
console.error(`Registry: ${error.registry}`);
// Provide specific guidance based on registry
if (error.registry.includes('npmjs.org')) {
console.log('\nTo fix this:');
console.log('1. Run: npm login');
console.log('2. Or set NPM_TOKEN environment variable');
} else {
console.log('\nTo fix this:');
console.log('1. Contact your registry administrator');
console.log('2. Ensure you have valid credentials');
console.log('3. Check registry URL is correct');
}
return false;
} else {
// Re-throw non-authentication errors
throw error;
}
}
return true;
}Graceful Degradation:
async function getRegistryCredentials(config, registry) {
try {
const credentials = config.getCredentialsByURI(registry);
return credentials;
} catch (error) {
if (error instanceof ErrInvalidAuth) {
console.warn(`No valid credentials for ${registry}, using anonymous access`);
return null;
}
throw error;
}
}Validation Before Operations:
function validateAuthenticationSetup(config, requiredRegistries) {
const errors = [];
for (const registry of requiredRegistries) {
try {
const credentials = config.getCredentialsByURI(registry);
if (!credentials) {
errors.push(new ErrInvalidAuth('No credentials configured', registry));
}
} catch (error) {
if (error instanceof ErrInvalidAuth) {
errors.push(error);
}
}
}
if (errors.length > 0) {
console.error('Authentication validation failed:');
errors.forEach(error => {
console.error(`- ${error.registry}: ${error.message}`);
});
return false;
}
return true;
}// Error instance properties
interface ErrInvalidAuth extends Error {
/** Error name, always "ErrInvalidAuth" */
name: "ErrInvalidAuth";
/** Descriptive error message */
message: string;
/** Registry URL where authentication failed */
registry: string;
/** Error stack trace */
stack?: string;
}
// Error detection
function isAuthError(error: any): error is ErrInvalidAuth {
return error instanceof ErrInvalidAuth || error.name === 'ErrInvalidAuth';
}Usage in Error Detection:
function handleConfigError(error) {
if (error instanceof ErrInvalidAuth) {
// Handle authentication errors
return handleAuthenticationError(error);
} else if (error.code === 'ENOENT') {
// Handle file not found errors
return handleFileError(error);
} else {
// Handle other errors
return handleGenericError(error);
}
}Install with Tessl CLI
npx tessl i tessl/npm-npmcli--config