CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-npmcli--config

Configuration management for the npm command-line interface with hierarchical layered configuration system.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

errors.mddocs/

Error Handling

Configuration-specific error classes for handling invalid authentication and configuration validation failures.

Capabilities

ErrInvalidAuth Error Class

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);
  }
}

Common Authentication Error Scenarios

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 missing

Invalid Token Format:

// Malformed authentication token
config.setCredentialsByURI('https://registry.npmjs.org/', {
  token: 'invalid-token-format'
});
// Throws: ErrInvalidAuth: Invalid token format for registry

Conflicting 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 authentication

Error Handling Best Practices

Comprehensive 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 Properties and Methods

// 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

docs

config-management.md

credentials.md

errors.md

index.md

utilities.md

tile.json