bun-workspaces 1.0.0-alpha.8 → 1.0.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.
Files changed (233) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +212 -19
  3. package/bin/cli.js +1 -1
  4. package/package.json +25 -9
  5. package/src/cli/commands/commandHandlerUtils.d.ts +45 -0
  6. package/src/cli/commands/commandHandlerUtils.mjs +81 -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 +250 -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 +71 -0
  24. package/src/cli/commands/runScript/output/renderGroupedOutput.mjs +307 -0
  25. package/src/cli/commands/runScript/output/renderPlainOutput.d.ts +22 -0
  26. package/src/cli/commands/runScript/output/renderPlainOutput.mjs +43 -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 +14 -8
  30. package/src/cli/createCli.mjs +94 -39
  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 +38 -2
  34. package/src/cli/globalOptions/globalOptions.mjs +96 -47
  35. package/src/cli/globalOptions/globalOptionsConfig.d.ts +37 -31
  36. package/src/cli/globalOptions/globalOptionsConfig.mjs +32 -30
  37. package/src/cli/globalOptions/index.mjs +1 -1
  38. package/src/cli/index.d.ts +3 -1
  39. package/src/cli/index.mjs +3 -2
  40. package/src/config/index.d.ts +3 -2
  41. package/src/config/index.mjs +3 -3
  42. package/src/config/rootConfig/errors.d.ts +1 -0
  43. package/src/config/rootConfig/errors.mjs +6 -0
  44. package/src/config/rootConfig/index.d.ts +5 -0
  45. package/src/config/rootConfig/index.mjs +5 -0
  46. package/src/config/rootConfig/loadRootConfig.d.ts +3 -0
  47. package/src/config/rootConfig/loadRootConfig.mjs +22 -0
  48. package/src/config/rootConfig/rootConfig.d.ts +17 -0
  49. package/src/config/rootConfig/rootConfig.mjs +43 -0
  50. package/src/config/rootConfig/rootConfigLocation.d.ts +2 -0
  51. package/src/config/rootConfig/rootConfigLocation.mjs +5 -0
  52. package/src/config/rootConfig/rootConfigSchema.d.ts +21 -0
  53. package/src/config/rootConfig/rootConfigSchema.mjs +24 -0
  54. package/src/config/userEnvVars/index.d.ts +1 -0
  55. package/src/config/userEnvVars/index.mjs +1 -0
  56. package/src/config/userEnvVars/userEnvVars.d.ts +13 -0
  57. package/src/config/userEnvVars/userEnvVars.mjs +10 -0
  58. package/src/config/util/ajvTypes.d.ts +10 -0
  59. package/src/config/util/ajvTypes.mjs +2 -0
  60. package/src/config/util/configLocation.d.ts +12 -0
  61. package/src/config/util/configLocation.mjs +11 -0
  62. package/src/config/util/index.d.ts +4 -0
  63. package/src/config/util/index.mjs +3 -0
  64. package/src/config/util/loadConfig.d.ts +16 -0
  65. package/src/config/util/loadConfig.mjs +118 -0
  66. package/src/config/util/validateConfig.d.ts +8 -0
  67. package/src/config/util/validateConfig.mjs +17 -0
  68. package/src/config/workspaceConfig/errors.d.ts +1 -0
  69. package/src/config/workspaceConfig/errors.mjs +6 -0
  70. package/src/config/workspaceConfig/index.d.ts +5 -0
  71. package/src/config/workspaceConfig/index.mjs +5 -0
  72. package/src/config/workspaceConfig/loadWorkspaceConfig.d.ts +3 -0
  73. package/src/config/workspaceConfig/loadWorkspaceConfig.mjs +25 -0
  74. package/src/config/workspaceConfig/workspaceConfig.d.ts +22 -0
  75. package/src/config/workspaceConfig/workspaceConfig.mjs +31 -0
  76. package/src/config/workspaceConfig/workspaceConfigLocation.d.ts +2 -0
  77. package/src/config/workspaceConfig/workspaceConfigLocation.mjs +5 -0
  78. package/src/config/workspaceConfig/workspaceConfigSchema.d.ts +25 -0
  79. package/src/config/workspaceConfig/workspaceConfigSchema.mjs +28 -0
  80. package/src/doctor/doctor.d.ts +35 -0
  81. package/src/doctor/doctor.mjs +52 -0
  82. package/src/doctor/index.d.ts +1 -0
  83. package/src/doctor/index.mjs +1 -0
  84. package/src/index.d.ts +37 -3
  85. package/src/index.mjs +16 -3
  86. package/src/internal/bun/bunLock.d.ts +20 -0
  87. package/src/internal/bun/bunLock.mjs +70 -0
  88. package/src/internal/bun/bunVersion.d.ts +21 -0
  89. package/src/internal/bun/bunVersion.mjs +43 -0
  90. package/src/internal/bun/index.d.ts +2 -0
  91. package/src/internal/bun/index.mjs +2 -0
  92. package/src/internal/core/error/error.d.ts +13 -0
  93. package/src/internal/core/error/error.mjs +36 -0
  94. package/src/internal/core/error/index.d.ts +1 -0
  95. package/src/internal/core/error/index.mjs +1 -0
  96. package/src/internal/core/index.d.ts +4 -0
  97. package/src/internal/core/index.mjs +4 -0
  98. package/src/internal/core/json/index.d.ts +2 -0
  99. package/src/internal/core/json/index.mjs +2 -0
  100. package/src/internal/core/json/json.d.ts +49 -0
  101. package/src/internal/core/json/json.mjs +12 -0
  102. package/src/internal/core/json/jsonc.d.ts +9 -0
  103. package/src/internal/core/json/jsonc.mjs +117 -0
  104. package/src/internal/core/language/array/index.d.ts +1 -0
  105. package/src/internal/core/language/array/index.mjs +1 -0
  106. package/src/internal/core/language/array/optionalArray.d.ts +15 -0
  107. package/src/internal/core/language/array/optionalArray.mjs +8 -0
  108. package/src/internal/core/language/asyncIterable/asyncIterableQueue.d.ts +16 -0
  109. package/src/internal/core/language/asyncIterable/asyncIterableQueue.mjs +81 -0
  110. package/src/internal/core/language/asyncIterable/index.d.ts +2 -0
  111. package/src/internal/core/language/asyncIterable/index.mjs +2 -0
  112. package/src/internal/core/language/asyncIterable/mergeAsyncIterables.d.ts +5 -0
  113. package/src/internal/core/language/asyncIterable/mergeAsyncIterables.mjs +27 -0
  114. package/src/internal/core/language/events/typedEventTarget.d.ts +50 -0
  115. package/src/internal/core/language/events/typedEventTarget.mjs +14 -0
  116. package/src/internal/core/language/index.d.ts +5 -0
  117. package/src/internal/core/language/index.mjs +5 -0
  118. package/src/internal/core/language/regex/index.d.ts +1 -0
  119. package/src/internal/core/language/regex/index.mjs +1 -0
  120. package/src/internal/{regex.d.ts → core/language/regex/regex.d.ts} +1 -0
  121. package/src/internal/core/language/regex/regex.mjs +10 -0
  122. package/src/internal/core/language/string/id.d.ts +1 -0
  123. package/src/internal/core/language/string/id.mjs +10 -0
  124. package/src/internal/core/language/string/index.d.ts +1 -0
  125. package/src/internal/core/language/string/index.mjs +1 -0
  126. package/src/internal/core/language/string/utf/eastAsianWidth.d.ts +16 -0
  127. package/src/internal/core/language/string/utf/eastAsianWidth.mjs +326 -0
  128. package/src/internal/core/language/string/utf/visibleLength.d.ts +5 -0
  129. package/src/internal/core/language/string/utf/visibleLength.mjs +29 -0
  130. package/src/internal/core/language/types/index.d.ts +2 -0
  131. package/src/internal/core/language/types/index.mjs +1 -0
  132. package/src/internal/core/language/types/typeof.d.ts +102 -0
  133. package/src/internal/core/language/types/typeof.mjs +123 -0
  134. package/src/internal/core/language/types/types.d.ts +14 -0
  135. package/src/internal/core/language/types/types.mjs +2 -0
  136. package/src/internal/{env.d.ts → core/runtime/env.d.ts} +1 -0
  137. package/src/internal/core/runtime/env.mjs +36 -0
  138. package/src/internal/core/runtime/index.d.ts +5 -0
  139. package/src/internal/core/runtime/index.mjs +5 -0
  140. package/src/internal/core/runtime/onExit.d.ts +4 -0
  141. package/src/internal/core/runtime/onExit.mjs +54 -0
  142. package/src/internal/core/runtime/os.d.ts +4 -0
  143. package/src/internal/core/runtime/os.mjs +7 -0
  144. package/src/internal/core/runtime/tempFile.d.ts +20 -0
  145. package/src/internal/core/runtime/tempFile.mjs +87 -0
  146. package/src/internal/core/runtime/terminal.d.ts +1 -0
  147. package/src/internal/core/runtime/terminal.mjs +4 -0
  148. package/src/internal/generated/ajv/validateRootConfig.mjs +1 -0
  149. package/src/internal/generated/ajv/validateWorkspaceConfig.mjs +1 -0
  150. package/src/internal/logger/index.d.ts +1 -0
  151. package/src/internal/logger/index.mjs +1 -0
  152. package/src/internal/logger/logger.d.ts +39 -0
  153. package/src/internal/logger/logger.mjs +116 -0
  154. package/src/internal/version.d.ts +1 -0
  155. package/src/internal/version.mjs +6 -0
  156. package/src/project/errors.d.ts +5 -1
  157. package/src/project/errors.mjs +10 -3
  158. package/src/project/implementations/fileSystemProject.d.ts +148 -0
  159. package/src/project/implementations/fileSystemProject.mjs +455 -0
  160. package/src/project/implementations/memoryProject.d.ts +41 -0
  161. package/src/project/implementations/memoryProject.mjs +148 -0
  162. package/src/project/implementations/projectBase.d.ts +35 -0
  163. package/src/project/implementations/projectBase.mjs +197 -0
  164. package/src/project/index.d.ts +5 -1
  165. package/src/project/index.mjs +4 -2
  166. package/src/project/project.d.ts +72 -28
  167. package/src/project/project.mjs +6 -72
  168. package/src/runScript/index.d.ts +7 -0
  169. package/src/runScript/index.mjs +7 -0
  170. package/src/runScript/output/index.d.ts +3 -0
  171. package/src/runScript/output/index.mjs +2 -0
  172. package/src/runScript/output/multiProcessOutput.d.ts +14 -0
  173. package/src/runScript/output/multiProcessOutput.mjs +21 -0
  174. package/src/runScript/output/outputStream.d.ts +1 -0
  175. package/src/runScript/output/outputStream.mjs +1 -0
  176. package/src/runScript/output/processOutput.d.ts +33 -0
  177. package/src/runScript/output/processOutput.mjs +124 -0
  178. package/src/runScript/parallel.d.ts +15 -0
  179. package/src/runScript/parallel.mjs +56 -0
  180. package/src/runScript/recursion.d.ts +4 -0
  181. package/src/runScript/recursion.mjs +17 -0
  182. package/src/runScript/runScript.d.ts +45 -0
  183. package/src/runScript/runScript.mjs +89 -0
  184. package/src/runScript/runScripts.d.ts +65 -0
  185. package/src/runScript/runScripts.mjs +263 -0
  186. package/src/runScript/scriptCommand.d.ts +33 -0
  187. package/src/runScript/scriptCommand.mjs +19 -0
  188. package/src/runScript/scriptExecution.d.ts +9 -0
  189. package/src/runScript/scriptExecution.mjs +50 -0
  190. package/src/runScript/scriptRuntimeMetadata.d.ts +73 -0
  191. package/src/runScript/scriptRuntimeMetadata.mjs +61 -0
  192. package/src/runScript/scriptShellOption.d.ts +8 -0
  193. package/src/runScript/scriptShellOption.mjs +39 -0
  194. package/src/runScript/subprocesses.d.ts +11 -0
  195. package/src/runScript/subprocesses.mjs +34 -0
  196. package/src/workspaces/dependencyGraph/cycles.d.ts +9 -0
  197. package/src/workspaces/dependencyGraph/cycles.mjs +91 -0
  198. package/src/workspaces/dependencyGraph/index.d.ts +2 -0
  199. package/src/workspaces/dependencyGraph/index.mjs +2 -0
  200. package/src/workspaces/dependencyGraph/resolveDependencies.d.ts +18 -0
  201. package/src/workspaces/dependencyGraph/resolveDependencies.mjs +52 -0
  202. package/src/workspaces/errors.d.ts +13 -1
  203. package/src/workspaces/errors.mjs +18 -3
  204. package/src/workspaces/findWorkspaces.d.ts +20 -13
  205. package/src/workspaces/findWorkspaces.mjs +208 -57
  206. package/src/workspaces/index.d.ts +4 -3
  207. package/src/workspaces/index.mjs +3 -2
  208. package/src/workspaces/packageJson.d.ts +28 -5
  209. package/src/workspaces/packageJson.mjs +177 -54
  210. package/src/workspaces/workspace.d.ts +19 -13
  211. package/src/workspaces/workspace.mjs +2 -0
  212. package/src/workspaces/workspacePattern.d.ts +21 -0
  213. package/src/workspaces/workspacePattern.mjs +104 -0
  214. package/src/cli/projectCommands/index.d.ts +0 -2
  215. package/src/cli/projectCommands/index.mjs +0 -2
  216. package/src/cli/projectCommands/projectCommandHandlers.d.ts +0 -8
  217. package/src/cli/projectCommands/projectCommandHandlers.mjs +0 -180
  218. package/src/cli/projectCommands/projectCommandsConfig.d.ts +0 -191
  219. package/src/cli/projectCommands/projectCommandsConfig.mjs +0 -100
  220. package/src/config/bunWorkspacesConfig.d.ts +0 -13
  221. package/src/config/bunWorkspacesConfig.mjs +0 -18
  222. package/src/config/configFile.d.ts +0 -3
  223. package/src/config/configFile.mjs +0 -21
  224. package/src/internal/bunVersion.d.ts +0 -14
  225. package/src/internal/bunVersion.mjs +0 -8
  226. package/src/internal/env.mjs +0 -15
  227. package/src/internal/error.d.ts +0 -7
  228. package/src/internal/error.mjs +0 -26
  229. package/src/internal/logger.d.ts +0 -21
  230. package/src/internal/logger.mjs +0 -85
  231. package/src/internal/regex.mjs +0 -3
  232. package/src/project/scriptCommand.d.ts +0 -15
  233. package/src/project/scriptCommand.mjs +0 -18
