Validates npm package names according to current and legacy npm registry rules, returning detailed validation results with specific error and warning messages.
npx @tessl/cli install tessl/npm-validate-npm-package-name@6.0.0Validates npm package names according to current and legacy npm registry rules, returning detailed validation results with specific error and warning messages. This library helps determine if a string is valid as an npm package name, distinguishing between packages that can be newly published versus those that were valid under older naming rules.
npm install validate-npm-package-nameconst validate = require("validate-npm-package-name");For ES modules:
import validate from "validate-npm-package-name";const validate = require("validate-npm-package-name");
// Valid package names
const result1 = validate("some-package");
// { validForNewPackages: true, validForOldPackages: true }
const result2 = validate("@npm/scoped-package");
// { validForNewPackages: true, validForOldPackages: true }
// Invalid package names with errors
const result3 = validate(" leading-space");
// {
// validForNewPackages: false,
// validForOldPackages: false,
// errors: ['name cannot contain leading or trailing spaces', 'name can only contain URL-friendly characters']
// }
// Legacy names with warnings
const result4 = validate("UPPERCASE-NAME");
// {
// validForNewPackages: false,
// validForOldPackages: true,
// warnings: ['name can no longer contain capital letters']
// }
const result5 = validate("crazy!");
// {
// validForNewPackages: false,
// validForOldPackages: true,
// warnings: ['name can no longer contain special characters ("~\'!()*")']
// }The main validation function that checks npm package names against all naming rules.
/**
* Validates an npm package name according to current and legacy rules
* @param {any} name - The package name to validate (expected to be string)
* @returns {ValidationResult} Validation result with validity flags and messages
*/
function validate(name);Validation Rules:
Error Conditions (invalid for both new and old packages):
null, undefined, or not a string.) or underscore (_)node_modules, favicon.ico)Warning Conditions (invalid for new packages, valid for legacy):
http, events, etc.)~, ', !, (, ), *Special Handling:
@scope/package receive special validationencodeURIComponent comparison/**
* Result object returned by the validate function
*/
interface ValidationResult {
/** True if the name is valid for newly published packages */
validForNewPackages: boolean;
/** True if the name is valid under legacy npm naming rules */
validForOldPackages: boolean;
/** Array of warning messages for legacy rule violations (omitted if empty) */
warnings?: string[];
/** Array of error messages for naming rule violations (omitted if empty) */
errors?: string[];
}const validate = require("validate-npm-package-name");
// Simple package names
validate("lodash"); // { validForNewPackages: true, validForOldPackages: true }
validate("express"); // { validForNewPackages: true, validForOldPackages: true }
validate("my-package"); // { validForNewPackages: true, validForOldPackages: true }
validate("under_score"); // { validForNewPackages: true, validForOldPackages: true }
validate("example.com"); // { validForNewPackages: true, validForOldPackages: true }
validate("123numeric"); // { validForNewPackages: true, validForOldPackages: true }
// Scoped package names
validate("@babel/core"); // { validForNewPackages: true, validForOldPackages: true }
validate("@types/node"); // { validForNewPackages: true, validForOldPackages: true }
validate("@my-org/utils"); // { validForNewPackages: true, validForOldPackages: true }// Names that were never valid
validate(""); // { validForNewPackages: false, validForOldPackages: false, errors: ['name length must be greater than zero'] }
validate(null); // { validForNewPackages: false, validForOldPackages: false, errors: ['name cannot be null'] }
validate(undefined); // { validForNewPackages: false, validForOldPackages: false, errors: ['name cannot be undefined'] }
validate(42); // { validForNewPackages: false, validForOldPackages: false, errors: ['name must be a string'] }
validate(".hidden"); // { validForNewPackages: false, validForOldPackages: false, errors: ['name cannot start with a period'] }
validate("_private"); // { validForNewPackages: false, validForOldPackages: false, errors: ['name cannot start with an underscore'] }
validate(" spaces "); // { validForNewPackages: false, validForOldPackages: false, errors: ['name cannot contain leading or trailing spaces', 'name can only contain URL-friendly characters'] }
validate("node_modules"); // { validForNewPackages: false, validForOldPackages: false, errors: ['node_modules is not a valid package name'] }
validate("favicon.ico"); // { validForNewPackages: false, validForOldPackages: false, errors: ['favicon.ico is not a valid package name'] }// Names valid under old rules but not new ones
validate("UPPERCASE"); // { validForNewPackages: false, validForOldPackages: true, warnings: ['name can no longer contain capital letters'] }
validate("crazy!"); // { validForNewPackages: false, validForOldPackages: true, warnings: ['name can no longer contain special characters ("~\'!()*")'] }
validate("http"); // { validForNewPackages: false, validForOldPackages: true, warnings: ['http is a core module name'] }
// Very long names (214+ characters)
const longName = "a".repeat(215);
validate(longName); // { validForNewPackages: false, validForOldPackages: true, warnings: ['name can no longer contain more than 214 characters'] }// Valid scoped packages
validate("@user/package"); // { validForNewPackages: true, validForOldPackages: true }
validate("@org/my-lib"); // { validForNewPackages: true, validForOldPackages: true }
// Scoped packages with legacy warnings
validate("@user/CAPS"); // { validForNewPackages: false, validForOldPackages: true, warnings: ['name can no longer contain capital letters'] }
validate("@user/special!"); // { validForNewPackages: false, validForOldPackages: true, warnings: ['name can no longer contain special characters ("~\'!()*")'] }
// Scoped packages with errors
validate("@user/.dotfile"); // { validForNewPackages: false, validForOldPackages: false, errors: ['name cannot start with a period'] }
// Note: Scoped packages have relaxed rules - they can contain core module names
validate("@user/http"); // { validForNewPackages: true, validForOldPackages: true }
validate("@user/node_modules"); // { validForNewPackages: true, validForOldPackages: true }