• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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