Skip to content

Commit

Permalink
init: use npx for extended initializers (#20303)
Browse files Browse the repository at this point in the history
PR-URL: npm/npm#20303
Credit: @jdalton
Reviewed-By: @zkat
  • Loading branch information
jdalton authored and zkat committed Apr 18, 2018
1 parent ad7a596 commit 008a836
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 11 deletions.
35 changes: 25 additions & 10 deletions doc/cli/npm-init.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,38 @@ npm-init(1) -- Interactively create a package.json file

## SYNOPSIS

npm init [-f|--force|-y|--yes]
npm init [--force|-f|--yes|-y]
npm init <@scope> (same as `npx <@scope>/create`)
npm init [<@scope>/]<pkg> (same as `npx [<@scope>/]create-<pkg>`)

## DESCRIPTION

This will ask you a bunch of questions, and then write a package.json for you.
* `npm init [--force|-f|--yes|-y]`:

It attempts to make reasonable guesses about what you want things to be set to,
and then writes a package.json file with the options you've selected.
This will ask you a bunch of questions, and then write a package.json for
you.

If you already have a package.json file, it'll read that first, and default to
the options in there.
It attempts to make reasonable guesses about what you want things to be set
to, and then writes a package.json file with the options you've selected.

It is strictly additive, so it does not delete options from your package.json
without a really good reason to do so.
If you already have a package.json file, it'll read that first, and default
to the options in there.

If you invoke it with `-f`, `--force`, `-y`, or `--yes`, it will use only
defaults and not prompt you for any options.
It is strictly additive, so it does not delete options from your
package.json without a really good reason to do so.

If you invoke it with `--force`, `-f`, `--yes`, or `-y`, it will use only
defaults and not prompt you for any options.

* `npm init <@scope>` (same as `npx <@scope>/create`):

Run `<@scope>/create` as the package initializer instead of
[`npm-init`](https://www.npmjs.com/package/init-package-json).

* `npm init [<@scope>/]<pkg>` (same as `npx [<@scope>/]create-<pkg>`):

Run `[<@scope>/]create-<pkg>` as the package initializer instead of
[`npm-init`](https://www.npmjs.com/package/init-package-json).

## CONFIGURATION

Expand Down
2 changes: 2 additions & 0 deletions lib/config/cmd-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ var shorthands = {
'rb': 'rebuild',
'list': 'ls',
'ln': 'link',
'create': 'init',
'i': 'install',
'it': 'install-test',
'cit': 'install-ci-test',
Expand All @@ -24,6 +25,7 @@ var affordances = {
'll': 'ls',
'verison': 'version',
'ic': 'ci',
'innit': 'init',
'isntall': 'install',
'dist-tags': 'dist-tag',
'apihelp': 'help',
Expand Down
24 changes: 23 additions & 1 deletion lib/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,37 @@

module.exports = init

var path = require('path')
var log = require('npmlog')
var npm = require('./npm.js')
var npx = require('libnpx')
var initJson = require('init-package-json')
var output = require('./utils/output.js')
var noProgressTillDone = require('./utils/no-progress-while-running').tillDone
var usage = require('./utils/usage')

init.usage = 'npm init [--force|-f|--yes|-y]'
init.usage = usage(
'init',
'\nnpm init [--force|-f|--yes|-y]' +
'\nnpm init <@scope> (same as `npx <@scope>/create`)' +
'\nnpm init [<@scope>/]<pkg> (same as `npx [<@scope>/]create-<pkg>`)'
)

function init (args, cb) {
if (args.length) {
var NPM_PATH = path.resolve(__dirname, '../bin/npm-cli.js')
var initerName = args[0]
var packageName = /^@[^/]+$/.test(initerName)
? initerName + '/create'
: initerName.replace(/^(@[^/]+\/)?/, '$1create-')

var npxArgs = [process.argv0, '[fake arg]', '--always-spawn', packageName, ...process.argv.slice(4)]
var parsed = npx.parseArgs(npxArgs, NPM_PATH)

return npx(parsed)
.then(() => cb())
.catch(cb)
}
var dir = process.cwd()
log.pause()
var initFile = npm.config.get('init-module')
Expand Down
61 changes: 61 additions & 0 deletions test/tap/init-create.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* eslint-disable standard/no-callback-literal */
var test = require('tap').test
var requireInject = require('require-inject')

var npm = require('../../lib/npm.js')

test('npm init <pkg-name>', function (t) {
var initJsonMock = function () {
t.ok(false, 'should not run initJson()')
}
initJsonMock.yes = function () {
t.ok(false, 'should not run initJson.yes()')
return false
}
var libnpxMock = function () {
return Promise.resolve()
}
libnpxMock.parseArgs = function (argv, defaultNpm) {
t.ok(argv[0].includes('node'), 'node is the first arg')
t.equals(argv[2], '--always-spawn', 'set npx opts.alwaysSpawn')
t.equals(argv[3], 'create-pkg-name', 'expands pkg-name')
t.ok(defaultNpm.endsWith('npm-cli.js'), 'passes npx bin path')
}

npm.load({ loglevel: 'silent' }, function () {
var init = requireInject('../../lib/init', {
'init-package-json': initJsonMock,
'libnpx': libnpxMock
})

init(['pkg-name'], function () {})

t.end()
})
})

test('npm init with scoped packages', function (t) {
var libnpxMock = function () {
return Promise.resolve()
}

npm.load({ loglevel: 'silent' }, function () {
var init = requireInject('../../lib/init', {
'libnpx': libnpxMock
})

libnpxMock.parseArgs = function (argv) {
t.equals(argv[3], '@scope/create', 'expands @scope')
}

init(['@scope'], function () {})

libnpxMock.parseArgs = function (argv) {
t.equals(argv[3], '@scope/create-pkg-name', 'expands @scope/pkg-name')
}

init(['@scope/pkg-name'], function () {})

t.end()
})
})

0 comments on commit 008a836

Please sign in to comment.