Skip to content

Commit cf655e2

Browse files
committed
RFC: npm workspaces part 2
- Defines ways to run cli commands in the context of child workspaces - Define a standard way to filter workspaces - Categorizes cli commands in different groups for implementation PR-URL: #117 Credit: @ruyadorno Close: #117 Reviewed-by: @darcyclarke, @mtdev2, @wesleytodd
1 parent f573cf4 commit cf655e2

File tree

1 file changed

+194
-0
lines changed

1 file changed

+194
-0
lines changed
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
# npm Workspaces: Running commands
2+
3+
## Summary
4+
5+
Introduces basic support for running **npm commands** across a project's **workspaces**.
6+
7+
## Motivation
8+
9+
The need for running **npm commands** across a project's **workspaces** was surfaced by the community during the discourse spun out of the [initial **npm workspaces** RFC](https://github.com/npm/rfcs/pull/103).
10+
11+
## Detailed Explanation
12+
13+
Following up on the original **npm workspaces** RFC are the following command-related additions/changes:
14+
15+
- A subset of the standard **npm commands** need to be made aware of **npm workspaces**
16+
- It's desired to have a standard way to filter out **workspaces** in which to run specific **npm commands**
17+
18+
## Rationale and Alternatives
19+
20+
The ability to run **npm commands** across a project's **workspaces** is essential to effecient management of, & enabling, complex developer workflows.
21+
22+
The following are possible alternatives to unlock this functionality:
23+
24+
- Do not implement further support to manage running commands across **workspaces**, keep the **npm workspaces** set of features to a minimum
25+
- Defer to other tools from the ecosystem - such as **Lerna** - to solve the problem of running top-level commands across **workspaces**
26+
- Implement the proposed features of this RFC as a standalone package apart from the **npm cli**
27+
28+
## Implementation
29+
30+
### 1. Run commands across all child workspaces
31+
32+
Create a new **npm cli** config, `--workspaces` (aliased to `--ws`), that can route any of the supported subcommands to run in the context of the configured **workspaces** as long as a **workspaces configuration** field is properly defined in `package.json`
33+
34+
There are currently five distinct categories of _"workspace-awareness"_ that existing subcommands will belong to:
35+
36+
#### 1. Commands that _just_ need context from `package.json`
37+
38+
Commands that, from a user's point of view, are the equivalent of: `cd <workspace-name> && npm <cmd>`.
39+
40+
- `docs`
41+
- `doctor`
42+
- `diff`
43+
- `dist-tag`
44+
- `pack`
45+
- `publish`
46+
- `repo`
47+
- `set-script`
48+
- `unpublish`
49+
- `view`
50+
51+
#### 2. Custom implementation
52+
53+
##### 2.1. Reads from installed dependency tree
54+
55+
General class of helper commands that load from the installed tree to produce some form of useful output.
56+
57+
- `audit`
58+
- `explain`
59+
- `fund`
60+
- `ls`
61+
- `outdated`
62+
63+
##### 2.2. Modify installed dependency tree
64+
65+
The set of commands that will modify an install tree (from an implementation stand-point, these are just [arborist.reify](https://github.com/npm/arborist/) proxies).
66+
67+
- `ci`
68+
- `dedupe|find-dupes`
69+
- `install-ci-test`
70+
- `install-test`
71+
- `install`
72+
- `link`
73+
- `rebuild`
74+
- `update`
75+
- `uninstall`
76+
77+
##### 2.3. Other
78+
79+
Commands that need a special/custom _"workspace-aware"_ implementation outside of the context of reading/writing to the install tree.
80+
81+
- `exec`
82+
- `init`
83+
- `run-script|restart|start|stop|test`
84+
- `version`
85+
86+
#### 3. Unsupported
87+
88+
This category of **npm cli** commands is completely unrelated to anything that the current working directory could affect. This includes a number of registry-specific helper/management operations which don't make sense/have no effect within the context of a workspace. Trying to run these commands with a workspace flag/config will exit with a descriptive error code.
89+
90+
- `adduser|login`
91+
- `bin`
92+
- `birthday`
93+
- `cache`
94+
- `completion`
95+
- `config|get|set`
96+
- `deprecate`
97+
- `edit`
98+
- `explore`
99+
- `help`
100+
- `help-search`
101+
- `hook`
102+
- `logout`
103+
- `org`
104+
- `owner`
105+
- `ping`
106+
- `prefix`
107+
- `profile`
108+
- `search`
109+
- `shrinkwrap`
110+
- `star`
111+
- `team`
112+
- `token`
113+
- `unstar`
114+
- `whoami`
115+
- `workspaces`
116+
117+
#### Example:
118+
119+
Running tests across all configured **workspaces**:
120+
121+
```
122+
├── package.json { "name": "foo", "workspaces": ["dep-a", "dep-b"] }
123+
├── dep-a
124+
│ └── package.json { "version": "1.0.0" }
125+
└── dep-b
126+
└── package.json { "version": "1.3.1" }
127+
128+
$ npm test --workspaces
129+
130+
> [email protected] test /Users/username/foo
131+
> echo "Error: no test specified" && exit 1
132+
133+
Error: no test specified
134+
npm ERR! Test failed. See above for more details.
135+
136+
> [email protected] test /Users/username/foo/dep-a
137+
> done
138+
139+
> [email protected] test /Users/username/foo/dep-b
140+
> done
141+
```
142+
143+
### 2. Filter a subset of workspaces
144+
145+
Filter is done via named argument (`--workspace`, short: `-w`) and here are some of the reasons why we decided to go that route:
146+
- [Lerna filters](https://www.npmjs.com/package/@lerna/filter-options) were the starting point but early in the discussion some other considerations were brought forward, specially the many pitfalls of supporting globs in the variety of supported shells and operational systems.
147+
148+
### 3. Examples
149+
150+
Given the results of all this preliminar investigation, the preferred way to run a command in the context of a single workspace is to use the named `--workspace` argument or its `-w` short alias, e.g:
151+
152+
In a project with the following structure:
153+
```
154+
./
155+
├── package.json { "name": "root", "workspaces": ["packages/foo", "packages/bar"] }
156+
└── packages/
157+
├── foo/
158+
│ └── package.json { "name": "foo", "version": "1.0.0" }
159+
└── bar/
160+
└── package.json { "name": "foo", "version": "1.0.0" }
161+
```
162+
163+
You can run tests for the `foo` workspace from the root of your project, with the following syntax:
164+
165+
```
166+
npm test --workspace=foo
167+
```
168+
169+
170+
#### Install dependency example:
171+
172+
Add `tap` as a **dependency** for all of your configured **workspaces**:
173+
174+
```sh
175+
npm install tap --workspaces
176+
```
177+
178+
179+
> Note: **Globs** are not supported as a valid `--workspace` argument value, the proposed alternative is to use `npm <cmd> --workspace=<dir>` in which `<dir>` is a folder containing multiple workspaces.
180+
181+
## Prior Art
182+
183+
#### Previously
184+
185+
- [npm workspaces](https://github.com/npm/rfcs/blob/de8d71c0453f5cf443d3ef2f47e313f12dd6aaf9/accepted/0000-workspaces.md)
186+
187+
#### Filtering a subset of workspaces
188+
189+
- [lerna filter-options](https://www.npmjs.com/package/@lerna/filter-options)
190+
- [Yarn v1 workspace cmd](https://classic.yarnpkg.com/en/docs/cli/workspace)
191+
- [Yarn v1 workspaces cmd](https://classic.yarnpkg.com/en/docs/cli/workspaces)
192+
- [Yarn v2 foreach include/exclude](https://yarnpkg.com/cli/workspaces/foreach)
193+
- [pnpm Filtering](https://pnpm.js.org/en/filtering)
194+

0 commit comments

Comments
 (0)