@@ -0,0 +1,307 @@
1
+ import { runOnExit } from "../../../../internal/core/index.mjs";
2
+ import {
3
+ TypedEventTarget,
4
+ createTypedEventFactory,
5
+ } from "../../../../internal/core/language/events/typedEventTarget.mjs";
6
+ import {
7
+ calculateVisibleLength,
8
+ truncateTerminalString,
9
+ } from "../../../../internal/core/language/string/utf/visibleLength.mjs";
10
+ import { logger } from "../../../../internal/logger/index.mjs";
11
+ import { generatePlainOutputLines } from "./renderPlainOutput.mjs"; // CONCATENATED MODULE: external "../../../../internal/core/index.mjs"
12
+ // CONCATENATED MODULE: external "../../../../internal/core/language/events/typedEventTarget.mjs"
13
+ // CONCATENATED MODULE: external "../../../../internal/core/language/string/utf/visibleLength.mjs"
14
+ // CONCATENATED MODULE: external "../../../../internal/logger/index.mjs"
15
+ // CONCATENATED MODULE: external "./renderPlainOutput.mjs"
16
+ // CONCATENATED MODULE: ./src/cli/commands/runScript/output/renderGroupedOutput.ts
17
+
18
+ class ScriptEventTarget extends TypedEventTarget {}
19
+ const createScriptEventTarget = () => new ScriptEventTarget();
20
+ const createScriptEvent = {
21
+ start: createTypedEventFactory("start"),
22
+ skip: createTypedEventFactory("skip"),
23
+ exit: createTypedEventFactory("exit"),
24
+ };
25
+ const cursorOps = {
26
+ up: (n) => `\x1b[${n}A`,
27
+ down: (n) => `\x1b[${n}B`,
28
+ toColumn: (n) => `\x1b[${n}G`,
29
+ hide: () => `\x1b[?25l`,
30
+ show: () => `\x1b[?25h`,
31
+ };
32
+ const lineOps = {
33
+ clearToEnd: () => `\x1b[0K`,
34
+ clearToStart: () => `\x1b[1K`,
35
+ clearFull: () => `\x1b[2K`,
36
+ };
37
+ const textOps = {
38
+ bold: (s) => `\x1b[1m${s}\x1b[0m`,
39
+ red: (s) => `\x1b[31m${s}\x1b[0m`,
40
+ green: (s) => `\x1b[32m${s}\x1b[0m`,
41
+ yellow: (s) => `\x1b[33m${s}\x1b[0m`,
42
+ blue: (s) => `\x1b[34m${s}\x1b[0m`,
43
+ magenta: (s) => `\x1b[35m${s}\x1b[0m`,
44
+ cyan: (s) => `\x1b[36m${s}\x1b[0m`,
45
+ white: (s) => `\x1b[37m${s}\x1b[0m`,
46
+ gray: (s) => `\x1b[90m${s}\x1b[0m`,
47
+ intenseBlack: (s) => `\x1b[0;90m${s}\x1b[0m`,
48
+ intenseRed: (s) => `\x1b[0;91m${s}\x1b[0m`,
49
+ intenseGreen: (s) => `\x1b[0;92m${s}\x1b[0m`,
50
+ intenseYellow: (s) => `\x1b[0;93m${s}\x1b[0m`,
51
+ intenseBlue: (s) => `\x1b[0;94m${s}\x1b[0m`,
52
+ intenseMagenta: (s) => `\x1b[0;95m${s}\x1b[0m`,
53
+ intenseCyan: (s) => `\x1b[0;96m${s}\x1b[0m`,
54
+ intenseWhite: (s) => `\x1b[0;97m${s}\x1b[0m`,
55
+ };
56
+ const STATUS_COLORS = {
57
+ pending: "gray",
58
+ running: "intenseCyan",
59
+ skipped: "gray",
60
+ success: "intenseGreen",
61
+ failure: "intenseRed",
62
+ interrupted: "intenseYellow",
63
+ cancelled: "gray",
64
+ killed: "intenseRed",
65
+ };
66
+ const BORDER_COLOR = "blue";
67
+ const renderGroupedOutput = async (
68
+ workspaces,
69
+ output,
70
+ summary,
71
+ scriptEventTarget,
72
+ activeScriptLines,
73
+ ) => {
74
+ const workspaceState = workspaces.reduce((acc, workspace) => {
75
+ acc[workspace.name] = {
76
+ lines: [],
77
+ status: "pending",
78
+ exitCode: null,
79
+ signal: null,
80
+ };
81
+ return acc;
82
+ }, {});
83
+ let isInitialized = false;
84
+ const initializeTuiTerminal = () => {
85
+ if (isInitialized) {
86
+ return;
87
+ }
88
+ isInitialized = true;
89
+ logger.debug("Initializing TUI state");
90
+ process.stdout.write(cursorOps.hide());
91
+ process.stdin.setRawMode?.(true);
92
+ };
93
+ let isReset = false;
94
+ const resetTuiTerminal = () => {
95
+ if (isReset) {
96
+ return;
97
+ }
98
+ isReset = true;
99
+ logger.debug("Resetting TUI state");
100
+ process.stdout.write(cursorOps.show());
101
+ process.stdin.unref();
102
+ process.stdin.setRawMode?.(false);
103
+ };
104
+ let previousHeight = 0;
105
+ let didFinalRender = false;
106
+ const render = (isFinal = false) => {
107
+ if (didFinalRender) {
108
+ return;
109
+ }
110
+ if (isFinal) {
111
+ didFinalRender = true;
112
+ }
113
+ const width = Math.max(2, process.stdout.columns);
114
+ const linesToWrite = [];
115
+ workspaces.forEach((workspace) => {
116
+ const state = workspaceState[workspace.name];
117
+ linesToWrite.push({
118
+ text: textOps[BORDER_COLOR](
119
+ "┌" + "─".repeat(Math.max(0, width - 2)) + "┐",
120
+ ),
121
+ type: "border",
122
+ });
123
+ const borderText = (text) => {
124
+ const padding = 4; // left border, spaces, right border
125
+ const visibleLength = calculateVisibleLength(text);
126
+ const truncated =
127
+ visibleLength > width - padding
128
+ ? truncateTerminalString(text, width - padding - 1) + "\x1b[0m…"
129
+ : text;
130
+ return (
131
+ textOps[BORDER_COLOR]("│ ") +
132
+ truncated +
133
+ " ".repeat(Math.max(0, width - visibleLength - padding)) +
134
+ textOps[BORDER_COLOR](" │")
135
+ );
136
+ };
137
+ linesToWrite.push({
138
+ text: borderText("Workspace: " + textOps.bold(workspace.name)),
139
+ type: "borderedContent",
140
+ });
141
+ let statusText = state.status;
142
+ const hasExitCode = state.exitCode && state.exitCode !== -1;
143
+ const exitState =
144
+ hasExitCode && state.signal
145
+ ? "exitAndSignal"
146
+ : hasExitCode
147
+ ? "exit"
148
+ : state.signal
149
+ ? "signal"
150
+ : null;
151
+ if (exitState === "exitAndSignal") {
152
+ statusText += ` (exit code: ${state.exitCode}, signal: ${state.signal})`;
153
+ } else if (exitState === "exit") {
154
+ statusText += ` (exit code: ${state.exitCode})`;
155
+ } else if (exitState === "signal") {
156
+ statusText += ` (signal: ${state.signal})`;
157
+ }
158
+ linesToWrite.push({
159
+ text: borderText(
160
+ " Status: " + textOps[STATUS_COLORS[state.status]](statusText),
161
+ ),
162
+ type: "borderedContent",
163
+ });
164
+ linesToWrite.push({
165
+ text: textOps[BORDER_COLOR](
166
+ "└" + "─".repeat(Math.max(0, width - 2)) + "┘",
167
+ ),
168
+ type: "border",
169
+ });
170
+ if (
171
+ activeScriptLines !== "all" &&
172
+ state.lines.length > activeScriptLines &&
173
+ !isFinal
174
+ ) {
175
+ const hiddenLines = state.lines.length - activeScriptLines;
176
+ linesToWrite.push({
177
+ text: textOps.gray(
178
+ `(${hiddenLines} line${hiddenLines === 1 ? "" : "s"} hidden until exit)`,
179
+ ),
180
+ type: "scriptOutput",
181
+ });
182
+ }
183
+ linesToWrite.push(
184
+ ...state.lines
185
+ .slice(isFinal ? undefined : -activeScriptLines)
186
+ .map((line) => ({
187
+ text: line.text,
188
+ type: "scriptOutput",
189
+ })),
190
+ );
191
+ return linesToWrite;
192
+ });
193
+ if (previousHeight > 0) {
194
+ // clear previous frame
195
+ process.stdout.write(cursorOps.up(previousHeight));
196
+ for (let i = 0; i < previousHeight; i++) {
197
+ process.stdout.write(cursorOps.toColumn(1));
198
+ process.stdout.write(lineOps.clearFull());
199
+ process.stdout.write("\n");
200
+ }
201
+ process.stdout.write(cursorOps.up(previousHeight));
202
+ }
203
+ for (const line of linesToWrite) {
204
+ if (isFinal && line.type === "scriptOutput") {
205
+ process.stdout.write(line.text.replace(/\n?$/, "\n"));
206
+ } else {
207
+ const visibleLength = calculateVisibleLength(line.text);
208
+ const truncated =
209
+ visibleLength > width
210
+ ? truncateTerminalString(line.text, width - 2) + "\x1b[0m…"
211
+ : line.text;
212
+ process.stdout.write(truncated.replace(/\n?$/, "\n"));
213
+ }
214
+ }
215
+ previousHeight = linesToWrite.length;
216
+ if (isFinal) {
217
+ resetTuiTerminal();
218
+ }
219
+ };
220
+ const handleExitResult = (result) => {
221
+ const state = workspaceState[result.metadata.workspace.name];
222
+ if (result.signal) {
223
+ if (state.status === "running") {
224
+ if (result.signal === "SIGINT") {
225
+ state.status = "interrupted";
226
+ } else {
227
+ state.status = "killed";
228
+ state.signal = result.signal ?? null;
229
+ }
230
+ } else if (state.status === "pending") {
231
+ state.status = "cancelled";
232
+ }
233
+ } else {
234
+ state.status = result.skipped
235
+ ? "skipped"
236
+ : result.success
237
+ ? "success"
238
+ : "failure";
239
+ }
240
+ state.exitCode = result.exitCode ?? process.exitCode ?? null;
241
+ };
242
+ scriptEventTarget.addEventListener("start", (event) => {
243
+ const { workspace } = event;
244
+ workspaceState[workspace.name].status = "running";
245
+ render();
246
+ });
247
+ scriptEventTarget.addEventListener("skip", (event) => {
248
+ const { workspace } = event;
249
+ workspaceState[workspace.name].status = "skipped";
250
+ render();
251
+ });
252
+ scriptEventTarget.addEventListener("exit", (event) => {
253
+ if (event.exitResult) handleExitResult(event.exitResult);
254
+ render();
255
+ });
256
+ process.on("SIGWINCH", render);
257
+ process.stdin.on("data", (data) => {
258
+ if (data[0] === 0x03) process.kill(process.pid, "SIGINT");
259
+ if (data[0] === 0x1c) process.kill(process.pid, "SIGQUIT");
260
+ });
261
+ runOnExit((reason) => {
262
+ try {
263
+ if (typeof reason === "string" && reason.startsWith("SIG")) {
264
+ process.stdout.write("\r" + lineOps.clearFull());
265
+ }
266
+ Object.keys(workspaceState).forEach((workspaceName) => {
267
+ handleExitResult({
268
+ metadata: {
269
+ workspace: {
270
+ name: workspaceName,
271
+ },
272
+ },
273
+ skipped: false,
274
+ success: false,
275
+ exitCode:
276
+ typeof process.exitCode === "number" ? process.exitCode : -1,
277
+ signal: typeof reason === "string" ? reason : null,
278
+ });
279
+ });
280
+ render(true);
281
+ } finally {
282
+ resetTuiTerminal();
283
+ }
284
+ });
285
+ initializeTuiTerminal();
286
+ render();
287
+ for await (const { metadata, line } of generatePlainOutputLines(output, {
288
+ stripDisruptiveControls: true,
289
+ prefix: false,
290
+ })) {
291
+ const workspaceName = metadata.workspace.name;
292
+ workspaceState[workspaceName].lines.push({
293
+ text: line.replace(/\n$/, ""),
294
+ type: "scriptOutput",
295
+ });
296
+ render();
297
+ }
298
+ await summary.then((summary) => {
299
+ // fallback logic to resolve race conditions with script events
300
+ summary.scriptResults.forEach((result) => {
301
+ handleExitResult(result);
302
+ });
303
+ render(true);
304
+ });
305
+ };
306
+
307
+ export { createScriptEvent, createScriptEventTarget, renderGroupedOutput };
@@ -0,0 +1,22 @@
1
+ import type { RunScriptAcrossWorkspacesOutput } from "../../../../project";
2
+ export type RenderPlainOutputOptions = {
3
+ stripDisruptiveControls?: boolean;
4
+ prefix?: boolean;
5
+ };
6
+ export declare function generatePlainOutputLines(
7
+ output: RunScriptAcrossWorkspacesOutput,
8
+ { stripDisruptiveControls, prefix }: RenderPlainOutputOptions,
9
+ ): AsyncGenerator<
10
+ {
11
+ line: string;
12
+ metadata: import("../../../..").RunWorkspaceScriptMetadata & {
13
+ streamName: import("../../../..").OutputStreamName;
14
+ };
15
+ },
16
+ void,
17
+ unknown
18
+ >;
19
+ export declare const renderPlainOutput: (
20
+ output: RunScriptAcrossWorkspacesOutput,
21
+ { stripDisruptiveControls, prefix }: RenderPlainOutputOptions,
22
+ ) => Promise<void>;
@@ -0,0 +1,43 @@
1
+ import { sanitizeChunk } from "./sanitizeChunk.mjs"; // CONCATENATED MODULE: external "./sanitizeChunk.mjs"
2
+ // CONCATENATED MODULE: ./src/cli/commands/runScript/output/renderPlainOutput.ts
3
+
4
+ async function* generatePlainOutputLines(
5
+ output,
6
+ { stripDisruptiveControls = true, prefix = false },
7
+ ) {
8
+ const workspaceLineBuffers = {};
9
+ const formatLine = (line, workspaceName) => {
10
+ const prefixedLine = prefix ? `[${workspaceName}] ${line}` : line;
11
+ return `\x1b[0m${prefixedLine}`;
12
+ };
13
+ for await (const { metadata, chunk } of output.text()) {
14
+ const workspaceName = metadata.workspace.name;
15
+ const sanitizedChunk = sanitizeChunk(chunk, stripDisruptiveControls);
16
+ const prior = workspaceLineBuffers[workspaceName] ?? "";
17
+ const content = prior + sanitizedChunk;
18
+ const lines = content.split("\n");
19
+ for (const line of lines) {
20
+ if (line)
21
+ yield {
22
+ line: formatLine(line, workspaceName),
23
+ metadata,
24
+ };
25
+ }
26
+ workspaceLineBuffers[workspaceName] = content.endsWith("\n")
27
+ ? ""
28
+ : (lines[lines.length - 1] ?? "");
29
+ }
30
+ }
31
+ const renderPlainOutput = async (
32
+ output,
33
+ { stripDisruptiveControls = true, prefix = false },
34
+ ) => {
35
+ for await (const { line, metadata } of generatePlainOutputLines(output, {
36
+ stripDisruptiveControls,
37
+ prefix,
38
+ })) {
39
+ process[metadata.streamName].write(line + "\n");
40
+ }
41
+ };
42
+
43
+ export { generatePlainOutputLines, renderPlainOutput };
@@ -0,0 +1,4 @@
1
+ export declare const sanitizeChunk: (
2
+ input: string,
3
+ stripDisruptiveControls?: boolean,
4
+ ) => string;
@@ -0,0 +1,101 @@
1
+ // CONCATENATED MODULE: ./src/cli/commands/runScript/output/sanitizeChunk.ts
2
+ const sanitizeChunk = (input, stripDisruptiveControls = false) => {
3
+ if (!stripDisruptiveControls) {
4
+ return input.replace(/\r\n/g, "\n");
5
+ }
6
+ // 1) Normalize newline-ish controls
7
+ let normalizedText = input
8
+ .replace(/\r\n/g, "\n")
9
+ .replace(/\r/g, "\n")
10
+ .replace(/\f/g, "\n")
11
+ .replace(/\v/g, "\n");
12
+ // 2) Remove disruptive single-byte controls (except \n, \t)
13
+ // - backspace, bell, and C1 controls
14
+ // eslint-disable-next-line no-control-regex
15
+ normalizedText = normalizedText.replace(/[\b\x07\x80-\x9F]/g, "");
16
+ // 3) Strip ANSI sequences, keeping only SGR (CSI ... m)
17
+ //
18
+ // We'll scan rather than rely on one giant regex so we can:
19
+ // - keep SGR exactly
20
+ // - drop any other ESC sequence
21
+ // - handle incomplete ESC sequences conservatively (drop the ESC byte itself)
22
+ //
23
+ // ESC = \x1B
24
+ const ESC = "\x1B";
25
+ let result = "";
26
+ for (let index = 0; index < normalizedText.length; index++) {
27
+ const currentChar = normalizedText[index];
28
+ if (currentChar !== ESC) {
29
+ result += currentChar;
30
+ continue;
31
+ }
32
+ // If ESC is last char, drop it
33
+ if (index + 1 >= normalizedText.length) break;
34
+ const nextChar = normalizedText[index + 1];
35
+ // Keep only CSI ... m (ESC [ ... m)
36
+ if (nextChar === "[") {
37
+ // Find final byte of CSI sequence (per spec: 0x40-0x7E).
38
+ // We only keep it if the final byte is 'm'.
39
+ let scanIndex = index + 2;
40
+ while (scanIndex < normalizedText.length) {
41
+ const code = normalizedText.charCodeAt(scanIndex);
42
+ if (code >= 0x40 && code <= 0x7e) break; // final byte
43
+ scanIndex++;
44
+ }
45
+ // If we didn't find a final byte, drop the ESC and stop (incomplete)
46
+ if (scanIndex >= normalizedText.length) break;
47
+ const finalByte = normalizedText[scanIndex];
48
+ if (finalByte === "m") {
49
+ // Keep full SGR sequence
50
+ result += normalizedText.slice(index, scanIndex + 1);
51
+ }
52
+ // else: drop the entire CSI sequence
53
+ index = scanIndex; // advance past sequence
54
+ continue;
55
+ }
56
+ // All other ESC sequences: drop them.
57
+ //
58
+ // For 2-byte sequences (like ESC c), we can just drop ESC+next.
59
+ // For string-terminated families (OSC/DCS/APC/PM/SOS), we should skip until terminator.
60
+ //
61
+ // OSC: ESC ] ... (BEL or ESC \)
62
+ // DCS: ESC P ... (ST = ESC \)
63
+ // APC: ESC _ ... (ST)
64
+ // PM : ESC ^ ... (ST)
65
+ // SOS: ESC X ... (ST)
66
+ if (
67
+ nextChar === "]" ||
68
+ nextChar === "P" ||
69
+ nextChar === "_" ||
70
+ nextChar === "^" ||
71
+ nextChar === "X"
72
+ ) {
73
+ let scanIndex = index + 2;
74
+ while (scanIndex < normalizedText.length) {
75
+ const currentByte = normalizedText[scanIndex];
76
+ // BEL terminator (OSC can end with BEL)
77
+ if (currentByte === "\x07") {
78
+ scanIndex++;
79
+ break;
80
+ }
81
+ // ST terminator: ESC \
82
+ if (
83
+ currentByte === ESC &&
84
+ scanIndex + 1 < normalizedText.length &&
85
+ normalizedText[scanIndex + 1] === "\\"
86
+ ) {
87
+ scanIndex += 2;
88
+ break;
89
+ }
90
+ scanIndex++;
91
+ }
92
+ index = scanIndex - 1; // -1 because loop will index++
93
+ continue;
94
+ }
95
+ // Fallback: treat as a 2-byte escape and drop ESC + next.
96
+ index += 1;
97
+ }
98
+ return result;
99
+ };
100
+
101
+ export { sanitizeChunk };
@@ -1,13 +1,19 @@
1
1
  import { type Command } from "commander";
