11'use strict'
22// vim: set ft=javascript ts=2 sw=2:
3+ const path = require ( 'path' )
34const inquirer = require ( 'inquirer' )
45const validatePackageName = require ( 'validate-npm-package-name' )
6+ const realizePackageSpecifier = require ( 'realize-package-specifier' )
57const arrayFromList = require ( './array-from-list' )
68const arrayOrUndefined = require ( './array-or-undefined' )
79
@@ -28,7 +30,8 @@ module.exports = async function prompt (opts = {}, options = {}) {
2830 } , {
2931 name : 'description' ,
3032 message : 'Description:' ,
31- default : opts . description ,
33+ // This is because inquirer treats an empty string as truthy and shows ()
34+ default : opts . description ? opts . description : undefined ,
3235 when : ! options . description
3336 } , {
3437 name : 'author' ,
@@ -42,34 +45,46 @@ module.exports = async function prompt (opts = {}, options = {}) {
4245 when : ! options . repository
4346 } , {
4447 name : 'keywords' ,
45- message : 'Keywords ( ex: blockchain, ninja) :' ,
48+ message : 'Keywords [ ex: blockchain, ninja] :' ,
4649 default : arrayOrUndefined ( opts . keywords ) ,
4750 when : ! options . keywords ,
4851 filter : arrayFromList
4952 } , {
5053 name : 'license' ,
51- message : 'License ( ex: MIT, unlicensed) :' ,
54+ message : 'License [ ex: MIT, unlicensed] :' ,
5255 default : opts . license ,
5356 when : ! options . license
5457 } , {
5558 name : 'main' ,
56- message : 'Entry point (main) :' ,
59+ message : 'Entry point:' ,
5760 default : opts . main ,
5861 when : ! options . main
5962 } , {
6063 name : 'dependencies' ,
61- message : 'Dependencies ( ex: express, react) :' ,
64+ message : 'Dependencies [ ex: express, react] :' ,
6265 default : arrayOrUndefined ( opts . dependencies ) ,
6366 when : ! options . dependencies ,
6467 filter : arrayFromList ,
6568 validate : validatePackageNames
6669 } , {
6770 name : 'devDependencies' ,
68- message : 'Dev Dependencies ( ex: mocha, webpack) :' ,
71+ message : 'Dev Dependencies [ ex: mocha, webpack] :' ,
6972 default : arrayOrUndefined ( opts . devDependencies ) ,
7073 when : ! options . devDependencies ,
7174 filter : arrayFromList ,
7275 validate : validatePackageNames
76+ } , {
77+ name : 'private' ,
78+ type : 'confirm' ,
79+ message : 'Is this package private?' ,
80+ default : ! ! opts . private ,
81+ when : opts . extended && typeof options . private === 'undefined'
82+ } , {
83+ name : 'man' ,
84+ message : 'Man Pages:' ,
85+ default : opts . man ,
86+ when : opts . extended && ! options . man ,
87+ filter : arrayFromList
7388 } ] )
7489
7590 // Get custom scripts
@@ -89,28 +104,28 @@ async function promptForScripts (opts = {}, options = {}) {
89104 when : ! options . scripts || ! options . scripts . test
90105 } , {
91106 name : 'prepare' ,
92- message : 'Prepare script ( run before publish and on local install) :' ,
107+ message : 'Prepare script [ run before publish and on local install] :' ,
93108 default : s . prepare ,
94- when : ! options . scripts || ! options . scripts . prepare
109+ when : opts . extended && ( ! options . scripts || ! options . scripts . prepare )
95110 } , {
96111 name : 'prepublushOnly' ,
97- message : 'Pre publush script ( run only before publish) :' ,
112+ message : 'Pre publush script [ run only before publish] :' ,
98113 default : s . prepublushOnly || 'npm t' ,
99114 when : ! options . scripts || ! options . scripts . prepublushOnly
100115 } , {
101116 name : 'postpublish' ,
102117 message : 'Post publish script:' ,
103118 default : s . postpublish ,
104- when : ! options . scripts || ! options . scripts . postpublish
119+ when : opts . extended && ( ! options . scripts || ! options . scripts . postpublish )
105120 } , {
106121 name : 'preversion' ,
107122 message : 'Pre version script:' ,
108- default : s . postpublish ,
109- when : ! options . scripts || ! options . scripts . postpublish
123+ default : s . preversion ,
124+ when : opts . extended && ( ! options . scripts || ! options . scripts . preversion )
110125 } ] )
111126
112127 // Merge scripts and add any customs
113- const scripts = await promptForCustomScript ( Object . assign ( s , commonScripts ) )
128+ const scripts = await promptForCustomScript ( opts , Object . assign ( s , commonScripts ) )
114129
115130 // Remove empty scripts
116131 return Object . keys ( scripts ) . reduce ( ( s , key ) => {
@@ -121,7 +136,11 @@ async function promptForScripts (opts = {}, options = {}) {
121136 } , { } )
122137}
123138
124- async function promptForCustomScript ( scripts = { } ) {
139+ async function promptForCustomScript ( opts = { } , scripts = { } ) {
140+ if ( ! opts . extended ) {
141+ return scripts
142+ }
143+
125144 const { another} = await inquirer . prompt ( [ {
126145 name : 'another' ,
127146 message : 'Add another script?' ,
@@ -143,13 +162,55 @@ async function promptForCustomScript (scripts = {}) {
143162
144163 scripts [ script . name ] = script . content
145164
146- return promptForCustomScript ( scripts )
165+ return promptForCustomScript ( opts , scripts )
166+ }
167+
168+ async function validatePackageNames ( input ) {
169+ if ( ! input ) {
170+ return true
171+ }
172+
173+ let valid = true
174+ for ( let i = 0 ; i < input . length && valid === true ; i ++ ) {
175+ let pkg
176+ try {
177+ pkg = await realizePkgSpec ( input [ i ] )
178+ } catch ( e ) {
179+ return e
180+ }
181+
182+ switch ( pkg . type ) {
183+ // Directory checkes for package.json and
184+ // hosted means it looks like a remote repo or tarball
185+ case 'directory' :
186+ case 'hosted' :
187+ return true
188+ case 'local' :
189+ // check for something that looks like a path
190+ // because any random string is marked as local
191+ if ( pkg . raw . includes ( '.' ) || pkg . raw . includes ( path . sep ) ) {
192+ continue
193+ }
194+ }
195+
196+ // Manual check because the validate package just says "name cannot be null"
197+ if ( ! pkg . name ) {
198+ return new Error ( 'Invalid package name: ' + pkg . raw )
199+ }
200+
201+ let v = validatePackageName ( pkg . name )
202+ valid = v . validForNewPackages || v . validForOldPackages ? true : ( ( v . errors && v . errors [ 0 ] ) || `Invalid package name: ${ input [ i ] } ` )
203+ }
204+ return valid
147205}
148206
149- function validatePackageNames ( input ) {
150- const error = input . reduce ( ( err , name ) => {
151- let v = validatePackageName ( name )
152- return err || ( v . validForNewPackages || v . validForOldPackages ? true : ( ( v . errors && v . errors [ 0 ] ) || `Invalid package name: ${ name } ` ) )
153- } , null )
154- return error || true
207+ function realizePkgSpec ( name ) {
208+ return new Promise ( ( resolve , reject ) => {
209+ realizePackageSpecifier ( name , ( err , pkg ) => {
210+ if ( err ) {
211+ return reject ( err )
212+ }
213+ resolve ( pkg )
214+ } )
215+ } )
155216}
0 commit comments