Skip to content
This repository has been archived by the owner on Nov 19, 2024. It is now read-only.

Commit

Permalink
fix: support scoped packages; closes #3
Browse files Browse the repository at this point in the history
  • Loading branch information
boneskull committed Jul 23, 2019
1 parent 391a401 commit 89d6a2e
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 33 deletions.
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,4 @@ jobs:
deploy:
provider: script
skip_cleanup: true
script:
- npx semantic-release
script: npx semantic-release
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ You _could_ install this, but you shouldn't have to. Use `npm` to install global
## Usage

```shell
$ npm init yo <some-generator>
$ npm init yo <some-generator>[:subgenerator]
```

All Yeoman generator packages start with `generator-`; this prefix is _optional_. In other words, `npm init yo license` will work just as well as `npm init yo generator-license`.
All Yeoman generator packages start with `generator-`; this prefix is _optional_ **unless you are using a scoped package**. In other words, `npm init yo license` will work just as well as `npm init yo generator-license`, but to use generator `@butts/generator-butts`, you must specify the complete package name with `npm init yo @butts/generator-butts`.

See [a list of generators here](http://yeoman.io/generators/).

Expand Down
22 changes: 15 additions & 7 deletions src/create-yo.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,33 @@ async function create(
}

let generator = argv.pop();

let generatorPackage = generator.startsWith(PREFIX)
? generator
: `${PREFIX}${generator}`;
let generatorName = generatorPackage.slice(PREFIX.length);
let generatorPackage;
let generatorName;
if (generator.startsWith('@')) {
// handle scoped packages
generatorName = generatorPackage = generator;
} else {
generatorPackage = generator.startsWith(PREFIX)
? generator
: `${PREFIX}${generator}`;
generatorName = generatorPackage.slice(PREFIX.length);
}

// handle subgenerators
generatorPackage = generatorPackage.split(':').shift();

return npx(
npx.parseArgs(
argv.concat(
[
...argv,
'--package',
'yo',
'--package',
generatorPackage,
'--',
'yo',
generatorName
),
],
npmPath
)
);
Expand Down
110 changes: 88 additions & 22 deletions test/create-yo.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,29 @@ const {parseArgs} = importFrom(
describe('create-yo', function() {
let sandbox;

describe('failures', function() {
let libnpx;
let create;
let libnpx;
let create;

beforeEach(function() {
sandbox = sinon.createSandbox();
libnpx = sandbox.spy();
libnpx.parseArgs = parseArgs;
rewiremock.enable();
create = rewiremock.proxy('..', r => ({
'global-dirs': r.by(() => ({
npm: {
packages: '/path/to/global/packages',
binaries: '/path/to/global/binaries'
}
})),
'import-from': r.by(() => () => libnpx)
})).create;
});
beforeEach(function() {
sandbox = sinon.createSandbox();
libnpx = sandbox.spy();
libnpx.parseArgs = parseArgs;
create = rewiremock.proxy('..', r => ({
'global-dirs': r.by(() => ({
npm: {
packages: '/path/to/global/packages',
binaries: '/path/to/global/binaries'
}
})),
'import-from': r.by(() => () => libnpx)
})).create;
});

afterEach(function() {
sandbox.restore();
rewiremock.disable();
});
afterEach(function() {
sandbox.restore();
});

describe('failure', function() {
describe('when no generator specified', function() {
it('should fail', async function() {
expect(
Expand Down Expand Up @@ -69,7 +67,9 @@ describe('create-yo', function() {
});
});
});
});

describe('success', function() {
describe('when subgenerator specified', function() {
it('should ask npx for the parent generator but use the subgenerator', async function() {
await create([
Expand All @@ -89,5 +89,71 @@ describe('create-yo', function() {
});
});
});

describe('when scoped package specified', function() {
describe('when subgenerator specified', function() {
it('should ask npx for the parent generator but use the subgenerator', async function() {
await create([
'/path/to/node',
'/path/to/create-yo',
'@scoped-package/generator-some-generator:subgenerator'
]);
expect(libnpx, 'to have a call satisfying', {
args: [
{
package: [
'yo@latest',
'@scoped-package/generator-some-generator@latest'
],
command: 'yo',
cmdOpts: [
'@scoped-package/generator-some-generator:subgenerator'
],
npm: '/path/to/global/binaries/npm'
}
]
});
});
});

it('should call libnpx with the correct parameters', async function() {
await create([
'/path/to/node',
'/path/to/create-yo',
'@scoped-package/generator-some-generator'
]);
expect(libnpx, 'to have a call satisfying', {
args: [
{
package: [
'yo@latest',
'@scoped-package/generator-some-generator@latest'
],
command: 'yo',
cmdOpts: ['@scoped-package/generator-some-generator'],
npm: '/path/to/global/binaries/npm'
}
]
});
});
});

it('should call libnpx with the correct parameters', async function() {
await create([
'/path/to/node',
'/path/to/create-yo',
'generator-some-generator'
]);
expect(libnpx, 'to have a call satisfying', {
args: [
{
package: ['yo@latest', 'generator-some-generator@latest'],
command: 'yo',
cmdOpts: ['some-generator'],
npm: '/path/to/global/binaries/npm'
}
]
});
});
});
});

0 comments on commit 89d6a2e

Please sign in to comment.