1var fs = require('fs') 2var glob = require('glob') 3var path = require('path') 4var validateLicense = require('validate-npm-package-license') 5var validateName = require('validate-npm-package-name') 6var npa = require('npm-package-arg') 7var semver = require('semver') 8 9// more popular packages should go here, maybe? 10function isTestPkg (p) { 11 return !!p.match(/^(expresso|mocha|tap|coffee-script|coco|streamline)$/) 12} 13 14function niceName (n) { 15 return n.replace(/^node-|[.-]js$/g, '').replace(' ', '-').toLowerCase() 16} 17 18function readDeps (test, excluded) { return function (cb) { 19 fs.readdir('node_modules', function (er, dir) { 20 if (er) return cb() 21 var deps = {} 22 var n = dir.length 23 if (n === 0) return cb(null, deps) 24 dir.forEach(function (d) { 25 if (d.match(/^\./)) return next() 26 if (test !== isTestPkg(d) || excluded[d]) 27 return next() 28 29 var dp = path.join(dirname, 'node_modules', d, 'package.json') 30 fs.readFile(dp, 'utf8', function (er, p) { 31 if (er) return next() 32 try { p = JSON.parse(p) } 33 catch (e) { return next() } 34 if (!p.version) return next() 35 if (p._requiredBy) { 36 if (!p._requiredBy.some(function (req) { return req === '#USER' })) return next() 37 } 38 deps[d] = config.get('save-exact') ? p.version : config.get('save-prefix') + p.version 39 return next() 40 }) 41 }) 42 function next () { 43 if (--n === 0) return cb(null, deps) 44 } 45 }) 46}} 47 48var name = package.name || basename 49var spec 50try { 51 spec = npa(name) 52} catch (e) { 53 spec = {} 54} 55var scope = config.get('scope') 56if (scope) { 57 if (scope.charAt(0) !== '@') scope = '@' + scope 58 if (spec.scope) { 59 name = scope + '/' + spec.name.split('/')[1] 60 } else { 61 name = scope + '/' + name 62 } 63} 64exports.name = yes ? name : prompt('package name', niceName(name), function (data) { 65 var its = validateName(data) 66 if (its.validForNewPackages) return data 67 var errors = (its.errors || []).concat(its.warnings || []) 68 var er = new Error('Sorry, ' + errors.join(' and ') + '.') 69 er.notValid = true 70 return er 71}) 72 73var version = package.version || 74 config.get('init.version') || 75 config.get('init-version') || 76 '1.0.0' 77exports.version = yes ? 78 version : 79 prompt('version', version, function (version) { 80 if (semver.valid(version)) return version 81 var er = new Error('Invalid version: "' + version + '"') 82 er.notValid = true 83 return er 84 }) 85 86if (!package.description) { 87 exports.description = yes ? '' : prompt('description') 88} 89 90if (!package.main) { 91 exports.main = function (cb) { 92 fs.readdir(dirname, function (er, f) { 93 if (er) f = [] 94 95 f = f.filter(function (f) { 96 return f.match(/\.js$/) 97 }) 98 99 if (f.indexOf('index.js') !== -1) 100 f = 'index.js' 101 else if (f.indexOf('main.js') !== -1) 102 f = 'main.js' 103 else if (f.indexOf(basename + '.js') !== -1) 104 f = basename + '.js' 105 else 106 f = f[0] 107 108 var index = f || 'index.js' 109 return cb(null, yes ? index : prompt('entry point', index)) 110 }) 111 } 112} 113 114if (!package.bin) { 115 exports.bin = function (cb) { 116 fs.readdir(path.resolve(dirname, 'bin'), function (er, d) { 117 // no bins 118 if (er) return cb() 119 // just take the first js file we find there, or nada 120 return cb(null, d.filter(function (f) { 121 return f.match(/\.js$/) 122 })[0]) 123 }) 124 } 125} 126 127exports.directories = function (cb) { 128 fs.readdir(dirname, function (er, dirs) { 129 if (er) return cb(er) 130 var res = {} 131 dirs.forEach(function (d) { 132 switch (d) { 133 case 'example': case 'examples': return res.example = d 134 case 'test': case 'tests': return res.test = d 135 case 'doc': case 'docs': return res.doc = d 136 case 'man': return res.man = d 137 case 'lib': return res.lib = d 138 } 139 }) 140 if (Object.keys(res).length === 0) res = undefined 141 return cb(null, res) 142 }) 143} 144 145if (!package.dependencies) { 146 exports.dependencies = readDeps(false, package.devDependencies || {}) 147} 148 149if (!package.devDependencies) { 150 exports.devDependencies = readDeps(true, package.dependencies || {}) 151} 152 153// MUST have a test script! 154var s = package.scripts || {} 155var notest = 'echo "Error: no test specified" && exit 1' 156if (!package.scripts) { 157 exports.scripts = function (cb) { 158 fs.readdir(path.join(dirname, 'node_modules'), function (er, d) { 159 setupScripts(d || [], cb) 160 }) 161 } 162} 163function setupScripts (d, cb) { 164 // check to see what framework is in use, if any 165 function tx (test) { 166 return test || notest 167 } 168 if (!s.test || s.test === notest) { 169 var commands = { 170 'tap':'tap test/*.js' 171 , 'expresso':'expresso test' 172 , 'mocha':'mocha' 173 } 174 var command 175 Object.keys(commands).forEach(function (k) { 176 if (d.indexOf(k) !== -1) command = commands[k] 177 }) 178 var ps = 'test command' 179 if (yes) { 180 s.test = command || notest 181 } else { 182 s.test = command ? prompt(ps, command, tx) : prompt(ps, tx) 183 } 184 } 185 return cb(null, s) 186} 187 188if (!package.repository) { 189 exports.repository = function (cb) { 190 fs.readFile('.git/config', 'utf8', function (er, gconf) { 191 if (er || !gconf) { 192 return cb(null, yes ? '' : prompt('git repository')) 193 } 194 gconf = gconf.split(/\r?\n/) 195 var i = gconf.indexOf('[remote "origin"]') 196 if (i !== -1) { 197 var u = gconf[i + 1] 198 if (!u.match(/^\s*url =/)) u = gconf[i + 2] 199 if (!u.match(/^\s*url =/)) u = null 200 else u = u.replace(/^\s*url = /, '') 201 } 202 if (u && u.match(/^git@github.com:/)) 203 u = u.replace(/^git@github.com:/, 'https://github.com/') 204 205 return cb(null, yes ? u : prompt('git repository', u)) 206 }) 207 } 208} 209 210if (!package.keywords) { 211 exports.keywords = yes ? '' : prompt('keywords', function (s) { 212 if (!s) return undefined 213 if (Array.isArray(s)) s = s.join(' ') 214 if (typeof s !== 'string') return s 215 return s.split(/[\s,]+/) 216 }) 217} 218 219if (!package.author) { 220 exports.author = config.get('init.author.name') || 221 config.get('init-author-name') 222 ? { 223 "name" : config.get('init.author.name') || 224 config.get('init-author-name'), 225 "email" : config.get('init.author.email') || 226 config.get('init-author-email'), 227 "url" : config.get('init.author.url') || 228 config.get('init-author-url') 229 } 230 : yes ? '' : prompt('author') 231} 232 233var license = package.license || 234 config.get('init.license') || 235 config.get('init-license') || 236 'ISC' 237exports.license = yes ? license : prompt('license', license, function (data) { 238 var its = validateLicense(data) 239 if (its.validForNewPackages) return data 240 var errors = (its.errors || []).concat(its.warnings || []) 241 var er = new Error('Sorry, ' + errors.join(' and ') + '.') 242 er.notValid = true 243 return er 244}) 245