@vnejs/monorepo 0.0.5 → 0.0.6
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 +4 -2
- package/src/bump/index.js +54 -4
- package/src/changed-packages.js +8 -2
- package/src/cli.js +16 -26
- package/src/graph/index.js +59 -19
- package/src/index.js +2 -1
- package/src/{build → run}/index.js +9 -3
- package/src/run-changed/index.js +56 -10
- package/src/sync-deps/index.js +2 -1
- package/src/test/index.js +16 -0
- package/src/utils/confirm.js +14 -0
- package/src/utils/format-package.js +13 -0
- package/src/workspace/filter-packages.js +7 -1
- package/src/workspace/is-stub-test-script.js +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vnejs/monorepo",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Monorepo tooling for @vnejs",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
"license": "ISC",
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"commander": "~15.0.0",
|
|
19
|
-
"
|
|
19
|
+
"happy-dom": "~20.0.0",
|
|
20
|
+
"typescript": "6.0.3",
|
|
21
|
+
"vitest": "~3.2.4"
|
|
20
22
|
}
|
|
21
23
|
}
|
package/src/bump/index.js
CHANGED
|
@@ -3,6 +3,8 @@ const listWorkspacePackages = require("../workspace/list-packages");
|
|
|
3
3
|
const syncDeps = require("../sync-deps");
|
|
4
4
|
const runChanged = require("../run-changed");
|
|
5
5
|
const { run } = require("../publish/utils");
|
|
6
|
+
const confirm = require("../utils/confirm");
|
|
7
|
+
const { formatPackageLine } = require("../utils/format-package");
|
|
6
8
|
|
|
7
9
|
const PHASES = ["graph", "sync-all", "patch"];
|
|
8
10
|
|
|
@@ -27,9 +29,45 @@ const previousMinorLine = (version) => {
|
|
|
27
29
|
process.exit(1);
|
|
28
30
|
};
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
const describeBumpPlan = (version, options, phases) => {
|
|
33
|
+
const expectVersion = options.expectVersion ?? version;
|
|
34
|
+
const onlyVersion = options.onlyVersion ?? previousMinorLine(version);
|
|
35
|
+
const lines = [`\nBump target: ${expectVersion}.x`];
|
|
36
|
+
|
|
37
|
+
if (phases.includes("graph")) {
|
|
38
|
+
const { order } = resolveGraph({
|
|
39
|
+
cwd: options.cwd,
|
|
40
|
+
onlyVersion,
|
|
41
|
+
script: "publish:minor",
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (!order.length) {
|
|
45
|
+
console.error("No packages matched graph filters for phase 1.");
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
lines.push(`Phase 1: sync-deps + publish:minor (${order.length} packages, filter ${onlyVersion}.x)`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (phases.includes("sync-all")) {
|
|
53
|
+
const { packages } = listWorkspacePackages({ cwd: options.cwd });
|
|
54
|
+
lines.push(`Phase 2: sync-deps --all (${packages.length} packages)`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (phases.includes("patch")) {
|
|
58
|
+
lines.push(`Phase 3: publish:patch changed packages (ref ${options.ref ?? "HEAD"})`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (options.dryRun) {
|
|
62
|
+
lines.push("\nMode: dry run");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return lines.join("\n");
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
module.exports = async (version, options = {}) => {
|
|
31
69
|
const dryRun = Boolean(options.dryRun);
|
|
32
|
-
const phases = options.phase ? [options.phase] :
|
|
70
|
+
const phases = options.phase ? [options.phase] : PHASES;
|
|
33
71
|
|
|
34
72
|
if (options.phase && !PHASES.includes(options.phase)) {
|
|
35
73
|
console.error(`phase must be one of: ${PHASES.join(", ")}`);
|
|
@@ -41,6 +79,17 @@ module.exports = (version, options = {}) => {
|
|
|
41
79
|
const expectVersion = options.expectVersion ?? version;
|
|
42
80
|
const onlyVersion = options.onlyVersion ?? previousMinorLine(version);
|
|
43
81
|
|
|
82
|
+
console.log(describeBumpPlan(version, { ...options, expectVersion, onlyVersion }, phases));
|
|
83
|
+
|
|
84
|
+
if (!dryRun) {
|
|
85
|
+
const confirmed = await confirm("Continue? [y/N] ");
|
|
86
|
+
|
|
87
|
+
if (!confirmed) {
|
|
88
|
+
console.log("Aborted.");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
44
93
|
const graphOptions = {
|
|
45
94
|
cwd: options.cwd,
|
|
46
95
|
onlyVersion,
|
|
@@ -66,7 +115,7 @@ module.exports = (version, options = {}) => {
|
|
|
66
115
|
}
|
|
67
116
|
|
|
68
117
|
order.forEach((pkg, index) => {
|
|
69
|
-
console.log(
|
|
118
|
+
console.log(formatPackageLine(pkg, { leadingNewline: true, tag: `[${index + 1}/${order.length}]` }));
|
|
70
119
|
|
|
71
120
|
if (dryRun) {
|
|
72
121
|
console.log(` sync-deps --expect-version ${syncOptions.expectVersion}`);
|
|
@@ -96,7 +145,8 @@ module.exports = (version, options = {}) => {
|
|
|
96
145
|
if (phases.includes("patch")) {
|
|
97
146
|
console.log(`\n=== Phase 3: publish:changed:patch ===`);
|
|
98
147
|
|
|
99
|
-
runChanged(
|
|
148
|
+
await runChanged({
|
|
149
|
+
script: "publish:patch",
|
|
100
150
|
ref: options.ref ?? "HEAD",
|
|
101
151
|
dryRun,
|
|
102
152
|
});
|
package/src/changed-packages.js
CHANGED
|
@@ -3,6 +3,7 @@ const { existsSync } = require("fs");
|
|
|
3
3
|
const path = require("path");
|
|
4
4
|
const readPackageJson = require("./workspace/read-package-json");
|
|
5
5
|
const findMonorepoRoot = require("./workspace/find-root");
|
|
6
|
+
const isStubTestScript = require("./workspace/is-stub-test-script");
|
|
6
7
|
|
|
7
8
|
const getChangedFiles = (root, ref = "HEAD") => {
|
|
8
9
|
const files = new Set();
|
|
@@ -30,7 +31,7 @@ const findPackageForFile = (root, filePath) => {
|
|
|
30
31
|
const pkg = readPackageJson(dir);
|
|
31
32
|
if (dir === root) return null;
|
|
32
33
|
|
|
33
|
-
return { name: pkg.name, dir: path.relative(root, dir) || "." };
|
|
34
|
+
return { name: pkg.name, version: pkg.version ?? "0.0.0", dir: path.relative(root, dir) || "." };
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
if (dir === root) break;
|
|
@@ -54,7 +55,12 @@ const getChangedPackages = (options = {}) => {
|
|
|
54
55
|
if (options.script) {
|
|
55
56
|
result = result.filter((pkg) => {
|
|
56
57
|
const pkgJson = readPackageJson(path.join(root, pkg.dir));
|
|
57
|
-
|
|
58
|
+
const script = pkgJson.scripts?.[options.script];
|
|
59
|
+
|
|
60
|
+
if (!script) return false;
|
|
61
|
+
if (options.script === "test" && isStubTestScript(script)) return false;
|
|
62
|
+
|
|
63
|
+
return true;
|
|
58
64
|
});
|
|
59
65
|
}
|
|
60
66
|
|
package/src/cli.js
CHANGED
|
@@ -4,12 +4,11 @@ const { Command } = require("commander");
|
|
|
4
4
|
|
|
5
5
|
const packageJson = require("../package.json");
|
|
6
6
|
const publishAction = require("./publish");
|
|
7
|
-
const { getChangedPackages } = require("./changed-packages");
|
|
8
7
|
const runChangedAction = require("./run-changed");
|
|
9
8
|
const graphAction = require("./graph");
|
|
10
9
|
const syncDepsAction = require("./sync-deps");
|
|
11
10
|
const bumpAction = require("./bump");
|
|
12
|
-
const
|
|
11
|
+
const runAction = require("./run");
|
|
13
12
|
const clearAction = require("./clear");
|
|
14
13
|
|
|
15
14
|
const program = new Command();
|
|
@@ -39,7 +38,7 @@ program
|
|
|
39
38
|
.option("--only-version <pattern>", "filter by version prefix, e.g. 0.0.x")
|
|
40
39
|
.option("--name <pattern>", "filter by package name substring")
|
|
41
40
|
.option("--script <script>", "only packages that define this npm script")
|
|
42
|
-
.option("--
|
|
41
|
+
.option("--flat", "show packages as a flat list with layer column", false)
|
|
43
42
|
.option("--format <format>", "output format: text | json", "text")
|
|
44
43
|
.action(graphAction);
|
|
45
44
|
|
|
@@ -67,7 +66,7 @@ program
|
|
|
67
66
|
.option("--dry-run", "show planned steps without making changes", false)
|
|
68
67
|
.option("--only-version <pattern>", "graph version filter for phase 1 (default: previous minor line)")
|
|
69
68
|
.option("--phase <phase>", "run only one phase: graph | sync-all | patch")
|
|
70
|
-
.option("--ref <ref>", "git ref for phase 3 changed
|
|
69
|
+
.option("--ref <ref>", "git ref for phase 3 run-changed", "HEAD")
|
|
71
70
|
.option("--workspace", "use workspace versions in sync-deps (phase 2)", false)
|
|
72
71
|
.option("--expect-version <version>", "wait until npm has this major.minor line (default: <version>)")
|
|
73
72
|
.option("--expect-wait <ms>", "delay between npm retries", "10000")
|
|
@@ -81,37 +80,28 @@ program
|
|
|
81
80
|
);
|
|
82
81
|
|
|
83
82
|
program
|
|
84
|
-
.command("
|
|
85
|
-
.description("
|
|
83
|
+
.command("test")
|
|
84
|
+
.description("run vitest in current directory")
|
|
85
|
+
.action((options) => require("./test")(options));
|
|
86
|
+
|
|
87
|
+
program
|
|
88
|
+
.command("run")
|
|
89
|
+
.description("Run an npm script in workspace packages in dependency order (turbo per layer)")
|
|
86
90
|
.option("--script <script>", "npm script to run in each package", "build")
|
|
87
91
|
.option("--only-version <pattern>", "filter by version prefix, e.g. 0.0.x")
|
|
88
92
|
.option("--name <pattern>", "filter by package name substring (includes dependency closure)")
|
|
89
|
-
.option("--sequential", "
|
|
93
|
+
.option("--sequential", "run one package at a time in flat graph order", false)
|
|
90
94
|
.option("--force", "pass --force to turbo (bypass cache)", false)
|
|
91
|
-
.option("--dry-run", "show
|
|
92
|
-
.action((options) =>
|
|
93
|
-
|
|
94
|
-
program
|
|
95
|
-
.command("changed-packages")
|
|
96
|
-
.description("List workspace packages changed in git")
|
|
97
|
-
.option("--ref <ref>", "git ref to compare against", "HEAD")
|
|
98
|
-
.option("--script <script>", "only packages that define this npm script")
|
|
99
|
-
.action((options) => {
|
|
100
|
-
const { packages } = getChangedPackages({ ref: options.ref, script: options.script });
|
|
101
|
-
|
|
102
|
-
packages.forEach((pkg, index) => {
|
|
103
|
-
console.log(`==> [${index + 1}/${packages.length}] ${pkg.name} (${pkg.dir})`);
|
|
104
|
-
});
|
|
105
|
-
console.log("");
|
|
106
|
-
console.log(`Total: ${packages.length}`);
|
|
107
|
-
});
|
|
95
|
+
.option("--dry-run", "show run plan without executing", false)
|
|
96
|
+
.action((options) => runAction(options));
|
|
108
97
|
|
|
109
98
|
program
|
|
110
99
|
.command("run-changed")
|
|
111
100
|
.description("Run npm script sequentially in git-changed workspace packages")
|
|
112
|
-
.
|
|
101
|
+
.option("--script <script>", "npm script name from package.json")
|
|
113
102
|
.option("--ref <ref>", "git ref to compare against", "HEAD")
|
|
114
|
-
.option("--dry-run", "list packages without running the script", false)
|
|
103
|
+
.option("--dry-run", "list changed packages without running the script", false)
|
|
104
|
+
.option("--confirm", "ask for confirmation before running the script", false)
|
|
115
105
|
.action(runChangedAction);
|
|
116
106
|
|
|
117
107
|
program
|
package/src/graph/index.js
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
2
|
const resolveGraph = require("../workspace/resolve-graph");
|
|
3
|
+
const { formatPackageLine, formatPackageRef } = require("../utils/format-package");
|
|
4
|
+
|
|
5
|
+
const buildLayerMeta = (layers) => {
|
|
6
|
+
const byName = new Map();
|
|
7
|
+
|
|
8
|
+
layers.forEach((layer, layerIndex) => {
|
|
9
|
+
layer.forEach((pkg, packageIndex) => {
|
|
10
|
+
byName.set(pkg.name, {
|
|
11
|
+
layer: layerIndex + 1,
|
|
12
|
+
layerTotal: layers.length,
|
|
13
|
+
layerIndex: packageIndex + 1,
|
|
14
|
+
layerSize: layer.length,
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
return byName;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const toPackageEntry = (pkg, meta) => ({
|
|
23
|
+
name: pkg.name,
|
|
24
|
+
version: pkg.version,
|
|
25
|
+
dir: pkg.dir,
|
|
26
|
+
...meta,
|
|
27
|
+
});
|
|
3
28
|
|
|
4
29
|
module.exports = (options = {}) => {
|
|
5
30
|
const { root, order, layers } = resolveGraph(options);
|
|
@@ -9,16 +34,26 @@ module.exports = (options = {}) => {
|
|
|
9
34
|
return { root, packages: [], layers: [], order: [] };
|
|
10
35
|
}
|
|
11
36
|
|
|
37
|
+
const layerMetaByName = buildLayerMeta(layers);
|
|
38
|
+
|
|
12
39
|
if (options.format === "json") {
|
|
13
40
|
console.log(
|
|
14
41
|
JSON.stringify(
|
|
15
42
|
{
|
|
16
43
|
root,
|
|
17
44
|
total: order.length,
|
|
18
|
-
|
|
19
|
-
|
|
45
|
+
layerTotal: layers.length,
|
|
46
|
+
layers: layers.map((layer, layerIndex) =>
|
|
47
|
+
layer.map((pkg, packageIndex) =>
|
|
48
|
+
toPackageEntry(pkg, {
|
|
49
|
+
layer: layerIndex + 1,
|
|
50
|
+
layerTotal: layers.length,
|
|
51
|
+
layerIndex: packageIndex + 1,
|
|
52
|
+
layerSize: layer.length,
|
|
53
|
+
}),
|
|
54
|
+
),
|
|
20
55
|
),
|
|
21
|
-
order: order.map((pkg) => (
|
|
56
|
+
order: order.map((pkg) => toPackageEntry(pkg, layerMetaByName.get(pkg.name))),
|
|
22
57
|
},
|
|
23
58
|
null,
|
|
24
59
|
2,
|
|
@@ -28,26 +63,31 @@ module.exports = (options = {}) => {
|
|
|
28
63
|
return { root, packages: order, layers, order: order.map((pkg) => pkg.name) };
|
|
29
64
|
}
|
|
30
65
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
console.log(`# layer ${index + 1} (${layer.length})`);
|
|
66
|
+
console.log(`\n=== Graph: ${order.length} packages, ${layers.length} layers ===`);
|
|
67
|
+
console.log(`Root: ${path.relative(process.cwd(), root) || "."}\n`);
|
|
34
68
|
|
|
35
|
-
|
|
36
|
-
console.log(`${pkg.name}\t${pkg.version}\t${pkg.dir}`);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
if (index < layers.length - 1) console.log("");
|
|
40
|
-
});
|
|
41
|
-
} else {
|
|
69
|
+
if (options.flat) {
|
|
42
70
|
order.forEach((pkg, index) => {
|
|
43
|
-
|
|
71
|
+
const meta = layerMetaByName.get(pkg.name);
|
|
72
|
+
console.log(
|
|
73
|
+
`${index + 1}\t${meta.layer}/${meta.layerTotal}\t${formatPackageRef(pkg)}\t${pkg.dir}`,
|
|
74
|
+
);
|
|
44
75
|
});
|
|
45
|
-
}
|
|
76
|
+
} else {
|
|
77
|
+
for (let layerIndex = 0; layerIndex < layers.length; layerIndex++) {
|
|
78
|
+
const layer = layers[layerIndex];
|
|
79
|
+
console.log(`\n=== Layer ${layerIndex + 1}/${layers.length} (${layer.length} packages) ===`);
|
|
46
80
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
81
|
+
layer.forEach((pkg, packageIndex) => {
|
|
82
|
+
console.log(
|
|
83
|
+
formatPackageLine(pkg, {
|
|
84
|
+
indent: " ",
|
|
85
|
+
tag: `[${layerIndex + 1}/${layers.length}:${packageIndex + 1}/${layer.length}]`,
|
|
86
|
+
}),
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
51
91
|
|
|
52
92
|
return {
|
|
53
93
|
root,
|
package/src/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
package: require("./package"),
|
|
3
|
+
test: require("./test"),
|
|
3
4
|
publish: require("./publish"),
|
|
4
5
|
getChangedPackages: require("./changed-packages").getChangedPackages,
|
|
5
6
|
runChanged: require("./run-changed"),
|
|
6
7
|
graph: require("./graph"),
|
|
7
8
|
syncDeps: require("./sync-deps"),
|
|
8
9
|
bump: require("./bump"),
|
|
9
|
-
|
|
10
|
+
run: require("./run"),
|
|
10
11
|
clear: require("./clear"),
|
|
11
12
|
resolveGraph: require("./workspace/resolve-graph"),
|
|
12
13
|
listWorkspacePackages: require("./workspace/list-packages"),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const resolveGraph = require("../workspace/resolve-graph");
|
|
2
2
|
const findRoot = require("../workspace/find-root");
|
|
3
3
|
const { run } = require("../publish/utils");
|
|
4
|
+
const { formatPackageLine } = require("../utils/format-package");
|
|
4
5
|
|
|
5
6
|
const runLayerTurbo = (layer, root, { script, force }) => {
|
|
6
7
|
const filters = layer.map((pkg) => `--filter=${pkg.name}`).join(" ");
|
|
@@ -28,13 +29,13 @@ module.exports = (options = {}) => {
|
|
|
28
29
|
process.exit(1);
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
console.log(`\n===
|
|
32
|
+
console.log(`\n=== Run: ${order.length} packages, ${layers.length} layers ===`);
|
|
32
33
|
console.log(`Script: ${script}`);
|
|
33
34
|
console.log(`Root: ${root}`);
|
|
34
35
|
console.log(`Mode: ${sequential ? "sequential" : "layers (turbo)"}\n`);
|
|
35
36
|
|
|
36
37
|
const runPackage = (pkg, label) => {
|
|
37
|
-
console.log(
|
|
38
|
+
console.log(formatPackageLine(pkg, { leadingNewline: true, tag: label }));
|
|
38
39
|
|
|
39
40
|
if (dryRun) return;
|
|
40
41
|
|
|
@@ -51,7 +52,12 @@ module.exports = (options = {}) => {
|
|
|
51
52
|
if (dryRun) {
|
|
52
53
|
console.log(` turbo run ${script} ${layer.map((pkg) => `--filter=${pkg.name}`).join(" ")}`);
|
|
53
54
|
layer.forEach((pkg, index) => {
|
|
54
|
-
console.log(
|
|
55
|
+
console.log(
|
|
56
|
+
formatPackageLine(pkg, {
|
|
57
|
+
indent: " ",
|
|
58
|
+
tag: `[${layerIndex + 1}/${layers.length}:${index + 1}/${layer.length}]`,
|
|
59
|
+
}),
|
|
60
|
+
);
|
|
55
61
|
});
|
|
56
62
|
continue;
|
|
57
63
|
}
|
package/src/run-changed/index.js
CHANGED
|
@@ -1,24 +1,70 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
2
|
|
|
3
3
|
const { getChangedPackages } = require("../changed-packages");
|
|
4
|
+
const resolveGraph = require("../workspace/resolve-graph");
|
|
4
5
|
const { run } = require("../publish/utils");
|
|
6
|
+
const confirm = require("../utils/confirm");
|
|
7
|
+
const { formatPackageLine } = require("../utils/format-package");
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
const
|
|
9
|
+
const sortByGraphOrder = (root, changedPackages, script) => {
|
|
10
|
+
const changedNames = new Set(changedPackages.map((pkg) => pkg.name));
|
|
11
|
+
const { order } = resolveGraph({ cwd: root, script });
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
const sorted = order.filter((pkg) => changedNames.has(pkg.name));
|
|
14
|
+
|
|
15
|
+
const sortedNames = new Set(sorted.map((pkg) => pkg.name));
|
|
16
|
+
const rest = changedPackages.filter((pkg) => !sortedNames.has(pkg.name));
|
|
17
|
+
|
|
18
|
+
return [...sorted, ...rest];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const printPackages = (packages) => {
|
|
22
|
+
packages.forEach((pkg, index) => {
|
|
23
|
+
console.log(formatPackageLine(pkg, { tag: `[${index + 1}/${packages.length}]` }));
|
|
24
|
+
});
|
|
25
|
+
console.log("");
|
|
26
|
+
console.log(`Total: ${packages.length}`);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
module.exports = async (options = {}) => {
|
|
30
|
+
const script = options.script;
|
|
31
|
+
|
|
32
|
+
if (!options.dryRun && !script) {
|
|
33
|
+
console.error('Missing required option "--script".');
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const { root, packages: changedPackages } = getChangedPackages({ ref: options.ref, script });
|
|
38
|
+
|
|
39
|
+
if (!changedPackages.length) {
|
|
40
|
+
console.log(script ? `No changed packages with script "${script}".` : "No changed packages.");
|
|
11
41
|
return;
|
|
12
42
|
}
|
|
13
43
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
44
|
+
const packages = sortByGraphOrder(root, changedPackages, script);
|
|
45
|
+
|
|
46
|
+
if (options.dryRun) {
|
|
47
|
+
printPackages(packages);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
17
50
|
|
|
18
|
-
|
|
51
|
+
if (options.confirm) {
|
|
52
|
+
console.log(`\nThe following packages will run "${script}":\n`);
|
|
53
|
+
printPackages(packages);
|
|
19
54
|
|
|
20
|
-
|
|
55
|
+
const confirmed = await confirm(`Continue? [y/N] `);
|
|
56
|
+
|
|
57
|
+
if (!confirmed) {
|
|
58
|
+
console.log("Aborted.");
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
console.log("");
|
|
21
63
|
}
|
|
22
64
|
|
|
23
|
-
|
|
65
|
+
for (const [index, pkg] of packages.entries()) {
|
|
66
|
+
const pkgDir = path.join(root, pkg.dir);
|
|
67
|
+
console.log(formatPackageLine(pkg, { leadingNewline: true, tag: `[${index + 1}/${packages.length}]` }));
|
|
68
|
+
run(`npm run ${script}`, pkgDir);
|
|
69
|
+
}
|
|
24
70
|
};
|
package/src/sync-deps/index.js
CHANGED
|
@@ -5,6 +5,7 @@ const listWorkspacePackages = require("../workspace/list-packages");
|
|
|
5
5
|
const fetchNpmVersion = require("../workspace/fetch-npm-version");
|
|
6
6
|
const toTildeMinor = require("../workspace/to-tilde-minor");
|
|
7
7
|
const { DEPENDENCY_FIELDS } = require("../workspace/build-graph");
|
|
8
|
+
const { formatPackageLine } = require("../utils/format-package");
|
|
8
9
|
|
|
9
10
|
const resolveVersion = (name, options) => {
|
|
10
11
|
if (options.workspace) {
|
|
@@ -102,7 +103,7 @@ module.exports = (options = {}) => {
|
|
|
102
103
|
console.log(`Syncing dependencies in ${packages.length} workspace packages...`);
|
|
103
104
|
|
|
104
105
|
for (const pkg of packages) {
|
|
105
|
-
console.log(
|
|
106
|
+
console.log(formatPackageLine(pkg, { leadingNewline: true }));
|
|
106
107
|
|
|
107
108
|
if (options.dryRun) {
|
|
108
109
|
console.log(" sync-deps");
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const { execSync } = require("child_process");
|
|
2
|
+
const { existsSync } = require("fs");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
|
|
5
|
+
module.exports = (options = {}) => {
|
|
6
|
+
const pkgDir = options.cwd || process.cwd();
|
|
7
|
+
const configPath = path.join(pkgDir, "vitest.config.js");
|
|
8
|
+
|
|
9
|
+
if (!existsSync(configPath)) {
|
|
10
|
+
console.error(`vitest.config.js not found: ${configPath}`);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const vitest = require.resolve("vitest/vitest.mjs");
|
|
15
|
+
execSync(`node "${vitest}" run`, { cwd: pkgDir, stdio: "inherit" });
|
|
16
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const readline = require("readline/promises");
|
|
2
|
+
|
|
3
|
+
const confirm = async (message) => {
|
|
4
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
5
|
+
|
|
6
|
+
try {
|
|
7
|
+
const answer = await rl.question(message);
|
|
8
|
+
return /^y(es)?$/i.test(answer.trim());
|
|
9
|
+
} finally {
|
|
10
|
+
rl.close();
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
module.exports = confirm;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const formatPackageRef = (pkg) => `${pkg.name}@${pkg.version ?? "0.0.0"}`;
|
|
2
|
+
|
|
3
|
+
const formatPackageLine = (pkg, options = {}) => {
|
|
4
|
+
const { prefix = "==>", tag, indent = "", leadingNewline = false } = options;
|
|
5
|
+
const tagPart = tag ? `${tag} ` : "";
|
|
6
|
+
|
|
7
|
+
return `${leadingNewline ? "\n" : ""}${indent}${prefix} ${tagPart}${formatPackageRef(pkg)} (${pkg.dir})`;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
formatPackageRef,
|
|
12
|
+
formatPackageLine,
|
|
13
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const readPackageJson = require("./read-package-json");
|
|
2
2
|
const matchVersion = require("./match-version");
|
|
3
|
+
const isStubTestScript = require("./is-stub-test-script");
|
|
3
4
|
|
|
4
5
|
const DEFAULT_EXCLUDED_DIRS = ["cli"];
|
|
5
6
|
|
|
@@ -24,7 +25,12 @@ module.exports = (packages, options = {}) => {
|
|
|
24
25
|
if (options.script) {
|
|
25
26
|
result = result.filter((pkg) => {
|
|
26
27
|
const pkgJson = readPackageJson(pkg.absDir);
|
|
27
|
-
|
|
28
|
+
const script = pkgJson.scripts?.[options.script];
|
|
29
|
+
|
|
30
|
+
if (!script) return false;
|
|
31
|
+
if (options.script === "test" && isStubTestScript(script)) return false;
|
|
32
|
+
|
|
33
|
+
return true;
|
|
28
34
|
});
|
|
29
35
|
}
|
|
30
36
|
|