Regex nom de paquet npm
Un nom de paquet npm, ce n'est pas juste « des lettres, chiffres et tirets » : npm valide en réalité le nom via une suite de vérifications impératives (liste noire, longueur maximale, encodage URL), jamais une seule regex de forme. La bibliothèque scoped-regex, très suivie et publiée par un auteur reconnu, active le flag insensible à la casse — ce qui « valide » à tort un scope en majuscules, alors que npm les interdit strictement. Voici un motif qui respecte cette contrainte, comparé à cette bibliothèque et deux autres tentatives qui omettent chacune une règle réelle de l'implémentation officielle.
/^(?:@[a-z0-9~][a-z0-9-._~]*/)?[a-z0-9~][a-z0-9-._~]*$/passe 20/20 cas
Comparatif des patterns existants
| Source | pattern | Score sur le corpus | ReDoS |
|---|---|---|---|
| sindresorhus/scoped-regex (paquet npm réel et populaire) — utilisé avec le flag insensible à la casse, « valide » à tort un scope en majuscules pourtant strictement interdit par npm | @[a-z\d][\w-.]+/[a-z\d][\w-.]* | 13 / 20 | sûr |
| Gist GitHub (mhafemann) — accepte à tort un nom commençant par un tiret (seuls le point et l'underscore sont documentés comme interdits en tête dans cette regex précise), et ne vérifie ni la limite de 214 caractères, ni la liste noire (node_modules, favicon.ico), ni les modules cœur de Node | ^(@[a-z0-9-~][a-z0-9-._~]*/)?[a-z0-9-~][a-z0-9-._~]*$ | 19 / 20 | sûr |
| Pattern interne de validate-npm-package-name (scopedPackagePattern), volontairement permissif — ne sert qu'à séparer @scope et nom, jamais à valider la forme complète d'un nom de paquet | ^(?:@([^/]+?)[/])?([^/]+?)$ | 10 / 20 | sûr |
Implémentation
const re = new RegExp("^(?:@[a-z0-9~][a-z0-9-._~]*/)?[a-z0-9~][a-z0-9-._~]*$", "");
re.test(input);Limites
- Valide seulement la FORME générale (minuscules, scope optionnel) : n'impose pas la limite officielle de 214 caractères (avertissement seulement dans l'implémentation réelle npm, pas un rejet), ni la liste noire de noms réservés (« node_modules », « favicon.ico »).
- N'exclut pas les noms de modules cœur de Node.js (« http », « fs », « path »…) : npm les rejette pour éviter toute confusion avec un import natif, une règle par liste explicite qu'une regex de forme ne peut pas exprimer.
- Ne vérifie pas que le nom reste sûr une fois encodé en URL (l'implémentation officielle compare le nom à `encodeURIComponent(name)`) : certains caractères spéciaux structurellement acceptés par ce motif peuvent malgré tout être rejetés par npm pour cette raison.
- npm valide en réalité un nom de paquet avec une suite de vérifications impératives, jamais une seule regex : cette page teste la partie « forme » de cette suite, pas son équivalent complet.