bun-workspaces 1.0.1-alpha → 1.0.1

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.
Files changed (238) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +189 -70
  3. package/bin/cli.js +1 -2
  4. package/package.json +27 -30
  5. package/src/cli/commands/commandHandlerUtils.d.ts +49 -0
  6. package/src/cli/commands/commandHandlerUtils.mjs +91 -0
  7. package/src/cli/commands/commands.d.ts +10 -0
  8. package/src/cli/commands/commands.mjs +23 -0
  9. package/src/cli/commands/commandsConfig.d.ts +351 -0
  10. package/src/cli/commands/commandsConfig.mjs +183 -0
  11. package/src/cli/commands/handleSimpleCommands.d.ts +15 -0
  12. package/src/cli/commands/handleSimpleCommands.mjs +174 -0
  13. package/src/cli/commands/index.d.ts +3 -0
  14. package/src/cli/commands/index.mjs +3 -0
  15. package/src/cli/commands/runScript/handleRunScript.d.ts +3 -0
  16. package/src/cli/commands/runScript/handleRunScript.mjs +249 -0
  17. package/src/cli/commands/runScript/index.d.ts +2 -0
  18. package/src/cli/commands/runScript/index.mjs +2 -0
  19. package/src/cli/commands/runScript/output/index.d.ts +1 -0
  20. package/src/cli/commands/runScript/output/index.mjs +1 -0
  21. package/src/cli/commands/runScript/output/outputStyle.d.ts +8 -0
  22. package/src/cli/commands/runScript/output/outputStyle.mjs +17 -0
  23. package/src/cli/commands/runScript/output/renderGroupedOutput.d.ts +73 -0
  24. package/src/cli/commands/runScript/output/renderGroupedOutput.mjs +308 -0
  25. package/src/cli/commands/runScript/output/renderPlainOutput.d.ts +24 -0
  26. package/src/cli/commands/runScript/output/renderPlainOutput.mjs +44 -0
  27. package/src/cli/commands/runScript/output/sanitizeChunk.d.ts +4 -0
  28. package/src/cli/commands/runScript/output/sanitizeChunk.mjs +101 -0
  29. package/src/cli/createCli.d.ts +25 -0
  30. package/src/cli/createCli.mjs +154 -0
  31. package/src/cli/fatalErrorLogger.d.ts +1 -0
  32. package/src/cli/fatalErrorLogger.mjs +7 -0
  33. package/src/cli/globalOptions/globalOptions.d.ts +40 -0
  34. package/src/cli/globalOptions/globalOptions.mjs +105 -0
  35. package/src/cli/globalOptions/globalOptionsConfig.d.ts +43 -0
  36. package/src/cli/globalOptions/globalOptionsConfig.mjs +34 -0
  37. package/src/cli/globalOptions/index.d.ts +2 -0
  38. package/src/cli/globalOptions/index.mjs +2 -0
  39. package/src/cli/index.d.ts +3 -0
  40. package/src/cli/index.mjs +3 -0
  41. package/src/cli/middleware.d.ts +72 -0
  42. package/src/cli/middleware.mjs +38 -0
  43. package/src/config/index.d.ts +3 -0
  44. package/src/config/index.mjs +3 -0
  45. package/src/config/rootConfig/errors.d.ts +1 -0
  46. package/src/config/rootConfig/errors.mjs +6 -0
  47. package/src/config/rootConfig/index.d.ts +5 -0
  48. package/src/config/rootConfig/index.mjs +5 -0
  49. package/src/config/rootConfig/loadRootConfig.d.ts +3 -0
  50. package/src/config/rootConfig/loadRootConfig.mjs +22 -0
  51. package/src/config/rootConfig/rootConfig.d.ts +17 -0
  52. package/src/config/rootConfig/rootConfig.mjs +43 -0
  53. package/src/config/rootConfig/rootConfigLocation.d.ts +2 -0
  54. package/src/config/rootConfig/rootConfigLocation.mjs +5 -0
  55. package/src/config/rootConfig/rootConfigSchema.d.ts +21 -0
  56. package/src/config/rootConfig/rootConfigSchema.mjs +24 -0
  57. package/src/config/userEnvVars/index.d.ts +1 -0
  58. package/src/config/userEnvVars/index.mjs +1 -0
  59. package/src/config/userEnvVars/userEnvVars.d.ts +13 -0
  60. package/src/config/userEnvVars/userEnvVars.mjs +10 -0
  61. package/src/config/util/ajvTypes.d.ts +10 -0
  62. package/src/config/util/ajvTypes.mjs +2 -0
  63. package/src/config/util/configLocation.d.ts +12 -0
  64. package/src/config/util/configLocation.mjs +11 -0
  65. package/src/config/util/index.d.ts +4 -0
  66. package/src/config/util/index.mjs +3 -0
  67. package/src/config/util/loadConfig.d.ts +16 -0
  68. package/src/config/util/loadConfig.mjs +118 -0
  69. package/src/config/util/validateConfig.d.ts +8 -0
  70. package/src/config/util/validateConfig.mjs +17 -0
  71. package/src/config/workspaceConfig/errors.d.ts +1 -0
  72. package/src/config/workspaceConfig/errors.mjs +6 -0
  73. package/src/config/workspaceConfig/index.d.ts +5 -0
  74. package/src/config/workspaceConfig/index.mjs +5 -0
  75. package/src/config/workspaceConfig/loadWorkspaceConfig.d.ts +3 -0
  76. package/src/config/workspaceConfig/loadWorkspaceConfig.mjs +25 -0
  77. package/src/config/workspaceConfig/workspaceConfig.d.ts +22 -0
  78. package/src/config/workspaceConfig/workspaceConfig.mjs +31 -0
  79. package/src/config/workspaceConfig/workspaceConfigLocation.d.ts +2 -0
  80. package/src/config/workspaceConfig/workspaceConfigLocation.mjs +5 -0
  81. package/src/config/workspaceConfig/workspaceConfigSchema.d.ts +25 -0
  82. package/src/config/workspaceConfig/workspaceConfigSchema.mjs +28 -0
  83. package/src/doctor/doctor.d.ts +35 -0
  84. package/src/doctor/doctor.mjs +52 -0
  85. package/src/doctor/index.d.ts +1 -0
  86. package/src/doctor/index.mjs +1 -0
  87. package/src/index.d.ts +37 -0
  88. package/src/index.mjs +16 -0
  89. package/src/internal/bun/bunLock.d.ts +20 -0
  90. package/src/internal/bun/bunLock.mjs +70 -0
  91. package/src/internal/bun/bunVersion.d.ts +21 -0
  92. package/src/internal/bun/bunVersion.mjs +43 -0
  93. package/src/internal/bun/index.d.ts +2 -0
  94. package/src/internal/bun/index.mjs +2 -0
  95. package/src/internal/core/error/error.d.ts +13 -0
  96. package/src/internal/{error.ts → core/error/error.mjs} +16 -18
  97. package/src/internal/core/error/index.d.ts +1 -0
  98. package/src/internal/core/error/index.mjs +1 -0
  99. package/src/internal/core/index.d.ts +4 -0
  100. package/src/internal/core/index.mjs +4 -0
  101. package/src/internal/core/json/index.d.ts +2 -0
  102. package/src/internal/core/json/index.mjs +2 -0
  103. package/src/internal/core/json/json.d.ts +49 -0
  104. package/src/internal/core/json/json.mjs +12 -0
  105. package/src/internal/core/json/jsonc.d.ts +9 -0
  106. package/src/internal/core/json/jsonc.mjs +117 -0
  107. package/src/internal/core/language/array/index.d.ts +1 -0
  108. package/src/internal/core/language/array/index.mjs +1 -0
  109. package/src/internal/core/language/array/optionalArray.d.ts +15 -0
  110. package/src/internal/core/language/array/optionalArray.mjs +8 -0
  111. package/src/internal/core/language/asyncIterable/asyncIterableQueue.d.ts +16 -0
  112. package/src/internal/core/language/asyncIterable/asyncIterableQueue.mjs +81 -0
  113. package/src/internal/core/language/asyncIterable/index.d.ts +2 -0
  114. package/src/internal/core/language/asyncIterable/index.mjs +2 -0
  115. package/src/internal/core/language/asyncIterable/mergeAsyncIterables.d.ts +5 -0
  116. package/src/internal/core/language/asyncIterable/mergeAsyncIterables.mjs +27 -0
  117. package/src/internal/core/language/events/typedEventTarget.d.ts +50 -0
  118. package/src/internal/core/language/events/typedEventTarget.mjs +14 -0
  119. package/src/internal/core/language/index.d.ts +5 -0
  120. package/src/internal/core/language/index.mjs +5 -0
  121. package/src/internal/core/language/regex/index.d.ts +1 -0
  122. package/src/internal/core/language/regex/index.mjs +1 -0
  123. package/src/internal/core/language/regex/regex.d.ts +3 -0
  124. package/src/internal/core/language/regex/regex.mjs +10 -0
  125. package/src/internal/core/language/string/id.d.ts +1 -0
  126. package/src/internal/core/language/string/id.mjs +10 -0
  127. package/src/internal/core/language/string/index.d.ts +1 -0
  128. package/src/internal/core/language/string/index.mjs +1 -0
  129. package/src/internal/core/language/string/utf/eastAsianWidth.d.ts +16 -0
  130. package/src/internal/core/language/string/utf/eastAsianWidth.mjs +326 -0
  131. package/src/internal/core/language/string/utf/visibleLength.d.ts +5 -0
  132. package/src/internal/core/language/string/utf/visibleLength.mjs +29 -0
  133. package/src/internal/core/language/types/index.d.ts +2 -0
  134. package/src/internal/core/language/types/index.mjs +1 -0
  135. package/src/internal/core/language/types/typeof.d.ts +102 -0
  136. package/src/internal/core/language/types/typeof.mjs +123 -0
  137. package/src/internal/core/language/types/types.d.ts +14 -0
  138. package/src/internal/core/language/types/types.mjs +2 -0
  139. package/src/internal/core/runtime/env.d.ts +6 -0
  140. package/src/internal/core/runtime/env.mjs +36 -0
  141. package/src/internal/core/runtime/index.d.ts +5 -0
  142. package/src/internal/core/runtime/index.mjs +5 -0
  143. package/src/internal/core/runtime/onExit.d.ts +4 -0
  144. package/src/internal/core/runtime/onExit.mjs +54 -0
  145. package/src/internal/core/runtime/os.d.ts +4 -0
  146. package/src/internal/core/runtime/os.mjs +7 -0
  147. package/src/internal/core/runtime/tempFile.d.ts +20 -0
  148. package/src/internal/core/runtime/tempFile.mjs +87 -0
  149. package/src/internal/core/runtime/terminal.d.ts +1 -0
  150. package/src/internal/core/runtime/terminal.mjs +4 -0
  151. package/src/internal/generated/ajv/validateRootConfig.mjs +1 -0
  152. package/src/internal/generated/ajv/validateWorkspaceConfig.mjs +1 -0
  153. package/src/internal/logger/index.d.ts +1 -0
  154. package/src/internal/logger/index.mjs +1 -0
  155. package/src/internal/logger/logger.d.ts +45 -0
  156. package/src/internal/logger/logger.mjs +133 -0
  157. package/src/internal/version.d.ts +1 -0
  158. package/src/internal/version.mjs +6 -0
  159. package/src/project/errors.d.ts +5 -0
  160. package/src/project/errors.mjs +10 -0
  161. package/src/project/implementations/fileSystemProject.d.ts +148 -0
  162. package/src/project/implementations/fileSystemProject.mjs +455 -0
  163. package/src/project/implementations/memoryProject.d.ts +41 -0
  164. package/src/project/implementations/memoryProject.mjs +148 -0
  165. package/src/project/implementations/projectBase.d.ts +35 -0
  166. package/src/project/implementations/projectBase.mjs +197 -0
  167. package/src/project/index.d.ts +5 -0
  168. package/src/project/index.mjs +4 -0
  169. package/src/project/project.d.ts +75 -0
  170. package/src/project/project.mjs +6 -0
  171. package/src/runScript/index.d.ts +7 -0
  172. package/src/runScript/index.mjs +7 -0
  173. package/src/runScript/output/index.d.ts +3 -0
  174. package/src/runScript/output/index.mjs +2 -0
  175. package/src/runScript/output/multiProcessOutput.d.ts +14 -0
  176. package/src/runScript/output/multiProcessOutput.mjs +21 -0
  177. package/src/runScript/output/outputStream.d.ts +1 -0
  178. package/src/runScript/output/outputStream.mjs +1 -0
  179. package/src/runScript/output/processOutput.d.ts +33 -0
  180. package/src/runScript/output/processOutput.mjs +124 -0
  181. package/src/runScript/parallel.d.ts +15 -0
  182. package/src/runScript/parallel.mjs +56 -0
  183. package/src/runScript/recursion.d.ts +4 -0
  184. package/src/runScript/recursion.mjs +17 -0
  185. package/src/runScript/runScript.d.ts +45 -0
  186. package/src/runScript/runScript.mjs +89 -0
  187. package/src/runScript/runScripts.d.ts +65 -0
  188. package/src/runScript/runScripts.mjs +263 -0
  189. package/src/runScript/scriptCommand.d.ts +33 -0
  190. package/src/runScript/scriptCommand.mjs +19 -0
  191. package/src/runScript/scriptExecution.d.ts +9 -0
  192. package/src/runScript/scriptExecution.mjs +50 -0
  193. package/src/runScript/scriptRuntimeMetadata.d.ts +73 -0
  194. package/src/runScript/scriptRuntimeMetadata.mjs +61 -0
  195. package/src/runScript/scriptShellOption.d.ts +8 -0
  196. package/src/runScript/scriptShellOption.mjs +39 -0
  197. package/src/runScript/subprocesses.d.ts +11 -0
  198. package/src/runScript/subprocesses.mjs +34 -0
  199. package/src/workspaces/dependencyGraph/cycles.d.ts +9 -0
  200. package/src/workspaces/dependencyGraph/cycles.mjs +91 -0
  201. package/src/workspaces/dependencyGraph/index.d.ts +2 -0
  202. package/src/workspaces/dependencyGraph/index.mjs +2 -0
  203. package/src/workspaces/dependencyGraph/resolveDependencies.d.ts +18 -0
  204. package/src/workspaces/dependencyGraph/resolveDependencies.mjs +52 -0
  205. package/src/workspaces/errors.d.ts +13 -0
  206. package/src/workspaces/errors.mjs +18 -0
  207. package/src/workspaces/findWorkspaces.d.ts +24 -0
  208. package/src/workspaces/findWorkspaces.mjs +217 -0
  209. package/src/workspaces/index.d.ts +4 -0
  210. package/src/workspaces/index.mjs +3 -0
  211. package/src/workspaces/packageJson.d.ts +31 -0
  212. package/src/workspaces/packageJson.mjs +188 -0
  213. package/src/workspaces/{workspace.ts → workspace.d.ts} +11 -6
  214. package/src/workspaces/workspace.mjs +2 -0
  215. package/src/workspaces/workspacePattern.d.ts +21 -0
  216. package/src/workspaces/workspacePattern.mjs +104 -0
  217. package/bun.lock +0 -576
  218. package/src/cli/cli.ts +0 -87
  219. package/src/cli/globalOptions.ts +0 -122
  220. package/src/cli/index.ts +0 -1
  221. package/src/cli/projectCommands.ts +0 -396
  222. package/src/config/bunWorkspacesConfig.ts +0 -62
  223. package/src/config/configFile.ts +0 -33
  224. package/src/config/index.ts +0 -7
  225. package/src/index.ts +0 -3
  226. package/src/internal/bunVersion.ts +0 -26
  227. package/src/internal/env.ts +0 -25
  228. package/src/internal/logger.ts +0 -145
  229. package/src/internal/regex.ts +0 -5
  230. package/src/project/errors.ts +0 -6
  231. package/src/project/index.ts +0 -6
  232. package/src/project/project.ts +0 -155
  233. package/src/project/scriptCommand.ts +0 -40
  234. package/src/workspaces/errors.ts +0 -14
  235. package/src/workspaces/findWorkspaces.ts +0 -137
  236. package/src/workspaces/index.ts +0 -7
  237. package/src/workspaces/packageJson.ts +0 -166
  238. package/tsconfig.json +0 -28
