Skip to content

Commit cfe93fb

Browse files
alan-agius4dgp1130
authored andcommitted
feat(@angular/create): add support for yarn create and npm init
With this change we add support to scaffold an Angular workspace using `yarn create @angular` and `npm init @angular`. These shortcuts support all of the `ng-new` options. Closes #10339 and closes #14292
1 parent cf24008 commit cfe93fb

File tree

10 files changed

+158
-7
lines changed

10 files changed

+158
-7
lines changed

.monorepo.json

+10
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@
1414
],
1515
"snapshotRepo": "angular/cli-builds"
1616
},
17+
"@angular/create": {
18+
"name": "Angular Create",
19+
"section": "Misc",
20+
"links": [
21+
{
22+
"label": "README",
23+
"url": "/packages/angular/create/README.md"
24+
}
25+
]
26+
},
1727
"@angular/pwa": {
1828
"name": "Angular PWA Schematics",
1929
"section": "Schematics",

CONTRIBUTING.md

+1
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ The scope should be the name of the npm package affected as perceived by the per
212212
The following is the list of supported scopes:
213213
214214
* **@angular/cli**
215+
* **@angular/create**
215216
* **@angular/pwa**
216217
* **@angular-devkit/architect**
217218
* **@angular-devkit/architect-cli**

README.md

+6-5
Original file line numberDiff line numberDiff line change
@@ -164,18 +164,19 @@ This is a monorepo which contains many tools and packages:
164164
**Core** | [`@angular-devkit/core`](https://npmjs.com/package/@angular-devkit/core) | [![latest](https://img.shields.io/npm/v/%40angular-devkit%2Fcore/latest.svg)](https://npmjs.com/package/@angular-devkit/core) | [![README](https://img.shields.io/badge/README--green.svg)](/packages/angular_devkit/core/README.md) [![snapshot](https://img.shields.io/badge/snapshot--blue.svg)](https://github.com/angular/angular-devkit-core-builds)
165165
**Schematics** | [`@angular-devkit/schematics`](https://npmjs.com/package/@angular-devkit/schematics) | [![latest](https://img.shields.io/npm/v/%40angular-devkit%2Fschematics/latest.svg)](https://npmjs.com/package/@angular-devkit/schematics) | [![README](https://img.shields.io/badge/README--green.svg)](/packages/angular_devkit/schematics/README.md) [![snapshot](https://img.shields.io/badge/snapshot--blue.svg)](https://github.com/angular/angular-devkit-schematics-builds)
166166

167-
#### Schematics
167+
#### Misc
168168

169169
| Project | Package | Version | Links |
170170
|---|---|---|---|
171-
**Angular PWA Schematics** | [`@angular/pwa`](https://npmjs.com/package/@angular/pwa) | [![latest](https://img.shields.io/npm/v/%40angular%2Fpwa/latest.svg)](https://npmjs.com/package/@angular/pwa) | [![snapshot](https://img.shields.io/badge/snapshot--blue.svg)](https://github.com/angular/angular-pwa-builds)
172-
**Angular Schematics** | [`@schematics/angular`](https://npmjs.com/package/@schematics/angular) | [![latest](https://img.shields.io/npm/v/%40schematics%2Fangular/latest.svg)](https://npmjs.com/package/@schematics/angular) | [![snapshot](https://img.shields.io/badge/snapshot--blue.svg)](https://github.com/angular/schematics-angular-builds)
171+
**Angular Create** | [`@angular/create`](https://npmjs.com/package/@angular/create) | [![latest](https://img.shields.io/npm/v/%40angular%2Fcreate/latest.svg)](https://npmjs.com/package/@angular/create) | [![README](https://img.shields.io/badge/README--green.svg)](/packages/angular/create/README.md)
172+
**Webpack Angular Plugin** | [`@ngtools/webpack`](https://npmjs.com/package/@ngtools/webpack) | [![latest](https://img.shields.io/npm/v/%40ngtools%2Fwebpack/latest.svg)](https://npmjs.com/package/@ngtools/webpack) | [![snapshot](https://img.shields.io/badge/snapshot--blue.svg)](https://github.com/angular/ngtools-webpack-builds)
173173

174-
#### Misc
174+
#### Schematics
175175

176176
| Project | Package | Version | Links |
177177
|---|---|---|---|
178-
**Webpack Angular Plugin** | [`@ngtools/webpack`](https://npmjs.com/package/@ngtools/webpack) | [![latest](https://img.shields.io/npm/v/%40ngtools%2Fwebpack/latest.svg)](https://npmjs.com/package/@ngtools/webpack) | [![snapshot](https://img.shields.io/badge/snapshot--blue.svg)](https://github.com/angular/ngtools-webpack-builds)
178+
**Angular PWA Schematics** | [`@angular/pwa`](https://npmjs.com/package/@angular/pwa) | [![latest](https://img.shields.io/npm/v/%40angular%2Fpwa/latest.svg)](https://npmjs.com/package/@angular/pwa) | [![snapshot](https://img.shields.io/badge/snapshot--blue.svg)](https://github.com/angular/angular-pwa-builds)
179+
**Angular Schematics** | [`@schematics/angular`](https://npmjs.com/package/@schematics/angular) | [![latest](https://img.shields.io/npm/v/%40schematics%2Fangular/latest.svg)](https://npmjs.com/package/@schematics/angular) | [![snapshot](https://img.shields.io/badge/snapshot--blue.svg)](https://github.com/angular/schematics-angular-builds)
179180

180181

181182

packages/angular/create/BUILD.bazel

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright Google Inc. All Rights Reserved.
2+
#
3+
# Use of this source code is governed by an MIT-style license that can be
4+
# found in the LICENSE file at https://angular.io/license
5+
6+
load("//tools:defaults.bzl", "pkg_npm", "ts_library")
7+
8+
licenses(["notice"]) # MIT
9+
10+
ts_library(
11+
name = "create",
12+
package_name = "@angular/create",
13+
srcs = glob(
14+
["**/*.ts"],
15+
exclude = [
16+
# NB: we need to exclude the nested node_modules that is laid out by yarn workspaces
17+
"node_modules/**",
18+
],
19+
),
20+
deps = [
21+
"//packages/angular/cli:angular-cli",
22+
"@npm//@types/node",
23+
],
24+
)
25+
26+
genrule(
27+
name = "license",
28+
srcs = ["//:LICENSE"],
29+
outs = ["LICENSE"],
30+
cmd = "cp $(execpath //:LICENSE) $@",
31+
)
32+
33+
pkg_npm(
34+
name = "npm_package",
35+
visibility = ["//visibility:public"],
36+
deps = [
37+
":README.md",
38+
":create",
39+
":license",
40+
],
41+
)

packages/angular/create/README.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# `@angular/create`
2+
3+
# Create an Angular CLI workspace
4+
5+
Scaffold an Angular CLI workspace without needing to install the Angular CLI globally. All of the [ng new](https://angular.io/cli/new) options and features are supported.
6+
7+
# Usage
8+
9+
NPM
10+
11+
```
12+
npm init @angular@latest [project-name] -- [...options]
13+
```
14+
15+
Yarn
16+
17+
```
18+
yarn create @angular [project-name] [...options]
19+
```

packages/angular/create/package.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "@angular/create",
3+
"version": "0.0.0-PLACEHOLDER",
4+
"description": "Scaffold an Angular CLI workspace.",
5+
"keywords": [
6+
"angular",
7+
"angular-cli",
8+
"Angular CLI",
9+
"code generation",
10+
"schematics"
11+
],
12+
"bin": {
13+
"create": "./src/index.js"
14+
},
15+
"dependencies": {
16+
"@angular/cli": "0.0.0-PLACEHOLDER"
17+
}
18+
}

packages/angular/create/src/index.ts

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env node
2+
/**
3+
* @license
4+
* Copyright Google LLC All Rights Reserved.
5+
*
6+
* Use of this source code is governed by an MIT-style license that can be
7+
* found in the LICENSE file at https://angular.io/license
8+
*/
9+
10+
import { spawnSync } from 'child_process';
11+
import { join } from 'path';
12+
13+
const binPath = join(require.resolve('@angular/cli/package.json'), '../bin/ng.js');
14+
15+
// Invoke ng new with any parameters provided.
16+
const { error } = spawnSync(process.execPath, [binPath, 'new', ...process.argv.slice(2)], {
17+
stdio: 'inherit',
18+
});
19+
20+
if (error) {
21+
// eslint-disable-next-line no-console
22+
console.error(error);
23+
process.exitCode = 1;
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { join, resolve } from 'path';
2+
import { expectFileToExist, rimraf } from '../../utils/fs';
3+
import { getActivePackageManager } from '../../utils/packages';
4+
import { silentNpm, silentYarn } from '../../utils/process';
5+
6+
export default async function () {
7+
const currentDirectory = process.cwd();
8+
const newDirectory = resolve('../');
9+
10+
const projectName = 'test-project-create';
11+
12+
try {
13+
process.chdir(newDirectory);
14+
const packageManager = getActivePackageManager();
15+
16+
switch (packageManager) {
17+
case 'npm':
18+
await silentNpm('init', '@angular', projectName, '--', '--skip-install', '--style=scss');
19+
20+
break;
21+
case 'yarn':
22+
await silentYarn('create', '@angular', projectName, '--skip-install', '--style=scss');
23+
24+
break;
25+
default:
26+
throw new Error(`This test is not configured to use ${packageManager}.`);
27+
}
28+
29+
await expectFileToExist(join(projectName, 'angular.json'));
30+
// Verify styles was create with correct extension.
31+
await expectFileToExist(join(projectName, 'src/styles.scss'));
32+
} finally {
33+
await rimraf(projectName);
34+
// Change directory back
35+
process.chdir(currentDirectory);
36+
}
37+
}

tests/legacy-cli/e2e/utils/project.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export async function prepareProjectForE2e(name: string) {
3939
const argv: yargsParser.Arguments = getGlobalVariable('argv');
4040

4141
await git('config', 'user.email', '[email protected]');
42-
await git('config', 'user.name', 'Angular CLI E2e');
42+
await git('config', 'user.name', 'Angular CLI E2E');
4343
await git('config', 'commit.gpgSign', 'false');
4444

4545
if (argv['ng-snapshots'] || argv['ng-tag']) {

tests/legacy-cli/verdaccio.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ uplinks:
1717
maxFreeSockets: 8
1818

1919
packages:
20-
'@angular/{cli,pwa}':
20+
'@angular/{create,cli,pwa}':
2121
access: $all
2222
publish: $all
2323

0 commit comments

Comments
 (0)