bun-workspaces 0.1.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/extensions.json +12 -0
- package/.vscode/settings.json +23 -0
- package/README.md +23 -5
- package/ignore-me-CHANGELOG_TEMPLATE.md +264 -0
- package/ignore-me-test-projects/no-fail/applications/applicationA/package.json +8 -0
- package/ignore-me-test-projects/no-fail/applications/applicationB/package.json +8 -0
- package/ignore-me-test-projects/no-fail/libraries/libraryA/package.json +8 -0
- package/ignore-me-test-projects/no-fail/libraries/libraryB/package.json +8 -0
- package/ignore-me-test-projects/no-fail/libraries/nested/libraryC/package.json +8 -0
- package/ignore-me-test-projects/no-fail/package.json +7 -0
- package/ignore-me-test-projects/one-fail/applications/applicationA/package.json +8 -0
- package/ignore-me-test-projects/one-fail/applications/applicationB/package.json +8 -0
- package/ignore-me-test-projects/one-fail/libraries/libraryA/package.json +8 -0
- package/ignore-me-test-projects/one-fail/libraries/libraryB/package.json +8 -0
- package/ignore-me-test-projects/one-fail/libraries/nested/libraryC/package.json +8 -0
- package/ignore-me-test-projects/one-fail/package.json +7 -0
- package/ignore-me-test-projects/two-fail/applications/applicationA/package.json +8 -0
- package/ignore-me-test-projects/two-fail/applications/applicationB/package.json +8 -0
- package/ignore-me-test-projects/two-fail/libraries/libraryA/package.json +8 -0
- package/ignore-me-test-projects/two-fail/libraries/libraryB/package.json +8 -0
- package/ignore-me-test-projects/two-fail/libraries/nested/libraryC/package.json +8 -0
- package/ignore-me-test-projects/two-fail/package.json +7 -0
- package/package.json +2 -1
- package/src/cli/cli.ts +1 -1
- package/src/cli/projectCommands.ts +222 -110
- package/src/internal/bunVersion.ts +4 -2
- package/src/internal/logger.ts +7 -3
- package/src/internal/regex.ts +5 -0
- package/src/project/project.ts +10 -0
- package/src/workspaces/errors.ts +1 -0
- package/src/workspaces/findWorkspaces.ts +1 -3
- package/src/workspaces/packageJson.ts +15 -7
- package/tsconfig.json +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"recommendations": [
|
|
3
|
+
"esbenp.prettier-vscode",
|
|
4
|
+
"oven.bun-vscode",
|
|
5
|
+
"streetsidesoftware.code-spell-checker",
|
|
6
|
+
"jasonnutter.vscode-codeowners",
|
|
7
|
+
"EditorConfig.EditorConfig",
|
|
8
|
+
"dbaeumer.vscode-eslint",
|
|
9
|
+
"github.vscode-github-actions",
|
|
10
|
+
"aaron-bond.better-comments"
|
|
11
|
+
]
|
|
12
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"editor.codeActionsOnSave": {
|
|
3
|
+
"source.fixAll.eslint": "explicit"
|
|
4
|
+
},
|
|
5
|
+
"eslint.codeActionsOnSave.rules": ["import/order"],
|
|
6
|
+
"eslint.validate": ["javascript", "typescript"],
|
|
7
|
+
"[typescript]": {
|
|
8
|
+
"editor.formatOnSave": true,
|
|
9
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
10
|
+
},
|
|
11
|
+
"[javascript]": {
|
|
12
|
+
"editor.formatOnSave": true,
|
|
13
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
14
|
+
},
|
|
15
|
+
"[json]": {
|
|
16
|
+
"editor.formatOnSave": true,
|
|
17
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
18
|
+
},
|
|
19
|
+
"[jsonc]": {
|
|
20
|
+
"editor.formatOnSave": true,
|
|
21
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
22
|
+
}
|
|
23
|
+
}
|
package/README.md
CHANGED
|
@@ -23,11 +23,16 @@ alias bw="bunx bun-workspaces"
|
|
|
23
23
|
# List all workspaces
|
|
24
24
|
bw list-workspaces
|
|
25
25
|
bw ls
|
|
26
|
+
|
|
26
27
|
# List workspace names only
|
|
27
28
|
bw list-workspaces --name-only
|
|
28
29
|
|
|
30
|
+
# Filter list of workspaces with wildcard
|
|
31
|
+
bw list-workspaces "my-*"
|
|
32
|
+
|
|
29
33
|
# List all workspace scripts
|
|
30
34
|
bw list-scripts
|
|
35
|
+
|
|
31
36
|
# List script names only
|
|
32
37
|
bw list-scripts --name-only
|
|
33
38
|
|
|
@@ -37,25 +42,38 @@ bw info my-workspace
|
|
|
37
42
|
|
|
38
43
|
# Get info about a script
|
|
39
44
|
bw script-info my-script
|
|
45
|
+
|
|
40
46
|
# Only print list of workspace names that have the script
|
|
41
47
|
bw script-info my-script --workspaces-only
|
|
42
48
|
|
|
49
|
+
# Get JSON output
|
|
50
|
+
bw list-workspaces --json --pretty # optionally pretty print JSON
|
|
51
|
+
bw list-scripts --json
|
|
52
|
+
bw workspace-info my-workspace --json
|
|
53
|
+
bw script-info my-script --json
|
|
54
|
+
|
|
43
55
|
# Run a script for all
|
|
44
56
|
# workspaces that have it
|
|
45
57
|
# in their `scripts` field
|
|
46
|
-
bw run
|
|
58
|
+
bw run my-script
|
|
47
59
|
|
|
48
60
|
# Run a script for a specific workspace
|
|
49
|
-
bw run
|
|
61
|
+
bw run my-script my-workspace
|
|
50
62
|
|
|
51
63
|
# Run a script for multiple workspaces
|
|
52
|
-
bw run
|
|
64
|
+
bw run my-script workspace-a workspace-b
|
|
65
|
+
|
|
66
|
+
# Run a script for workspaces using wildcard
|
|
67
|
+
bw run my-script "my-workspace-*"
|
|
53
68
|
|
|
54
69
|
# Run script in parallel for all workspaces
|
|
55
|
-
bw run
|
|
70
|
+
bw run my-script --parallel
|
|
56
71
|
|
|
57
72
|
# Append args to each script call
|
|
58
|
-
bw run
|
|
73
|
+
bw run my-script --args "--my --args"
|
|
74
|
+
|
|
75
|
+
# Use the workspace name in args
|
|
76
|
+
bw run my-script --args "--my --args=<workspace>"
|
|
59
77
|
|
|
60
78
|
# Help (--help can also be passed to any command)
|
|
61
79
|
bw help
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- v1.1 Brazilian Portuguese translation.
|
|
13
|
+
- v1.1 German Translation
|
|
14
|
+
- v1.1 Spanish translation.
|
|
15
|
+
- v1.1 Italian translation.
|
|
16
|
+
- v1.1 Polish translation.
|
|
17
|
+
- v1.1 Ukrainian translation.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Use frontmatter title & description in each language version template
|
|
22
|
+
- Replace broken OpenGraph image with an appropriately-sized Keep a Changelog
|
|
23
|
+
image that will render properly (although in English for all languages)
|
|
24
|
+
- Fix OpenGraph title & description for all languages so the title and
|
|
25
|
+
description when links are shared are language-appropriate
|
|
26
|
+
|
|
27
|
+
### Removed
|
|
28
|
+
|
|
29
|
+
- Trademark sign previously shown after the project description in version
|
|
30
|
+
0.3.0
|
|
31
|
+
|
|
32
|
+
## [1.1.1] - 2023-03-05
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
|
|
36
|
+
- Arabic translation (#444).
|
|
37
|
+
- v1.1 French translation.
|
|
38
|
+
- v1.1 Dutch translation (#371).
|
|
39
|
+
- v1.1 Russian translation (#410).
|
|
40
|
+
- v1.1 Japanese translation (#363).
|
|
41
|
+
- v1.1 Norwegian Bokmål translation (#383).
|
|
42
|
+
- v1.1 "Inconsistent Changes" Turkish translation (#347).
|
|
43
|
+
- Default to most recent versions available for each languages.
|
|
44
|
+
- Display count of available translations (26 to date!).
|
|
45
|
+
- Centralize all links into `/data/links.json` so they can be updated easily.
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
|
|
49
|
+
- Improve French translation (#377).
|
|
50
|
+
- Improve id-ID translation (#416).
|
|
51
|
+
- Improve Persian translation (#457).
|
|
52
|
+
- Improve Russian translation (#408).
|
|
53
|
+
- Improve Swedish title (#419).
|
|
54
|
+
- Improve zh-CN translation (#359).
|
|
55
|
+
- Improve French translation (#357).
|
|
56
|
+
- Improve zh-TW translation (#360, #355).
|
|
57
|
+
- Improve Spanish (es-ES) transltion (#362).
|
|
58
|
+
- Foldout menu in Dutch translation (#371).
|
|
59
|
+
- Missing periods at the end of each change (#451).
|
|
60
|
+
- Fix missing logo in 1.1 pages.
|
|
61
|
+
- Display notice when translation isn't for most recent version.
|
|
62
|
+
- Various broken links, page versions, and indentations.
|
|
63
|
+
|
|
64
|
+
### Changed
|
|
65
|
+
|
|
66
|
+
- Upgrade dependencies: Ruby 3.2.1, Middleman, etc.
|
|
67
|
+
|
|
68
|
+
### Removed
|
|
69
|
+
|
|
70
|
+
- Unused normalize.css file.
|
|
71
|
+
- Identical links assigned in each translation file.
|
|
72
|
+
- Duplicate index file for the english version.
|
|
73
|
+
|
|
74
|
+
## [1.1.0] - 2019-02-15
|
|
75
|
+
|
|
76
|
+
### Added
|
|
77
|
+
|
|
78
|
+
- Danish translation (#297).
|
|
79
|
+
- Georgian translation from (#337).
|
|
80
|
+
- Changelog inconsistency section in Bad Practices.
|
|
81
|
+
|
|
82
|
+
### Fixed
|
|
83
|
+
|
|
84
|
+
- Italian translation (#332).
|
|
85
|
+
- Indonesian translation (#336).
|
|
86
|
+
|
|
87
|
+
## [1.0.0] - 2017-06-20
|
|
88
|
+
|
|
89
|
+
### Added
|
|
90
|
+
|
|
91
|
+
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
|
92
|
+
- Version navigation.
|
|
93
|
+
- Links to latest released version in previous versions.
|
|
94
|
+
- "Why keep a changelog?" section.
|
|
95
|
+
- "Who needs a changelog?" section.
|
|
96
|
+
- "How do I make a changelog?" section.
|
|
97
|
+
- "Frequently Asked Questions" section.
|
|
98
|
+
- New "Guiding Principles" sub-section to "How do I make a changelog?".
|
|
99
|
+
- Simplified and Traditional Chinese translations from [@tianshuo](https://github.com/tianshuo).
|
|
100
|
+
- German translation from [@mpbzh](https://github.com/mpbzh) & [@Art4](https://github.com/Art4).
|
|
101
|
+
- Italian translation from [@azkidenz](https://github.com/azkidenz).
|
|
102
|
+
- Swedish translation from [@magol](https://github.com/magol).
|
|
103
|
+
- Turkish translation from [@emreerkan](https://github.com/emreerkan).
|
|
104
|
+
- French translation from [@zapashcanon](https://github.com/zapashcanon).
|
|
105
|
+
- Brazilian Portuguese translation from [@Webysther](https://github.com/Webysther).
|
|
106
|
+
- Polish translation from [@amielucha](https://github.com/amielucha) & [@m-aciek](https://github.com/m-aciek).
|
|
107
|
+
- Russian translation from [@aishek](https://github.com/aishek).
|
|
108
|
+
- Czech translation from [@h4vry](https://github.com/h4vry).
|
|
109
|
+
- Slovak translation from [@jkostolansky](https://github.com/jkostolansky).
|
|
110
|
+
- Korean translation from [@pierceh89](https://github.com/pierceh89).
|
|
111
|
+
- Croatian translation from [@porx](https://github.com/porx).
|
|
112
|
+
- Persian translation from [@Hameds](https://github.com/Hameds).
|
|
113
|
+
- Ukrainian translation from [@osadchyi-s](https://github.com/osadchyi-s).
|
|
114
|
+
|
|
115
|
+
### Changed
|
|
116
|
+
|
|
117
|
+
- Start using "changelog" over "change log" since it's the common usage.
|
|
118
|
+
- Start versioning based on the current English version at 0.3.0 to help
|
|
119
|
+
translation authors keep things up-to-date.
|
|
120
|
+
- Rewrite "What makes unicorns cry?" section.
|
|
121
|
+
- Rewrite "Ignoring Deprecations" sub-section to clarify the ideal
|
|
122
|
+
scenario.
|
|
123
|
+
- Improve "Commit log diffs" sub-section to further argument against
|
|
124
|
+
them.
|
|
125
|
+
- Merge "Why can’t people just use a git log diff?" with "Commit log
|
|
126
|
+
diffs".
|
|
127
|
+
- Fix typos in Simplified Chinese and Traditional Chinese translations.
|
|
128
|
+
- Fix typos in Brazilian Portuguese translation.
|
|
129
|
+
- Fix typos in Turkish translation.
|
|
130
|
+
- Fix typos in Czech translation.
|
|
131
|
+
- Fix typos in Swedish translation.
|
|
132
|
+
- Improve phrasing in French translation.
|
|
133
|
+
- Fix phrasing and spelling in German translation.
|
|
134
|
+
|
|
135
|
+
### Removed
|
|
136
|
+
|
|
137
|
+
- Section about "changelog" vs "CHANGELOG".
|
|
138
|
+
|
|
139
|
+
## [0.3.0] - 2015-12-03
|
|
140
|
+
|
|
141
|
+
### Added
|
|
142
|
+
|
|
143
|
+
- RU translation from [@aishek](https://github.com/aishek).
|
|
144
|
+
- pt-BR translation from [@tallesl](https://github.com/tallesl).
|
|
145
|
+
- es-ES translation from [@ZeliosAriex](https://github.com/ZeliosAriex).
|
|
146
|
+
|
|
147
|
+
## [0.2.0] - 2015-10-06
|
|
148
|
+
|
|
149
|
+
### Changed
|
|
150
|
+
|
|
151
|
+
- Remove exclusionary mentions of "open source" since this project can
|
|
152
|
+
benefit both "open" and "closed" source projects equally.
|
|
153
|
+
|
|
154
|
+
## [0.1.0] - 2015-10-06
|
|
155
|
+
|
|
156
|
+
### Added
|
|
157
|
+
|
|
158
|
+
- Answer "Should you ever rewrite a change log?".
|
|
159
|
+
|
|
160
|
+
### Changed
|
|
161
|
+
|
|
162
|
+
- Improve argument against commit logs.
|
|
163
|
+
- Start following [SemVer](https://semver.org) properly.
|
|
164
|
+
|
|
165
|
+
## [0.0.8] - 2015-02-17
|
|
166
|
+
|
|
167
|
+
### Changed
|
|
168
|
+
|
|
169
|
+
- Update year to match in every README example.
|
|
170
|
+
- Reluctantly stop making fun of Brits only, since most of the world
|
|
171
|
+
writes dates in a strange way.
|
|
172
|
+
|
|
173
|
+
### Fixed
|
|
174
|
+
|
|
175
|
+
- Fix typos in recent README changes.
|
|
176
|
+
- Update outdated unreleased diff link.
|
|
177
|
+
|
|
178
|
+
## [0.0.7] - 2015-02-16
|
|
179
|
+
|
|
180
|
+
### Added
|
|
181
|
+
|
|
182
|
+
- Link, and make it obvious that date format is ISO 8601.
|
|
183
|
+
|
|
184
|
+
### Changed
|
|
185
|
+
|
|
186
|
+
- Clarified the section on "Is there a standard change log format?".
|
|
187
|
+
|
|
188
|
+
### Fixed
|
|
189
|
+
|
|
190
|
+
- Fix Markdown links to tag comparison URL with footnote-style links.
|
|
191
|
+
|
|
192
|
+
## [0.0.6] - 2014-12-12
|
|
193
|
+
|
|
194
|
+
### Added
|
|
195
|
+
|
|
196
|
+
- README section on "yanked" releases.
|
|
197
|
+
|
|
198
|
+
## [0.0.5] - 2014-08-09
|
|
199
|
+
|
|
200
|
+
### Added
|
|
201
|
+
|
|
202
|
+
- Markdown links to version tags on release headings.
|
|
203
|
+
- Unreleased section to gather unreleased changes and encourage note
|
|
204
|
+
keeping prior to releases.
|
|
205
|
+
|
|
206
|
+
## [0.0.4] - 2014-08-09
|
|
207
|
+
|
|
208
|
+
### Added
|
|
209
|
+
|
|
210
|
+
- Better explanation of the difference between the file ("CHANGELOG")
|
|
211
|
+
and its function "the change log".
|
|
212
|
+
|
|
213
|
+
### Changed
|
|
214
|
+
|
|
215
|
+
- Refer to a "change log" instead of a "CHANGELOG" throughout the site
|
|
216
|
+
to differentiate between the file and the purpose of the file — the
|
|
217
|
+
logging of changes.
|
|
218
|
+
|
|
219
|
+
### Removed
|
|
220
|
+
|
|
221
|
+
- Remove empty sections from CHANGELOG, they occupy too much space and
|
|
222
|
+
create too much noise in the file. People will have to assume that the
|
|
223
|
+
missing sections were intentionally left out because they contained no
|
|
224
|
+
notable changes.
|
|
225
|
+
|
|
226
|
+
## [0.0.3] - 2014-08-09
|
|
227
|
+
|
|
228
|
+
### Added
|
|
229
|
+
|
|
230
|
+
- "Why should I care?" section mentioning The Changelog podcast.
|
|
231
|
+
|
|
232
|
+
## [0.0.2] - 2014-07-10
|
|
233
|
+
|
|
234
|
+
### Added
|
|
235
|
+
|
|
236
|
+
- Explanation of the recommended reverse chronological release ordering.
|
|
237
|
+
|
|
238
|
+
## [0.0.1] - 2014-05-31
|
|
239
|
+
|
|
240
|
+
### Added
|
|
241
|
+
|
|
242
|
+
- This CHANGELOG file to hopefully serve as an evolving example of a
|
|
243
|
+
standardized open source project CHANGELOG.
|
|
244
|
+
- CNAME file to enable GitHub Pages custom domain.
|
|
245
|
+
- README now contains answers to common questions about CHANGELOGs.
|
|
246
|
+
- Good examples and basic guidelines, including proper date formatting.
|
|
247
|
+
- Counter-examples: "What makes unicorns cry?".
|
|
248
|
+
|
|
249
|
+
[unreleased]: https://github.com/olivierlacan/keep-a-changelog/compare/v1.1.1...HEAD
|
|
250
|
+
[1.1.1]: https://github.com/olivierlacan/keep-a-changelog/compare/v1.1.0...v1.1.1
|
|
251
|
+
[1.1.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v1.0.0...v1.1.0
|
|
252
|
+
[1.0.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.3.0...v1.0.0
|
|
253
|
+
[0.3.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.2.0...v0.3.0
|
|
254
|
+
[0.2.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.1.0...v0.2.0
|
|
255
|
+
[0.1.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.8...v0.1.0
|
|
256
|
+
[0.0.8]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.7...v0.0.8
|
|
257
|
+
[0.0.7]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.6...v0.0.7
|
|
258
|
+
[0.0.6]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.5...v0.0.6
|
|
259
|
+
[0.0.5]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.4...v0.0.5
|
|
260
|
+
[0.0.4]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.3...v0.0.4
|
|
261
|
+
[0.0.3]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.2...v0.0.3
|
|
262
|
+
[0.0.2]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.1...v0.0.2
|
|
263
|
+
[0.0.1]: https://github.com/olivierlacan/keep-a-changelog/releases/tag/v0.0.1
|
|
264
|
+
Wh
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bun-workspaces",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"main": "src/index.ts",
|
|
5
5
|
"homepage": "https://github.com/ScottMorse/bun-workspaces#readme",
|
|
6
6
|
"bin": {
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"commander": "^12.1.0",
|
|
35
|
+
"glob": "^11.0.0",
|
|
35
36
|
"pino": "^9.5.0",
|
|
36
37
|
"pino-pretty": "^13.0.0"
|
|
37
38
|
},
|
package/src/cli/cli.ts
CHANGED
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
} from "../internal/bunVersion";
|
|
7
7
|
import { logger } from "../internal/logger";
|
|
8
8
|
import { initializeWithGlobalOptions } from "./globalOptions";
|
|
9
|
-
import { defineProjectCommands } from "./projectCommands";
|
|
10
9
|
import { OUTPUT_CONFIG } from "./output";
|
|
10
|
+
import { defineProjectCommands } from "./projectCommands";
|
|
11
11
|
|
|
12
12
|
export interface RunCliOptions {
|
|
13
13
|
argv?: string | string[];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type Command } from "commander";
|
|
2
|
-
import {
|
|
2
|
+
import { BunWorkspacesError } from "../internal/error";
|
|
3
|
+
import { logger, createLogger } from "../internal/logger";
|
|
3
4
|
import type { Project } from "../project";
|
|
4
5
|
import type { Workspace } from "../workspaces";
|
|
5
6
|
|
|
@@ -21,38 +22,62 @@ const createScriptInfoLines = (script: string, workspaces: Workspace[]) => [
|
|
|
21
22
|
...workspaces.map((workspace) => ` - ${workspace.name}`),
|
|
22
23
|
];
|
|
23
24
|
|
|
25
|
+
const createJsonLines = (data: unknown, options: { pretty: boolean }) =>
|
|
26
|
+
JSON.stringify(data, null, options.pretty ? 2 : undefined).split("\n");
|
|
27
|
+
|
|
24
28
|
const listWorkspaces = ({
|
|
25
29
|
program,
|
|
26
30
|
project,
|
|
27
31
|
printLines,
|
|
28
32
|
}: ProjectCommandsContext) => {
|
|
29
33
|
program
|
|
30
|
-
.command("list-workspaces")
|
|
34
|
+
.command("list-workspaces [pattern]")
|
|
31
35
|
.aliases(["ls", "list"])
|
|
32
36
|
.description("List all workspaces")
|
|
33
37
|
.option("--name-only", "Only show workspace names")
|
|
34
|
-
.
|
|
35
|
-
|
|
38
|
+
.option("--json", "Output as JSON")
|
|
39
|
+
.option("--pretty", "Pretty print JSON")
|
|
40
|
+
.action(
|
|
41
|
+
(
|
|
42
|
+
pattern,
|
|
43
|
+
options: { nameOnly: boolean; json: boolean; pretty: boolean },
|
|
44
|
+
) => {
|
|
45
|
+
logger.debug(
|
|
46
|
+
`Command: List workspaces (options: ${JSON.stringify(options)})`,
|
|
47
|
+
);
|
|
36
48
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
const lines: string[] = [];
|
|
50
|
+
|
|
51
|
+
const workspaces = pattern
|
|
52
|
+
? project.findWorkspacesByPattern(pattern)
|
|
53
|
+
: project.workspaces;
|
|
40
54
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
55
|
+
if (options.json) {
|
|
56
|
+
lines.push(
|
|
57
|
+
...createJsonLines(
|
|
58
|
+
options.nameOnly
|
|
59
|
+
? workspaces.map(({ name }) => name)
|
|
60
|
+
: workspaces,
|
|
61
|
+
options,
|
|
62
|
+
),
|
|
63
|
+
);
|
|
45
64
|
} else {
|
|
46
|
-
|
|
65
|
+
workspaces.forEach((workspace) => {
|
|
66
|
+
if (options.nameOnly) {
|
|
67
|
+
lines.push(workspace.name);
|
|
68
|
+
} else {
|
|
69
|
+
lines.push(...createWorkspaceInfoLines(workspace));
|
|
70
|
+
}
|
|
71
|
+
});
|
|
47
72
|
}
|
|
48
|
-
});
|
|
49
73
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
74
|
+
if (!lines.length) {
|
|
75
|
+
lines.push("No workspaces found");
|
|
76
|
+
}
|
|
53
77
|
|
|
54
|
-
|
|
55
|
-
|
|
78
|
+
printLines(...lines);
|
|
79
|
+
},
|
|
80
|
+
);
|
|
56
81
|
};
|
|
57
82
|
|
|
58
83
|
const listScripts = ({
|
|
@@ -64,27 +89,50 @@ const listScripts = ({
|
|
|
64
89
|
.command("list-scripts")
|
|
65
90
|
.description("List all scripts available with their workspaces")
|
|
66
91
|
.option("--name-only", "Only show script names")
|
|
67
|
-
.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
.forEach(({ name, workspaces }) => {
|
|
75
|
-
if (options.nameOnly) {
|
|
76
|
-
lines.push(name);
|
|
77
|
-
} else {
|
|
78
|
-
lines.push(...createScriptInfoLines(name, workspaces));
|
|
79
|
-
}
|
|
80
|
-
});
|
|
92
|
+
.option("--json", "Output as JSON")
|
|
93
|
+
.option("--pretty", "Pretty print JSON")
|
|
94
|
+
.action(
|
|
95
|
+
(options: { nameOnly: boolean; json: boolean; pretty: boolean }) => {
|
|
96
|
+
logger.debug(
|
|
97
|
+
`Command: List scripts (options: ${JSON.stringify(options)})`,
|
|
98
|
+
);
|
|
81
99
|
|
|
82
|
-
|
|
83
|
-
lines
|
|
84
|
-
|
|
100
|
+
const scripts = project.listScriptsWithWorkspaces();
|
|
101
|
+
const lines: string[] = [];
|
|
102
|
+
|
|
103
|
+
if (options.json) {
|
|
104
|
+
lines.push(
|
|
105
|
+
...createJsonLines(
|
|
106
|
+
options.nameOnly
|
|
107
|
+
? Object.keys(scripts)
|
|
108
|
+
: Object.values(scripts).map(({ workspaces, ...rest }) => ({
|
|
109
|
+
...rest,
|
|
110
|
+
workspaces: workspaces.map(({ name }) => name),
|
|
111
|
+
})),
|
|
112
|
+
options,
|
|
113
|
+
),
|
|
114
|
+
);
|
|
115
|
+
} else {
|
|
116
|
+
Object.values(scripts)
|
|
117
|
+
.sort(({ name: nameA }, { name: nameB }) =>
|
|
118
|
+
nameA.localeCompare(nameB),
|
|
119
|
+
)
|
|
120
|
+
.forEach(({ name, workspaces }) => {
|
|
121
|
+
if (options.nameOnly) {
|
|
122
|
+
lines.push(name);
|
|
123
|
+
} else {
|
|
124
|
+
lines.push(...createScriptInfoLines(name, workspaces));
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
if (!lines.length) {
|
|
129
|
+
lines.push("No scripts found");
|
|
130
|
+
}
|
|
131
|
+
}
|
|
85
132
|
|
|
86
|
-
|
|
87
|
-
|
|
133
|
+
printLines(...lines);
|
|
134
|
+
},
|
|
135
|
+
);
|
|
88
136
|
};
|
|
89
137
|
|
|
90
138
|
const workspaceInfo = ({
|
|
@@ -96,17 +144,29 @@ const workspaceInfo = ({
|
|
|
96
144
|
.command("workspace-info <workspace>")
|
|
97
145
|
.aliases(["info"])
|
|
98
146
|
.description("Show information about a workspace")
|
|
99
|
-
.
|
|
100
|
-
|
|
147
|
+
.option("--json", "Output as JSON")
|
|
148
|
+
.option("--pretty", "Pretty print JSON")
|
|
149
|
+
.action(
|
|
150
|
+
(workspaceName: string, options: { json: boolean; pretty: boolean }) => {
|
|
151
|
+
logger.debug(
|
|
152
|
+
`Command: Workspace info for ${workspaceName} (options: ${JSON.stringify(options)})`,
|
|
153
|
+
);
|
|
101
154
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
155
|
+
const workspace = project.findWorkspaceByName(workspaceName);
|
|
156
|
+
if (!workspace) {
|
|
157
|
+
logger.error(
|
|
158
|
+
`Workspace not found: (options: ${JSON.stringify(workspaceName)})`,
|
|
159
|
+
);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
107
162
|
|
|
108
|
-
|
|
109
|
-
|
|
163
|
+
printLines(
|
|
164
|
+
...(options.json
|
|
165
|
+
? createJsonLines(workspace, options)
|
|
166
|
+
: createWorkspaceInfoLines(workspace)),
|
|
167
|
+
);
|
|
168
|
+
},
|
|
169
|
+
);
|
|
110
170
|
};
|
|
111
171
|
|
|
112
172
|
const scriptInfo = ({
|
|
@@ -118,55 +178,80 @@ const scriptInfo = ({
|
|
|
118
178
|
.command("script-info <script>")
|
|
119
179
|
.description("Show information about a script")
|
|
120
180
|
.option("--workspaces-only", "Only show script's workspace names")
|
|
121
|
-
.
|
|
122
|
-
|
|
181
|
+
.option("--json", "Output as JSON")
|
|
182
|
+
.option("--pretty", "Pretty print JSON")
|
|
183
|
+
.action(
|
|
184
|
+
(
|
|
185
|
+
script,
|
|
186
|
+
options: { workspacesOnly: boolean; json: boolean; pretty: boolean },
|
|
187
|
+
) => {
|
|
188
|
+
logger.debug(
|
|
189
|
+
`Command: Script info for ${script} (options: ${JSON.stringify(options)})`,
|
|
190
|
+
);
|
|
123
191
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
192
|
+
const scripts = project.listScriptsWithWorkspaces();
|
|
193
|
+
const scriptMetadata = scripts[script];
|
|
194
|
+
if (!scriptMetadata) {
|
|
195
|
+
printLines(
|
|
196
|
+
`Script not found: ${JSON.stringify(
|
|
197
|
+
script,
|
|
198
|
+
)} (available: ${Object.keys(scripts).join(", ")})`,
|
|
199
|
+
);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
127
202
|
printLines(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
203
|
+
...(options.json
|
|
204
|
+
? createJsonLines(
|
|
205
|
+
options.workspacesOnly
|
|
206
|
+
? scriptMetadata.workspaces.map(({ name }) => name)
|
|
207
|
+
: {
|
|
208
|
+
name: scriptMetadata.name,
|
|
209
|
+
workspaces: scriptMetadata.workspaces.map(
|
|
210
|
+
({ name }) => name,
|
|
211
|
+
),
|
|
212
|
+
},
|
|
213
|
+
options,
|
|
214
|
+
)
|
|
215
|
+
: options.workspacesOnly
|
|
216
|
+
? scriptMetadata.workspaces.map(({ name }) => name)
|
|
217
|
+
: createScriptInfoLines(script, scriptMetadata.workspaces)),
|
|
131
218
|
);
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
printLines(
|
|
135
|
-
...(options.workspacesOnly
|
|
136
|
-
? scriptMetadata.workspaces.map(({ name }) => name)
|
|
137
|
-
: createScriptInfoLines(script, scriptMetadata.workspaces)),
|
|
138
|
-
);
|
|
139
|
-
});
|
|
219
|
+
},
|
|
220
|
+
);
|
|
140
221
|
};
|
|
141
222
|
|
|
142
|
-
const runScript = ({
|
|
143
|
-
program,
|
|
144
|
-
project,
|
|
145
|
-
printLines,
|
|
146
|
-
}: ProjectCommandsContext) => {
|
|
223
|
+
const runScript = ({ program, project }: ProjectCommandsContext) => {
|
|
147
224
|
program
|
|
148
225
|
.command("run <script> [workspaces...]")
|
|
149
226
|
.description("Run a script in all workspaces")
|
|
150
227
|
.option("--parallel", "Run the scripts in parallel")
|
|
151
228
|
.option("--args <args>", "Args to append to the script command", "")
|
|
152
|
-
.action(async (script: string,
|
|
229
|
+
.action(async (script: string, _workspaces: string[], options) => {
|
|
153
230
|
logger.debug(
|
|
154
231
|
`Command: Run script ${JSON.stringify(script)} for ${
|
|
155
|
-
|
|
156
|
-
? "workspaces " +
|
|
232
|
+
_workspaces.length
|
|
233
|
+
? "workspaces " + _workspaces.join(", ")
|
|
157
234
|
: "all workspaces"
|
|
158
235
|
} (parallel: ${!!options.parallel}, method: ${JSON.stringify(
|
|
159
236
|
options.method,
|
|
160
237
|
)}, args: ${JSON.stringify(options.args)})`,
|
|
161
238
|
);
|
|
162
239
|
|
|
163
|
-
workspaces =
|
|
164
|
-
?
|
|
240
|
+
const workspaces = _workspaces.length
|
|
241
|
+
? _workspaces.flatMap((workspacePattern) => {
|
|
242
|
+
if (workspacePattern.includes("*")) {
|
|
243
|
+
return project
|
|
244
|
+
.findWorkspacesByPattern(workspacePattern)
|
|
245
|
+
.filter(({ packageJson: { scripts } }) => scripts?.[script])
|
|
246
|
+
.map(({ name }) => name);
|
|
247
|
+
}
|
|
248
|
+
return [workspacePattern];
|
|
249
|
+
})
|
|
165
250
|
: project.listWorkspacesWithScript(script).map(({ name }) => name);
|
|
166
251
|
|
|
167
252
|
if (!workspaces.length) {
|
|
168
253
|
program.error(
|
|
169
|
-
`No workspaces found for script ${JSON.stringify(script)}`,
|
|
254
|
+
`No ${_workspaces.length ? "matching " : ""}workspaces found for script ${JSON.stringify(script)}`,
|
|
170
255
|
);
|
|
171
256
|
}
|
|
172
257
|
|
|
@@ -190,9 +275,11 @@ const runScript = ({
|
|
|
190
275
|
scriptName,
|
|
191
276
|
workspace,
|
|
192
277
|
}: (typeof scriptCommands)[number]) => {
|
|
278
|
+
const commandLogger = createLogger(`${workspace.name}:${scriptName}`);
|
|
279
|
+
|
|
193
280
|
const splitCommand = command.command.split(/\s+/g);
|
|
194
281
|
|
|
195
|
-
|
|
282
|
+
commandLogger.debug(
|
|
196
283
|
`Running script ${scriptName} in workspace ${workspace.name} (cwd: ${
|
|
197
284
|
command.cwd
|
|
198
285
|
}): ${splitCommand.join(" ")}`,
|
|
@@ -200,21 +287,25 @@ const runScript = ({
|
|
|
200
287
|
|
|
201
288
|
const silent = logger.level === "silent";
|
|
202
289
|
|
|
203
|
-
if (!silent) {
|
|
204
|
-
printLines(
|
|
205
|
-
`Running script ${JSON.stringify(
|
|
206
|
-
scriptName,
|
|
207
|
-
)} in workspace ${JSON.stringify(workspace.name)}`,
|
|
208
|
-
);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
290
|
const proc = Bun.spawn(command.command.split(/\s+/g), {
|
|
212
291
|
cwd: command.cwd,
|
|
213
292
|
env: process.env,
|
|
214
|
-
stdout: silent ? "ignore" : "
|
|
215
|
-
stderr: silent ? "ignore" : "
|
|
293
|
+
stdout: silent ? "ignore" : "pipe",
|
|
294
|
+
stderr: silent ? "ignore" : "pipe",
|
|
216
295
|
});
|
|
217
296
|
|
|
297
|
+
if (proc.stdout) {
|
|
298
|
+
for await (const chunk of proc.stdout) {
|
|
299
|
+
commandLogger.info(new TextDecoder().decode(chunk).trim());
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (proc.stderr) {
|
|
304
|
+
for await (const chunk of proc.stderr) {
|
|
305
|
+
commandLogger.error(new TextDecoder().decode(chunk).trim());
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
218
309
|
await proc.exited;
|
|
219
310
|
|
|
220
311
|
return {
|
|
@@ -222,30 +313,20 @@ const runScript = ({
|
|
|
222
313
|
workspace,
|
|
223
314
|
command,
|
|
224
315
|
success: proc.exitCode === 0,
|
|
316
|
+
error:
|
|
317
|
+
proc.exitCode === 0
|
|
318
|
+
? null
|
|
319
|
+
: new BunWorkspacesError(
|
|
320
|
+
`Script exited with code ${proc.exitCode}`,
|
|
321
|
+
),
|
|
225
322
|
};
|
|
226
323
|
};
|
|
227
324
|
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
const handleResult = ({
|
|
236
|
-
scriptName,
|
|
237
|
-
workspace,
|
|
238
|
-
success,
|
|
239
|
-
}: (typeof scriptCommands)[number] & { success: boolean }) => {
|
|
240
|
-
logger.info(
|
|
241
|
-
`${success ? "✅" : "❌"} ${workspace.name}: ${scriptName}`,
|
|
242
|
-
);
|
|
243
|
-
if (!success) {
|
|
244
|
-
program.error(
|
|
245
|
-
`Script ${scriptName} failed in workspace ${workspace.name}`,
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
};
|
|
325
|
+
const results = [] as {
|
|
326
|
+
success: boolean;
|
|
327
|
+
workspaceName: string;
|
|
328
|
+
error: Error | null;
|
|
329
|
+
}[];
|
|
249
330
|
|
|
250
331
|
if (options.parallel) {
|
|
251
332
|
let i = 0;
|
|
@@ -253,9 +334,17 @@ const runScript = ({
|
|
|
253
334
|
scriptCommands.map(runCommand),
|
|
254
335
|
)) {
|
|
255
336
|
if (result.status === "rejected") {
|
|
256
|
-
|
|
337
|
+
results.push({
|
|
338
|
+
success: false,
|
|
339
|
+
workspaceName: workspaces[i],
|
|
340
|
+
error: result.reason,
|
|
341
|
+
});
|
|
257
342
|
} else {
|
|
258
|
-
|
|
343
|
+
results.push({
|
|
344
|
+
success: result.value.success,
|
|
345
|
+
workspaceName: workspaces[i],
|
|
346
|
+
error: result.value.error,
|
|
347
|
+
});
|
|
259
348
|
}
|
|
260
349
|
i++;
|
|
261
350
|
}
|
|
@@ -264,12 +353,35 @@ const runScript = ({
|
|
|
264
353
|
for (const command of scriptCommands) {
|
|
265
354
|
try {
|
|
266
355
|
const result = await runCommand(command);
|
|
267
|
-
|
|
356
|
+
results.push({
|
|
357
|
+
success: result.success,
|
|
358
|
+
workspaceName: workspaces[i],
|
|
359
|
+
error: result.error,
|
|
360
|
+
});
|
|
268
361
|
} catch (error) {
|
|
269
|
-
|
|
362
|
+
results.push({
|
|
363
|
+
success: false,
|
|
364
|
+
workspaceName: workspaces[i],
|
|
365
|
+
error: error as Error,
|
|
366
|
+
});
|
|
270
367
|
}
|
|
368
|
+
i++;
|
|
271
369
|
}
|
|
272
|
-
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
let failCount = 0;
|
|
373
|
+
results.forEach(({ success, workspaceName }) => {
|
|
374
|
+
if (!success) failCount++;
|
|
375
|
+
logger.info(`${success ? "✅" : "❌"} ${workspaceName}: ${script}`);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
const s = results.length === 1 ? "" : "s";
|
|
379
|
+
if (failCount) {
|
|
380
|
+
const message = `${failCount} of ${results.length} script${s} failed`;
|
|
381
|
+
logger.info(message);
|
|
382
|
+
process.exit(1);
|
|
383
|
+
} else {
|
|
384
|
+
logger.info(`${results.length} script${s} ran successfully`);
|
|
273
385
|
}
|
|
274
386
|
});
|
|
275
387
|
};
|
|
@@ -8,12 +8,14 @@ export const BUILD_BUN_VERSION = rootPackageJson.custom.bunVersion.build;
|
|
|
8
8
|
export const getRequiredBunVersion = (build?: boolean) =>
|
|
9
9
|
build ? BUILD_BUN_VERSION : LIBRARY_CONSUMER_BUN_VERSION;
|
|
10
10
|
|
|
11
|
+
const _Bun = typeof Bun === "undefined" ? ({} as typeof Bun) : Bun;
|
|
12
|
+
|
|
11
13
|
/**
|
|
12
14
|
* Validates that the provided version satisfies the required Bun version
|
|
13
15
|
* specified in the root `package.json`.
|
|
14
16
|
*/
|
|
15
17
|
export const validateBunVersion = (version: string, build?: boolean) =>
|
|
16
|
-
|
|
18
|
+
_Bun ? _Bun.semver.satisfies(version, getRequiredBunVersion(build)) : true;
|
|
17
19
|
|
|
18
20
|
/**
|
|
19
21
|
*
|
|
@@ -21,4 +23,4 @@ export const validateBunVersion = (version: string, build?: boolean) =>
|
|
|
21
23
|
* required Bun version specified in the root `package.json`.
|
|
22
24
|
*/
|
|
23
25
|
export const validateCurrentBunVersion = (build?: boolean) =>
|
|
24
|
-
validateBunVersion(
|
|
26
|
+
validateBunVersion(_Bun?.version, build);
|
package/src/internal/logger.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import createPinoLogger from "pino";
|
|
2
2
|
|
|
3
|
-
export const logger =
|
|
4
|
-
msgPrefix:
|
|
3
|
+
export const logger = createPinoLogger({
|
|
4
|
+
msgPrefix: `[bw] `,
|
|
5
5
|
level:
|
|
6
6
|
process.env.NODE_ENV === "test"
|
|
7
7
|
? "silent"
|
|
@@ -12,6 +12,10 @@ export const logger = createLogger({
|
|
|
12
12
|
target: "pino-pretty",
|
|
13
13
|
options: {
|
|
14
14
|
color: true,
|
|
15
|
+
ignore: "hostname,pid,time",
|
|
15
16
|
},
|
|
16
17
|
},
|
|
17
18
|
});
|
|
19
|
+
|
|
20
|
+
export const createLogger = (prefixContent: string) =>
|
|
21
|
+
logger.child({}, { msgPrefix: `[${prefixContent}] ` });
|
package/src/project/project.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import path from "path";
|
|
2
|
+
import { createWildcardRegex } from "../internal/regex";
|
|
2
3
|
import { findWorkspacesFromPackage, type Workspace } from "../workspaces";
|
|
3
4
|
import { ERRORS } from "./errors";
|
|
4
5
|
import {
|
|
@@ -32,6 +33,7 @@ export interface Project {
|
|
|
32
33
|
listWorkspacesWithScript(scriptName: string): Workspace[];
|
|
33
34
|
listScriptsWithWorkspaces(): Record<string, ScriptMetadata>;
|
|
34
35
|
findWorkspaceByName(workspaceName: string): Workspace | null;
|
|
36
|
+
findWorkspacesByPattern(workspaceName: string): Workspace[];
|
|
35
37
|
createScriptCommand(
|
|
36
38
|
options: CreateProjectScriptCommandOptions,
|
|
37
39
|
): CreateProjectScriptCommandResult;
|
|
@@ -68,6 +70,7 @@ class _Project implements Project {
|
|
|
68
70
|
);
|
|
69
71
|
});
|
|
70
72
|
return Array.from(scripts)
|
|
73
|
+
.sort((a, b) => a.localeCompare(b))
|
|
71
74
|
.map((name) => ({
|
|
72
75
|
name,
|
|
73
76
|
workspaces: this.listWorkspacesWithScript(name),
|
|
@@ -88,6 +91,13 @@ class _Project implements Project {
|
|
|
88
91
|
);
|
|
89
92
|
}
|
|
90
93
|
|
|
94
|
+
/** Accepts wildcard for finding a list of workspaces */
|
|
95
|
+
findWorkspacesByPattern(workspacePattern: string): Workspace[] {
|
|
96
|
+
if (!workspacePattern) return [];
|
|
97
|
+
const regex = createWildcardRegex(workspacePattern);
|
|
98
|
+
return this.workspaces.filter((workspace) => regex.test(workspace.name));
|
|
99
|
+
}
|
|
100
|
+
|
|
91
101
|
createScriptCommand(
|
|
92
102
|
options: CreateProjectScriptCommandOptions,
|
|
93
103
|
): CreateProjectScriptCommandResult {
|
package/src/workspaces/errors.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import { Glob } from "bun";
|
|
4
3
|
import { logger } from "../internal/logger";
|
|
5
4
|
import { ERRORS } from "./errors";
|
|
6
5
|
import {
|
|
@@ -52,8 +51,7 @@ export const findWorkspaces = ({
|
|
|
52
51
|
for (const pattern of workspaceGlobs) {
|
|
53
52
|
if (!validatePattern(pattern)) continue;
|
|
54
53
|
|
|
55
|
-
const
|
|
56
|
-
for (const item of scanWorkspaceGlob(glob, rootDir)) {
|
|
54
|
+
for (const item of scanWorkspaceGlob(pattern, rootDir)) {
|
|
57
55
|
const packageJsonPath = resolvePackageJsonPath(item);
|
|
58
56
|
if (packageJsonPath) {
|
|
59
57
|
const packageJsonContent = resolvePackageJsonContent(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import { Glob } from "
|
|
3
|
+
import { Glob } from "glob";
|
|
4
4
|
import { logger } from "../internal/logger";
|
|
5
5
|
import { ERRORS } from "./errors";
|
|
6
6
|
|
|
@@ -22,12 +22,8 @@ export type ResolvedPackageJsonContent = {
|
|
|
22
22
|
|
|
23
23
|
type UnknownPackageJson = Record<string, unknown>;
|
|
24
24
|
|
|
25
|
-
export const scanWorkspaceGlob = (
|
|
26
|
-
|
|
27
|
-
cwd: rootDir,
|
|
28
|
-
onlyFiles: false,
|
|
29
|
-
absolute: true,
|
|
30
|
-
});
|
|
25
|
+
export const scanWorkspaceGlob = (pattern: string, rootDir: string) =>
|
|
26
|
+
new Glob(pattern, { absolute: true, cwd: rootDir }).iterateSync();
|
|
31
27
|
|
|
32
28
|
const validateJsonRoot = (json: UnknownPackageJson) => {
|
|
33
29
|
if (!json || typeof json !== "object" || Array.isArray(json)) {
|
|
@@ -46,6 +42,18 @@ const validateName = (json: UnknownPackageJson) => {
|
|
|
46
42
|
);
|
|
47
43
|
}
|
|
48
44
|
|
|
45
|
+
if (!json.name.trim()) {
|
|
46
|
+
throw new ERRORS.NoWorkspaceName(
|
|
47
|
+
`Expected package.json to have a non-empty "name" field`,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (json.name.includes("*")) {
|
|
52
|
+
throw new ERRORS.InvalidWorkspaceName(
|
|
53
|
+
`Package name cannot contain the character '*' (workspace: "${json.name}")`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
49
57
|
return json.name;
|
|
50
58
|
};
|
|
51
59
|
|