## File: README.md

<h1 style="text-align: center">Angular CLI - The CLI tool for Angular.</h1>


  
  
  
  The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold,
    and maintain Angular applications directly from a command shell.
  



  [**angular.dev/tools/cli**](https://angular.dev/tools/cli)
  



  [Contributing Guidelines](CONTRIBUTING.md)
  ·
  [Submit an Issue](https://github.com/angular/angular-cli/issues)
  ·
  [Blog](https://blog.angular.dev)
  
  


<hr>

## Documentation

Get started with Angular CLI, learn the fundamentals and explore advanced topics on our documentation website.

- [Getting started][quickstart]
- [CLI][cli]
- [Workspace and project file structure][filestructure]
- [Workspace configuration][workspaceconfig]
- [Schematics][schematics]

## Development Setup


### Prerequisites

- Install [Node.js] which includes [Node Package Manager][npm]

### Setting Up a Project

Install the Angular CLI globally:

```
npm install @angular/cli
```

Create workspace:

```
ng new [PROJECT NAME]
```

Run the application:

```
cd [PROJECT NAME]
ng serve
```

Angular is cross-platform, fast, scalable, has incredible tooling, and is loved by millions.

## Quickstart

[Get started in 5 minutes][quickstart].

## Ecosystem


  


- [Angular Framework][adev]
- [Angular Material][angularmaterial]

## Changelog

[Learn about the latest improvements][changelog].

## Upgrading

Check out our [upgrade guide](https://update.angular.dev/) to find out the best way to upgrade your project.

## Contributing

### Contributing Guidelines

Read through our [contributing guidelines][contributing] to learn about our submission process, coding rules and more.

### Want to Help?

Want to report a bug, contribute some code, or improve documentation? Excellent! Read up on our guidelines for [contributing][contributing] and then check out one of our issues labeled as <kbd>[help wanted](https://github.com/angular/angular-cli/labels/help%20wanted)</kbd> or <kbd>[good first issue](https://github.com/angular/angular-cli/labels/good%20first%20issue)</kbd>.

### Code of Conduct

Help us keep Angular open and inclusive. Please read and follow our [Code of Conduct][codeofconduct].

### Developer Guide

Read through our [developer guide][developer] to learn about how to build and test the Angular CLI locally.


## Community

Join the conversation and help the community.

- [X (formerly Twitter)][twitter]
- [Discord][discord]
- [Gitter][gitter]
- [YouTube][youtube]
- [StackOverflow][stackoverflow]
- Find a Local [Meetup][meetup]

## Packages

This is a monorepo which contains many tools and packages:



### Tools

| Project | Package | Version | Links |
|---|---|---|---|
**Angular Build System** | [`@angular/build`](https://npmjs.com/package/@angular/build) | [](https://npmjs.com/package/@angular/build) | [](/packages/angular/build/README.md) [](https://github.com/angular/angular-build-builds)
**Angular CLI** | [`@angular/cli`](https://npmjs.com/package/@angular/cli) | [](https://npmjs.com/package/@angular/cli) | [](/packages/angular/cli/README.md) [](https://github.com/angular/cli-builds)
**Schematics CLI** | [`@angular-devkit/schematics-cli`](https://npmjs.com/package/@angular-devkit/schematics-cli) | [](https://npmjs.com/package/@angular-devkit/schematics-cli) |  [](https://github.com/angular/angular-devkit-schematics-cli-builds)


### Packages


| Project | Package | Version | Links |
|---|---|---|---|
**Angular SSR** | [`@angular/ssr`](https://npmjs.com/package/@angular/ssr) | [](https://npmjs.com/package/@angular/ssr) | [](/packages/angular/ssr/README.md) [](https://github.com/angular/angular-ssr-builds)
**Architect** | [`@angular-devkit/architect`](https://npmjs.com/package/@angular-devkit/architect) | [](https://npmjs.com/package/@angular-devkit/architect) | [](/packages/angular_devkit/architect/README.md) [](https://github.com/angular/angular-devkit-architect-builds)
**Build Angular** | [`@angular-devkit/build-angular`](https://npmjs.com/package/@angular-devkit/build-angular) | [](https://npmjs.com/package/@angular-devkit/build-angular) | [](/packages/angular_devkit/build_angular/README.md) [](https://github.com/angular/angular-devkit-build-angular-builds)
**Build Webpack** | [`@angular-devkit/build-webpack`](https://npmjs.com/package/@angular-devkit/build-webpack) | [](https://npmjs.com/package/@angular-devkit/build-webpack) | [](/packages/angular_devkit/build_webpack/README.md) [](https://github.com/angular/angular-devkit-build-webpack-builds)
**Core** | [`@angular-devkit/core`](https://npmjs.com/package/@angular-devkit/core) | [](https://npmjs.com/package/@angular-devkit/core) | [](/packages/angular_devkit/core/README.md) [](https://github.com/angular/angular-devkit-core-builds)
**Schematics** | [`@angular-devkit/schematics`](https://npmjs.com/package/@angular-devkit/schematics) | [](https://npmjs.com/package/@angular-devkit/schematics) | [](/packages/angular_devkit/schematics/README.md) [](https://github.com/angular/angular-devkit-schematics-builds)

#### Misc

| Project | Package | Version | Links |
|---|---|---|---|
**Angular Create** | [`@angular/create`](https://npmjs.com/package/@angular/create) | [](https://npmjs.com/package/@angular/create) | [](/packages/angular/create/README.md)
**Webpack Angular Plugin** | [`@ngtools/webpack`](https://npmjs.com/package/@ngtools/webpack) | [](https://npmjs.com/package/@ngtools/webpack) |  [](https://github.com/angular/ngtools-webpack-builds)

#### Schematics

| Project | Package | Version | Links |
|---|---|---|---|
**Angular PWA Schematics** | [`@angular/pwa`](https://npmjs.com/package/@angular/pwa) | [](https://npmjs.com/package/@angular/pwa) |  [](https://github.com/angular/angular-pwa-builds)
**Angular Schematics** | [`@schematics/angular`](https://npmjs.com/package/@schematics/angular) | [](https://npmjs.com/package/@schematics/angular) |  [](https://github.com/angular/schematics-angular-builds)



**Love Angular CLI? Give our repo a star :star: :arrow_up:.**

[contributing]: CONTRIBUTING.md
[developer]: docs/DEVELOPER.md
[quickstart]: https://angular.dev/tutorials/learn-angular
[changelog]: CHANGELOG.md
[documentation]: https://angular.dev/overview
[angularmaterial]: https://material.angular.dev/
[cli]: https://angular.dev/tools/cli
[adev]: https://angular.dev/
[workspaceconfig]: https://angular.dev/reference/configs/workspace-config
[schematics]: https://angular.dev/tools/cli/schematics
[filestructure]: https://angular.dev/reference/configs/file-structure
[node.js]: https://nodejs.org/
[npm]: https://www.npmjs.com/get-npm
[codeofconduct]: https://github.com/angular/angular/blob/main/CODE_OF_CONDUCT.md
[twitter]: https://www.x.com/angular
[discord]: https://discord.gg/angular
[gitter]: https://gitter.im/angular/angular-cli
[stackoverflow]: https://stackoverflow.com/questions/tagged/angular-cli
[youtube]: https://youtube.com/angular
[meetup]: https://www.meetup.com/find/?keywords=angular

---

## File: docs/design/analytics.md

# Usage Metrics Gathering

This document list exactly what is gathered and how.

Any change to analytics should most probably include a change to this document.

## Dimensions and Metrics

Google Analytics Custom Dimensions are used to track system values and flag values. These
dimensions are aggregated automatically on the backend.

One dimension per flag, and although technically there can be an overlap between 2 commands, for
simplicity it should remain unique across all CLI commands. The dimension is the value of the
`x-user-analytics` field in the `schema.json` files.

### Adding dimension or metic.
1. Create the dimension or metric in [Google Analytics](https://analytics.google.com/) first. These are not tracked if they aren't
   defined in Google Analytics.
1. Use the ID of the dimension as the `x-user-analytics` value in the `schema.json` file.
1. New dimension and metrics PRs need to be approved by the tooling lead and require a new [Launch](http://go/launch).

### Deleting a dimension or metic.
1. Archive the dimension and metric in [Google Analytics](https://analytics.google.com/).


**DO NOT ADD `x-user-analytics` FOR VALUES THAT ARE USER IDENTIFIABLE (PII), FOR EXAMPLE A
PROJECT NAME TO BUILD OR A MODULE NAME.**

### Limits
| Item                           	| Standard property limits 	|
|--------------------------------	|--------------------------	|
| Event-scoped custom dimensions 	| 50                       	|
| User-scoped custom dimensions  	| 25                       	|
| All custom metrics             	| 50                       	|

### List of User Custom Dimensions


| Name | Parameter | Type |
|:---:|:---|:---|
| UserId | `up.ng_user_id` | `string` |
| OsArchitecture | `up.ng_os_architecture` | `string` |
| NodeVersion | `up.ng_node_version` | `string` |
| NodeMajorVersion | `upn.ng_node_major_version` | `number` |
| AngularCLIVersion | `up.ng_cli_version` | `string` |
| AngularCLIMajorVersion | `upn.ng_cli_major_version` | `number` |
| PackageManager | `up.ng_package_manager` | `string` |
| PackageManagerVersion | `up.ng_pkg_manager_version` | `string` |
| PackageManagerMajorVersion | `upn.ng_pkg_manager_major_v` | `number` |


### List of Event Custom Dimensions


| Name | Parameter | Type |
|:---:|:---|:---|
| Command | `ep.ng_command` | `string` |
| SchematicCollectionName | `ep.ng_schematic_collection_name` | `string` |
| SchematicName | `ep.ng_schematic_name` | `string` |
| Standalone | `ep.ng_standalone` | `string` |
| SSR | `ep.ng_ssr` | `string` |
| Style | `ep.ng_style` | `string` |
| Routing | `ep.ng_routing` | `string` |
| InlineTemplate | `ep.ng_inline_template` | `string` |
| InlineStyle | `ep.ng_inline_style` | `string` |
| BuilderTarget | `ep.ng_builder_target` | `string` |
| Aot | `ep.ng_aot` | `string` |
| Optimization | `ep.ng_optimization` | `string` |


### List of Event Custom Metrics


| Name | Parameter | Type |
|:---:|:---|:---|
| AllChunksCount | `epn.ng_all_chunks_count` | `number` |
| LazyChunksCount | `epn.ng_lazy_chunks_count` | `number` |
| InitialChunksCount | `epn.ng_initial_chunks_count` | `number` |
| ChangedChunksCount | `epn.ng_changed_chunks_count` | `number` |
| DurationInMs | `epn.ng_duration_ms` | `number` |
| CssSizeInBytes | `epn.ng_css_size_bytes` | `number` |
| JsSizeInBytes | `epn.ng_js_size_bytes` | `number` |
| NgComponentCount | `epn.ng_component_count` | `number` |
| AllProjectsCount | `epn.all_projects_count` | `number` |
| LibraryProjectsCount | `epn.libs_projects_count` | `number` |
| ApplicationProjectsCount | `epn.apps_projects_count` | `number` |


## Debugging

Using `NG_DEBUG=1` will enable Google Analytics debug mode, To view the debug events, in Google Analytics go to `Configure > DebugView`.

## Disabling Usage Analytics

There are 2 ways of disabling usage analytics:

1. using `ng analytics disable --global` (or changing the global configuration file yourself). This is the same
   as answering "No" to the prompt.
1. There is an `NG_CLI_ANALYTICS` environment variable that overrides the global configuration.
   That flag is a string that represents the User ID. If the string `"false"` is used it will
   disable analytics for this run.

---

## File: docs/design/build-system.md

# Build System

Angular CLI includes a first-party build system for Angular applications distributed as `@angular-devkit/build-angular`.
This build system is responsible for creating a standalone single-page application (SPA) from user source files and third-party dependencies.

`@angular-devkit/build-angular` itself integrates with the rest of Angular CLI by being an [Architect builder](https://angular.dev/tools/cli/cli-builder).
This document describes a top level view of the functionality in `@angular-devkit/build-angular`, referred as just the "build system".
Deprecated or soon to be removed features are not described here.

In broad strokes the main areas are:

- loading and processing sources
- code splitting
- production optimizations
- post-processing steps

Many tools are used in this process, and most of these steps happen within a [Webpack](https://webpack.js.org/) build.
We maintain a number of Webpack-centric plugins in this repository, some of these are public but most are private since they are very specific to our setup.

## Overview diagram

Below is a diagram of processing sources go through.
It's not strictly accurate because some options remove certain processing stages while adding others.
This diagram doesn't show these conditionals and only shows the possible processing steps.
Relative paths, such as `./raw-css-loader.ts`, refer to internal plugins, while other names usually refer to public npm packages.



## Loading and processing sources

Sources for Angular CLI browser apps are comprised of TypeScript files, style sheets, assets, scripts, and third party dependencies.
A given build will load these sources from disk, process them, and bundle them together.

### TypeScript and Ahead-Of-Time Compilation

Angular builds rely heavily on TypeScript-specific functionality for [Ahead-of-Time template compilation](https://angular.dev/tools/cli/aot-compiler) (AOT).
Outside Angular CLI, this is performed by the Angular Compiler (`ngc`), provided by `@angular/compiler-cli`.
To avail of Ahead-of-Time template compilation within a Webpack compilation we use and distribute the `@ngtools/webpack` Webpack plugin.

Typescript sources are loaded from disk and compiled in-memory into JavaScript files that are stored in a virtual file system and made available to Webpack.
During compilation we also perform a number of code transformations using TypeScript transformers that enable automatic usage of AOT, internationalization features, and server-side rendering.

AOT compilation requires loading HTML and CSS resources, referenced on Angular Components, as standalone strings with no external dependencies.
However, Webpack compilations operate on the basis of modules and references between them.
It's not possible to get the full compilation result for a given resource before the end of the compilation in webpack.
To obtain the standalone string for a HTML/CSS resource we compile it using a separate Webpack child compilation then extract the results.
These child compilations inherit configuration and access to the same files as the parent compilation, but have their own compilation life cycle and complete independently.

The build system allows specifying replacements for specific files by replacing what path is loaded from the virtual file system.
This is used for conditional loading of code at build time.

### Stylesheets

Two types of stylesheets are used in the build system: global stylesheets and component stylesheets.
Global stylesheets are injected into the `index.html` file, while component stylesheets are loaded directly into compiled Angular components.

The build system supports plain CSS stylesheets as well as the Sass and LESS CSS pre-processors.
Stylesheet processing functionality is provided by `sass-loader`, `less-loader`, `postcss-loader`, `postcss-import`, augmented in the build system by custom webpack plugins.

### Assets

Assets in the build system refer specifically to a list of files or directories that are meant to be copied verbatim as build artifacts.
These files are not processed and commonly include images, favicons, pdfs and other generic file types.
They are loaded into the compilation using `copy-webpack-plugin`.

### Scripts

Scripts in the build system refer specifically to JavaScript files that are meant to be loaded directly on `index.html` without being processed.
They are loaded into the compilation using a custom webpack plugin.

### Third party dependencies

Third party dependencies are mostly inside `node_modules` and are referenced via imports in source files.
Stylesheet third party dependencies are treated mostly the same as sources.

JavaScript third party dependencies suffer a more involved process.
They are first resolved to a folder in `node_modules` via [Node Module Resolution](https://nodejs.org/api/modules.html#modules_modules).
A given module might have several different entry points, for instance one for use in NodeJS and another one for using in the browser.
Although `package.json` only officially supports listing one entry point under the `main` key, it's common for npm packages to list [other entry points](https://2ality.com/2017/04/setting-up-multi-platform-packages.html).
Each entry point is listed in under a key in that module's `package.json` whose value is a string containing a relative file path.
We use `es2015 > browser > module > main` a priority list of keys, where the first key matched name determines which entry point to use.
For instance, for a module that has both `browser` and `main` entry points, we pick `browser`.

Once the actual JavaScript file is determined, it is loaded into the compilation together with it's source map.

This resolution strategy supports the [Angular Package Format](https://docs.google.com/document/d/1CZC2rcpxffTDfRDs6p1cfbmKNLA6x5O-NtkJglDaBVs/edit#heading=h.k0mh3o8u5hx).

## Code splitting

Code is automatically split into different files (or chunks, for js files) based on a few different triggers.

The main TypeScript entry point and it's dependencies are bundled into the `main` chunk.
Global styles and scripts get one file per entry, named after themselves.

JavaScript code imported only via dynamic imports is automatically split into a separate chunk that is loaded asynchronously named after the file containing the dynamic import.
If multiple asynchronous chunks contain a reference to the same module, it is placed in a new asynchronously loaded chunk named after the other chunks that use it.

There is also a special chunk called `runtime` that contains the module loading logic and is loaded before the others.

## Optimizations

The build system contains optimizations aimed at improving the performance (for development builds) or the size of artifacts (for production builds).
These are often mutually exclusive and thus we cannot just default to always using them.

### Development optimizations

Development optimizations focus on reducing rebuild time on watched builds.
Although faster is always better, our threshold is to keep rebuilds even for large projects below 2 seconds.

Computation needed to bundle code grows with its total size because of the cost of string concatenation and source map operations.
Third party dependencies that are initially loaded are split into a synchronously loaded chunk called `vendor`.
Splitting the infrequently changed vendor code from the frequently changed source code thus helps make rebuilds faster.

When processing stylesheets, Webpack stores the intermediate modules as JavaScript code.
The JavaScript wrapper code makes stylesheets larger and `mini-css-extract-plugin` must be used to obtain the actually stylesheet content into a CSS file.
In development however, we skip the CSS extraction and leave it as JavaScript code for faster rebuild times.

Watched builds split the processing load of TypeScript compilation between file emission on the main process and type checking on a forked process.
Large projects can also opt-out of AOT compilation for faster rebuilds.

### Production optimizations

Angular CLI focuses on enabling tree-shaking (removing unused modules) and dead code elimination (removing unused module code).
These two categories have high potential for size reduction because of network effects: removing code can lead to more code being removed.

The main tool we use to achieve this goal are the dead code elimination capabilities of [Terser](https://github.com/terser/terser).
We also use Terser's mangling, by which names, but not properties, are renamed to shorter forms.
The main characteristics of Terser to keep in mind is that it operates via static analysis and does not support the indirection introduced by module loading.
Thus the rest of the pipeline is directed towards providing Terser with code that can be removed via static analysis in large single modules scopes.

To this end we developed [@angular-devkit/build-optimizer](https://github.com/angular/angular-cli/tree/main/packages/angular_devkit/build_optimizer), a post-processing tool for TS code.
Build Optimizer searches for code patterns produced by the TypeScript and Angular compiler that are known to inhibit dead code elimination, and converts them into equivalent structures that enable it instead (the link above contains some examples).
It also adds Terser [annotations](https://github.com/terser/terser#annotations) marking top-level functions as free from side effects for libraries that have the `sideEffects` flag set to false in `package.json`.

Webpack itself also contains two major features that enable tree-shaking and dead code elimination: [`sideEffects` flag](https://github.com/webpack/webpack/tree/master/examples/side-effects) support and [module concatenation](https://webpack.js.org/plugins/module-concatenation-plugin/).
Having the `sideEffects` flag set to false in `package.json` of a library means that library has no top-level side-effects and only exposes imports, which allows Webpack to rewrite imports to that library directly to the modules used and not including non-imported modules at all.
Module concatenation allows Webpack to collect in a single module the content of several modules, which in turn allows Terser to more easily remove unused code since there is no module loading indirection between those modules.

One significant pitfall of this optimization strategy is the use of code splitting.
Using code splitting is desirable in order to speed up loading of web apps by deferring code that is not necessary on the initial load.
But since code splitting necessarily makes use of module loading, it is at odds with Terser-based optimizations.

The use of lazy loading can not only prevent further optimizations, but also regress the currently possible ones by [preventing module concatenation](https://webpack.js.org/plugins/module-concatenation-plugin/#optimization-bailouts).
Modules that were concatenated when lazy modules are not present might not be concatenated anymore after lazy loading is introduced because these modules now need to be accessed from the lazy modules and thus get their own module scope.

Aside from tree-shaking, scripts and styles (as defined in the sources above) also undergo optimizations via [Terser](https://github.com/terser/terser) and [CleanCSS](https://github.com/jakubpawlowicz/clean-css) respectively.

## Post-processing steps

There are some steps that are meant to operate over whole applications and thus happen after the compilation finishes and outputs files.
The steps are described in the order in which they are executed during a build.
The execution order was determined based on the complexity of the step with a primary goal of minimizing the repetition of computationally expensive operations.

### Differential Loading

Differential loading is a strategy that allows your web application to support multiple browsers, but only load the necessary code that the browser needs.
When differential loading is enabled, the CLI generates two distinct variants of application bundles.

- The first contains ES2015 syntax, takes advantage of built-in support in modern browsers, ships fewer polyfills, and results in a smaller total size.
- The second contains code in the older ES5 syntax, along with all necessary polyfills for Angular to function. This results in a larger total size, but supports older browsers.

This process as designed has the advantage that only one full compilation of the application in ES2015 syntax is required.
This removes a large amount of otherwise unnecessary and duplicate processing such as module resolution and dead code elimination.
It also guarantees that the application is ES5 compliant including third-party code.
The two variants of application bundles are created by the following steps:

1. A full build of the application is performed using an ES2015 output target.
   The application's global stylesheets, scripts, and assets are also processed during this step via the full build. These elements are reused for both of application variants.
2. A copy of the JavaScript output application files are transformed (commonly referred to as down-leveled) to ES5 compatible syntax.
   ES2015+ syntax elements such as classes are converted into functionally equivalent ES5 code structures.
3. An additional ES5-only polyfills file is generated that contains the required Angular polyfills for ES5-only browsers.
4. A single index HTML file is created that references both application variants and is designed to only load the appropriate files for each browser.

To support loading the file sets in the appropriate browsers, the HTML `script` element's `type` and `nomodule` attributes are leveraged.
Browsers will only load a script with a known type.
The ES2015 files are referenced using a type of `module` which is only supported on browsers that support ES2015+ code.
Since browsers that do not support ES2015+ code also do not support the `module` script type, these scripts are ignored for browsers that cannot parse and execute the ES2015 code.
Browsers that support the `module` script type also support the `nomodule` attribute.
This attribute instructs a browser that supports module scripts to ignore the script with the attribute. There is one browser exception in this case: Safari 10.1.
This browser supports module scripts but does not support the `nomodule` attribute.
To support this case, a special polyfill script is included to provide a workaround for the browser.
This arrangement of script elements ensures that ES5-only browsers will only execute the ES5 script files and browsers that support ES2015+ will only execute the ES2015 script files.

### Localization (i18n)

The second of these post-processing steps is build-time localization.
The final js bundles are processed using `@angular/localize`, replacing any locale-specific translations.
This sort of localization produces one application for each locale, each in their own folders.

### Service Worker

The third and last post-processing step is the creation of a [service worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API).
A listing of final application files is taken, fingerprinted according to their content, and added to the service worker manifest.
This must be the last step because it needs each application file to not be modified further.

---

## File: docs/design/deployurl-basehref.md

|                                             | Deploy URL | Base HREF |
| ------------------------------------------- | :--------: | :-------: |
| Initial scripts (index.html)                |   ✅ 👍    |   ✅ 👍   |
| Initial stylesheets (index.html)            |   ✅ 👍    |   ✅ 👍   |
| Lazy scripts (routes/import()/etc.)         |   ✅ 👍    |   ✅ 👍   |
| Processed CSS resources (images/fonts/etc.) |   ✅ 👍    |   ✅ 👍   |
| Relative template (HTML) assets             |   ❌ 👎    |   ✅ 👍   |
| Angular Router Default Base (APP_BASE_HREF) |     ❌     |  ✅ \*1   |
| Single reference in deployed Application    |   ❌ 👎    |   ✅ 👍   |
| Special resource logic within CLI           |   ✅ 👎    |   ❌ 👍   |
| Relative fetch/XMLHttpRequest               |     ❌     |    ✅     |

✅ - has/affects the item/trait
❌ - does not have/affect the item/trait
👍 - favorable behavior
👎 - unfavorable behavior

\*1 -- Users with more complicated setups may need to manually configure the `APP_BASE_HREF` token within the application. (e.g., application routing base is `/` but assets/scripts/etc. are at `/assets/`)

---

## File: docs/design/ngConfig.md

# ngConfig - Design

## Goals

Currently, a project scaffolded with the CLI has no way of specifying options and configurations affecting their projects. There are ways to affect the build (with the `angular-cli-build.js` file), but the following questions cannot be answered without actual project options:

- Where in my directory is my karma.conf file?
- What is my firebase database URL?
- Where is my client code?
- How can I use a different lazy-loading boundary prefix (or none at all)?
- Any other backend I want to run prior to `ng serve`?

# Proposed Solution

Since the data is static, we only need to keep it in a static store somewhere.

One solution would be to keep the data in the `package.json`. Unfortunately, the metadata contains too much data and the `package.json` file would become unmanageable.

Instead of polluting the package file, a `.angular-cli.json` file will be created that contains all the values. Access to that file will be allowed to the user if he knows the structure of the file (unknown keys will be kept but ignored), and it's easy to read and write.

## Fallback

There should be two `.angular-cli.json` files; one for the project and a general one. The general one should contain information that can be useful when scaffolding new apps, or information about the user.

The project `.angular-cli.json` goes into the project root. The global configuration should live at `$HOME/.angular-cli.json`.

## Structure

The structure should be defined by a JSON schema (see [here](http://json-schema.org/)). The schema will be used to generate the `d.ts`, but that file will be kept in the file system along with the schema for IDEs.

Every PR that would change the schema should include the update to the `d.ts`.

# API

## CLI

#### Getting values

The new command `get` should be used to output values on the terminal. It takes a set of flags and an optional array of [paths](#path);

- `--glob` or `-g`; the path follows a glob format, where `*` can be replaced by any amount of characters and `?` by a single character. This will output `name=value` for each values matched.

Otherwise, outputs the value of the path passed in. If multiple paths are passed in, they follow the format of `name=value`.

#### Setting values

The new command `set` should be used to set values in the local configuration file. It takes a set of flags and an optional array of `[path](#path)=value`;

- `--global`; sets the value in the global configuration.
- `--remove`; removes the key (no value should be passed in).

The schema needs to be taken into account when setting the value of the field;

- If the field is a number, the string received from the command line is parsed. `NaN` throws an error.
- If the field is an object, an error is thrown.
- If the path is inside an object but the object hasn't been defined yet, sets the object with empty values (use the schema to create a valid object).

#### Path<a name="path"></a>

The paths are json formatted path; each `.` separates a map, while `[]` indicates an index in an array.

An example is the following:

    keyA.keyB.arrayC[3].value

## Model

A model should be created that will include loading and saving the configuration, including the global configuration.

**The model should be part of the project and created on the `project` object.**

That model can be used internally by the tool to get information. It will include a proxy handler that throws if an operation doesn't respect the schema. It will also set values on globals and locals depending on which branches you access.

A simple API would return the TypeScript interface:

```typescript
class Config {
  // ...
  get local(): ICliConfig {
    /* ... */
  }
  get global(): ICliConfig {
    /* ... */
  }
}
```

The `local` and `global` getters return proxies that respect the JSON Schema defined for the Angular config. These proxies allow users to not worry about the existence of values; those values will only be created on disc when they are set.

Also, `local` will always defer to the same key-path in `global` if a value isn't available. If a value is set and the parent exists in `global`, it should be created to `local` such that it's saved locally to the project. The proxies only care about the end points of `local` and `global`, not the existence of a parent in either.

For example, assuming the following globals/locals:

```js
// Global
{
  "key1": {
    "key2": {
      "value": 0,
      "value2": 1
    }
  }
}

// Local
{
  "key1": {
    "key2": {
      "value2": 2,
      "value3": 3
    }
  }
}
```

The following stands true:

```typescript
const config = new Config(/* ... */);

console.log(config.local.key1.key2.value); // 0, even if it doesn't exist.
console.log(config.local.key1.key2.value2); // 2, local overrides.
console.log(config.local.key1.key2.value3); // 3.
console.log(config.local.key1.key2.value4); // Schema's default value.

console.log(config.global.key1.key2.value); // 0.
console.log(config.global.key1.key2.value2); // 1, only global.
console.log(config.global.key1.key2.value3); // Schema's default value.

config.local.key1.key2.value = 1;
// Now the value is 1 inside the local. Global stays the same.

config.local.key1.key2.value3 = 5;
// The global config isn't modified.

config.global.key1.key2.value4 = 99;
// The local config stays the same.
console.log(config.local.key1.key2.value4); // 99, the global value.

config.save(); // Commits if there's a change to global and/or local.
```

---

## File: docs/design/third-party-libraries.md

# Installing third party libraries

# Abstract

The current `ng install` process is faulty; third parties have to add a `bundles/` directory
with metadata that we expect. This document explores ways to improve on the process.

# Requirements

The following use cases need to be supported by `ng install`:

1. Support for _any_ thirdparties, ultimately falling back to running `npm install` only and
   doing nothing else, if necessary.
1. Not a new package manager.
1. Metadata storage by thirdparties in `package.json`. This must be accessible by plugins for
   the build process or even when scaffolding.
1. Proper configuration of SystemJs in the browser.
1. SystemJS configuration managed by the user needs to be kept separated from the autogenerated
   part.
1. The build process right now is faulty because the `tmp/` directory used by Broccoli is
   inside the project. TypeScript when using `moduleResolution: "node"` can resolve the
   `node_modules` directory (since it's in an ancestor folder), which means that TypeScript
   compiles properly, but the build does not copy files used by TypeScript to `dist/`. We need
   to proper map the imports and move them to `tmp` before compiling, then to `dist/` properly.
1. Potentially hook into scaffolding.
1. Potentially hook into the build.
1. Safe uninstall path.

# Usages

Here's a few stories that should work right off:

```sh
$ ng new my-app && cd my-app/
$ ng install jquery
```

^(this makes jQuery available in the index)

```sh
$ ng install angularfire2
> Please specify your Firebase database URL [my-app.firebaseio.com]: _
```

^(makes firebase available and provided to the App)

```sh
$ ng install angularfire2 --dbUrl=my-firebase-db.example.com
```

^(skip prompts for values passed on the command line)

```sh
$ ng install angularfire2 --quiet
```

^(using `--quiet` to skip all prompts and use default values)

```sh
$ ng install less
```

^(now compiles CSS files with less for the appropriate extensions)

# Proposed Solution

The `install` task will perform the following subtasks:

1. **Run `npm install ${libName}`.** On failure, fail the install process.
1. **Run `preinstall` scripts.** If any script fails, run `npm uninstall ${libName}` and fail
   the install process.
1. **Copy the `appData` to the `angular.json` file of the generated app, creating it if it
   doesn't exist, under the `"modules"` key.** This data will be sent to the App as is. See the
   [appData](#appData) section for more information.
1. **Read the `package["angular-cli"].appPrompt` and prompt the user configuration values,
   if any.** See the [appData](#appData) section for more information.
1. **Add the providers specified in `package["angular-cli"]["providers"]` to the angular.js
   `providers` list.** Rebuild the `providers.js` file. See the [Providers](#providers)
   section for more information.
1. **Run `package["angular-cli"].scripts["install"]` if it exists.** If the script fails,
   run `npm uninstall ${libName}` and fail the install process.
1. **Detect if a package named `angular/cli-wrapper-${libName}` exist in the angular
   organization.** If so, run the steps above as if ng install angular/angular-${libName}. If
   this install fails, ignore the failure.

   These packages can be used to wrap libraries that we want to support but can't update
   easily, like Jasmine or LESS.

1. **Install typings.** See the [Typings](#typings) section.
1. **Run `postinstall` scripts.**

# Proof of Concept

A proof of concept is being developed.

# Hooks

The third party library can implement hooks into the scaffolding, and the build system. The
CLI's tasks will look for the proper hooks prior to running and execute them.

The order of execution of these hooks is breadth first, going through all node packages and
checking for the `package['angular-cli']['hooks']['${hookName}']`. The hooks are then
`require()`'d as is, from within the app root folder. Within the same level of the dependency
tree, there is no guarantee for the order of execution.

## Install Hooks

The only tricky part here is install hooks. The installed package should recursively call
its `(pre|post|)install` hooks only on packages that are newly installed. It should call
`(pre|post|)reinstall` on those who were already installed. A map of the currently installed
packages should be kept before performing `npm install`.

# <a name="appData">appData</a>

The `angular-cli` key in the generated app should be used for Angular CLI specific data.
This includes the CLI configuration itself, as well as third-parties library configuration.

Third-parties can store data that will be passed to the app, and can use that data themselves.
That data can be anything. Any keys starting with either `$` or `_` will be ignored and not
passed to the client. It could be used for builds or scaffolding information.

During installation, there's a step to prompt the user for data. The schema contains a prompt
text and a default value. The default value type is used to convert the string entered by the
user. The key used in `appPrompt` is the key saved in appData.

Example:

```typescript
{ // ...
  "angular-cli": {
    "appPrompt": {
      "number": {
        "prompt": "Please enter a number:",
        "defaultValue": 0
      },
      "url": {
        "prompt": "URL of your website:",
        "defaultValue": "${homepage}"
      }
    }
  }
}
```

The default value is necessary as a `quiet` mode is enforced, using default values to fill
in the data without user interaction. The special strings `${...}` can be used to replace
with special values in the default string values. The values are taken from the `package.json`.

We use a declarative style to enforce sensible defaults and make sure developers think about
this. _In the case where developers want more complex interaction, they can use the
install/uninstall hooks to prompt users._ But 3rd party libraries developers need to be aware
that those hooks might not prompt users (no STDIN) and throw an error.

# <a name="providers">Providers</a>

Adding Angular providers to the app should be seamless. The install process will create a
`providers.js` from all the providers contained in all the dependencies. The User can disclude
providers it doesn't want.

The `providers.js` file will always be overwritten by the `install` / `uninstall` process. It
needs to exist for toolings to be able to understand dependencies. These providers are global
to the application.

In order to prevent providers from being global, the user can use the `--no-global-providers`
flag during installation, or can change the dependencies by using `ng providers`. As an example:

```bash
ng new my-todo-app
ng generate component database
ng install --no-global-providers angularfirebase2
ng providers database angularfirebase2
```

Or, alternatively, the user can add its own providers and dependencies to its components.

# Dependencies

Because dependencies are handled by `npm`, we don't have to handle it.

# <a name="typings">Typings</a>

Typings should be added, but failure to find typings should not be a failure of installation. The
user might still want to install custom typings himself in the worst case.

The `typings` package can be used to install/verify that typings exist. If the typings do not exist natively, we should tell the user to install the ambient version if he wants to.

# Index.html

We do not touch the `index.html` file during the installation task. The default page should
link to a SystemJS configuration file that is auto generated by the CLI and not user
configurable (see SystemJS below). If the user install a third party library, like jQuery, and
wants to use it, they have to import it using `import * as $ from 'vendor/jquery'`.

The `index.html` also includes a section to configure SystemJS that can be managed by the user.
This is separate from the generated code.

# SystemJS

It is important that SystemJS works without any modifications by the user. It is also important
to leave the liberty to the user to change the SystemJS configuration so that it fits their needs.

We will not use SystemJS bundles in development. This is for better debugging, future proofing
(when moving the build system) and better CDN support, as many of the loaded files will end up
being pulled from a CDN in production. During the `ng build` process for production, the
SystemJS configuration script will be rebuilt to fetch from the CDN.

# Upgrade Strategy

The upgrade process simply uses NPM. If new appData is added, it should be added manually using
a migration hook for `postinstall`.

# Remaining Problems

1. Installing dependencies of packages need to be further sketched out.
2. Need to add a fully fledged example with Firebase.

---

## File: docs/process/bazel.md

## Yarn Workspaces

The package architecture of `angular-cli` repository is originally setup using
yarn [workspaces](https://yarnpkg.com/lang/en/docs/workspaces/). This means the
dependencies of various `package.json` in the repository are linked and
installed together.

## Bazel

Since then, Bazel was introduced to manage some of the build dependencies in
`angular-cli` repo. However, Bazel does **not** yet support yarn workspaces,
since it requires laying out more than one `node_modules` directory. In this
mixed mode, developers ought to take extra care to synchronize the dependencies.

Since the `yarn_install` rule that installs all NPM dependencies in this
repository only reads from the **root** `package.json`, every Bazel target that
depends on packages downloaded from the NPM registry will need to have the
dependency declared in the **root** `package.json`.

In addition, if the dependency is also needed at runtime (non-dev dependencies),
the dependency on the individual package's `package.json` has to be updated as
well. This is to ensure that when users download a published version from NPM,
they will be able to install all dependencies correctly without Bazel. It is the
responsibility of the developer to keep both `package.json` in sync.

## Windows support

In general, any sort of node file lookup on Bazel should be subject to `require.resolve`.
This is how rules_nodejs resolves paths using the Bazel runfiles mechanism, where a given
Bazel target only has access to outputs from its dependencies.

In practice, this does not make a lot of difference on Linux.
A symlink forest is laid down where the target is going to actually run, and mostly the
files are resolved correctly whether you use `require.resolve` or not because the files are there.

On Windows though, that's a stricter. Bazel does not lay down a symlink forest on
windows by default. If you don't use `require.resolve`, it's still possible to correctly
resolve some files, like outputs from other rules. But other files, like node modules
dependencies and data files, need to be looked up in the runfiles.

Since the requirement is quite lax on Linux but quite strict on windows, what ends up
happening is that lack of `require.resolve` calls go unnoticed until someone tries to run
things on Windows, at which point it breaks.

## Debugging jasmine_node_test

On Linux, Bazel tests will run under a sandbox for isolation.
You can turn off this sandbox by adding the [`local = True`](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes-tests) attribute to the rule.
You can also force local execution by passing `--test_output=streamed`.

Then you will find the intermediate test files in `bazel-out/k8-fastbuild/bin`, followed by the test target path.

Tests that are sharded, via the `shard_count` attribute, can fail if you reduce the number of tests or focus only a few.
This will cause some shards to execute 0 tests, which makes the exit with an error code.

Tests that are marked as flaky, via the `flaky` attribute, will repeat when they fail.
This will cause any focused test to be repeated multiple time, since the presence of focused tests
causes jasmine to exit with a non-zero exit code.

While testing, you can remove the `shard_count` attribute to prevent sharding and the `flaky`
attribute to prevent repetition.
Setting `--test_output=streamed` will disable sharding and `--flaky_test_attempts=1` will disable
the reruns of tests that have been marked as `flaky`.

The `.bazelrc` includes a config for running tests with remote debugging enabled:

```sh
pnpm bazel test --config=debug //packages/angular/cli:angular-cli_test
# Also disable reruns of failing tests that were marked as flaky:
pnpm bazel test --config=debug --config=no-sharding //packages/angular/cli:angular-cli_test
```

---

## File: docs/process/release.md

# Setting Up Local Repository

1. Clone the Angular-CLI repo. A local copy works just fine.
1. Create an upstream remote:

```bash
$ git remote add upstream https://github.com/angular/angular-cli.git
```

# Caretaker

The caretaker should triage issues, merge PR, and sheppard the release.

Caretaker rotation can be found
[here](https://rotations.corp.google.com/rotation/5117919353110528) and individual shifts can
be modified as necessary to accommodate caretaker's schedules. This automatically syncs to a
Google Calendar
[here](https://calendar.google.com/calendar/u/0/embed?src=c_6s96kkvd7nhink3e2gnkvfrt1g@group.calendar.google.com).
Click the "+" button in the bottom right to add it to your calendar to see shifts alongside the
rest of your schedule.

The primary caretaker is responsible for both merging PRs and performing the weekly release.
The secondary caretaker does not have any _direct_ responsibilities, but they may need to take
over the primary's responsibilities if the primary is unavailable for an extended time (a day
or more) or in the event of an emergency.

At the end of each caretaker's rotation, the primary should perform a handoff in which they
provide information to the next caretaker about the current state of the repository and update
the access group to now include the next caretakers. To perform this update to the access group,
the caretaker can run:

```bash
$ pnpm ng-dev caretaker handoff
```

## Merging PRs

The list of PRs which are currently ready to merge (approved with passing status checks) can
be found with [this search](https://github.com/angular/angular-cli/pulls?q=is%3Apr+is%3Aopen+label%3A%22action%3A+merge%22+-is%3Adraft).
This list should be checked daily and any ready PRs should be merged. For each PR, check the
`target` label to understand where it should be merged to. You can find which branches a specific
PR will be merged into with the `pnpm ng-dev pr check-target-branches ` command.

When ready to merge a PR, run the following command:

```bash
pnpm ng-dev pr merge 
```

### Maintaining LTS branches

Releases that are under Long Term Support (LTS) are listed on [angular.dev](https://angular.dev/reference/releases#support-policy-and-schedule).

Since there could be more than one LTS branch at any one time, PR authors who want to
merge commits into LTS branches must open a pull request against the specific base branch they'd like to target.

In general, cherry picks for LTS should only be done if it meets one of the criteria below:

1. It addresses a critical security vulnerability.
2. It fixes a breaking change in the external environment.
   For example, this could happen if one of the dependencies is deleted from NPM.
3. It fixes a legitimate failure on CI for a particular LTS branch.

# Release

Releasing is performed using Angular's unified release tooling. Each week, two releases are expected, `latest` and `next` on npm.

**DURING a minor OR major CLI release:**

Once FW releases the actual minor/major release (for example: `13.0.0` or `13.1.0`), update dependencies with the following:

1.  Update [`constants.bzl`](../../constants.bzl) so `@angular/core` and `ng-packagr` are using the release version (drop `-rc.*`).
2.  Update all `package.json` dependencies on framework packages to to the release version (drop `-rc.*`).
    - Components packages release _after_ CLI, so those should be left as `-rc.*`.
3.  `pnpm install` to update the `pnpm-lock.yaml` file.

Create a PR with the above changes ([example](https://github.com/angular/angular-cli/pull/31872)) and merge it directly to the RC
branch. This PR must land _after_ FW releases (or else CI will fail) but _before_ the CLI release PR. Releases are built before
the PR is sent for review, so any changes after that point won't be included in the release and this cannot be combined with the
release PR.

**AFTER a minor OR major CLI release:**

`constants.bzl` also needs to be updated to use `-next.0` after a major or minor release. However this needs to happen _after_ FW
publishes the initial `-next.0` release, which will happen 1 week after the major or minor release.

## Releasing the CLI

Typical patch and next releases do not require FW to release in advance, as CLI does not pin the FW
dependency.

After confirming that the above steps have been done or are not necessary, run the following and
navigate the prompts:

```sh
pnpm ng-dev release publish
```

Releases should be done in "reverse semver order", meaning they should follow:

Oldest LTS -> Newest LTS -> Patch -> RC -> Next

This can skip any versions which don't need releases, so most weeks are just "Patch -> Next".

## Releasing a new package

Wombat has some special access requirements which need to be configured to publish a new NPM package.

See [this Wombat doc](http://g3doc/company/teams/cloud-client-libraries/team/automation/docs/npm-publish-service#existing-package)
and [this postmortem](http://docs/document/d/1emx2mhvF5xMzNUlDrVRYKI_u4iUOnVrg3rV6c5jk2is?resourcekey=0-qpsFbBfwioYT4f6kyUm8ZA&tab=t.0)
for more info.

Angular is _not_ an organization on NPM, therefore each package is published
independently and Wombat access needs to be managed individually. This also means
we can't rely on Wombat already having access to a new package.

In order to configure a brand new NPM package, it first needs to be published
manually so we can add Wombat access to it. Note that this step can and should be
done prior to weekly releases. The sooner this can be done, the less likely it
will block the next weekly release.

1.  Check out the `main` branch, which should always have a `-next` version.
    - This avoids having the initial publish actually be used in production.
1.  Trigger a release build locally.
    ```shell
    nvm install
    pnpm install --frozen-lockfile
    pnpm ng-dev release build
    ```
1.  Log in to NPM as `angular`.

    ```shell
    npm login
    ```

    - See these two Valentine entries for authentication details:
      - https://valentine.corp.google.com/#/show/1460636514618735
      - https://valentine.corp.google.com/#/show/1531867371192103

1.  Publish the release.
    ```shell
    (cd dist/releases/my-scope/my-pkg/ && npm publish --access public)
    ```
1.  Add Wombat to the package.
    ```shell
    npm owner add google-wombot @my-scope/my-pkg
    ```
1.  Don't forget to logout.
    ```shell
    npm logout
    ```
1.  File a bug like [b/336626936](http://b/336626936) to ask Wombat maintainers to
    accept the invite for the new package.

Once Wombat accepts the invite, regular automated releases should work as expected.

## Updating Browser Support

Angular's browser support is defined by a [Baseline](https://web.dev/baseline)
"widely available" date. Before a new major version is released, this should be
updated to approximately the current date.

A few weeks before a major (around feature freeze):

1.  Update `BASELINE_DATE` in
    [`/constants.bzl`](/constants.bzl) to the end of the most recent month.
    - For example, if it is currently May 12th, set `baselineThreshold` to April
      30th.
    - Picking a date at the end of a month makes it easier to cross-reference
      Angular's support with other tools (like MDN) which state Baseline support
      using month specificity.
    - Commit and merge the change, no other alterations or automation is
      necessary in the CLI repo.
2.  Update the date in the `ng-packagr` repo.
    [`/.stylesheet-processor.ts`](https://github.com/ng-packagr/ng-packagr/blob/main/src/lib/styles/stylesheet-processor.ts#L25).
3.  Update
    [`angular.dev` documentation](https://github.com/angular/angular/tree/main/adev/src/content/reference/versions.md#browser-support)
    to specify the date used and link to [browsersl.ist](https://browsersl.ist)
    with the generated configuration.

---

## File: docs/specifications/schematic-collections-config.md

# Schematics Collections (`schematicCollections`)

The `schematicCollections` can be placed under the `cli` option in the global `.angular.json` configuration, at the root or at project level in `angular.json` .

```jsonc
{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "cli": {
    "schematicCollections": ["@schematics/angular", "@angular/material"]
  }
  // ...
}
```

## Rationale

When this option is not configured and a user would like to run a schematic which is not part of `@schematics/angular`,
the collection name needs to be provided to `ng generate` command in the form of `[collection-name:schematic-name]`. This make the `ng generate` command too verbose for repeated usages.

This is where the `schematicCollections` option can be useful. When adding `@angular/material` to the list of `schematicCollections`, the generate command will try to locate the schematic in the specified collections.

```
ng generate navigation
```

is equivalent to:

```
ng generate @angular/material:navigation
```

## Conflicting schematic names

When multiple collections have a schematic with the same name. Both `ng generate` and `ng new` will run the first schematic matched based on the ordering (as specified) of `schematicCollections`.

---

## File: docs/specifications/schematic-prompts.md

# Schematic Prompts

Schematic prompts provide the ability to introduce user interaction into the schematic execution. The schematic runtime supports the ability to allow schematic options to be configured to display a customizable question to the user and then use the response as the value for the option. These prompts are displayed before the execution of the schematic. This allows users direct the operation of the schematic without requiring indepth knowledge of the full spectrum of options available to the user.

To enable this capability, the JSON Schema used to define the schematic's options supports extensions to allow the declarative definition of the prompts and their respective behavior. No additional logic or changes are required to the JavaScript for a schematic to support the prompts.

## Basic Usage

To illustrate the addition of a prompt to an existing schematic the following example JSON schema for a hypothetical _hello world_ schematic will be used.

```json
{
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "default": "world"
    },
    "useColor": {
      "type": "boolean"
    }
  }
}
```

Suppose it would be preferred if the user was asked for their name. This can be accomplished by augmenting the `name` property definition with an `x-prompt` field.

```json
"x-prompt": "What is your name?"
```

In most cases, only the text of the prompt is required. To minimize the amount of necessary configuration, the above _shorthand_ form is supported and will typically be all that is required. Full details regarding the _longhand_ form can be found in the **Configuration Reference** section.

Adding a prompt to allow the user to decided whether the schematic will use color when executing its hello action is also very similar. The schema with both prompts would be as follows:

```json
{
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "default": "world",
      "x-prompt": "What is your name?"
    },
    "useColor": {
      "type": "boolean",
      "x-prompt": "Would you like the response in color?"
    }
  }
}
```

Prompts have several different types which provide the ability to display an input method that best represents the schematic option's potential values.

- `confirmation` - A **yes** or **no** question; ideal for boolean options
- `input` - textual input; ideal for string or number options
- `list` - a predefined set of items which may be selected

When using the _shorthand_ form, the most appropriate type will automatically be selected based on the property's schema. In the example, the `name` prompt will use an `input` type because it is a `string` property. The `useColor` prompt will use a `confirmation` type because it is a boolean property with `yes` corresponding to `true` and `no` corresponding to `false`.

It is also important that the response from the user conforms to the constraints of the property. By specifying constraints using the JSON schema, the prompt runtime will automatically validate the response provided by the user. If the value is not acceptable, the user will be asked to enter a new value. This ensures that any values passed to the schematic will meet the expectations of the schematic's implementation and removes the need to add additional checks within the schematic's code.

## Configuration Reference

The `x-prompt` field supports two alternatives to enable a prompt for a schematic option. A shorthand form when additional customization is not required and a longhand form providing the ability for more control over the prompt. All user responses are validated against the property's schema. For example, string type properties can use a minimum length or regular expression constraint to control the allowed values. In the event the response fails validation, the user will be asked to enter a new value.

### Longhand Form

In the this form, the `x-prompt` field is an object with subfields that can be used to customize the behavior of the prompt. Note that some fields only apply to specific prompt types.

| Field     | Data Value                                | Default                           |
| --------- | ----------------------------------------- | --------------------------------- |
| `type`    | `confirmation`, `input`, `list`           | see shorthand section for details |
| `message` | string                                    | N/A (required)                    |
| `items`   | string and/or `label`/`value` object pair | only valid with type `list`       |

### Shorthand Form

`x-prompt` [type: string] --> Question to display to the user.

For this usage, the type of the prompt is determined by the type of the containing property.

| Property Schema     |  Prompt Type   |                Notes                |
| ------------------- | :------------: | :---------------------------------: |
| `"type": "boolean"` | `confirmation` |                                     |
| `"type": "string"`  |    `input`     |                                     |
| `"type": "number"`  |    `input`     |     only valid numbers accepted     |
| `"type": "integer"` |    `input`     |     only valid numbers accepted     |
| `"enum": [...]`     |     `list`     | enum members become list selections |

### `x-prompt` Schema

```json
{
  "oneOf": [
    { "type": "string" },
    {
      "type": "object",
      "properties": {
        "type": { "type": "string" },
        "message": { "type": "string" },
        "items": {
          "type": "array",
          "items": {
            "oneOf": [
              { "type": "string" },
              {
                "type": "object",
                "properties": {
                  "label": { "type": "string" },
                  "value": {}
                },
                "required": ["value"]
              }
            ]
          }
        }
      },
      "required": ["message"]
    }
  ]
}
```