bun-workspaces 1.0.1 → 1.0.2
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/package.json +1 -1
- package/src/cli/commands/commandHandlerUtils.d.ts +1 -0
- package/src/cli/commands/runScript/handleRunScript.mjs +2 -1
- package/src/cli/commands/runScript/output/renderGroupedOutput.d.ts +1 -0
- package/src/cli/commands/runScript/output/renderGroupedOutput.mjs +50 -27
- package/src/cli/createCli.mjs +4 -1
- package/src/cli/globalOptions/globalOptions.d.ts +2 -0
- package/src/cli/globalOptions/globalOptions.mjs +13 -5
- package/src/cli/middleware.d.ts +11 -0
- package/src/cli/middleware.mjs +1 -0
package/package.json
CHANGED
|
@@ -13,6 +13,7 @@ export type GlobalCommandContext = {
|
|
|
13
13
|
postTerminatorArgs: string[];
|
|
14
14
|
middleware: CliMiddleware;
|
|
15
15
|
outputWriters: Required<WriteOutputOptions>;
|
|
16
|
+
terminalWidth: number;
|
|
16
17
|
};
|
|
17
18
|
export type ProjectCommandContext = GlobalCommandContext & {
|
|
18
19
|
project: FileSystemProject;
|
|
@@ -28,7 +28,7 @@ import { renderPlainOutput } from "./output/renderPlainOutput.mjs"; // CONCATENA
|
|
|
28
28
|
const runScript = handleProjectCommand(
|
|
29
29
|
"runScript",
|
|
30
30
|
async (
|
|
31
|
-
{ project, postTerminatorArgs, outputWriters },
|
|
31
|
+
{ project, postTerminatorArgs, outputWriters, terminalWidth },
|
|
32
32
|
positionalScript,
|
|
33
33
|
positionalWorkspacePatterns,
|
|
34
34
|
options,
|
|
@@ -147,6 +147,7 @@ const runScript = handleProjectCommand(
|
|
|
147
147
|
scriptEventTarget,
|
|
148
148
|
groupedLines,
|
|
149
149
|
outputWriters,
|
|
150
|
+
terminalWidth,
|
|
150
151
|
),
|
|
151
152
|
prefixed: () =>
|
|
152
153
|
renderPlainOutput(output, outputWriters, {
|
|
@@ -71,6 +71,7 @@ const renderGroupedOutput = async (
|
|
|
71
71
|
scriptEventTarget,
|
|
72
72
|
activeScriptLines,
|
|
73
73
|
outputWriters,
|
|
74
|
+
terminalWidth,
|
|
74
75
|
) => {
|
|
75
76
|
const workspaceState = workspaces.reduce((acc, workspace) => {
|
|
76
77
|
acc[workspace.name] = {
|
|
@@ -99,7 +100,7 @@ const renderGroupedOutput = async (
|
|
|
99
100
|
isReset = true;
|
|
100
101
|
logger.debug("Resetting TUI state");
|
|
101
102
|
outputWriters.stdout(cursorOps.show());
|
|
102
|
-
process.stdin.unref();
|
|
103
|
+
process.stdin.unref?.();
|
|
103
104
|
process.stdin.setRawMode?.(false);
|
|
104
105
|
};
|
|
105
106
|
let previousHeight = 0;
|
|
@@ -111,18 +112,59 @@ const renderGroupedOutput = async (
|
|
|
111
112
|
if (isFinal) {
|
|
112
113
|
didFinalRender = true;
|
|
113
114
|
}
|
|
114
|
-
const width = Math.max(2, process.stdout.columns);
|
|
115
|
+
const width = Math.max(2, terminalWidth || process.stdout.columns);
|
|
115
116
|
const linesToWrite = [];
|
|
117
|
+
const workspaceBoxContents = {};
|
|
116
118
|
workspaces.forEach((workspace) => {
|
|
117
119
|
const state = workspaceState[workspace.name];
|
|
120
|
+
let statusText = state.status;
|
|
121
|
+
const hasExitCode = state.exitCode && state.exitCode !== -1;
|
|
122
|
+
const exitState =
|
|
123
|
+
hasExitCode && state.signal
|
|
124
|
+
? "exitAndSignal"
|
|
125
|
+
: hasExitCode
|
|
126
|
+
? "exit"
|
|
127
|
+
: state.signal
|
|
128
|
+
? "signal"
|
|
129
|
+
: null;
|
|
130
|
+
if (exitState === "exitAndSignal") {
|
|
131
|
+
statusText += ` (exit code: ${state.exitCode}, signal: ${state.signal})`;
|
|
132
|
+
} else if (exitState === "exit") {
|
|
133
|
+
statusText += ` (exit code: ${state.exitCode})`;
|
|
134
|
+
} else if (exitState === "signal") {
|
|
135
|
+
statusText += ` (signal: ${state.signal})`;
|
|
136
|
+
}
|
|
137
|
+
const workspaceLine = "Workspace: " + textOps.bold(workspace.name);
|
|
138
|
+
const statusLine =
|
|
139
|
+
" Status: " + textOps[STATUS_COLORS[state.status]](statusText);
|
|
140
|
+
workspaceBoxContents[workspace.name] = {
|
|
141
|
+
name: workspaceLine,
|
|
142
|
+
status: statusLine,
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
const padding = 4; // left border, spaces, right border
|
|
146
|
+
const workspaceBoxWidth = Math.min(
|
|
147
|
+
width,
|
|
148
|
+
Math.max(
|
|
149
|
+
...Object.values(workspaceBoxContents).map((content) =>
|
|
150
|
+
Math.max(
|
|
151
|
+
calculateVisibleLength(content.name),
|
|
152
|
+
calculateVisibleLength(content.status),
|
|
153
|
+
),
|
|
154
|
+
),
|
|
155
|
+
) + padding,
|
|
156
|
+
);
|
|
157
|
+
workspaces.forEach((workspace) => {
|
|
158
|
+
const state = workspaceState[workspace.name];
|
|
159
|
+
const { name: workspaceNameContent, status: statusTextContent } =
|
|
160
|
+
workspaceBoxContents[workspace.name];
|
|
118
161
|
linesToWrite.push({
|
|
119
162
|
text: textOps[BORDER_COLOR](
|
|
120
|
-
"┌" + "─".repeat(
|
|
163
|
+
"┌" + "─".repeat(workspaceBoxWidth - 2) + "┐",
|
|
121
164
|
),
|
|
122
165
|
type: "border",
|
|
123
166
|
});
|
|
124
167
|
const borderText = (text) => {
|
|
125
|
-
const padding = 4; // left border, spaces, right border
|
|
126
168
|
const visibleLength = calculateVisibleLength(text);
|
|
127
169
|
const truncated =
|
|
128
170
|
visibleLength > width - padding
|
|
@@ -131,40 +173,21 @@ const renderGroupedOutput = async (
|
|
|
131
173
|
return (
|
|
132
174
|
textOps[BORDER_COLOR]("│ ") +
|
|
133
175
|
truncated +
|
|
134
|
-
" ".repeat(Math.max(0,
|
|
176
|
+
" ".repeat(Math.max(0, workspaceBoxWidth - visibleLength - padding)) +
|
|
135
177
|
textOps[BORDER_COLOR](" │")
|
|
136
178
|
);
|
|
137
179
|
};
|
|
138
180
|
linesToWrite.push({
|
|
139
|
-
text: borderText(
|
|
181
|
+
text: borderText(workspaceNameContent),
|
|
140
182
|
type: "borderedContent",
|
|
141
183
|
});
|
|
142
|
-
let statusText = state.status;
|
|
143
|
-
const hasExitCode = state.exitCode && state.exitCode !== -1;
|
|
144
|
-
const exitState =
|
|
145
|
-
hasExitCode && state.signal
|
|
146
|
-
? "exitAndSignal"
|
|
147
|
-
: hasExitCode
|
|
148
|
-
? "exit"
|
|
149
|
-
: state.signal
|
|
150
|
-
? "signal"
|
|
151
|
-
: null;
|
|
152
|
-
if (exitState === "exitAndSignal") {
|
|
153
|
-
statusText += ` (exit code: ${state.exitCode}, signal: ${state.signal})`;
|
|
154
|
-
} else if (exitState === "exit") {
|
|
155
|
-
statusText += ` (exit code: ${state.exitCode})`;
|
|
156
|
-
} else if (exitState === "signal") {
|
|
157
|
-
statusText += ` (signal: ${state.signal})`;
|
|
158
|
-
}
|
|
159
184
|
linesToWrite.push({
|
|
160
|
-
text: borderText(
|
|
161
|
-
" Status: " + textOps[STATUS_COLORS[state.status]](statusText),
|
|
162
|
-
),
|
|
185
|
+
text: borderText(statusTextContent),
|
|
163
186
|
type: "borderedContent",
|
|
164
187
|
});
|
|
165
188
|
linesToWrite.push({
|
|
166
189
|
text: textOps[BORDER_COLOR](
|
|
167
|
-
"└" + "─".repeat(
|
|
190
|
+
"└" + "─".repeat(workspaceBoxWidth - 2) + "┘",
|
|
168
191
|
),
|
|
169
192
|
type: "border",
|
|
170
193
|
});
|
package/src/cli/createCli.mjs
CHANGED
|
@@ -29,7 +29,7 @@ const createCli = ({ defaultCwd = process.cwd(), defaultMiddleware } = {}) => {
|
|
|
29
29
|
programmatic,
|
|
30
30
|
middleware: _runMiddleware,
|
|
31
31
|
writeOutput,
|
|
32
|
-
terminalWidth,
|
|
32
|
+
terminalWidth = process.stdout.columns,
|
|
33
33
|
} = {}) => {
|
|
34
34
|
const middleware = resolveMiddleware(
|
|
35
35
|
defaultMiddleware ?? {},
|
|
@@ -94,6 +94,7 @@ const createCli = ({ defaultCwd = process.cwd(), defaultMiddleware } = {}) => {
|
|
|
94
94
|
program,
|
|
95
95
|
args,
|
|
96
96
|
defaultCwd,
|
|
97
|
+
middleware,
|
|
97
98
|
);
|
|
98
99
|
middleware.findProject({
|
|
99
100
|
...defaultContext,
|
|
@@ -111,12 +112,14 @@ const createCli = ({ defaultCwd = process.cwd(), defaultMiddleware } = {}) => {
|
|
|
111
112
|
postTerminatorArgs,
|
|
112
113
|
middleware,
|
|
113
114
|
outputWriters,
|
|
115
|
+
terminalWidth,
|
|
114
116
|
});
|
|
115
117
|
defineGlobalCommands({
|
|
116
118
|
program,
|
|
117
119
|
postTerminatorArgs,
|
|
118
120
|
middleware,
|
|
119
121
|
outputWriters,
|
|
122
|
+
terminalWidth,
|
|
120
123
|
});
|
|
121
124
|
logger.debug(`Commands initialized. Parsing args...`);
|
|
122
125
|
middleware.preParse({
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { type Command } from "commander";
|
|
2
|
+
import type { CliMiddleware } from "../middleware";
|
|
2
3
|
export declare const initializeWithGlobalOptions: (
|
|
3
4
|
program: Command,
|
|
4
5
|
args: string[],
|
|
5
6
|
defaultCwd: string,
|
|
7
|
+
middleware: CliMiddleware,
|
|
6
8
|
) => {
|
|
7
9
|
project: import("../../internal/core").Simplify<{
|
|
8
10
|
readonly rootDirectory: string;
|
|
@@ -47,14 +47,22 @@ const getWorkingDirectoryFromArgs = (program, args, defaultCwd) => {
|
|
|
47
47
|
program.parseOptions(args);
|
|
48
48
|
return program.opts().cwd;
|
|
49
49
|
};
|
|
50
|
-
const defineGlobalOptions = (program, args, defaultCwd) => {
|
|
50
|
+
const defineGlobalOptions = (program, args, defaultCwd, middleware) => {
|
|
51
51
|
const cwd = getWorkingDirectoryFromArgs(program, args, defaultCwd);
|
|
52
|
-
|
|
52
|
+
const exists = fs.existsSync(cwd);
|
|
53
|
+
const isDirectory = exists ? fs.statSync(cwd).isDirectory() : false;
|
|
54
|
+
middleware.processWorkingDirectory({
|
|
55
|
+
commanderProgram: program,
|
|
56
|
+
workingDirectory: cwd,
|
|
57
|
+
exists,
|
|
58
|
+
isDirectory,
|
|
59
|
+
});
|
|
60
|
+
if (!exists) {
|
|
53
61
|
throw new ERRORS.WorkingDirectoryNotFound(
|
|
54
62
|
`Working directory not found at path "${cwd}"`,
|
|
55
63
|
);
|
|
56
64
|
}
|
|
57
|
-
if (!
|
|
65
|
+
if (!isDirectory) {
|
|
58
66
|
throw new ERRORS.WorkingDirectoryNotADirectory(
|
|
59
67
|
`Working directory is not a directory at path "${cwd}"`,
|
|
60
68
|
);
|
|
@@ -90,9 +98,9 @@ const applyGlobalOptions = (options) => {
|
|
|
90
98
|
projectError: error,
|
|
91
99
|
};
|
|
92
100
|
};
|
|
93
|
-
const initializeWithGlobalOptions = (program, args, defaultCwd) => {
|
|
101
|
+
const initializeWithGlobalOptions = (program, args, defaultCwd, middleware) => {
|
|
94
102
|
program.allowUnknownOption(true);
|
|
95
|
-
const { cwd } = defineGlobalOptions(program, args, defaultCwd);
|
|
103
|
+
const { cwd } = defineGlobalOptions(program, args, defaultCwd, middleware);
|
|
96
104
|
program.parseOptions(args);
|
|
97
105
|
program.allowUnknownOption(false);
|
|
98
106
|
const options = program.opts();
|
package/src/cli/middleware.d.ts
CHANGED
|
@@ -10,9 +10,16 @@ export type InitProgramContext = {
|
|
|
10
10
|
argv: string[];
|
|
11
11
|
};
|
|
12
12
|
export type ProcessArgvContext = {
|
|
13
|
+
commanderProgram: CommanderProgram;
|
|
13
14
|
args: string[];
|
|
14
15
|
postTerminatorArgs: string[];
|
|
15
16
|
};
|
|
17
|
+
export type ProcessWorkingDirectoryContext = {
|
|
18
|
+
commanderProgram: CommanderProgram;
|
|
19
|
+
workingDirectory: string;
|
|
20
|
+
exists: boolean;
|
|
21
|
+
isDirectory: boolean;
|
|
22
|
+
};
|
|
16
23
|
export type FindProjectContext = {
|
|
17
24
|
commanderProgram: CommanderProgram;
|
|
18
25
|
project: FileSystemProject;
|
|
@@ -52,6 +59,10 @@ export type CliMiddleware = {
|
|
|
52
59
|
initProgram: (context: InitProgramContext) => CommanderProgram;
|
|
53
60
|
/** Before the true parsing, just splitting the argv into args and post-terminator args */
|
|
54
61
|
processArgv: (context: ProcessArgvContext) => CommanderProgram;
|
|
62
|
+
/** Before the working directory is changed */
|
|
63
|
+
processWorkingDirectory: (
|
|
64
|
+
context: ProcessWorkingDirectoryContext,
|
|
65
|
+
) => CommanderProgram;
|
|
55
66
|
/** After the project has been initialized from global options */
|
|
56
67
|
findProject: (context: FindProjectContext) => CommanderProgram;
|
|
57
68
|
/** Before the Commander program parses the args */
|