bun-workspaces 1.8.2 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +537 -0
- package/README.md +51 -13
- package/package.json +1 -1
- package/src/2392.mjs +184 -3
- package/src/5166.mjs +1 -0
- package/src/8529.mjs +10 -0
- package/src/affected/affectedBaseRef.mjs +12 -0
- package/src/affected/externalDependencyChanges.mjs +47 -0
- package/src/affected/fileAffectedWorkspaces.mjs +152 -54
- package/src/affected/gitAffectedFiles.mjs +44 -1
- package/src/affected/gitAffectedWorkspaces.mjs +73 -3
- package/src/affected/index.mjs +2 -0
- package/src/ai/mcp/serverState.mjs +1 -1
- package/src/cli/commands/commandHandlerUtils.mjs +12 -7
- package/src/cli/commands/commands.mjs +4 -1
- package/src/cli/commands/handleSimpleCommands.mjs +2 -2
- package/src/cli/commands/listAffected.mjs +184 -0
- package/src/cli/commands/runScript/handleRunAffected.mjs +99 -0
- package/src/cli/commands/runScript/handleRunScript.mjs +19 -202
- package/src/cli/commands/runScript/index.mjs +1 -0
- package/src/cli/commands/runScript/scriptRunFlow.mjs +213 -0
- package/src/cli/index.d.ts +749 -134
- package/src/config/public.d.ts +66 -2
- package/src/config/rootConfig/rootConfig.mjs +9 -9
- package/src/config/rootConfig/rootConfigSchema.mjs +3 -0
- package/src/config/workspaceConfig/mergeWorkspaceConfig.mjs +33 -19
- package/src/config/workspaceConfig/workspaceConfig.mjs +3 -0
- package/src/config/workspaceConfig/workspaceConfigSchema.mjs +26 -0
- package/src/index.d.ts +307 -5
- package/src/index.mjs +1 -0
- package/src/internal/bun/bunLock.mjs +33 -0
- package/src/internal/generated/aiDocs/docs.mjs +169 -9
- package/src/internal/generated/ajv/validateRootConfig.mjs +1 -1
- package/src/internal/generated/ajv/validateWorkspaceConfig.mjs +1 -1
- package/src/project/implementations/fileSystemProject/affectedWorkspaces.mjs +227 -0
- package/src/project/implementations/{fileSystemProject.mjs → fileSystemProject/fileSystemProject.mjs} +169 -12
- package/src/project/implementations/fileSystemProject/index.mjs +4 -0
- package/src/project/implementations/memoryProject.mjs +1 -0
- package/src/project/implementations/projectBase.mjs +11 -17
- package/src/project/index.mjs +1 -1
- package/src/rslib-runtime.mjs +0 -31
- package/src/workspaces/applyWorkspacePatternConfigs.mjs +16 -2
- package/src/workspaces/dependencyGraph/resolveDependencies.mjs +68 -18
- package/src/workspaces/dependencyGraph/validateDependencyRules.mjs +14 -7
- package/src/workspaces/findWorkspaces.mjs +3 -0
- package/src/workspaces/workspace.mjs +8 -2
- package/src/workspaces/workspacePattern.mjs +134 -46
|
@@ -1,22 +1,90 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { parseBunLockPackageVersions } from "../internal/bun/bunLock.mjs";
|
|
4
|
+
import { BunWorkspacesError } from "../internal/core/index.mjs";
|
|
5
|
+
import { logger } from "../internal/logger/index.mjs";
|
|
6
|
+
import { computeExternalDependencyChanges } from "./externalDependencyChanges.mjs";
|
|
1
7
|
import { getFileAffectedWorkspaces } from "./fileAffectedWorkspaces.mjs";
|
|
2
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
getGitAffectedFiles,
|
|
10
|
+
readProjectFileAtGitRef,
|
|
11
|
+
} from "./gitAffectedFiles.mjs";
|
|
3
12
|
|
|
13
|
+
const BUN_LOCK_PROJECT_RELATIVE_PATH = "bun.lock";
|
|
14
|
+
const readCurrentBunLock = (rootDirectory) => {
|
|
15
|
+
const lockPath = path.join(rootDirectory, BUN_LOCK_PROJECT_RELATIVE_PATH);
|
|
16
|
+
try {
|
|
17
|
+
return fs.readFileSync(lockPath, "utf8");
|
|
18
|
+
} catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
const loadVersionsAt = async (rootDirectory, ref) => {
|
|
23
|
+
const contents = await readProjectFileAtGitRef({
|
|
24
|
+
rootDirectory,
|
|
25
|
+
ref,
|
|
26
|
+
projectRelativePath: BUN_LOCK_PROJECT_RELATIVE_PATH,
|
|
27
|
+
});
|
|
28
|
+
if (contents === null) return new Map();
|
|
29
|
+
const parsed = parseBunLockPackageVersions(contents);
|
|
30
|
+
if (parsed instanceof BunWorkspacesError) {
|
|
31
|
+
logger.warn(
|
|
32
|
+
`Could not parse bun.lock at ref "${ref}": ${parsed.message}. Treating as empty.`,
|
|
33
|
+
);
|
|
34
|
+
return new Map();
|
|
35
|
+
}
|
|
36
|
+
return parsed;
|
|
37
|
+
};
|
|
38
|
+
const loadCurrentVersions = (rootDirectory) => {
|
|
39
|
+
const contents = readCurrentBunLock(rootDirectory);
|
|
40
|
+
if (contents === null) return new Map();
|
|
41
|
+
const parsed = parseBunLockPackageVersions(contents);
|
|
42
|
+
if (parsed instanceof BunWorkspacesError) {
|
|
43
|
+
logger.warn(
|
|
44
|
+
`Could not parse current bun.lock: ${parsed.message}. Treating as empty.`,
|
|
45
|
+
);
|
|
46
|
+
return new Map();
|
|
47
|
+
}
|
|
48
|
+
return parsed;
|
|
49
|
+
};
|
|
4
50
|
const getGitAffectedWorkspaces = async ({
|
|
5
51
|
rootDirectory,
|
|
6
52
|
workspacesOptions,
|
|
7
53
|
gitOptions,
|
|
8
54
|
}) => {
|
|
9
|
-
const {
|
|
55
|
+
const {
|
|
56
|
+
files: gitFiles,
|
|
57
|
+
baseSha,
|
|
58
|
+
headSha,
|
|
59
|
+
} = await getGitAffectedFiles({
|
|
10
60
|
rootDirectory,
|
|
11
61
|
...gitOptions,
|
|
12
62
|
});
|
|
13
63
|
const gitFileByPath = new Map(
|
|
14
64
|
gitFiles.map((file) => [file.projectFilePath, file]),
|
|
15
65
|
);
|
|
66
|
+
const projectWorkspaces = workspacesOptions.workspaces ?? [];
|
|
67
|
+
const externalDepChangesByWorkspace =
|
|
68
|
+
workspacesOptions.ignoreExternalDependencies || !projectWorkspaces.length
|
|
69
|
+
? new Map()
|
|
70
|
+
: computeExternalDependencyChanges({
|
|
71
|
+
workspaces: projectWorkspaces,
|
|
72
|
+
baseLock: await loadVersionsAt(rootDirectory, gitOptions.baseRef),
|
|
73
|
+
headLock:
|
|
74
|
+
gitOptions.headRef === "HEAD"
|
|
75
|
+
? loadCurrentVersions(rootDirectory)
|
|
76
|
+
: await loadVersionsAt(rootDirectory, gitOptions.headRef),
|
|
77
|
+
});
|
|
78
|
+
const {
|
|
79
|
+
workspaces: _omit,
|
|
80
|
+
ignoreExternalDependencies: _omit2,
|
|
81
|
+
...fileOpts
|
|
82
|
+
} = workspacesOptions;
|
|
16
83
|
const { affectedWorkspaces } = await getFileAffectedWorkspaces({
|
|
17
84
|
rootDirectory,
|
|
18
|
-
...
|
|
85
|
+
...fileOpts,
|
|
19
86
|
changedFilePaths: gitFiles.map((file) => file.projectFilePath),
|
|
87
|
+
externalDepChangesByWorkspace,
|
|
20
88
|
});
|
|
21
89
|
const annotatedWorkspaces = affectedWorkspaces.map((result) => ({
|
|
22
90
|
...result,
|
|
@@ -32,6 +100,8 @@ const getGitAffectedWorkspaces = async ({
|
|
|
32
100
|
}));
|
|
33
101
|
return {
|
|
34
102
|
affectedWorkspaces: annotatedWorkspaces,
|
|
103
|
+
baseSha,
|
|
104
|
+
headSha,
|
|
35
105
|
};
|
|
36
106
|
};
|
|
37
107
|
|
package/src/affected/index.mjs
CHANGED
|
@@ -3,12 +3,17 @@ import { BunWorkspacesError } from "../../internal/core/error/index.mjs";
|
|
|
3
3
|
import { createLogger, logger } from "../../internal/logger/index.mjs";
|
|
4
4
|
import { getCliCommandConfig } from "../../2392.mjs";
|
|
5
5
|
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Splits a multi-value CLI arg on whitespace (any of space/tab/newline). A
|
|
8
|
+
* literal space inside a value can be preserved by escaping it with a
|
|
9
|
+
* backslash (e.g. `path/with\ space`). Used for `--files` and
|
|
10
|
+
* `--workspace-patterns`, both of which accept output of `$(bw ...)`
|
|
11
|
+
* substitutions, which are typically newline-separated.
|
|
12
|
+
*/ const splitWhitespaceArg = (raw) =>
|
|
13
|
+
raw
|
|
14
|
+
.split(/(?<!\\)\s+/)
|
|
15
|
+
.filter(Boolean)
|
|
16
|
+
.map((value) => value.replace(/\\\s/g, " "));
|
|
12
17
|
const createWorkspaceInfoLines = (workspace) => [
|
|
13
18
|
`Workspace: ${workspace.name}${workspace.isRoot ? " (root)" : ""}`,
|
|
14
19
|
` - Aliases: ${workspace.aliases.join(", ")}`,
|
|
@@ -85,5 +90,5 @@ export {
|
|
|
85
90
|
createWorkspaceInfoLines,
|
|
86
91
|
handleGlobalCommand,
|
|
87
92
|
handleProjectCommand,
|
|
88
|
-
|
|
93
|
+
splitWhitespaceArg,
|
|
89
94
|
};
|
|
@@ -7,8 +7,9 @@ import {
|
|
|
7
7
|
tagInfo,
|
|
8
8
|
workspaceInfo,
|
|
9
9
|
} from "./handleSimpleCommands.mjs";
|
|
10
|
+
import { listAffected } from "./listAffected.mjs";
|
|
10
11
|
import { mcpServer } from "./mcp.mjs";
|
|
11
|
-
import { runScript } from "./runScript/index.mjs";
|
|
12
|
+
import { runAffected, runScript } from "./runScript/index.mjs";
|
|
12
13
|
|
|
13
14
|
const defineGlobalCommands = (context) => {
|
|
14
15
|
doctor(context);
|
|
@@ -22,6 +23,8 @@ const defineProjectCommands = (context) => {
|
|
|
22
23
|
tagInfo(context);
|
|
23
24
|
mcpServer(context);
|
|
24
25
|
runScript(context);
|
|
26
|
+
listAffected(context);
|
|
27
|
+
runAffected(context);
|
|
25
28
|
};
|
|
26
29
|
|
|
27
30
|
export { defineGlobalCommands, defineProjectCommands };
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
createWorkspaceInfoLines,
|
|
8
8
|
handleGlobalCommand,
|
|
9
9
|
handleProjectCommand,
|
|
10
|
-
|
|
10
|
+
splitWhitespaceArg,
|
|
11
11
|
} from "./commandHandlerUtils.mjs";
|
|
12
12
|
import { isJSONObject } from "../../8257.mjs";
|
|
13
13
|
|
|
@@ -51,7 +51,7 @@ const listWorkspaces = handleProjectCommand(
|
|
|
51
51
|
}
|
|
52
52
|
const patterns = positionalWorkspacePatterns?.length
|
|
53
53
|
? positionalWorkspacePatterns
|
|
54
|
-
:
|
|
54
|
+
: splitWhitespaceArg(options.workspacePatterns ?? "");
|
|
55
55
|
const workspaces = patterns?.length
|
|
56
56
|
? project.findWorkspacesByPattern(...patterns)
|
|
57
57
|
: project.workspaces;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { logger } from "../../internal/logger/index.mjs";
|
|
3
|
+
import {
|
|
4
|
+
commandOutputLogger,
|
|
5
|
+
createJsonLines,
|
|
6
|
+
handleProjectCommand,
|
|
7
|
+
splitWhitespaceArg,
|
|
8
|
+
} from "./commandHandlerUtils.mjs";
|
|
9
|
+
|
|
10
|
+
const SHORT_SHA_LENGTH = 7;
|
|
11
|
+
const shortSha = (sha) => sha.slice(0, SHORT_SHA_LENGTH);
|
|
12
|
+
const formatGitHeader = (metadata) => {
|
|
13
|
+
if (metadata.diffSource !== "git" || !metadata.git) return null;
|
|
14
|
+
const { baseRef, headRef, baseSha, headSha } = metadata.git;
|
|
15
|
+
return [
|
|
16
|
+
`Git base ref: \x1b[1m${baseRef}\x1b[0m (${shortSha(baseSha)})`,
|
|
17
|
+
`Git head ref: \x1b[1m${headRef}\x1b[0m (${shortSha(headSha)})`,
|
|
18
|
+
].join("\n");
|
|
19
|
+
};
|
|
20
|
+
const formatDependencyChain = (dependency) => {
|
|
21
|
+
const segments = dependency.chain.map((entry, index) => {
|
|
22
|
+
if (index === 0 || !entry.edgeSource) return entry.workspaceName;
|
|
23
|
+
return `\x1b[90m--[${entry.edgeSource}]->\x1b[0m ${entry.workspaceName}`;
|
|
24
|
+
});
|
|
25
|
+
return segments.join(" ");
|
|
26
|
+
};
|
|
27
|
+
const formatSourceMarker = (change) =>
|
|
28
|
+
change.source === "devDependencies" ? " (dev)" : "";
|
|
29
|
+
const formatExternalDepEntryShort = (change) =>
|
|
30
|
+
`${change.name}${formatSourceMarker(change)}`;
|
|
31
|
+
const formatExternalDepEntryDetailed = (change) => {
|
|
32
|
+
const versions =
|
|
33
|
+
change.baseVersion === null && change.headVersion === null
|
|
34
|
+
? "lockfile changed; precise diff unavailable"
|
|
35
|
+
: `${change.baseVersion ?? "(absent)"} -> ${change.headVersion ?? "(absent)"}`;
|
|
36
|
+
return `${change.name}${formatSourceMarker(change)} \x1b[90m[${versions}]\x1b[0m`;
|
|
37
|
+
};
|
|
38
|
+
const createWorkspaceSummaryLines = (result) => {
|
|
39
|
+
const { workspace, affectedReasons } = result;
|
|
40
|
+
const lines = [
|
|
41
|
+
`\x1b[1mWorkspace: ${workspace.name}\x1b[0m`,
|
|
42
|
+
`Path: ${workspace.path}`,
|
|
43
|
+
];
|
|
44
|
+
lines.push(
|
|
45
|
+
`\x1b[96mChanged input files:\x1b[0m ${affectedReasons.changedFiles.length}`,
|
|
46
|
+
);
|
|
47
|
+
if (affectedReasons.dependencies.length) {
|
|
48
|
+
lines.push(
|
|
49
|
+
`\x1b[96mAffected dependencies:\x1b[0m ${affectedReasons.dependencies.map(({ dependencyName }) => dependencyName).join(", ")}`,
|
|
50
|
+
);
|
|
51
|
+
} else {
|
|
52
|
+
lines.push(`\x1b[96mAffected dependencies:\x1b[0m (none)`);
|
|
53
|
+
}
|
|
54
|
+
if (affectedReasons.externalDependencies.length) {
|
|
55
|
+
lines.push(
|
|
56
|
+
`\x1b[96mChanged external dependencies:\x1b[0m ${affectedReasons.externalDependencies.map(formatExternalDepEntryShort).join(", ")}`,
|
|
57
|
+
);
|
|
58
|
+
} else {
|
|
59
|
+
lines.push(`\x1b[96mChanged external dependencies:\x1b[0m (none)`);
|
|
60
|
+
}
|
|
61
|
+
return lines;
|
|
62
|
+
};
|
|
63
|
+
const createWorkspaceDetailedLines = (result) => {
|
|
64
|
+
const { workspace, affectedReasons } = result;
|
|
65
|
+
const lines = [
|
|
66
|
+
`\x1b[1mWorkspace: ${workspace.name}\x1b[0m`,
|
|
67
|
+
`Path: ${workspace.path}`,
|
|
68
|
+
];
|
|
69
|
+
if (affectedReasons.changedFiles.length) {
|
|
70
|
+
lines.push("\x1b[96mChanged input files:\x1b[0m");
|
|
71
|
+
for (const file of affectedReasons.changedFiles) {
|
|
72
|
+
const reasons = file.gitReasons
|
|
73
|
+
?.filter((reason) => reason !== "diff")
|
|
74
|
+
.join(", ");
|
|
75
|
+
lines.push(
|
|
76
|
+
` - ${path.relative(workspace.path, file.projectFilePath)} \x1b[90m(input: ${JSON.stringify(file.inputMatch)})${reasons ? ` [${reasons}]` : ""}\x1b[0m`,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
lines.push("\x1b[96mChanged input files:\x1b[0m (none)");
|
|
81
|
+
}
|
|
82
|
+
if (affectedReasons.dependencies.length) {
|
|
83
|
+
lines.push("\x1b[96mAffected dependencies:\x1b[0m");
|
|
84
|
+
for (const dependency of affectedReasons.dependencies) {
|
|
85
|
+
lines.push(` - ${dependency.dependencyName}`);
|
|
86
|
+
lines.push(` chain: ${formatDependencyChain(dependency)}`);
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
lines.push("\x1b[96mAffected dependencies:\x1b[0m (none)");
|
|
90
|
+
}
|
|
91
|
+
if (affectedReasons.externalDependencies.length) {
|
|
92
|
+
lines.push("\x1b[96mChanged external dependencies:\x1b[0m");
|
|
93
|
+
for (const change of affectedReasons.externalDependencies) {
|
|
94
|
+
lines.push(` - ${formatExternalDepEntryDetailed(change)}`);
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
lines.push("\x1b[96mChanged external dependencies:\x1b[0m (none)");
|
|
98
|
+
}
|
|
99
|
+
return lines;
|
|
100
|
+
};
|
|
101
|
+
const listAffected = handleProjectCommand(
|
|
102
|
+
"listAffected",
|
|
103
|
+
async ({ project }, options) => {
|
|
104
|
+
logger.debug(`Options: ${JSON.stringify(options)}`);
|
|
105
|
+
if (options.files !== undefined && (options.base || options.head)) {
|
|
106
|
+
logger.error(
|
|
107
|
+
"CLI syntax error: --files cannot be used with --base or --head",
|
|
108
|
+
);
|
|
109
|
+
process.exit(1);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (options.detailed && !options.explain) {
|
|
113
|
+
logger.error("CLI syntax error: --detailed requires --explain");
|
|
114
|
+
process.exit(1);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const determineOptions =
|
|
118
|
+
options.files !== undefined
|
|
119
|
+
? {
|
|
120
|
+
diffSource: "fileList",
|
|
121
|
+
changedFiles: splitWhitespaceArg(options.files),
|
|
122
|
+
script: options.script,
|
|
123
|
+
ignoreWorkspaceDependencies:
|
|
124
|
+
options.ignoreWorkspaceDeps || undefined,
|
|
125
|
+
ignoreExternalDependencies: options.ignoreExternalDeps || undefined,
|
|
126
|
+
}
|
|
127
|
+
: {
|
|
128
|
+
diffSource: "git",
|
|
129
|
+
script: options.script,
|
|
130
|
+
ignoreWorkspaceDependencies:
|
|
131
|
+
options.ignoreWorkspaceDeps || undefined,
|
|
132
|
+
ignoreExternalDependencies: options.ignoreExternalDeps || undefined,
|
|
133
|
+
diffOptions: {
|
|
134
|
+
baseRef: options.base,
|
|
135
|
+
headRef: options.head,
|
|
136
|
+
ignoreUntracked: options.ignoreUntracked || undefined,
|
|
137
|
+
ignoreUnstaged: options.ignoreUnstaged || undefined,
|
|
138
|
+
ignoreStaged: options.ignoreStaged || undefined,
|
|
139
|
+
ignoreUncommitted: options.ignoreUncommitted || undefined,
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
const result = await project.determineAffectedWorkspaces(determineOptions);
|
|
143
|
+
const affectedResults = result.workspaceResults.filter(
|
|
144
|
+
({ isAffected }) => isAffected,
|
|
145
|
+
);
|
|
146
|
+
if (options.json) {
|
|
147
|
+
const payload = options.explain
|
|
148
|
+
? result
|
|
149
|
+
: affectedResults.map(({ workspace }) => workspace.name);
|
|
150
|
+
commandOutputLogger.info(createJsonLines(payload, options).join("\n"));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (!options.explain) {
|
|
154
|
+
if (affectedResults.length) {
|
|
155
|
+
commandOutputLogger.info(
|
|
156
|
+
affectedResults.map(({ workspace }) => workspace.name).join("\n"),
|
|
157
|
+
);
|
|
158
|
+
} else {
|
|
159
|
+
logger.info("No affected workspaces");
|
|
160
|
+
}
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const lines = [""];
|
|
164
|
+
const gitHeader = formatGitHeader(result.metadata);
|
|
165
|
+
if (gitHeader) lines.push(gitHeader, "");
|
|
166
|
+
if (!affectedResults.length) {
|
|
167
|
+
lines.push("No affected workspaces");
|
|
168
|
+
} else {
|
|
169
|
+
const renderWorkspace = options.detailed
|
|
170
|
+
? createWorkspaceDetailedLines
|
|
171
|
+
: createWorkspaceSummaryLines;
|
|
172
|
+
for (const workspaceResult of affectedResults) {
|
|
173
|
+
lines.push(...renderWorkspace(workspaceResult), "");
|
|
174
|
+
}
|
|
175
|
+
if (!options.detailed) {
|
|
176
|
+
// gray
|
|
177
|
+
lines.push("\x1b[90mPass --detailed for more info\x1b[0m");
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
commandOutputLogger.info(lines.join("\n"));
|
|
181
|
+
},
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
export { listAffected };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { logger } from "../../../internal/logger/index.mjs";
|
|
2
|
+
import {
|
|
3
|
+
handleProjectCommand,
|
|
4
|
+
splitWhitespaceArg,
|
|
5
|
+
} from "../commandHandlerUtils.mjs";
|
|
6
|
+
import { handleScriptRunFlow } from "./scriptRunFlow.mjs";
|
|
7
|
+
|
|
8
|
+
const runAffected = handleProjectCommand(
|
|
9
|
+
"runAffected",
|
|
10
|
+
async (
|
|
11
|
+
{
|
|
12
|
+
project,
|
|
13
|
+
postTerminatorArgs,
|
|
14
|
+
outputWriters,
|
|
15
|
+
terminalWidth,
|
|
16
|
+
terminalHeight,
|
|
17
|
+
},
|
|
18
|
+
positionalScript,
|
|
19
|
+
options,
|
|
20
|
+
) => {
|
|
21
|
+
options.inlineName = options.inlineName?.trim();
|
|
22
|
+
options.args = options.args?.trim();
|
|
23
|
+
options.jsonOutfile = options.jsonOutfile?.trim();
|
|
24
|
+
options.parallel =
|
|
25
|
+
typeof options.parallel === "string"
|
|
26
|
+
? options.parallel.trim()
|
|
27
|
+
: options.parallel;
|
|
28
|
+
if (positionalScript && options.script) {
|
|
29
|
+
logger.error(
|
|
30
|
+
"CLI syntax error: Cannot use both inline script positional and --script|-S option",
|
|
31
|
+
);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const script = options.script || positionalScript;
|
|
36
|
+
if (postTerminatorArgs.length && options.args) {
|
|
37
|
+
logger.error(
|
|
38
|
+
"CLI syntax error: Cannot use both --args and inline script args after --",
|
|
39
|
+
);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const scriptArgs = postTerminatorArgs.length
|
|
44
|
+
? postTerminatorArgs
|
|
45
|
+
: options.args;
|
|
46
|
+
if (options.files !== undefined && (options.base || options.head)) {
|
|
47
|
+
logger.error(
|
|
48
|
+
"CLI syntax error: --files cannot be used with --base or --head",
|
|
49
|
+
);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const affectedOptions =
|
|
54
|
+
options.files !== undefined
|
|
55
|
+
? {
|
|
56
|
+
diffSource: "fileList",
|
|
57
|
+
changedFiles: splitWhitespaceArg(options.files),
|
|
58
|
+
ignoreWorkspaceDependencies:
|
|
59
|
+
options.ignoreWorkspaceDeps || undefined,
|
|
60
|
+
ignoreExternalDependencies: options.ignoreExternalDeps || undefined,
|
|
61
|
+
}
|
|
62
|
+
: {
|
|
63
|
+
diffSource: "git",
|
|
64
|
+
ignoreWorkspaceDependencies:
|
|
65
|
+
options.ignoreWorkspaceDeps || undefined,
|
|
66
|
+
ignoreExternalDependencies: options.ignoreExternalDeps || undefined,
|
|
67
|
+
diffOptions: {
|
|
68
|
+
baseRef: options.base,
|
|
69
|
+
headRef: options.head,
|
|
70
|
+
ignoreUntracked: options.ignoreUntracked || undefined,
|
|
71
|
+
ignoreUnstaged: options.ignoreUnstaged || undefined,
|
|
72
|
+
ignoreStaged: options.ignoreStaged || undefined,
|
|
73
|
+
ignoreUncommitted: options.ignoreUncommitted || undefined,
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
logger.debug(
|
|
77
|
+
`Command: Run ${options.inline ? "inline " : ""}script ${JSON.stringify(script)} across affected workspaces (${affectedOptions.diffSource})`,
|
|
78
|
+
);
|
|
79
|
+
logger.debug(`Options: ${JSON.stringify(options)}`);
|
|
80
|
+
await handleScriptRunFlow({
|
|
81
|
+
project,
|
|
82
|
+
context: {
|
|
83
|
+
outputWriters,
|
|
84
|
+
terminalWidth,
|
|
85
|
+
terminalHeight,
|
|
86
|
+
},
|
|
87
|
+
script,
|
|
88
|
+
scriptArgs,
|
|
89
|
+
cliOptions: options,
|
|
90
|
+
runner: (scriptOptions) =>
|
|
91
|
+
project.runAffectedWorkspaceScript({
|
|
92
|
+
affectedOptions,
|
|
93
|
+
scriptOptions,
|
|
94
|
+
}),
|
|
95
|
+
});
|
|
96
|
+
},
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
export { runAffected };
|