-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
- I'd be willing to implement this feature (contributing guide)
- This feature is important to have in this repository; a contrib plugin wouldn't do
Describe the user story
Inspired by #3048. Note: some of the specifics may have changed since #3423 was merged -- I haven't had a chance to try it out -- but much of the below remains relevant.
:
is frequently used in package.json script definitions to represent the concept of "scope" or "specificity". Some tools have even built the concept in as a first-class behavior, such as npm-run-all's globbing feature to run a bunch of related scripts at once.
This idiomatic usage of colon-as-scope more or less coexists peacefully with the existing colon-means-global behavior as far as run
is concerned. This is because run
will prefer a script defined in the current workspace before attempting to run a global script from another workspace. This preference behavior is crucial, because in the case where multiple workspaces define the same script, run
will fail (since there are multiple definitions) if you run it in the "global manner", i.e., from a package that does not define that script name locally.
However, workspaces foreach
does not interact nicely with the colon-means-global behavior. Scripts that are defined using colon-as-scope and work as expected when run from the package -- because run
prefers the local script definition -- cannot be run in bulk with workspaces foreach run foo:bar
because that command will find conflicting definitions for the global script. This is very surprising because it breaks the expectation that workspaces foreach run
is just "bulk run
".
Furthermore, the colon-means-global behavior is very non-obvious and fragile. For instance, adding a script with the same name as a global script to a workspace can cause unrelated packages/commands to start failing because there are now two definitions for the global script. Or, removing the second definition of a script will silently make the remaining definition global. Spooky action at a distance!
Describe the solution you'd like
I think all of the former problems can be resolved by making "global scripts" an explicit opt-in feature. I imagine this as a --global/-g
flag to run
and workspaces foreach
.
Doing so should resolve all the aforementioned issues and preserve the existing feature set, albeit with slightly more work if you are using global scripts:
workspaces foreach
matchesrun
in all cases ---g
if you want to run a global script, nothing otherwise -- making it more clearly "bulkrun
"- spooky-action-at-a-distance breakages via duplicated script names become less spooky -- it's clear at the call site, even for someone unfamiliar with Yarn's more esoteric features, that a single global script was expected
- interoperability with other tools is improved, as Yarn no longer expresses any preferences or interpretation of script naming schemes
This change could be partially adopted in a non-breaking manner by adding the reverse of the -g
flag to workspaces foreach
-- that is, a flag that tells it to prefer local scripts, and to ignore the possibility of invoking global scripts. Perhaps it could be called --local/-l
. For my part, this would fix my immediate problem.
Describe the drawbacks of your solution
This would be a breaking change, though as noted above, it can be partially adopted with a new backwards-compatible flag.
The only other downside I can see is that it's marginally more keystrokes to invoke a script globally.
Describe alternatives you've considered
This doesn't make sense as a plugin since it's about undoing some interpretations that the core run
command makes about your project.