2
2
  export interface RunCliOptions {
3
- argv?: string | string[];
3
+ argv?: string | string[];
4
+ /** Should be `true` if args do not include the binary name (e.g. `bunx bun-workspaces`) */
5
+ programmatic?: true;
4
6
  }
5
- export interface CliProgram {
6
- run: (options?: RunCliOptions) => Promise<void>;
7
+ export interface CLI {
8
+ run: (options?: RunCliOptions) => Promise<void>;
7
9
  }
8
- export interface CreateCliProgramOptions {
9
- handleError?: (error: Error) => void;
10
- postInit?: (program: Command) => unknown;
11
- defaultCwd?: string;
10
+ export interface CreateCliOptions {
11
+ handleError?: (error: Error) => void;
12
+ postInit?: (program: Command) => unknown;
13
+ defaultCwd?: string;
12
14
  }
13
- export declare const createCli: ({ handleError, postInit, defaultCwd, }?: CreateCliProgramOptions) => CliProgram;
15
+ export declare const createCli: ({
16
+ handleError,
17
+ postInit,
18
+ defaultCwd,
19
+ }?: CreateCliOptions) => CLI;
@@ -1,43 +1,98 @@
1
1
  import { createCommand } from "commander";
2
2
  import package_0 from "../../package.json";
3
- import { getRequiredBunVersion, validateCurrentBunVersion } from "../internal/bunVersion.mjs";
4
- import { logger } from "../internal/logger.mjs";
5
- import { initializeWithGlobalOptions } from "./globalOptions/index.mjs";
6
- import { defineProjectCommands } from "./projectCommands/index.mjs";
7
- const createCli = ({ handleError, postInit, defaultCwd = process.cwd() } = {})=>{
8
- const run = async ({ argv = process.argv } = {})=>{
9
- const errorListener = handleError ?? ((error)=>{
10
- logger.error(error);
11
- logger.error("Unhandled rejection");
12
- process.exit(1);
13
- });
14
- process.on("unhandledRejection", errorListener);
15
- try {
16
- const program = createCommand("bunx bun-workspaces").description("CLI for utilities for Bun workspaces").version(package_0.version).configureOutput({
17
- writeOut: (s)=>logger.info(s),
18
- writeErr: (s)=>s.startsWith("Usage") ? logger.info(s) : logger.error(s)
19
- });
20
- postInit?.(program);
21
- if (!validateCurrentBunVersion()) {
22
- logger.error(`Bun version mismatch. Required: ${getRequiredBunVersion()}, Found: ${Bun.version}`);
23
- process.exit(1);
24
- }
25
- const args = "string" == typeof argv ? argv.split(" ") : argv;
26
- const { project } = initializeWithGlobalOptions(program, args, defaultCwd);
27
- if (!project) return;
28
- defineProjectCommands({
29
- program,
30
- project
31
- });
32
- await program.parseAsync(args);
33
- } catch (error) {
34
- errorListener(error);
35
- } finally{
36
- process.off("unhandledRejection", errorListener);
37
- }
38
- };
39
- return {
40
- run
41
- };
3
+ import { validateCurrentBunVersion } from "../internal/bun/index.mjs";
4
+ import { BunWorkspacesError } from "../internal/core/index.mjs";
5
+ import { logger } from "../internal/logger/index.mjs";
6
+ import {
7
+ defineGlobalCommands,
8
+ defineProjectCommands,
9
+ } from "./commands/index.mjs";
10
+ import { fatalErrorLogger } from "./fatalErrorLogger.mjs";
11
+ import { initializeWithGlobalOptions } from "./globalOptions/index.mjs"; // CONCATENATED MODULE: external "commander"
12
+ // CONCATENATED MODULE: external "../../package.json"
13
+ // CONCATENATED MODULE: external "../internal/bun/index.mjs"
14
+ // CONCATENATED MODULE: external "../internal/core/index.mjs"
15
+ // CONCATENATED MODULE: external "../internal/logger/index.mjs"
16
+ // CONCATENATED MODULE: external "./commands/index.mjs"
17
+ // CONCATENATED MODULE: external "./fatalErrorLogger.mjs"
18
+ // CONCATENATED MODULE: external "./globalOptions/index.mjs"
19
+ // CONCATENATED MODULE: ./src/cli/createCli.ts
20
+
21
+ const createCli = ({
22
+ handleError,
23
+ postInit,
24
+ defaultCwd = process.cwd(),
25
+ } = {}) => {
26
+ logger.debug(`Creating CLI with default cwd: ${defaultCwd}`);
27
+ const run = async ({ argv = process.argv, programmatic } = {}) => {
28
+ const errorListener =
29
+ handleError ??
30
+ ((error) => {
31
+ fatalErrorLogger.error(error);
32
+ process.exit(1);
33
+ });
34
+ process.on("unhandledRejection", errorListener);
35
+ try {
36
+ const program = createCommand("bun-workspaces")
37
+ .description("A CLI on top of native Bun workspaces")
38
+ .version(package_0.version)
39
+ .showHelpAfterError(true);
40
+ postInit?.(program);
41
+ const rawArgs = typeof argv === "string" ? argv.split(/s+/) : argv;
42
+ const { args, postTerminatorArgs } = (() => {
43
+ const terminatorIndex = rawArgs.findIndex((arg) => arg === "--");
44
+ return {
45
+ args:
46
+ terminatorIndex !== -1
47
+ ? rawArgs.slice(0, terminatorIndex)
48
+ : rawArgs,
49
+ postTerminatorArgs:
50
+ terminatorIndex !== -1 ? rawArgs.slice(terminatorIndex + 1) : [],
51
+ };
52
+ })();
53
+ const bunVersionError = validateCurrentBunVersion();
54
+ if (bunVersionError) {
55
+ fatalErrorLogger.error(bunVersionError.message);
56
+ process.exit(1);
57
+ }
58
+ const { project, projectError } = initializeWithGlobalOptions(
59
+ program,
60
+ args,
61
+ defaultCwd,
62
+ );
63
+ if (postTerminatorArgs.length) {
64
+ logger.debug("Has post-terminator args");
65
+ }
66
+ logger.debug(`Bun version: ${Bun.version}`);
67
+ defineProjectCommands({
68
+ program,
69
+ project,
70
+ projectError,
71
+ postTerminatorArgs,
72
+ });
73
+ defineGlobalCommands({
74
+ program,
75
+ postTerminatorArgs,
76
+ });
77
+ logger.debug(`Commands initialized. Parsing args...`);
78
+ await program.parseAsync(args, {
79
+ from: programmatic ? "user" : "node",
80
+ });
81
+ } catch (error) {
82
+ if (error instanceof BunWorkspacesError) {
83
+ logger.debug(error);
84
+ fatalErrorLogger.error(error.message);
85
+ process.exit(1);
86
+ } else {
87
+ errorListener(error);
88
+ }
89
+ } finally {
90
+ process.off("unhandledRejection", errorListener);
91
+ }
92
+ };
93
+ return {
94
+ run,
95
+ };
42
96
  };
97
+
43
98
  export { createCli };
@@ -0,0 +1 @@
1
+ export declare const fatalErrorLogger: import("../internal/logger").Logger;
@@ -0,0 +1,7 @@
1
+ import { createLogger } from "../internal/logger/index.mjs"; // CONCATENATED MODULE: external "../internal/logger/index.mjs"
2
+ // CONCATENATED MODULE: ./src/cli/fatalErrorLogger.ts
3
+
4
+ const fatalErrorLogger = createLogger("fatalError");
5
+ fatalErrorLogger.printLevel = "error";
6
+
7
+ export { fatalErrorLogger };