bun-workspaces 1.0.0-alpha.2 → 1.0.0-alpha.20
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/LICENSE.md +1 -1
- package/README.md +124 -79
- package/bin/cli.js +1 -2
- package/package.json +13 -27
- package/src/cli/createCli.d.ts +19 -0
- package/src/cli/createCli.mjs +99 -0
- package/src/cli/fatalErrorLogger.d.ts +1 -0
- package/src/cli/fatalErrorLogger.mjs +7 -0
- package/src/cli/globalOptions/globalOptions.d.ts +38 -0
- package/src/cli/globalOptions/globalOptions.mjs +120 -0
- package/src/cli/globalOptions/globalOptionsConfig.d.ts +43 -0
- package/src/cli/globalOptions/globalOptionsConfig.mjs +34 -0
- package/src/cli/globalOptions/index.d.ts +2 -0
- package/src/cli/globalOptions/index.mjs +2 -0
- package/src/cli/index.d.ts +3 -0
- package/src/cli/index.mjs +3 -0
- package/src/cli/projectCommands/commandHandlerUtils.d.ts +31 -0
- package/src/cli/projectCommands/commandHandlerUtils.mjs +52 -0
- package/src/cli/projectCommands/handleRunScript.d.ts +5 -0
- package/src/cli/projectCommands/handleRunScript.mjs +153 -0
- package/src/cli/projectCommands/handleSimpleCommands.d.ts +20 -0
- package/src/cli/projectCommands/handleSimpleCommands.mjs +131 -0
- package/src/cli/projectCommands/index.d.ts +2 -0
- package/src/cli/projectCommands/index.mjs +2 -0
- package/src/cli/projectCommands/projectCommands.d.ts +4 -0
- package/src/cli/projectCommands/projectCommands.mjs +19 -0
- package/src/cli/projectCommands/projectCommandsConfig.d.ts +218 -0
- package/src/cli/projectCommands/projectCommandsConfig.mjs +110 -0
- package/src/config/bunWorkspacesConfig.d.ts +17 -0
- package/src/config/bunWorkspacesConfig.mjs +50 -0
- package/src/config/configFile.d.ts +8 -0
- package/src/config/configFile.mjs +43 -0
- package/src/config/errors.d.ts +3 -0
- package/src/config/errors.mjs +10 -0
- package/src/config/{index.ts → index.d.ts} +1 -0
- package/src/config/index.mjs +11 -0
- package/src/config/workspaceConfig/errors.d.ts +3 -0
- package/src/config/workspaceConfig/errors.mjs +9 -0
- package/src/config/workspaceConfig/index.d.ts +4 -0
- package/src/config/workspaceConfig/index.mjs +4 -0
- package/src/config/workspaceConfig/loadWorkspaceConfig.d.ts +5 -0
- package/src/config/workspaceConfig/loadWorkspaceConfig.mjs +82 -0
- package/src/config/workspaceConfig/workspaceConfig.d.ts +14 -0
- package/src/config/workspaceConfig/workspaceConfig.mjs +48 -0
- package/src/config/workspaceConfig/workspaceConfigLocation.d.ts +2 -0
- package/src/config/workspaceConfig/workspaceConfigLocation.mjs +5 -0
- package/src/index.d.ts +23 -0
- package/src/index.mjs +9 -0
- package/src/internal/asyncIterableQueue.d.ts +15 -0
- package/src/internal/asyncIterableQueue.mjs +73 -0
- package/src/internal/bunVersion.d.ts +17 -0
- package/src/internal/bunVersion.mjs +28 -0
- package/src/internal/env.d.ts +5 -0
- package/src/internal/env.mjs +29 -0
- package/src/internal/error.d.ts +9 -0
- package/src/internal/{error.ts → error.mjs} +7 -16
- package/src/internal/json.d.ts +9 -0
- package/src/internal/json.mjs +6 -0
- package/src/internal/logger.d.ts +44 -0
- package/src/internal/logger.mjs +110 -0
- package/src/internal/mergeAsyncIterables.d.ts +5 -0
- package/src/internal/mergeAsyncIterables.mjs +27 -0
- package/src/internal/optionalArray.d.ts +15 -0
- package/src/internal/optionalArray.mjs +8 -0
- package/src/internal/os.d.ts +4 -0
- package/src/internal/os.mjs +7 -0
- package/src/internal/regex.d.ts +3 -0
- package/src/internal/regex.mjs +10 -0
- package/src/internal/types.d.ts +6 -0
- package/src/internal/types.mjs +3 -0
- package/src/project/errors.d.ts +3 -0
- package/src/project/errors.mjs +9 -0
- package/src/project/implementations/fileSystemProject.d.ts +88 -0
- package/src/project/implementations/fileSystemProject.mjs +152 -0
- package/src/project/implementations/memoryProject.d.ts +32 -0
- package/src/project/implementations/memoryProject.mjs +46 -0
- package/src/project/implementations/projectBase.d.ts +27 -0
- package/src/project/implementations/projectBase.mjs +97 -0
- package/src/project/index.d.ts +6 -0
- package/src/project/index.mjs +5 -0
- package/src/project/project.d.ts +64 -0
- package/src/project/project.mjs +6 -0
- package/src/project/runScript/index.d.ts +3 -0
- package/src/project/runScript/index.mjs +3 -0
- package/src/project/runScript/runScript.d.ts +41 -0
- package/src/project/runScript/runScript.mjs +63 -0
- package/src/project/runScript/runScripts.d.ts +47 -0
- package/src/project/runScript/runScripts.mjs +95 -0
- package/src/project/runScript/scriptCommand.d.ts +33 -0
- package/src/project/runScript/scriptCommand.mjs +19 -0
- package/src/project/runScript/scriptRuntimeMetadata.d.ts +73 -0
- package/src/project/runScript/scriptRuntimeMetadata.mjs +56 -0
- package/src/workspaces/errors.d.ts +12 -0
- package/src/workspaces/{errors.ts → errors.mjs} +5 -2
- package/src/workspaces/findWorkspaces.d.ts +20 -0
- package/src/workspaces/findWorkspaces.mjs +147 -0
- package/src/workspaces/index.d.ts +4 -0
- package/src/workspaces/index.mjs +3 -0
- package/src/workspaces/packageJson.d.ts +15 -0
- package/src/workspaces/packageJson.mjs +134 -0
- package/src/workspaces/{workspace.ts → workspace.d.ts} +5 -6
- package/src/workspaces/workspace.mjs +2 -0
- package/bun.lock +0 -576
- package/src/cli/cli.ts +0 -87
- package/src/cli/globalOptions.ts +0 -122
- package/src/cli/index.ts +0 -1
- package/src/cli/projectCommands.ts +0 -390
- package/src/config/bunWorkspacesConfig.ts +0 -62
- package/src/config/configFile.ts +0 -33
- package/src/index.ts +0 -3
- package/src/internal/bunVersion.ts +0 -26
- package/src/internal/env.ts +0 -25
- package/src/internal/logger.ts +0 -187
- package/src/internal/regex.ts +0 -5
- package/src/project/errors.ts +0 -6
- package/src/project/index.ts +0 -6
- package/src/project/project.ts +0 -155
- package/src/project/scriptCommand.ts +0 -40
- package/src/workspaces/findWorkspaces.ts +0 -137
- package/src/workspaces/index.ts +0 -7
- package/src/workspaces/packageJson.ts +0 -166
- package/tsconfig.json +0 -28
package/LICENSE.md
CHANGED
package/README.md
CHANGED
|
@@ -1,113 +1,158 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
This is a CLI meant to help manage [Bun workspaces](https://bun.sh/docs/install/workspaces).
|
|
1
|
+
<img src="./packages/doc-website/src/docs/public/bw-eye.png" alt="bun-workspaces" width="50" />
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
# bun-workspaces
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
### [**See Full Documentation Here:** _https://bunworkspaces.com_](https://bunworkspaces.com)
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
$ bun add --dev bun-workspaces
|
|
11
|
-
$ bunx bun-workspaces --help
|
|
12
|
-
```
|
|
7
|
+
**_New: [An API is now officially released!](https://bunworkspaces.com/api)_**
|
|
13
8
|
|
|
14
|
-
|
|
9
|
+
This is a CLI and API that help you manage your monorepo on top of native [Bun workspaces](https://bun.sh/docs/install/workspaces), with no additional setup required. Get metadata about your workspaces and scripts, and run scripts across your workspaces.
|
|
15
10
|
|
|
16
|
-
|
|
11
|
+
<a href="https://buymeacoffee.com/scottmorse">
|
|
12
|
+
<img src="./packages/doc-website/src/docs/public/bmac-logo-circle.png" alt="Link to Buy Me A Coffee" width="60" />
|
|
13
|
+
</a>
|
|
17
14
|
|
|
18
|
-
|
|
15
|
+
## Quick Start
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
Installation:
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"app-a": "@my-org/application-a",
|
|
28
|
-
"app-b": "@my-org/application-b"
|
|
29
|
-
},
|
|
30
|
-
"cli": {
|
|
31
|
-
"logLevel": "warn"
|
|
32
|
-
}
|
|
33
|
-
}
|
|
19
|
+
```bash
|
|
20
|
+
$ # Install to use the API and/or lock your CLI version for your project
|
|
21
|
+
$ bun add --dev bun-workspaces
|
|
22
|
+
$ # Start using the CLI with or without the installation step
|
|
23
|
+
$ bunx bun-workspaces --help
|
|
34
24
|
```
|
|
35
25
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
### Examples
|
|
26
|
+
### CLI
|
|
39
27
|
|
|
40
|
-
|
|
28
|
+
[Full CLI documentation here](https://bunworkspaces.com/cli)
|
|
41
29
|
|
|
42
30
|
```bash
|
|
43
|
-
alias bw="bunx bun-workspaces"
|
|
31
|
+
alias bw="bunx bun-workspaces" # can place in .zshrc, .bashrc, or similar
|
|
44
32
|
|
|
45
|
-
# List all workspaces
|
|
33
|
+
# List all workspaces in your project
|
|
46
34
|
bw list-workspaces
|
|
47
|
-
bw ls
|
|
48
35
|
|
|
49
|
-
#
|
|
50
|
-
bw
|
|
36
|
+
# ls is an alias for list-workspaces
|
|
37
|
+
bw ls --json --pretty # Output as formatted JSON
|
|
51
38
|
|
|
52
|
-
#
|
|
53
|
-
|
|
39
|
+
# Run the lint script for all workspaces
|
|
40
|
+
# that have it in their "scripts" field
|
|
41
|
+
bw run-script lint
|
|
54
42
|
|
|
55
|
-
#
|
|
56
|
-
bw
|
|
43
|
+
# run is an alias for run-script
|
|
44
|
+
bw run lint my-workspace # Run for a single workspace
|
|
45
|
+
bw run lint my-workspace-a my-workspace-b # Run for multiple workspaces
|
|
46
|
+
bw run lint "my-workspace-*" # Run for matching workspace names
|
|
47
|
+
bw run lint --parallel # Run at the same time
|
|
48
|
+
bw run lint --args="--my-appended-args" # Add args to each script call
|
|
49
|
+
bw run lint --args="--my-arg=<workspaceName>" # Use the workspace name in args
|
|
57
50
|
|
|
58
|
-
#
|
|
59
|
-
bw
|
|
51
|
+
# Run an inline command from the workspace directory
|
|
52
|
+
bw run "echo 'this is my inline script for <workspaceName>'" --inline
|
|
60
53
|
|
|
61
|
-
#
|
|
62
|
-
bw
|
|
63
|
-
bw
|
|
64
|
-
|
|
65
|
-
# Get info about a script
|
|
66
|
-
bw script-info my-script
|
|
54
|
+
# Show usage (you can pass --help to any command)
|
|
55
|
+
bw help
|
|
56
|
+
bw --help
|
|
67
57
|
|
|
68
|
-
#
|
|
69
|
-
bw
|
|
58
|
+
# Pass --cwd to any command
|
|
59
|
+
bw --cwd=/path/to/your/project ls
|
|
60
|
+
bw --cwd=/path/to/your/project run my-script
|
|
70
61
|
|
|
71
|
-
#
|
|
72
|
-
bw
|
|
73
|
-
|
|
74
|
-
bw workspace-info my-workspace --json
|
|
75
|
-
bw script-info my-script --json
|
|
62
|
+
# Pass --log-level to any command (debug, info, warn, error, or silent)
|
|
63
|
+
bw --log-level=silent run my-script
|
|
64
|
+
```
|
|
76
65
|
|
|
77
|
-
|
|
78
|
-
# workspaces that have it
|
|
79
|
-
# in their `scripts` field
|
|
80
|
-
bw run my-script
|
|
66
|
+
### API
|
|
81
67
|
|
|
82
|
-
|
|
83
|
-
bw run my-script my-workspace
|
|
68
|
+
[Full API documentation here](https://bunworkspaces.com/api)
|
|
84
69
|
|
|
85
|
-
|
|
86
|
-
|
|
70
|
+
```typescript
|
|
71
|
+
import { createFileSystemProject } from "bun-workspaces";
|
|
87
72
|
|
|
88
|
-
|
|
89
|
-
|
|
73
|
+
// A Project contains the core functionality of bun-workspaces.
|
|
74
|
+
const project = createFileSystemProject({
|
|
75
|
+
rootDirectory: "path/to/your/project",
|
|
76
|
+
});
|
|
90
77
|
|
|
91
|
-
|
|
92
|
-
|
|
78
|
+
// A Workspace that matches the name or alias "my-workspace"
|
|
79
|
+
const myWorkspace = project.findWorkspaceByNameOrAlias("my-workspace");
|
|
93
80
|
|
|
94
|
-
|
|
95
|
-
|
|
81
|
+
// Array of workspaces whose names match the wildcard pattern
|
|
82
|
+
const wildcardWorkspaces = project.findWorkspacesByPattern("my-workspace-*");
|
|
96
83
|
|
|
97
|
-
|
|
98
|
-
|
|
84
|
+
// Array of workspaces that have "my-script" in their package.json "scripts"
|
|
85
|
+
const workspacesWithScript = project.listWorkspacesWithScript("my-script");
|
|
99
86
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
87
|
+
// Run a script in a workspace
|
|
88
|
+
const runSingleScript = async () => {
|
|
89
|
+
const { output, exit } = project.runWorkspaceScript({
|
|
90
|
+
workspaceNameOrAlias: "my-workspace",
|
|
91
|
+
script: "my-script",
|
|
92
|
+
args: "--my --appended --args", // optional, arguments to add to the command
|
|
93
|
+
});
|
|
103
94
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
95
|
+
// Get a stream of the script subprocess's output
|
|
96
|
+
for await (const { text, textNoAnsi, streamName } of output) {
|
|
97
|
+
console.log(text); // The output chunk's content (string)
|
|
98
|
+
console.log(textNoAnsi); // Text with ANSI codes sanitized (string)
|
|
99
|
+
console.log(streamName); // The output stream, "stdout" or "stderr"
|
|
100
|
+
}
|
|
107
101
|
|
|
108
|
-
|
|
109
|
-
|
|
102
|
+
// Get data about the script execution after it exits
|
|
103
|
+
const exitResult = await exit;
|
|
104
|
+
|
|
105
|
+
console.log(exitResult.exitCode); // The exit code (number)
|
|
106
|
+
console.log(exitResult.signal); // The exit signal (string), or null
|
|
107
|
+
console.log(exitResult.success); // true if exit code was 0
|
|
108
|
+
console.log(exitResult.startTimeISO); // Start time (string)
|
|
109
|
+
console.log(exitResult.endTimeISO); // End time (string)
|
|
110
|
+
console.log(exitResult.durationMs); // Duration in milliseconds (number)
|
|
111
|
+
console.log(exitResult.metadata.workspace); // The target workspace (Workspace)
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Run a script in all workspaces that have it in their package.json "scripts" field
|
|
115
|
+
const runManyScripts = async () => {
|
|
116
|
+
const { output, summary } = project.runScriptAcrossWorkspaces({
|
|
117
|
+
workspacePatterns: ["*"], // this will run in all workspaces that have my-script
|
|
118
|
+
script: "my-script", // the package.json "scripts" field name to run
|
|
119
|
+
args: "--my --appended --args", // optional, arguments to add to the command
|
|
120
|
+
parallel: true, // optional, run the scripts in parallel
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Get a stream of script output
|
|
124
|
+
for await (const { outputChunk, scriptMetadata } of output) {
|
|
125
|
+
console.log(outputChunk.text); // the output chunk's content (string)
|
|
126
|
+
console.log(outputChunk.textNoAnsi); // text with ANSI codes sanitized (string)
|
|
127
|
+
console.log(outputChunk.streamName); // "stdout" or "stderr"
|
|
128
|
+
|
|
129
|
+
// The metadata can distinguish which workspace script
|
|
130
|
+
// the current output chunk came from
|
|
131
|
+
console.log(scriptMetadata.workspace); // Workspace object
|
|
132
|
+
}
|
|
110
133
|
|
|
111
|
-
|
|
112
|
-
|
|
134
|
+
// Get final summary data and script exit details after all scripts have completed
|
|
135
|
+
const summaryResult = await summary;
|
|
136
|
+
|
|
137
|
+
console.log(summaryResult.totalCount); // Total number of scripts
|
|
138
|
+
console.log(summaryResult.allSuccess); // true if all scripts succeeded
|
|
139
|
+
console.log(summaryResult.successCount); // Number of scripts that succeeded
|
|
140
|
+
console.log(summaryResult.failureCount); // Number of scripts that failed
|
|
141
|
+
console.log(summaryResult.startTimeISO); // Start time (string)
|
|
142
|
+
console.log(summaryResult.endTimeISO); // End time (string)
|
|
143
|
+
console.log(summaryResult.durationMs); // Total duration in milliseconds (number)
|
|
144
|
+
|
|
145
|
+
// The exit details of each workspace script
|
|
146
|
+
for (const exitResult of summaryResult.scriptResults) {
|
|
147
|
+
console.log(exitResult.exitCode); // The exit code (number)
|
|
148
|
+
console.log(exitResult.signal); // The exit signal (string), or null
|
|
149
|
+
console.log(exitResult.success); // true if exit code was 0
|
|
150
|
+
console.log(exitResult.startTimeISO); // Start time (ISO string)
|
|
151
|
+
console.log(exitResult.endTimeISO); // End time (ISO string)
|
|
152
|
+
console.log(exitResult.durationMs); // Duration in milliseconds (number)
|
|
153
|
+
console.log(exitResult.metadata.workspace); // The target workspace (Workspace)
|
|
154
|
+
}
|
|
155
|
+
};
|
|
113
156
|
```
|
|
157
|
+
|
|
158
|
+
_`bun-workspaces` is independent from the [Bun](https://bun.sh) project and is not affiliated with or endorsed by Oven. This project aims to enhance enhance the experience of Bun for its users._
|
package/bin/cli.js
CHANGED
package/package.json
CHANGED
|
@@ -1,40 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bun-workspaces",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "1.0.0-alpha.20",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"main": "src/index.mjs",
|
|
6
|
+
"types": "src/index.d.ts",
|
|
7
|
+
"homepage": "https://bunworkspaces.com",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/ScottMorse/bun-workspaces.git"
|
|
11
|
+
},
|
|
6
12
|
"bin": {
|
|
7
|
-
"bun-workspaces": "bin/cli.js"
|
|
13
|
+
"bun-workspaces": "bin/cli.js",
|
|
14
|
+
"bw": "bin/cli.js"
|
|
8
15
|
},
|
|
9
16
|
"custom": {
|
|
10
17
|
"bunVersion": {
|
|
11
|
-
"build": "1.
|
|
18
|
+
"build": "1.3.1",
|
|
12
19
|
"libraryConsumer": "^1.1.x"
|
|
13
20
|
}
|
|
14
21
|
},
|
|
15
|
-
"scripts": {
|
|
16
|
-
"cli": "bun run bin/cli.js",
|
|
17
|
-
"cli:dev": "_BW_RUNTIME_MODE=development bun run bin/cli.js",
|
|
18
|
-
"type-check": "tsc --noEmit",
|
|
19
|
-
"lint": "eslint .",
|
|
20
|
-
"format": "prettier --write .",
|
|
21
|
-
"format-check": "prettier --check ."
|
|
22
|
-
},
|
|
23
|
-
"devDependencies": {
|
|
24
|
-
"@types/bun": "^1.2.22",
|
|
25
|
-
"@typescript-eslint/eslint-plugin": "^8.44.1",
|
|
26
|
-
"@typescript-eslint/parser": "^8.44.1",
|
|
27
|
-
"bun-workspaces": "file:.",
|
|
28
|
-
"eslint": "^9.36.0",
|
|
29
|
-
"eslint-plugin-import": "^2.32.0",
|
|
30
|
-
"prettier": "^3.6.2",
|
|
31
|
-
"typescript-eslint": "^8.44.1"
|
|
32
|
-
},
|
|
33
22
|
"dependencies": {
|
|
34
23
|
"commander": "^12.1.0",
|
|
35
|
-
"glob": "^11.0
|
|
36
|
-
},
|
|
37
|
-
"peerDependencies": {
|
|
38
|
-
"typescript": "^5.9.2"
|
|
24
|
+
"glob": "^11.1.0"
|
|
39
25
|
}
|
|
40
26
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Command } from "commander";
|
|
2
|
+
export interface RunCliOptions {
|
|
3
|
+
argv?: string | string[];
|
|
4
|
+
/** Should be `true` if args do not include the binary name (e.g. `bunx bun-workspaces`) */
|
|
5
|
+
programmatic?: true;
|
|
6
|
+
}
|
|
7
|
+
export interface CLI {
|
|
8
|
+
run: (options?: RunCliOptions) => Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export interface CreateCliOptions {
|
|
11
|
+
handleError?: (error: Error) => void;
|
|
12
|
+
postInit?: (program: Command) => unknown;
|
|
13
|
+
defaultCwd?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const createCli: ({
|
|
16
|
+
handleError,
|
|
17
|
+
postInit,
|
|
18
|
+
defaultCwd,
|
|
19
|
+
}?: CreateCliOptions) => CLI;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { createCommand } from "commander";
|
|
2
|
+
import package_0 from "../../package.json";
|
|
3
|
+
import {
|
|
4
|
+
getRequiredBunVersion,
|
|
5
|
+
validateCurrentBunVersion,
|
|
6
|
+
} from "../internal/bunVersion.mjs";
|
|
7
|
+
import { BunWorkspacesError } from "../internal/error.mjs";
|
|
8
|
+
import { logger } from "../internal/logger.mjs";
|
|
9
|
+
import { fatalErrorLogger } from "./fatalErrorLogger.mjs";
|
|
10
|
+
import { initializeWithGlobalOptions } from "./globalOptions/index.mjs";
|
|
11
|
+
import { defineProjectCommands } from "./projectCommands/index.mjs"; // CONCATENATED MODULE: external "commander"
|
|
12
|
+
// CONCATENATED MODULE: external "../../package.json"
|
|
13
|
+
// CONCATENATED MODULE: external "../internal/bunVersion.mjs"
|
|
14
|
+
// CONCATENATED MODULE: external "../internal/error.mjs"
|
|
15
|
+
// CONCATENATED MODULE: external "../internal/logger.mjs"
|
|
16
|
+
// CONCATENATED MODULE: external "./fatalErrorLogger.mjs"
|
|
17
|
+
// CONCATENATED MODULE: external "./globalOptions/index.mjs"
|
|
18
|
+
// CONCATENATED MODULE: external "./projectCommands/index.mjs"
|
|
19
|
+
// CONCATENATED MODULE: ./src/cli/createCli.ts
|
|
20
|
+
|
|
21
|
+
const createCli = ({
|
|
22
|
+
handleError,
|
|
23
|
+
postInit,
|
|
24
|
+
defaultCwd = process.cwd(),
|
|
25
|
+
} = {}) => {
|
|
26
|
+
const run = async ({ argv = process.argv, programmatic } = {}) => {
|
|
27
|
+
const errorListener =
|
|
28
|
+
handleError ??
|
|
29
|
+
((error) => {
|
|
30
|
+
fatalErrorLogger.error(error);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
});
|
|
33
|
+
process.on("unhandledRejection", errorListener);
|
|
34
|
+
try {
|
|
35
|
+
const program = createCommand("bunx bun-workspaces")
|
|
36
|
+
.description("A CLI on top of native Bun workspaces")
|
|
37
|
+
.version(package_0.version)
|
|
38
|
+
.showHelpAfterError(true);
|
|
39
|
+
postInit?.(program);
|
|
40
|
+
if (!validateCurrentBunVersion()) {
|
|
41
|
+
fatalErrorLogger.error(
|
|
42
|
+
`Bun version mismatch. Required: ${getRequiredBunVersion()}, Found: ${Bun.version}`,
|
|
43
|
+
);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
const args = tempFixCamelCaseOptions(
|
|
47
|
+
typeof argv === "string" ? argv.split(/s+/) : argv,
|
|
48
|
+
);
|
|
49
|
+
const { project, error } = initializeWithGlobalOptions(
|
|
50
|
+
program,
|
|
51
|
+
args,
|
|
52
|
+
defaultCwd,
|
|
53
|
+
);
|
|
54
|
+
defineProjectCommands({
|
|
55
|
+
program,
|
|
56
|
+
project,
|
|
57
|
+
projectError: error,
|
|
58
|
+
});
|
|
59
|
+
await program.parseAsync(args, {
|
|
60
|
+
from: programmatic ? "user" : "node",
|
|
61
|
+
});
|
|
62
|
+
if (error) throw error;
|
|
63
|
+
} catch (error) {
|
|
64
|
+
if (error instanceof BunWorkspacesError) {
|
|
65
|
+
logger.debug(error);
|
|
66
|
+
fatalErrorLogger.error(error.message);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
} else {
|
|
69
|
+
errorListener(error);
|
|
70
|
+
}
|
|
71
|
+
} finally {
|
|
72
|
+
process.off("unhandledRejection", errorListener);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
return {
|
|
76
|
+
run,
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* @todo
|
|
81
|
+
* ! Temp backwards support for deprecated camel case options
|
|
82
|
+
* ! Added October 2025, drop support in some reasonable future release
|
|
83
|
+
*/ const tempOptions = {
|
|
84
|
+
"--nameOnly": "--name-only",
|
|
85
|
+
"--noPrefix": "--no-prefix",
|
|
86
|
+
"--configFile": "--config-file",
|
|
87
|
+
"--logLevel": "--log-level",
|
|
88
|
+
};
|
|
89
|
+
const tempFixCamelCaseOptions = (args) =>
|
|
90
|
+
args.map((arg) => {
|
|
91
|
+
for (const [camel, kebab] of Object.entries(tempOptions)) {
|
|
92
|
+
if (arg.startsWith(camel)) {
|
|
93
|
+
return arg.replace(camel, kebab);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return arg;
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
export { createCli };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const fatalErrorLogger: import("../internal/logger").Logger;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createLogger } from "../internal/logger.mjs"; // CONCATENATED MODULE: external "../internal/logger.mjs"
|
|
2
|
+
// CONCATENATED MODULE: ./src/cli/fatalErrorLogger.ts
|
|
3
|
+
|
|
4
|
+
const fatalErrorLogger = createLogger("fatalError");
|
|
5
|
+
fatalErrorLogger.printLevel = "error";
|
|
6
|
+
|
|
7
|
+
export { fatalErrorLogger };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type Command } from "commander";
|
|
2
|
+
export declare const initializeWithGlobalOptions: (
|
|
3
|
+
program: Command,
|
|
4
|
+
args: string[],
|
|
5
|
+
defaultCwd: string,
|
|
6
|
+
) => {
|
|
7
|
+
project: import("../../internal/types").Simplify<{
|
|
8
|
+
readonly rootDirectory: string;
|
|
9
|
+
readonly workspaces: import("../..").Workspace[];
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly sourceType: "fileSystem";
|
|
12
|
+
runWorkspaceScript(
|
|
13
|
+
options: import("../..").RunWorkspaceScriptOptions,
|
|
14
|
+
): import("../..").RunWorkspaceScriptResult;
|
|
15
|
+
runScriptAcrossWorkspaces(
|
|
16
|
+
options: import("../..").RunScriptAcrossWorkspacesOptions,
|
|
17
|
+
): import("../..").RunScriptAcrossWorkspacesResult;
|
|
18
|
+
listWorkspacesWithScript(scriptName: string): import("../..").Workspace[];
|
|
19
|
+
mapScriptsToWorkspaces(): Record<
|
|
20
|
+
string,
|
|
21
|
+
import("../..").WorkspaceScriptMetadata
|
|
22
|
+
>;
|
|
23
|
+
findWorkspaceByName(
|
|
24
|
+
workspaceName: string,
|
|
25
|
+
): import("../..").Workspace | null;
|
|
26
|
+
findWorkspaceByAlias(alias: string): import("../..").Workspace | null;
|
|
27
|
+
findWorkspaceByNameOrAlias(
|
|
28
|
+
nameOrAlias: string,
|
|
29
|
+
): import("../..").Workspace | null;
|
|
30
|
+
findWorkspacesByPattern(
|
|
31
|
+
workspacePattern: string,
|
|
32
|
+
): import("../..").Workspace[];
|
|
33
|
+
createScriptCommand(
|
|
34
|
+
options: import("../..").CreateProjectScriptCommandOptions,
|
|
35
|
+
): import("../..").CreateProjectScriptCommandResult;
|
|
36
|
+
}>;
|
|
37
|
+
error: Error | null;
|
|
38
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import node_fs from "node:fs";
|
|
2
|
+
import node_path from "node:path";
|
|
3
|
+
import { Option } from "commander";
|
|
4
|
+
import {
|
|
5
|
+
DEFAULT_CONFIG_FILE_PATH,
|
|
6
|
+
loadConfigFile,
|
|
7
|
+
} from "../../config/index.mjs";
|
|
8
|
+
import { defineErrors } from "../../internal/error.mjs";
|
|
9
|
+
import { logger } from "../../internal/logger.mjs";
|
|
10
|
+
import {
|
|
11
|
+
_internalCreateFileSystemProject,
|
|
12
|
+
createMemoryProject,
|
|
13
|
+
} from "../../project/index.mjs";
|
|
14
|
+
import { getCliGlobalOptionConfig } from "./globalOptionsConfig.mjs"; // CONCATENATED MODULE: external "node:fs"
|
|
15
|
+
// CONCATENATED MODULE: external "node:path"
|
|
16
|
+
// CONCATENATED MODULE: external "commander"
|
|
17
|
+
// CONCATENATED MODULE: external "../../config/index.mjs"
|
|
18
|
+
// CONCATENATED MODULE: external "../../internal/error.mjs"
|
|
19
|
+
// CONCATENATED MODULE: external "../../internal/logger.mjs"
|
|
20
|
+
// CONCATENATED MODULE: external "../../project/index.mjs"
|
|
21
|
+
// CONCATENATED MODULE: external "./globalOptionsConfig.mjs"
|
|
22
|
+
// CONCATENATED MODULE: ./src/cli/globalOptions/globalOptions.ts
|
|
23
|
+
|
|
24
|
+
const ERRORS = defineErrors(
|
|
25
|
+
"WorkingDirectoryNotFound",
|
|
26
|
+
"WorkingDirectoryNotADirectory",
|
|
27
|
+
);
|
|
28
|
+
const addGlobalOption = (program, optionName, defaultOverride) => {
|
|
29
|
+
const { mainOption, shortOption, description, param, values, defaultValue } =
|
|
30
|
+
getCliGlobalOptionConfig(optionName);
|
|
31
|
+
let option = new Option(
|
|
32
|
+
`${shortOption} ${mainOption}${param ? ` <${param}>` : ""}`,
|
|
33
|
+
description,
|
|
34
|
+
);
|
|
35
|
+
const effectiveDefaultValue = defaultOverride ?? defaultValue;
|
|
36
|
+
if (effectiveDefaultValue) {
|
|
37
|
+
option = option.default(effectiveDefaultValue);
|
|
38
|
+
}
|
|
39
|
+
if (values?.length) {
|
|
40
|
+
option = option.choices(values);
|
|
41
|
+
}
|
|
42
|
+
program.addOption(option);
|
|
43
|
+
};
|
|
44
|
+
const getWorkingDirectoryFromArgs = (program, args, defaultCwd) => {
|
|
45
|
+
addGlobalOption(program, "cwd", defaultCwd);
|
|
46
|
+
program.parseOptions(args);
|
|
47
|
+
return program.opts().cwd;
|
|
48
|
+
};
|
|
49
|
+
const getConfigFileFromArgs = (program, args) => {
|
|
50
|
+
addGlobalOption(program, "configFile");
|
|
51
|
+
program.parseOptions(args);
|
|
52
|
+
return program.opts().configFile;
|
|
53
|
+
};
|
|
54
|
+
const defineGlobalOptions = (program, args, defaultCwd) => {
|
|
55
|
+
const cwd = getWorkingDirectoryFromArgs(program, args, defaultCwd);
|
|
56
|
+
if (!node_fs.existsSync(cwd)) {
|
|
57
|
+
throw new ERRORS.WorkingDirectoryNotFound(
|
|
58
|
+
`Working directory not found at path "${cwd}"`,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
if (!node_fs.statSync(cwd).isDirectory()) {
|
|
62
|
+
throw new ERRORS.WorkingDirectoryNotADirectory(
|
|
63
|
+
`Working directory is not a directory at path "${cwd}"`,
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
const configFilePath = getConfigFileFromArgs(program, args);
|
|
67
|
+
const config = loadConfigFile(configFilePath, cwd);
|
|
68
|
+
if (config) {
|
|
69
|
+
logger.warn(
|
|
70
|
+
// TODO link to docs
|
|
71
|
+
`Using the config file at ${configFilePath || DEFAULT_CONFIG_FILE_PATH} is deprecated. Migrate to the new workspace config file.`,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
addGlobalOption(program, "logLevel");
|
|
75
|
+
return {
|
|
76
|
+
cwd,
|
|
77
|
+
config,
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
const applyGlobalOptions = (options, config) => {
|
|
81
|
+
logger.printLevel = options.logLevel;
|
|
82
|
+
logger.debug("Log level: " + options.logLevel);
|
|
83
|
+
let project;
|
|
84
|
+
let error = null;
|
|
85
|
+
try {
|
|
86
|
+
project = _internalCreateFileSystemProject({
|
|
87
|
+
rootDirectory: options.cwd,
|
|
88
|
+
workspaceAliases: config?.project?.workspaceAliases ?? {},
|
|
89
|
+
});
|
|
90
|
+
logger.debug(
|
|
91
|
+
`Project: ${JSON.stringify(project.name)} (${project.workspaces.length} workspace${project.workspaces.length === 1 ? "" : "s"})`,
|
|
92
|
+
);
|
|
93
|
+
logger.debug("Project root: " + node_path.resolve(project.rootDirectory));
|
|
94
|
+
} catch (_error) {
|
|
95
|
+
error = _error;
|
|
96
|
+
project = createMemoryProject({
|
|
97
|
+
workspaces: [],
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
project,
|
|
102
|
+
error,
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
const initializeWithGlobalOptions = (program, args, defaultCwd) => {
|
|
106
|
+
program.allowUnknownOption(true);
|
|
107
|
+
const { cwd, config } = defineGlobalOptions(program, args, defaultCwd);
|
|
108
|
+
program.parseOptions(args);
|
|
109
|
+
program.allowUnknownOption(false);
|
|
110
|
+
const options = program.opts();
|
|
111
|
+
return applyGlobalOptions(
|
|
112
|
+
{
|
|
113
|
+
...options,
|
|
114
|
+
cwd,
|
|
115
|
+
},
|
|
116
|
+
config,
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export { initializeWithGlobalOptions };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type LogLevelSetting } from "../../internal/logger";
|
|
2
|
+
export interface CliGlobalOptions {
|
|
3
|
+
logLevel: LogLevelSetting;
|
|
4
|
+
cwd: string;
|
|
5
|
+
configFile?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface CliGlobalOptionConfig {
|
|
8
|
+
mainOption: string;
|
|
9
|
+
shortOption: string;
|
|
10
|
+
description: string;
|
|
11
|
+
defaultValue: string;
|
|
12
|
+
values: LogLevelSetting[] | null;
|
|
13
|
+
param: string;
|
|
14
|
+
}
|
|
15
|
+
export type CliGlobalOptionName = keyof CliGlobalOptions;
|
|
16
|
+
export declare const getCliGlobalOptionConfig: (
|
|
17
|
+
optionName: CliGlobalOptionName,
|
|
18
|
+
) =>
|
|
19
|
+
| {
|
|
20
|
+
readonly mainOption: "--log-level";
|
|
21
|
+
readonly shortOption: "-l";
|
|
22
|
+
readonly description: "Log levels";
|
|
23
|
+
readonly defaultValue: "info";
|
|
24
|
+
readonly values: ["debug", "info", "warn", "error", "silent"];
|
|
25
|
+
readonly param: "level";
|
|
26
|
+
}
|
|
27
|
+
| {
|
|
28
|
+
readonly mainOption: "--cwd";
|
|
29
|
+
readonly shortOption: "-d";
|
|
30
|
+
readonly description: "Working directory";
|
|
31
|
+
readonly defaultValue: ".";
|
|
32
|
+
readonly values: null;
|
|
33
|
+
readonly param: "path";
|
|
34
|
+
}
|
|
35
|
+
| {
|
|
36
|
+
readonly mainOption: "--config-file";
|
|
37
|
+
readonly shortOption: "-c";
|
|
38
|
+
readonly description: "(DEPRECATED) Config file";
|
|
39
|
+
readonly defaultValue: "";
|
|
40
|
+
readonly values: null;
|
|
41
|
+
readonly param: "path";
|
|
42
|
+
};
|
|
43
|
+
export declare const getCliGlobalOptionNames: () => CliGlobalOptionName[];
|