Skip to content

Commit 6af44db

Browse files
committed
docs: Specification for ng update
1 parent 08658e2 commit 6af44db

File tree

1 file changed

+190
-0
lines changed

1 file changed

+190
-0
lines changed

docs/specifications/update.md

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
2+
# Update Command
3+
4+
`ng update` is a new command in the CLI to update one or multiple packages, its peer dependencies, and the peer dependencies that depends on it.
5+
6+
If there are inconsistencies, for example if peer dependencies cannot be matches by a simple semver range, the tool will error out (and nothing will be committed on the filesystem).
7+
8+
## Command Line Usage
9+
10+
```bash
11+
ng update <package1 [package2 [...]]> [options]
12+
```
13+
14+
You can specify more than one package. Each package follows the convention of `[@scope/]packageName[@version-range-or-dist-tag]`. Packages not found in your dependencies will trigger an error. Any package that has a higher version in your `package.json` will trigger an error.
15+
16+
| Flag | Argument | Description |
17+
|---|---|---|
18+
| `--all` | `boolean` | If true, implies that all dependencies should be updated. Defaults is false, using dependencies from the command line instead. |
19+
| `--next` | `boolean` | If true, allows version discovery to include Beta and RC. Defaults to false. |
20+
| `--migration-only` | `boolean` | If true, don't change the `package.json` file, only apply migration scripts. |
21+
| `--from` | `version` | Apply migrations from a certain version number. |
22+
| `--to` | `version` | Apply migrations up to a certain version number (inclusive). By default will update to the tag selected. |
23+
24+
## Details
25+
26+
The schematic performs the following steps, in order:
27+
28+
1. Get all installed package names and versions from the `package.json` into `dependencyMap: Map<string, string>`.
29+
1. From that map, fetch all `package.json` from the NPM repository, which contains all versions, and gather them in a `Map<string, NpmPackageJson>`.
30+
1. At the same time, update the `Map<>` with the version of the package which is believed to be installed (largest version number matching the version range).
31+
1. **WARNING**: this might not be the exact installed versions, unfortunately. We should have a proper `package-lock.json` loader, and support `yarn.lock` as well, but these are stretch goals (and where do we stop).
32+
1. For each packages mentioned on the command line, update to the target version (by default largest non-beta non-rc version):
33+
34+
```python
35+
# ARGV The packages being requested by the user.
36+
# NPM A map of package name to a map of version to PackageJson structure.
37+
# V A map of package name to available versions.
38+
# PKG A map of package name to PackageJson structure, for the installed versions.
39+
# next A flag for the "--next" command line argument.
40+
41+
# First add all updating packages' peer dependencies. This should be recursive but simplified
42+
# here for readability.
43+
ARGV += [ NPM[p][max([ v for v in V[p] if (not is_beta(v) or next) ])].peerDependencies
44+
for p in ARGV ]
45+
46+
for p in ARGV:
47+
x = max([ v for v in V[p] if (not is_beta(v) or next) ])
48+
49+
for other in set(PKG.keys()) - set([ p ]):
50+
# Verify all packages' peer dependencies.
51+
if has(other.peerDependencies, p) and !compatible(x, other.peerDependencies[p]):
52+
showError('Cannot update dependency "%s": "%s" is incompatible with the updated dependency' % (x, other))
53+
54+
if any( has(other.peerDependencies, peer) and !compatible(x, other.peerDependencies[peer])
55+
for peer in PKG[p].peerDependencies.keys() ):
56+
showError('Cannot update dependency "%s": "%s" depends on an incompatible peer dependency' % (x, other))
57+
58+
update_package_json(p, x)
59+
```
60+
61+
62+
63+
## Library Developers
64+
65+
Libraries are responsible for defining their own update schematics. The `ng update` tool will update the package.json, and if it detects am `"ng-update"` key in package.json of the library, will run the update schematic on it (with version information metadata).
66+
67+
If a library does not define the `"ng-update"` key in their package.json, they are considered not supporting the update workflow and `ng update` is basically equivalent to `npm install`.
68+
69+
### Migration
70+
71+
In order to implement migrations in a library, the author must add the `ng-update` key to its `package.json`. This key contains the following fields:
72+
73+
| Field Name | Type | Description |
74+
|---|---|---|
75+
| `requirements` | `{ [packageName: string]: VersionRange }` | A map of package names to version to check for minimal requirement. If one of the libraries listed here does not match the version range specified in `requirements`, an error will be shown to the user to manually update those libraries. For example, `@angular/core` does not support updates from versions earlier than 5, so this field would be `{ '@angular/core': '>= 5' }`.
76+
| `migrations` | `string` | A relative path (or resolved using Node module resolution) to a Schematics collection definition. |
77+
| `packageGroup` | `string[]` | A list of npm packages that are to be grouped together. When running
78+
79+
#### Example given:
80+
Library my-lib wants to have 2 steps to update from version 4 -> 4.5 and 4.5 to 5. It would add this information in its `package.json`:
81+
82+
```json
83+
{
84+
"ng-update": {
85+
"requirements": {
86+
"my-lib": "^5"
87+
},
88+
"migrations": "./migrations/migration-collection.json"
89+
}
90+
}
91+
```
92+
93+
And create a migration collection (same schema as the Schematics collection):
94+
95+
```json
96+
{
97+
"schematics": {
98+
"migration-01": {
99+
"version": "6",
100+
"factory": "./update-6"
101+
},
102+
"migration-02": {
103+
"version": "6.2",
104+
"factory": "./update-6_2"
105+
},
106+
"migration-03": {
107+
"version": "6.3",
108+
"factory": "./update-6_3"
109+
},
110+
"migration-04": {
111+
"version": "7",
112+
"factory": "./update-7"
113+
},
114+
"migration-05": {
115+
"version": "8",
116+
"factory": "./update-8"
117+
}
118+
}
119+
}
120+
```
121+
122+
The update tool would then read the current version of library installed, check against all `version` fields and run the schematics, until it reaches the version required by the user (inclusively). If such a collection is used to update from version 5 to version 7, the `01`, `02`, `03,` and `04` functions would be called. If the current version is 7 and a `--refactor-only` flag is passed, it would run the migration `04` only. More arguments are needed to know from which version you are updating.
123+
124+
Running `ng update @angular/core` would be the same as `ng generate @angular/core/migrations:migration-01`.
125+
126+
## Use cases
127+
128+
### Help
129+
130+
`ng update`, shows what updates would be applied;
131+
132+
```sh
133+
$ ng update
134+
We analyzed your package.json, there's some packages to update:
135+
136+
Name Version Command to update
137+
----------------------------------------------------------------------------
138+
@angular/cli 1.7.0 > 6.0.0 ng update @angular/cli
139+
@angular/core 5.4.3 > 6.0.1 ng update @angular/core
140+
@angular/material 5.2.1 > 6.0.0 ng update @angular/material
141+
@angular/router 5.4.3 > 6.0.1 ng update @angular/core
142+
143+
There might be additional packages that are outdated.
144+
```
145+
146+
### Simple Multi-steps
147+
148+
I have a dependency on Angular, Material and CLI. I want to update the CLI, then Angular, then Material in separate steps.
149+
150+
#### Details
151+
1. `ng update @angular/cli`.
152+
Updates the CLI and packages that have a peer dependencies on the CLI (none), running refactoring tools from CLI 1 to 6.
153+
1. `ng update @angular/core`.
154+
Updates the Core package and all packages that have a peer dependency on it. This can get tricky if `@angular/material` get caught in the update because the version installed does not directly allow the new version of `@angular/core`. In this case
155+
156+
### Complex Case
157+
158+
package.json:
159+
160+
```json
161+
{
162+
"dependencies": {
163+
"@angular/material": "5.0.0",
164+
"@angular/core": "5.5.5"
165+
}
166+
}
167+
```
168+
169+
Commands:
170+
171+
```bash
172+
ng update @angular/core
173+
```
174+
175+
- updates `@angular/core` to the `latest` dist-tag (6.0.0)
176+
- sees that `@angular/material` is not compatible with 6.0.0; **error out.**
177+
178+
```bash
179+
ng update @angular/material
180+
```
181+
182+
- update `@angular/material` to latest version, that should be compatible with the current `@angular/core`.
183+
- if that version is not compatible with you
184+
- tell the user about a higher version that requires an update to `@angular/core`.
185+
186+
187+
## Notes
188+
189+
1. if someone is on CLI 1.5, the command is not supported. The user needs to update to `@angular/cli@latest`, then `ng update @angular/cli`. Post install hook will check versions of cli configuration and show a message to run the `ng update` command.
190+
1. NPM proxies or cache are not supported by the first version of this command.

0 commit comments

Comments
 (0)