--- /dev/null
+var scopedPackagePattern = new RegExp("^(?:@([^/]+?)[/])?([^/]+?)$");
+var builtins = require("builtins")
+var blacklist = [
+ "node_modules",
+ "favicon.ico"
+];
+
+var validate = module.exports = function(name) {
+
+ var warnings = []
+ var errors = []
+
+ if (name === null) {
+ errors.push("name cannot be null")
+ return done(warnings, errors)
+ }
+
+ if (name === undefined) {
+ errors.push("name cannot be undefined")
+ return done(warnings, errors)
+ }
+
+ if (typeof name !== "string") {
+ errors.push("name must be a string")
+ return done(warnings, errors)
+ }
+
+ if (!name.length) {
+ errors.push("name length must be greater than zero")
+ }
+
+ if (name.match(/^\./)) {
+ errors.push("name cannot start with a period")
+ }
+
+ if (name.match(/^_/)) {
+ errors.push("name cannot start with an underscore")
+ }
+
+ if (name.trim() !== name) {
+ errors.push("name cannot contain leading or trailing spaces")
+ }
+
+ // No funny business
+ blacklist.forEach(function(blacklistedName){
+ if (name.toLowerCase() === blacklistedName) {
+ errors.push(blacklistedName + " is a blacklisted name")
+ }
+ })
+
+ // Generate warnings for stuff that used to be allowed
+
+ // core module names like http, events, util, etc
+ builtins.forEach(function(builtin){
+ if (name.toLowerCase() === builtin) {
+ warnings.push(builtin + " is a core module name")
+ }
+ })
+
+ // really-long-package-names-------------------------------such--length-----many---wow
+ // the thisisareallyreallylongpackagenameitshouldpublishdowenowhavealimittothelengthofpackagenames-poch.
+ if (name.length > 214) {
+ warnings.push("name can no longer contain more than 214 characters")
+ }
+
+ // mIxeD CaSe nAMEs
+ if (name.toLowerCase() !== name) {
+ warnings.push("name can no longer contain capital letters")
+ }
+
+ if (encodeURIComponent(name) !== name) {
+
+ // Maybe it's a scoped package name, like @user/package
+ var nameMatch = name.match(scopedPackagePattern)
+ if (nameMatch) {
+ var user = nameMatch[1]
+ var pkg = nameMatch[2]
+ if (encodeURIComponent(user) === user && encodeURIComponent(pkg) === pkg) {
+ return done(warnings, errors)
+ }
+ }
+
+ errors.push("name can only contain URL-friendly characters")
+ }
+
+ return done(warnings, errors)
+
+}
+
+validate.scopedPackagePattern = scopedPackagePattern
+
+var done = function (warnings, errors) {
+ var result = {
+ validForNewPackages: errors.length === 0 && warnings.length === 0,
+ validForOldPackages: errors.length === 0,
+ warnings: warnings,
+ errors: errors
+ }
+ if (!result.warnings.length) delete result.warnings
+ if (!result.errors.length) delete result.errors
+ return result
+}