diff --git a/.monorepo.json b/.monorepo.json index cdc8daa5c261..d2c6803b9103 100644 --- a/.monorepo.json +++ b/.monorepo.json @@ -14,6 +14,16 @@ ], "snapshotRepo": "angular/cli-builds" }, + "@angular/create": { + "name": "Angular Create", + "section": "Misc", + "links": [ + { + "label": "README", + "url": "/packages/angular/create/README.md" + } + ] + }, "@angular/pwa": { "name": "Angular PWA Schematics", "section": "Schematics", diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 16fb93f8fdf4..9c5f4c272d77 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -212,6 +212,7 @@ The scope should be the name of the npm package affected as perceived by the per The following is the list of supported scopes: * **@angular/cli** +* **@angular/create** * **@angular/pwa** * **@angular-devkit/architect** * **@angular-devkit/architect-cli** diff --git a/README.md b/README.md index 0113a346e324..8e8a4587dbfc 100644 --- a/README.md +++ b/README.md @@ -164,18 +164,19 @@ This is a monorepo which contains many tools and packages: **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) **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) -#### Schematics +#### Misc | Project | Package | Version | Links | |---|---|---|---| -**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) -**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) +**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) +**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) -#### Misc +#### Schematics | Project | Package | Version | Links | |---|---|---|---| -**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) +**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) +**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) diff --git a/packages/angular/create/BUILD.bazel b/packages/angular/create/BUILD.bazel new file mode 100644 index 000000000000..53ac6a3d9ced --- /dev/null +++ b/packages/angular/create/BUILD.bazel @@ -0,0 +1,41 @@ +# Copyright Google Inc. All Rights Reserved. +# +# Use of this source code is governed by an MIT-style license that can be +# found in the LICENSE file at https://angular.io/license + +load("//tools:defaults.bzl", "pkg_npm", "ts_library") + +licenses(["notice"]) # MIT + +ts_library( + name = "create", + package_name = "@angular/create", + srcs = glob( + ["**/*.ts"], + exclude = [ + # NB: we need to exclude the nested node_modules that is laid out by yarn workspaces + "node_modules/**", + ], + ), + deps = [ + "//packages/angular/cli:angular-cli", + "@npm//@types/node", + ], +) + +genrule( + name = "license", + srcs = ["//:LICENSE"], + outs = ["LICENSE"], + cmd = "cp $(execpath //:LICENSE) $@", +) + +pkg_npm( + name = "npm_package", + visibility = ["//visibility:public"], + deps = [ + ":README.md", + ":create", + ":license", + ], +) diff --git a/packages/angular/create/README.md b/packages/angular/create/README.md new file mode 100644 index 000000000000..0deeb5a4fe0a --- /dev/null +++ b/packages/angular/create/README.md @@ -0,0 +1,19 @@ +# `@angular/create` + +# Create an Angular CLI workspace + +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. + +# Usage + +NPM + +``` +npm init @angular@latest [project-name] -- [...options] +``` + +Yarn + +``` +yarn create @angular [project-name] [...options] +``` diff --git a/packages/angular/create/package.json b/packages/angular/create/package.json new file mode 100644 index 000000000000..48f351dfb089 --- /dev/null +++ b/packages/angular/create/package.json @@ -0,0 +1,18 @@ +{ + "name": "@angular/create", + "version": "0.0.0-PLACEHOLDER", + "description": "Scaffold an Angular CLI workspace.", + "keywords": [ + "angular", + "angular-cli", + "Angular CLI", + "code generation", + "schematics" + ], + "bin": { + "create": "./src/index.js" + }, + "dependencies": { + "@angular/cli": "0.0.0-PLACEHOLDER" + } +} diff --git a/packages/angular/create/src/index.ts b/packages/angular/create/src/index.ts new file mode 100644 index 000000000000..040a603bb106 --- /dev/null +++ b/packages/angular/create/src/index.ts @@ -0,0 +1,24 @@ +#!/usr/bin/env node +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import { spawnSync } from 'child_process'; +import { join } from 'path'; + +const binPath = join(require.resolve('@angular/cli/package.json'), '../bin/ng.js'); + +// Invoke ng new with any parameters provided. +const { error } = spawnSync(process.execPath, [binPath, 'new', ...process.argv.slice(2)], { + stdio: 'inherit', +}); + +if (error) { + // eslint-disable-next-line no-console + console.error(error); + process.exitCode = 1; +} diff --git a/tests/legacy-cli/e2e/tests/misc/create-angular.ts b/tests/legacy-cli/e2e/tests/misc/create-angular.ts new file mode 100644 index 000000000000..b18decd0173a --- /dev/null +++ b/tests/legacy-cli/e2e/tests/misc/create-angular.ts @@ -0,0 +1,37 @@ +import { join, resolve } from 'path'; +import { expectFileToExist, rimraf } from '../../utils/fs'; +import { getActivePackageManager } from '../../utils/packages'; +import { silentNpm, silentYarn } from '../../utils/process'; + +export default async function () { + const currentDirectory = process.cwd(); + const newDirectory = resolve('../'); + + const projectName = 'test-project-create'; + + try { + process.chdir(newDirectory); + const packageManager = getActivePackageManager(); + + switch (packageManager) { + case 'npm': + await silentNpm('init', '@angular', projectName, '--', '--skip-install', '--style=scss'); + + break; + case 'yarn': + await silentYarn('create', '@angular', projectName, '--skip-install', '--style=scss'); + + break; + default: + throw new Error(`This test is not configured to use ${packageManager}.`); + } + + await expectFileToExist(join(projectName, 'angular.json')); + // Verify styles was create with correct extension. + await expectFileToExist(join(projectName, 'src/styles.scss')); + } finally { + await rimraf(projectName); + // Change directory back + process.chdir(currentDirectory); + } +} diff --git a/tests/legacy-cli/e2e/utils/project.ts b/tests/legacy-cli/e2e/utils/project.ts index 29a88a5cbd83..15d72673ca6a 100644 --- a/tests/legacy-cli/e2e/utils/project.ts +++ b/tests/legacy-cli/e2e/utils/project.ts @@ -39,7 +39,7 @@ export async function prepareProjectForE2e(name: string) { const argv: yargsParser.Arguments = getGlobalVariable('argv'); await git('config', 'user.email', 'angular-core+e2e@google.com'); - await git('config', 'user.name', 'Angular CLI E2e'); + await git('config', 'user.name', 'Angular CLI E2E'); await git('config', 'commit.gpgSign', 'false'); if (argv['ng-snapshots'] || argv['ng-tag']) { diff --git a/tests/legacy-cli/verdaccio.yaml b/tests/legacy-cli/verdaccio.yaml index 075da2628cbe..1352103a3dcc 100644 --- a/tests/legacy-cli/verdaccio.yaml +++ b/tests/legacy-cli/verdaccio.yaml @@ -17,7 +17,7 @@ uplinks: maxFreeSockets: 8 packages: - '@angular/{cli,pwa}': + '@angular/{create,cli,pwa}': access: $all publish: $all