1 2module.exports = init 3module.exports.yes = yes 4 5var PZ = require('promzard').PromZard 6var path = require('path') 7var def = require.resolve('./default-input.js') 8 9var fs = require('fs') 10var semver = require('semver') 11var read = require('read') 12 13// to validate the data object at the end as a worthwhile package 14// and assign default values for things. 15// readJson.extras(file, data, cb) 16var readJson = require('read-package-json') 17 18function yes (conf) { 19 return !!( 20 conf.get('yes') || conf.get('y') || 21 conf.get('force') || conf.get('f') 22 ) 23} 24 25function init (dir, input, config, cb) { 26 if (typeof config === 'function') 27 cb = config, config = {} 28 29 // accept either a plain-jane object, or a config object 30 // with a "get" method. 31 if (typeof config.get !== 'function') { 32 var data = config 33 config = { 34 get: function (k) { 35 return data[k] 36 }, 37 toJSON: function () { 38 return data 39 } 40 } 41 } 42 43 var packageFile = path.resolve(dir, 'package.json') 44 input = path.resolve(input) 45 var pkg 46 var ctx = { yes: yes(config) } 47 48 var es = readJson.extraSet 49 readJson.extraSet = es.filter(function (fn) { 50 return fn.name !== 'authors' && fn.name !== 'mans' 51 }) 52 readJson(packageFile, function (er, d) { 53 readJson.extraSet = es 54 55 if (er) pkg = {} 56 else pkg = d 57 58 ctx.filename = packageFile 59 ctx.dirname = path.dirname(packageFile) 60 ctx.basename = path.basename(ctx.dirname) 61 if (!pkg.version || !semver.valid(pkg.version)) 62 delete pkg.version 63 64 ctx.package = pkg 65 ctx.config = config || {} 66 67 // make sure that the input is valid. 68 // if not, use the default 69 var pz = new PZ(input, ctx) 70 pz.backupFile = def 71 pz.on('error', cb) 72 pz.on('data', function (data) { 73 Object.keys(data).forEach(function (k) { 74 if (data[k] !== undefined && data[k] !== null) pkg[k] = data[k] 75 }) 76 77 // only do a few of these. 78 // no need for mans or contributors if they're in the files 79 var es = readJson.extraSet 80 readJson.extraSet = es.filter(function (fn) { 81 return fn.name !== 'authors' && fn.name !== 'mans' 82 }) 83 readJson.extras(packageFile, pkg, function (er, pkg) { 84 readJson.extraSet = es 85 if (er) return cb(er, pkg) 86 pkg = unParsePeople(pkg) 87 // no need for the readme now. 88 delete pkg.readme 89 delete pkg.readmeFilename 90 91 // really don't want to have this lying around in the file 92 delete pkg._id 93 94 // ditto 95 delete pkg.gitHead 96 97 // if the repo is empty, remove it. 98 if (!pkg.repository) 99 delete pkg.repository 100 101 // readJson filters out empty descriptions, but init-package-json 102 // traditionally leaves them alone 103 if (!pkg.description) 104 pkg.description = data.description 105 106 var d = JSON.stringify(pkg, null, 2) + '\n' 107 function write (yes) { 108 fs.writeFile(packageFile, d, 'utf8', function (er) { 109 if (!er && yes && !config.get('silent')) { 110 console.log('Wrote to %s:\n\n%s\n', packageFile, d) 111 } 112 return cb(er, pkg) 113 }) 114 } 115 if (ctx.yes) { 116 return write(true) 117 } 118 console.log('About to write to %s:\n\n%s\n', packageFile, d) 119 read({prompt:'Is this OK? ', default: 'yes'}, function (er, ok) { 120 if (er) { 121 return cb(er) 122 } 123 if (!ok || ok.toLowerCase().charAt(0) !== 'y') { 124 console.log('Aborted.') 125 } else { 126 return write() 127 } 128 }) 129 }) 130 }) 131 }) 132 133} 134 135// turn the objects into somewhat more humane strings. 136function unParsePeople (data) { 137 if (data.author) data.author = unParsePerson(data.author) 138 ;["maintainers", "contributors"].forEach(function (set) { 139 if (!Array.isArray(data[set])) return; 140 data[set] = data[set].map(unParsePerson) 141 }) 142 return data 143} 144 145function unParsePerson (person) { 146 if (typeof person === "string") return person 147 var name = person.name || "" 148 var u = person.url || person.web 149 var url = u ? (" ("+u+")") : "" 150 var e = person.email || person.mail 151 var email = e ? (" <"+e+">") : "" 152 return name+email+url 153} 154 155