Skip to content

Commit fd28b8c

Browse files
committed
fix(new): Make sure the project name is valid.
1 parent 8d88446 commit fd28b8c

File tree

2 files changed

+52
-24
lines changed

2 files changed

+52
-24
lines changed

packages/angular-cli/commands/new.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as chalk from 'chalk';
22
import InitCommand from './init';
3+
import {oneLine} from 'common-tags';
34

45
const Command = require('../ember-cli/lib/models/command');
56
const Project = require('../ember-cli/lib/models/project');
@@ -37,6 +38,12 @@ const NewCommand = Command.extend({
3738
`The "ng ${this.name}" command requires a name argument to be specified. ` +
3839
`For more details, use "ng help".`));
3940
}
41+
if (!packageName.match(/^[a-zA-Z][.0-9a-zA-Z]*(-[a-zA-Z][.0-9a-zA-Z]*)*$/)) {
42+
return Promise.reject(new SilentError(oneLine`
43+
Project name "${packageName}" is not valid. New project names must
44+
start with a letter, and must contain only alphanumeric characters or dashes.
45+
`));
46+
}
4047

4148
commandOptions.name = packageName;
4249
if (commandOptions.dryRun) {

tests/acceptance/new.spec.js renamed to tests/acceptance/new.spec.ts

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
'use strict';
2-
3-
var fs = require('fs-extra');
4-
var ng = require('../helpers/ng');
5-
var existsSync = require('exists-sync');
6-
var expect = require('chai').expect;
7-
var forEach = require('lodash/forEach');
8-
var walkSync = require('walk-sync');
9-
var Blueprint = require('angular-cli/ember-cli/lib/models/blueprint');
10-
var path = require('path');
11-
var tmp = require('../helpers/tmp');
12-
var root = process.cwd();
13-
var util = require('util');
14-
var EOL = require('os').EOL;
15-
var SilentError = require('silent-error');
1+
const fs = require('fs-extra');
2+
const ng = require('../helpers/ng');
3+
const existsSync = require('exists-sync');
4+
const expect = require('chai').expect;
5+
const forEach = require('lodash/forEach');
6+
const walkSync = require('walk-sync');
7+
const Blueprint = require('angular-cli/ember-cli/lib/models/blueprint');
8+
const path = require('path');
9+
const tmp = require('../helpers/tmp');
10+
const root = process.cwd();
11+
const util = require('util');
12+
const EOL = require('os').EOL;
13+
const SilentError = require('silent-error');
14+
1615

1716
describe('Acceptance: ng new', function () {
1817
beforeEach(function () {
@@ -29,10 +28,10 @@ describe('Acceptance: ng new', function () {
2928

3029
function confirmBlueprintedForDir(dir) {
3130
return function () {
32-
var blueprintPath = path.join(root, dir, 'files');
33-
var expected = walkSync(blueprintPath);
34-
var actual = walkSync('.').sort();
35-
var directory = path.basename(process.cwd());
31+
let blueprintPath = path.join(root, dir, 'files');
32+
let expected = walkSync(blueprintPath);
33+
let actual = walkSync('.').sort();
34+
let directory = path.basename(process.cwd());
3635

3736
forEach(Blueprint.renamedFiles, function (destFile, srcFile) {
3837
expected[expected.indexOf(srcFile)] = destFile;
@@ -56,6 +55,28 @@ describe('Acceptance: ng new', function () {
5655
return confirmBlueprintedForDir('blueprints/ng2');
5756
}
5857

58+
it('requires a valid name (!)', () => {
59+
return ng(['new', '!', '--skip-npm', '--skip-git', '--inline-template']).then(() => { throw new Error(); }, () => {});
60+
});
61+
it('requires a valid name (abc-.)', () => {
62+
return ng(['new', 'abc-.', '--skip-npm', '--skip-git', '--inline-template']).then(() => { throw new Error(); }, () => {});
63+
});
64+
it('requires a valid name (abc-)', () => {
65+
return ng(['new', 'abc-', '--skip-npm', '--skip-git', '--inline-template']).then(() => { throw new Error(); }, () => {});
66+
});
67+
it('requires a valid name (abc-def-)', () => {
68+
return ng(['new', 'abc-def-', '--skip-npm', '--skip-git', '--inline-template']).then(() => { throw new Error(); }, () => {});
69+
});
70+
it('requires a valid name (abc-123)', () => {
71+
return ng(['new', 'abc-123', '--skip-npm', '--skip-git', '--inline-template']).then(() => { throw new Error(); }, () => {});
72+
});
73+
it('requires a valid name (abc)', () => {
74+
return ng(['new', 'abc', '--skip-npm', '--skip-git', '--inline-template']);
75+
});
76+
it('requires a valid name (abc-def)', () => {
77+
return ng(['new', 'abc-def', '--skip-npm', '--skip-git', '--inline-template']);
78+
});
79+
5980
it('ng new foo, where foo does not yet exist, works', function () {
6081
return ng(['new', 'foo', '--skip-npm', '--skip-bower']).then(confirmBlueprinted);
6182
});
@@ -72,7 +93,7 @@ describe('Acceptance: ng new', function () {
7293
return ng(['new', 'FooApp', '--skip-npm', '--skip-bower', '--skip-git']).then(function () {
7394
expect(!existsSync('FooApp'));
7495

75-
var pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
96+
const pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
7697
expect(pkgJson.name).to.equal('foo-app');
7798
});
7899
});
@@ -81,7 +102,7 @@ describe('Acceptance: ng new', function () {
81102
return ng(['new', 'FooApp', '--skip-npm', '--skip-bower', '--skip-git']).then(function () {
82103
expect(!existsSync('FooApp'));
83104

84-
var editorConfig = fs.readFileSync('.editorconfig', 'utf8');
105+
const editorConfig = fs.readFileSync('.editorconfig', 'utf8');
85106
expect(editorConfig).to.exist;
86107
});
87108
});
@@ -106,7 +127,7 @@ describe('Acceptance: ng new', function () {
106127

107128
it('ng new with --dry-run does not create new directory', function () {
108129
return ng(['new', 'foo', '--dry-run']).then(function () {
109-
var cwd = process.cwd();
130+
const cwd = process.cwd();
110131
expect(cwd).to.not.match(/foo/, 'does not change cwd to foo in a dry run');
111132
expect(!existsSync(path.join(cwd, 'foo')), 'does not create new directory');
112133
expect(!existsSync(path.join(cwd, '.git')), 'does not create git in current directory');
@@ -116,14 +137,14 @@ describe('Acceptance: ng new', function () {
116137
it('ng new with --directory uses given directory name and has correct package name', function () {
117138
return ng(['new', 'foo', '--skip-npm', '--skip-bower', '--skip-git', '--directory=bar'])
118139
.then(function () {
119-
var cwd = process.cwd();
140+
const cwd = process.cwd();
120141
expect(cwd).to.not.match(/foo/, 'does not use app name for directory name');
121142
expect(!existsSync(path.join(cwd, 'foo')), 'does not create new directory with app name');
122143

123144
expect(cwd).to.match(/bar/, 'uses given directory name');
124145
expect(existsSync(path.join(cwd, 'bar')), 'creates new directory with specified name');
125146

126-
var pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
147+
const pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
127148
expect(pkgJson.name).to.equal('foo', 'uses app name for package name');
128149
});
129150
});

0 commit comments

Comments
 (0)