package/src/cli/cli.ts DELETED
@@ -1,87 +0,0 @@
1
- import { createCommand, Command } from "commander";
2
- import packageJson from "../../package.json";
3
- import {
4
- getRequiredBunVersion,
5
- validateCurrentBunVersion,
6
- } from "../internal/bunVersion";
7
- import { logger } from "../internal/logger";
8
- import { initializeWithGlobalOptions } from "./globalOptions";
9
- import { defineProjectCommands } from "./projectCommands";
10
-
11
- export interface RunCliOptions {
12
- argv?: string | string[];
13
- }
14
-
15
- export interface CliProgram {
16
- run: (options?: RunCliOptions) => Promise<void>;
17
- }
18
-
19
- export interface CreateCliProgramOptions {
20
- handleError?: (error: Error) => void;
21
- postInit?: (program: Command) => unknown;
22
- defaultCwd?: string;
23
- }
24
-
25
- export const createCliProgram = ({
26
- handleError,
27
- postInit,
28
- defaultCwd = process.cwd(),
29
- }: CreateCliProgramOptions = {}): CliProgram => {
30
- const run = async ({ argv = process.argv }: RunCliOptions = {}) => {
31
- const errorListener =
32
- handleError ??
33
- ((error) => {
34
- logger.error(error);
35
- logger.error("Unhandled rejection");
36
- process.exit(1);
37
- });
38
-
39
- process.on("unhandledRejection", errorListener);
40
-
41
- try {
42
- const program = createCommand("bunx bun-workspaces")
43
- .description("CLI for utilities for Bun workspaces")
44
- .version(packageJson.version)
45
- .configureOutput({
46
- writeOut: (s) => logger.info(s),
47
- writeErr: (s) =>
48
- s.startsWith("Usage") ? logger.info(s) : logger.error(s),
49
- });
50
-
51
- postInit?.(program);
52
-
53
- if (!validateCurrentBunVersion()) {
54
- logger.error(
55
- `Bun version mismatch. Required: ${getRequiredBunVersion()}, Found: ${
56
- Bun.version
57
- }`,
58
- );
59
- process.exit(1);
60
- }
61
-
62
- const args = typeof argv === "string" ? argv.split(" ") : argv;
63
-
64
- const { project } = initializeWithGlobalOptions(
65
- program,
66
- args,
67
- defaultCwd,
68
- );
69
- if (!project) return;
70
-
71
- defineProjectCommands({
72
- program,
73
- project,
74
- });
75
-
76
- await program.parseAsync(args);
77
- } catch (error) {
78
- errorListener(error as Error);
79
- } finally {
80
- process.off("unhandledRejection", errorListener);
81
- }
82
- };
83
-
84
- return {
85
- run,
86
- };
87
- };
@@ -1,122 +0,0 @@
1
- import path from "path";
2
- import { type Command, Option } from "commander";
3
- import { loadConfigFile, type BunWorkspacesConfig } from "../config";
4
- import { LOG_LEVELS, logger, type LogLevelSetting } from "../internal/logger";
5
- import { createProject } from "../project";
6
-
7
- export interface CliGlobalOptions {
8
- logLevel: LogLevelSetting;
9
- cwd: string;
10
- configFile?: string;
11
- }
12
-
13
- export type CliGlobalOptionName = keyof CliGlobalOptions;
14
-
15
- const getWorkingDirectory = (
16
- program: Command,
17
- args: string[],
18
- defaultCwd: string,
19
- ) => {
20
- program.addOption(
21
- new Option("-d --cwd <path>", "Working directory").default(defaultCwd),
22
- );
23
- program.parseOptions(args);
24
- return program.opts().cwd;
25
- };
26
-
27
- const getConfig = (program: Command, args: string[]) => {
28
- program.addOption(new Option("-c --configFile <path>", "Config file"));
29
- program.parseOptions(args);
30
- return program.opts().configFile;
31
- };
32
-
33
- const defineGlobalOptions = (
34
- program: Command,
35
- args: string[],
36
- defaultCwd: string,
37
- ) => {
38
- const cwd = getWorkingDirectory(program, args, defaultCwd);
39
-
40
- const configFilePath = getConfig(program, args);
41
-
42
- const config = loadConfigFile(configFilePath, cwd);
43
-
44
- const globalOptions: {
45
- [K in Exclude<CliGlobalOptionName, "configFile" | "cwd">]: {
46
- shortName: string;
47
- description: string;
48
- defaultValue: CliGlobalOptions[K];
49
- values?: readonly CliGlobalOptions[K][];
50
- param?: string;
51
- };
52
- } = {
53
- logLevel: {
54
- shortName: "l",
55
- description: "Log levels",
56
- defaultValue:
57
- config?.cli?.logLevel ?? (logger.printLevel as LogLevelSetting),
58
- values: [...LOG_LEVELS, "silent"],
59
- param: "level",
60
- },
61
- };
62
-
63
- Object.entries(globalOptions).forEach(
64
- ([name, { shortName, description, param, values, defaultValue }]) => {
65
- const option = new Option(
66
- `-${shortName} --${name}${param ? ` <${param}>` : ""}`,
67
- description,
68
- ).default(defaultValue);
69
-
70
- program.addOption(
71
- values?.length ? option.choices(values as string[]) : option,
72
- );
73
- },
74
- );
75
-
76
- return { cwd, config };
77
- };
78
-
79
- const applyGlobalOptions = (
80
- options: CliGlobalOptions,
81
- config: BunWorkspacesConfig | null,
82
- ) => {
83
- logger.printLevel = options.logLevel;
84
- logger.debug("Log level: " + options.logLevel);
85
-
86
- const project = createProject({
87
- rootDir: options.cwd,
88
- workspaceAliases: config?.project?.workspaceAliases ?? {},
89
- });
90
-
91
- logger.debug(
92
- `Project: ${JSON.stringify(project.name)} (${
93
- project.workspaces.length
94
- } workspace${project.workspaces.length === 1 ? "" : "s"})`,
95
- );
96
- logger.debug("Project root: " + path.resolve(project.rootDir));
97
-
98
- return { project };
99
- };
100
-
101
- export const initializeWithGlobalOptions = (
102
- program: Command,
103
- args: string[],
104
- defaultCwd: string,
105
- ) => {
106
- program.allowUnknownOption(true);
107
-
108
- const { cwd, config } = defineGlobalOptions(program, args, defaultCwd);
109
-
110
- program.parseOptions(args);
111
- program.allowUnknownOption(false);
112
-
113
- const options = program.opts() as CliGlobalOptions;
114
-
115
- return applyGlobalOptions(
116
- {
117
- ...options,
118
- cwd,
119
- },
120
- config,
121
- );
122
- };
package/src/cli/index.ts DELETED
@@ -1 +0,0 @@
1
- export { createCliProgram as createCli } from "./cli";
@@ -1,396 +0,0 @@
1
- import { type Command } from "commander";
2
- import { BunWorkspacesError } from "../internal/error";
3
- import { logger, createLogger } from "../internal/logger";
4
- import type { Project } from "../project";
5
- import type { Workspace } from "../workspaces";
6
-
7
- export interface ProjectCommandsContext {
8
- project: Project;
9
- program: Command;
10
- }
11
-
12
- const createWorkspaceInfoLines = (workspace: Workspace) => [
13
- `Workspace: ${workspace.name}`,
14
- ` - Aliases: ${workspace.aliases.join(", ")}`,
15
- ` - Path: ${workspace.path}`,
16
- ` - Glob Match: ${workspace.matchPattern}`,
17
- ` - Scripts: ${Object.keys(workspace.packageJson.scripts).sort().join(", ")}`,
18
- ];
19
-
20
- const createScriptInfoLines = (script: string, workspaces: Workspace[]) => [
21
- `Script: ${script}`,
22
- ...workspaces.map((workspace) => ` - ${workspace.name}`),
23
- ];
24
-
25
- const createJsonLines = (data: unknown, options: { pretty: boolean }) =>
26
- JSON.stringify(data, null, options.pretty ? 2 : undefined).split("\n");
27
-
28
- export const commandOutputLogger = createLogger("");
29
- commandOutputLogger.printLevel = "info";
30
-
31
- const listWorkspaces = ({ program, project }: ProjectCommandsContext) => {
32
- program
33
- .command("list-workspaces [pattern]")
34
- .aliases(["ls", "list"])
35
- .description("List all workspaces")
36
- .option("--name-only", "Only show workspace names")
37
- .option("--json", "Output as JSON")
38
- .option("--pretty", "Pretty print JSON")
39
- .action(
40
- (
41
- pattern,
42
- options: { nameOnly: boolean; json: boolean; pretty: boolean },
43
- ) => {
44
- logger.debug(
45
- `Command: List workspaces (options: ${JSON.stringify(options)})`,
46
- );
47
-
48
- const lines: string[] = [];
49
-
50
- const workspaces = pattern
51
- ? project.findWorkspacesByPattern(pattern)
52
- : project.workspaces;
53
-
54
- if (options.json) {
55
- lines.push(
56
- ...createJsonLines(
57
- options.nameOnly
58
- ? workspaces.map(({ name }) => name)
59
- : workspaces,
60
- options,
61
- ),
62
- );
63
- } else {
64
- workspaces.forEach((workspace) => {
65
- if (options.nameOnly) {
66
- lines.push(workspace.name);
67
- } else {
68
- lines.push(...createWorkspaceInfoLines(workspace));
69
- }
70
- });
71
- }
72
-
73
- if (!lines.length) {
74
- logger.info("No workspaces found");
75
- }
76
-
77
- if (lines.length) commandOutputLogger.info(lines.join("\n"));
78
- },
79
- );
80
- };
81
-
82
- const listScripts = ({ program, project }: ProjectCommandsContext) => {
83
- program
84
- .command("list-scripts")
85
- .description("List all scripts available with their workspaces")
86
- .option("--name-only", "Only show script names")
87
- .option("--json", "Output as JSON")
88
- .option("--pretty", "Pretty print JSON")
89
- .action(
90
- (options: { nameOnly: boolean; json: boolean; pretty: boolean }) => {
91
- logger.debug(
92
- `Command: List scripts (options: ${JSON.stringify(options)})`,
93
- );
94
-
95
- const scripts = project.listScriptsWithWorkspaces();
96
- const lines: string[] = [];
97
-
98
- if (options.json) {
99
- lines.push(
100
- ...createJsonLines(
101
- options.nameOnly
102
- ? Object.keys(scripts)
103
- : Object.values(scripts).map(({ workspaces, ...rest }) => ({
104
- ...rest,
105
- workspaces: workspaces.map(({ name }) => name),
106
- })),
107
- options,
108
- ),
109
- );
110
- } else {
111
- Object.values(scripts)
112
- .sort(({ name: nameA }, { name: nameB }) =>
113
- nameA.localeCompare(nameB),
114
- )
115
- .forEach(({ name, workspaces }) => {
116
- if (options.nameOnly) {
117
- lines.push(name);
118
- } else {
119
- lines.push(...createScriptInfoLines(name, workspaces));
120
- }
121
- });
122
-
123
- if (!lines.length) {
124
- logger.info("No scripts found");
125
- }
126
- }
127
-
128
- if (lines.length) commandOutputLogger.info(lines.join("\n"));
129
- },
130
- );
131
- };
132
-
133
- const workspaceInfo = ({ program, project }: ProjectCommandsContext) => {
134
- program
135
- .command("workspace-info <workspace>")
136
- .aliases(["info"])
137
- .description("Show information about a workspace")
138
- .option("--json", "Output as JSON")
139
- .option("--pretty", "Pretty print JSON")
140
- .action(
141
- (workspaceName: string, options: { json: boolean; pretty: boolean }) => {
142
- logger.debug(
143
- `Command: Workspace info for ${workspaceName} (options: ${JSON.stringify(options)})`,
144
- );
145
-
146
- const workspace = project.findWorkspaceByNameOrAlias(workspaceName);
147
- if (!workspace) {
148
- logger.error(
149
- `Workspace not found: (options: ${JSON.stringify(workspaceName)})`,
150
- );
151
- return;
152
- }
153
-
154
- commandOutputLogger.info(
155
- (options.json
156
- ? createJsonLines(workspace, options)
157
- : createWorkspaceInfoLines(workspace)
158
- ).join("\n"),
159
- );
160
- },
161
- );
162
- };
163
-
164
- const scriptInfo = ({ program, project }: ProjectCommandsContext) => {
165
- program
166
- .command("script-info <script>")
167
- .description("Show information about a script")
168
- .option("--workspaces-only", "Only show script's workspace names")
169
- .option("--json", "Output as JSON")
170
- .option("--pretty", "Pretty print JSON")
171
- .action(
172
- (
173
- script,
174
- options: { workspacesOnly: boolean; json: boolean; pretty: boolean },
175
- ) => {
176
- logger.debug(
177
- `Command: Script info for ${script} (options: ${JSON.stringify(options)})`,
178
- );
179
-
180
- const scripts = project.listScriptsWithWorkspaces();
181
- const scriptMetadata = scripts[script];
182
- if (!scriptMetadata) {
183
- logger.error(
184
- `Script not found: ${JSON.stringify(
185
- script,
186
- )} (available: ${Object.keys(scripts).join(", ")})`,
187
- );
188
- return;
189
- }
190
- commandOutputLogger.info(
191
- (options.json
192
- ? createJsonLines(
193
- options.workspacesOnly
194
- ? scriptMetadata.workspaces.map(({ name }) => name)
195
- : {
196
- name: scriptMetadata.name,
197
- workspaces: scriptMetadata.workspaces.map(
198
- ({ name }) => name,
199
- ),
200
- },
201
- options,
202
- )
203
- : options.workspacesOnly
204
- ? scriptMetadata.workspaces.map(({ name }) => name)
205
- : createScriptInfoLines(script, scriptMetadata.workspaces)
206
- ).join("\n"),
207
- );
208
- },
209
- );
210
- };
211
-
212
- const runScript = ({ program, project }: ProjectCommandsContext) => {
213
- program
214
- .command("run <script> [workspaces...]")
215
- .description("Run a script in all workspaces")
216
- .option("--parallel", "Run the scripts in parallel")
217
- .option("--args <args>", "Args to append to the script command", "")
218
- .action(async (script: string, _workspaces: string[], options) => {
219
- logger.debug(
220
- `Command: Run script ${JSON.stringify(script)} for ${
221
- _workspaces.length
222
- ? "workspaces " + _workspaces.join(", ")
223
- : "all workspaces"
224
- } (parallel: ${!!options.parallel}, method: ${JSON.stringify(
225
- options.method,
226
- )}, args: ${JSON.stringify(options.args)})`,
227
- );
228
-
229
- const workspaces = _workspaces.length
230
- ? _workspaces.flatMap((workspacePattern) => {
231
- if (workspacePattern.includes("*")) {
232
- return project
233
- .findWorkspacesByPattern(workspacePattern)
234
- .filter(({ packageJson: { scripts } }) => scripts?.[script])
235
- .map(({ name }) => name);
236
- }
237
- return [workspacePattern];
238
- })
239
- : project.listWorkspacesWithScript(script).map(({ name }) => name);
240
-
241
- if (!workspaces.length) {
242
- program.error(
243
- `No ${_workspaces.length ? "matching " : ""}workspaces found for script ${JSON.stringify(script)}`,
244
- );
245
- }
246
-
247
- let scriptCommands: ReturnType<typeof project.createScriptCommand>[];
248
- try {
249
- scriptCommands = workspaces.map((workspaceName) =>
250
- project.createScriptCommand({
251
- scriptName: script,
252
- workspaceName,
253
- method: "cd",
254
- args: options.args.replace(/<workspace>/g, workspaceName),
255
- }),
256
- );
257
- } catch (error) {
258
- program.error((error as Error).message);
259
- throw error;
260
- }
261
-
262
- const runCommand = async ({
263
- command,
264
- scriptName,
265
- workspace,
266
- }: (typeof scriptCommands)[number]) => {
267
- const commandLogger = createLogger(`${workspace.name}:${scriptName}`);
268
-
269
- const splitCommand = command.command.split(/\s+/g);
270
-
271
- commandLogger.debug(
272
- `Running script ${scriptName} in workspace ${workspace.name} (cwd: ${
273
- command.cwd
274
- }): ${splitCommand.join(" ")}`,
275
- );
276
-
277
- const isSilent = logger.printLevel === "silent";
278
-
279
- const proc = Bun.spawn(command.command.split(/\s+/g), {
280
- cwd: command.cwd,
281
- env: process.env,
282
- stdout: isSilent ? "ignore" : "pipe",
283
- stderr: isSilent ? "ignore" : "pipe",
284
- });
285
-
286
- const linePrefix = `[${workspace.name}:${scriptName}] `;
287
-
288
- if (proc.stdout) {
289
- for await (const chunk of proc.stdout) {
290
- const line = new TextDecoder().decode(chunk).trim();
291
- line.split("\n").forEach((line) => {
292
- commandLogger.info(linePrefix + line);
293
- });
294
- }
295
- }
296
-
297
- if (proc.stderr) {
298
- for await (const chunk of proc.stderr) {
299
- const line = new TextDecoder().decode(chunk).trim();
300
- line.split("\n").forEach((line) => {
301
- commandLogger.error(linePrefix + line);
302
- });
303
- }
304
- }
305
-
306
- await proc.exited;
307
-
308
- return {
309
- scriptName,
310
- workspace,
311
- command,
312
- success: proc.exitCode === 0,
313
- error:
314
- proc.exitCode === 0
315
- ? null
316
- : new BunWorkspacesError(
317
- `Script exited with code ${proc.exitCode}`,
318
- ),
319
- };
320
- };
321
-
322
- const results = [] as {
323
- success: boolean;
324
- workspaceName: string;
325
- error: Error | null;
326
- }[];
327
-
328
- if (options.parallel) {
329
- let i = 0;
330
- for await (const result of await Promise.allSettled(
331
- scriptCommands.map(runCommand),
332
- )) {
333
- if (result.status === "rejected") {
334
- results.push({
335
- success: false,
336
- workspaceName: workspaces[i],
337
- error: result.reason,
338
- });
339
- } else {
340
- results.push({
341
- success: result.value.success,
342
- workspaceName: workspaces[i],
343
- error: result.value.error,
344
- });
345
- }
346
- i++;
347
- }
348
- } else {
349
- let i = 0;
350
- for (const command of scriptCommands) {
351
- try {
352
- const result = await runCommand(command);
353
- results.push({
354
- success: result.success,
355
- workspaceName: workspaces[i],
356
- error: result.error,
357
- });
358
- } catch (error) {
359
- results.push({
360
- success: false,
361
- workspaceName: workspaces[i],
362
- error: error as Error,
363
- });
364
- }
365
- i++;
366
- }
367
- }
368
-
369
- let failCount = 0;
370
- results.forEach(({ success, workspaceName }) => {
371
- if (!success) failCount++;
372
- commandOutputLogger.info(
373
- `${success ? "✅" : "❌"} ${workspaceName}: ${script}`,
374
- );
375
- });
376
-
377
- const s = results.length === 1 ? "" : "s";
378
- if (failCount) {
379
- const message = `${failCount} of ${results.length} script${s} failed`;
380
- commandOutputLogger.info(message);
381
- process.exit(1);
382
- } else {
383
- commandOutputLogger.info(
384
- `${results.length} script${s} ran successfully`,
385
- );
386
- }
387
- });
388
- };
389
-
390
- export const defineProjectCommands = (context: ProjectCommandsContext) => {
391
- listWorkspaces(context);
392
- listScripts(context);
393
- workspaceInfo(context);
394
- scriptInfo(context);
395
- runScript(context);
396
- };
@@ -1,62 +0,0 @@
1
- import { validateLogLevel, type LogLevelSetting } from "../internal/logger";
2
-
3
- export interface CliConfig {
4
- logLevel?: LogLevelSetting;
5
- }
6
-
7
- export interface ProjectConfig {
8
- /** A map of aliases to a workspace name */
9
- workspaceAliases?: Record<string, string>;
10
- }
11
-
12
- export interface BunWorkspacesConfig {
13
- cli?: CliConfig;
14
- project?: ProjectConfig;
15
- }
16
-
17
- const validateCliConfig = (cliConfig: CliConfig) => {
18
- if (typeof cliConfig !== "object" || Array.isArray(cliConfig)) {
19
- throw new Error(`Config file: "cli" must be an object`);
20
- }
21
-
22
- if (cliConfig?.logLevel) {
23
- validateLogLevel(cliConfig.logLevel);
24
- }
25
- };
26
-
27
- const validateProjectConfig = (projectConfig: ProjectConfig) => {
28
- if (typeof projectConfig !== "object" || Array.isArray(projectConfig)) {
29
- throw new Error(`Config file: "project" must be an object`);
30
- }
31
-
32
- if (projectConfig?.workspaceAliases) {
33
- if (
34
- typeof projectConfig.workspaceAliases !== "object" ||
35
- Array.isArray(projectConfig.workspaceAliases)
36
- ) {
37
- throw new Error(
38
- `Config file: project.workspaceAliases must be an object`,
39
- );
40
- }
41
- for (const alias of Object.values(projectConfig.workspaceAliases)) {
42
- if (typeof alias !== "string") {
43
- throw new Error(
44
- `Config file: project.workspaceAliases must be an object with string keys and values`,
45
- );
46
- }
47
- }
48
- }
49
- };
50
-
51
- export const validateBunWorkspacesConfig = (config: BunWorkspacesConfig) => {
52
- if (typeof config !== "object" || Array.isArray(config)) {
53
- throw new Error(`Config file: must be an object`);
54
- }
55
-
56
- if (typeof config.cli !== "undefined") {
57
- validateCliConfig(config.cli);
58
- }
59
- if (typeof config.project !== "undefined") {
60
- validateProjectConfig(config.project);
61
- }
62
- };
@@ -1,33 +0,0 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import {
4
- validateBunWorkspacesConfig,
5
- type BunWorkspacesConfig,
6
- } from "./bunWorkspacesConfig";
7
-
8
- export const DEFAULT_CONFIG_FILE_PATH = "bw.json";
9
-
10
- export const loadConfigFile = (filePath?: string, rootDir = ".") => {
11
- if (!filePath) {
12
- const defaultFilePath = path.resolve(rootDir, DEFAULT_CONFIG_FILE_PATH);
13
- if (fs.existsSync(defaultFilePath)) {
14
- filePath = defaultFilePath;
15
- } else {
16
- return null;
17
- }
18
- }
19
-
20
- filePath = path.resolve(rootDir, filePath);
21
-
22
- const configFile = fs.readFileSync(filePath, "utf8");
23
-
24
- try {
25
- const json = JSON.parse(configFile);
26
- validateBunWorkspacesConfig(json);
27
- return json as BunWorkspacesConfig;
28
- } catch (error) {
29
- throw new Error(
30
- `Config file: "${filePath}" is not a valid JSON file: ${error}`,
31
- );
32
- }
33
- };
@@ -1,7 +0,0 @@
1
- export {
2
- validateBunWorkspacesConfig,
3
- type BunWorkspacesConfig,
4
- type CliConfig,
5
- type ProjectConfig,
6
- } from "./bunWorkspacesConfig";
7
- export { loadConfigFile, DEFAULT_CONFIG_FILE_PATH } from "./configFile";