@vnejs/monorepo 0.0.3 → 0.0.5
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/build/index.js +64 -0
- package/src/bump/index.js +106 -0
- package/src/changed-packages.js +3 -22
- package/src/clear/index.js +24 -0
- package/src/cli.js +65 -28
- package/src/graph/index.js +58 -0
- package/src/index.js +10 -3
- package/src/run-changed/index.js +2 -2
- package/src/sync-deps/index.js +132 -0
- package/src/workspace/build-graph.js +65 -0
- package/src/workspace/expect-version.js +39 -0
- package/src/workspace/fetch-npm-version.js +57 -0
- package/src/workspace/filter-packages.js +35 -0
- package/src/workspace/find-root.js +22 -0
- package/src/workspace/list-packages.js +82 -0
- package/src/workspace/match-version.js +7 -0
- package/src/workspace/read-package-json.js +4 -0
- package/src/workspace/resolve-graph.js +29 -0
- package/src/workspace/to-tilde-minor.js +7 -0
- package/src/workspace/topo-sort.js +49 -0
- package/src/publish-configs/index.js +0 -38
- package/src/publish-helpers/index.js +0 -36
- package/src/publish-uis/index.js +0 -36
package/package.json
CHANGED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const resolveGraph = require("../workspace/resolve-graph");
|
|
2
|
+
const findRoot = require("../workspace/find-root");
|
|
3
|
+
const { run } = require("../publish/utils");
|
|
4
|
+
|
|
5
|
+
const runLayerTurbo = (layer, root, { script, force }) => {
|
|
6
|
+
const filters = layer.map((pkg) => `--filter=${pkg.name}`).join(" ");
|
|
7
|
+
const forceFlag = force ? " --force" : "";
|
|
8
|
+
|
|
9
|
+
run(`npx turbo run ${script} ${filters}${forceFlag}`, root);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
module.exports = (options = {}) => {
|
|
13
|
+
const script = options.script ?? "build";
|
|
14
|
+
const root = findRoot(options.cwd ?? process.cwd());
|
|
15
|
+
const dryRun = Boolean(options.dryRun);
|
|
16
|
+
const sequential = Boolean(options.sequential);
|
|
17
|
+
|
|
18
|
+
const { order, layers } = resolveGraph({
|
|
19
|
+
cwd: options.cwd ?? root,
|
|
20
|
+
script,
|
|
21
|
+
onlyVersion: options.onlyVersion,
|
|
22
|
+
name: options.name,
|
|
23
|
+
includeDependencies: Boolean(options.name || options.onlyVersion),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (!order.length) {
|
|
27
|
+
console.error(`No workspace packages matched filters with script "${script}".`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
console.log(`\n=== Build: ${order.length} packages, ${layers.length} layers ===`);
|
|
32
|
+
console.log(`Script: ${script}`);
|
|
33
|
+
console.log(`Root: ${root}`);
|
|
34
|
+
console.log(`Mode: ${sequential ? "sequential" : "layers (turbo)"}\n`);
|
|
35
|
+
|
|
36
|
+
const runPackage = (pkg, label) => {
|
|
37
|
+
console.log(`\n==> ${label} ${pkg.name} (${pkg.dir})`);
|
|
38
|
+
|
|
39
|
+
if (dryRun) return;
|
|
40
|
+
|
|
41
|
+
run(`npm run ${script}`, pkg.absDir);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
if (sequential) {
|
|
45
|
+
order.forEach((pkg, index) => runPackage(pkg, `[${index + 1}/${order.length}]`));
|
|
46
|
+
} else {
|
|
47
|
+
for (let layerIndex = 0; layerIndex < layers.length; layerIndex++) {
|
|
48
|
+
const layer = layers[layerIndex];
|
|
49
|
+
console.log(`\n=== Layer ${layerIndex + 1}/${layers.length} (${layer.length} packages) ===`);
|
|
50
|
+
|
|
51
|
+
if (dryRun) {
|
|
52
|
+
console.log(` turbo run ${script} ${layer.map((pkg) => `--filter=${pkg.name}`).join(" ")}`);
|
|
53
|
+
layer.forEach((pkg, index) => {
|
|
54
|
+
console.log(` ==> [${layerIndex + 1}/${layers.length}:${index + 1}/${layer.length}] ${pkg.name} (${pkg.dir})`);
|
|
55
|
+
});
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
runLayerTurbo(layer, root, { script, force: options.force });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (dryRun) console.log("\nDry run complete.");
|
|
64
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const resolveGraph = require("../workspace/resolve-graph");
|
|
2
|
+
const listWorkspacePackages = require("../workspace/list-packages");
|
|
3
|
+
const syncDeps = require("../sync-deps");
|
|
4
|
+
const runChanged = require("../run-changed");
|
|
5
|
+
const { run } = require("../publish/utils");
|
|
6
|
+
|
|
7
|
+
const PHASES = ["graph", "sync-all", "patch"];
|
|
8
|
+
|
|
9
|
+
const parseMinorLine = (version) => {
|
|
10
|
+
const match = /^(\d+)\.(\d+)$/.exec(version);
|
|
11
|
+
|
|
12
|
+
if (!match) {
|
|
13
|
+
console.error("version must be major.minor, e.g. 0.1");
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return { major: Number(match[1]), minor: Number(match[2]) };
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const previousMinorLine = (version) => {
|
|
21
|
+
const { major, minor } = parseMinorLine(version);
|
|
22
|
+
|
|
23
|
+
if (minor > 0) return `${major}.${minor - 1}`;
|
|
24
|
+
if (major > 0) return `${major - 1}.9`;
|
|
25
|
+
|
|
26
|
+
console.error("cannot derive previous minor line from 0.0");
|
|
27
|
+
process.exit(1);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
module.exports = (version, options = {}) => {
|
|
31
|
+
const dryRun = Boolean(options.dryRun);
|
|
32
|
+
const phases = options.phase ? [options.phase] : ["graph", "sync-all", "patch"];
|
|
33
|
+
|
|
34
|
+
if (options.phase && !PHASES.includes(options.phase)) {
|
|
35
|
+
console.error(`phase must be one of: ${PHASES.join(", ")}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
parseMinorLine(version);
|
|
40
|
+
|
|
41
|
+
const expectVersion = options.expectVersion ?? version;
|
|
42
|
+
const onlyVersion = options.onlyVersion ?? previousMinorLine(version);
|
|
43
|
+
|
|
44
|
+
const graphOptions = {
|
|
45
|
+
cwd: options.cwd,
|
|
46
|
+
onlyVersion,
|
|
47
|
+
script: "publish:minor",
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const syncOptions = {
|
|
51
|
+
expectVersion,
|
|
52
|
+
expectWaitMs: options.expectWaitMs,
|
|
53
|
+
expectMaxAttempts: options.expectMaxAttempts,
|
|
54
|
+
workspace: options.workspace,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
if (phases.includes("graph")) {
|
|
58
|
+
const { order } = resolveGraph(graphOptions);
|
|
59
|
+
|
|
60
|
+
console.log(`\n=== Phase 1: sync-deps + publish:minor (${order.length} packages) ===`);
|
|
61
|
+
console.log(`Filter: ${onlyVersion}.x → target npm line: ${expectVersion}.x`);
|
|
62
|
+
|
|
63
|
+
if (!order.length) {
|
|
64
|
+
console.error("No packages matched graph filters for phase 1.");
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
order.forEach((pkg, index) => {
|
|
69
|
+
console.log(`\n==> [${index + 1}/${order.length}] ${pkg.name} (${pkg.dir})`);
|
|
70
|
+
|
|
71
|
+
if (dryRun) {
|
|
72
|
+
console.log(` sync-deps --expect-version ${syncOptions.expectVersion}`);
|
|
73
|
+
console.log(" npm run publish:minor");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
syncDeps({ cwd: pkg.absDir, ...syncOptions });
|
|
78
|
+
run("npm run publish:minor", pkg.absDir);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (phases.includes("sync-all")) {
|
|
83
|
+
const { packages } = listWorkspacePackages({ cwd: options.cwd });
|
|
84
|
+
|
|
85
|
+
console.log(`\n=== Phase 2: sync-deps --all (${packages.length} packages) ===`);
|
|
86
|
+
|
|
87
|
+
syncDeps({
|
|
88
|
+
cwd: options.cwd,
|
|
89
|
+
all: true,
|
|
90
|
+
dryRun,
|
|
91
|
+
quiet: false,
|
|
92
|
+
...syncOptions,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (phases.includes("patch")) {
|
|
97
|
+
console.log(`\n=== Phase 3: publish:changed:patch ===`);
|
|
98
|
+
|
|
99
|
+
runChanged("publish:patch", {
|
|
100
|
+
ref: options.ref ?? "HEAD",
|
|
101
|
+
dryRun,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (dryRun) console.log("\nDry run complete.");
|
|
106
|
+
};
|
package/src/changed-packages.js
CHANGED
|
@@ -1,27 +1,8 @@
|
|
|
1
1
|
const { execSync } = require("child_process");
|
|
2
|
-
const { existsSync
|
|
2
|
+
const { existsSync } = require("fs");
|
|
3
3
|
const path = require("path");
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
const findMonorepoRoot = (start = process.cwd()) => {
|
|
8
|
-
let dir = path.resolve(start);
|
|
9
|
-
|
|
10
|
-
while (true) {
|
|
11
|
-
const pkgPath = path.join(dir, "package.json");
|
|
12
|
-
|
|
13
|
-
if (existsSync(pkgPath)) {
|
|
14
|
-
const pkg = readPackageJson(dir);
|
|
15
|
-
if (pkg.workspaces) return dir;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const parent = path.dirname(dir);
|
|
19
|
-
if (parent === dir) break;
|
|
20
|
-
dir = parent;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return path.resolve(start);
|
|
24
|
-
};
|
|
4
|
+
const readPackageJson = require("./workspace/read-package-json");
|
|
5
|
+
const findMonorepoRoot = require("./workspace/find-root");
|
|
25
6
|
|
|
26
7
|
const getChangedFiles = (root, ref = "HEAD") => {
|
|
27
8
|
const files = new Set();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const findRoot = require("../workspace/find-root");
|
|
2
|
+
const { run } = require("../publish/utils");
|
|
3
|
+
|
|
4
|
+
module.exports = (options = {}) => {
|
|
5
|
+
const root = findRoot(options.cwd ?? process.cwd());
|
|
6
|
+
|
|
7
|
+
console.log(`Monorepo root: ${root}\n`);
|
|
8
|
+
|
|
9
|
+
console.log("==> Removing node_modules...");
|
|
10
|
+
run("rm -rf node_modules", root);
|
|
11
|
+
run('find . -name node_modules -type d -prune -exec rm -rf {} +', root);
|
|
12
|
+
|
|
13
|
+
console.log("==> Removing Turbo cache...");
|
|
14
|
+
run("rm -rf .turbo", root);
|
|
15
|
+
run('find . -name .turbo -type d -prune -exec rm -rf {} +', root);
|
|
16
|
+
|
|
17
|
+
console.log("==> Removing dist folders...");
|
|
18
|
+
run('find . -name dist -type d -prune -exec rm -rf {} +', root);
|
|
19
|
+
|
|
20
|
+
console.log("==> Removing package-lock files...");
|
|
21
|
+
run('find . -name package-lock.json -type f -delete', root);
|
|
22
|
+
|
|
23
|
+
console.log("\n==> Clear complete.");
|
|
24
|
+
};
|
package/src/cli.js
CHANGED
|
@@ -4,11 +4,13 @@ const { Command } = require("commander");
|
|
|
4
4
|
|
|
5
5
|
const packageJson = require("../package.json");
|
|
6
6
|
const publishAction = require("./publish");
|
|
7
|
-
const publishUisAction = require("./publish-uis");
|
|
8
|
-
const publishHelpersAction = require("./publish-helpers");
|
|
9
|
-
const publishConfigsAction = require("./publish-configs");
|
|
10
7
|
const { getChangedPackages } = require("./changed-packages");
|
|
11
8
|
const runChangedAction = require("./run-changed");
|
|
9
|
+
const graphAction = require("./graph");
|
|
10
|
+
const syncDepsAction = require("./sync-deps");
|
|
11
|
+
const bumpAction = require("./bump");
|
|
12
|
+
const buildAction = require("./build");
|
|
13
|
+
const clearAction = require("./clear");
|
|
12
14
|
|
|
13
15
|
const program = new Command();
|
|
14
16
|
|
|
@@ -32,34 +34,62 @@ program
|
|
|
32
34
|
.action(publishAction);
|
|
33
35
|
|
|
34
36
|
program
|
|
35
|
-
.command("
|
|
36
|
-
.description("
|
|
37
|
-
.
|
|
38
|
-
.option("--
|
|
39
|
-
.option("--
|
|
40
|
-
.option("--
|
|
41
|
-
.option("--
|
|
42
|
-
.action(
|
|
37
|
+
.command("graph")
|
|
38
|
+
.description("Show workspace packages in publish order (dependencies first)")
|
|
39
|
+
.option("--only-version <pattern>", "filter by version prefix, e.g. 0.0.x")
|
|
40
|
+
.option("--name <pattern>", "filter by package name substring")
|
|
41
|
+
.option("--script <script>", "only packages that define this npm script")
|
|
42
|
+
.option("--layers", "group packages into parallel publish layers", false)
|
|
43
|
+
.option("--format <format>", "output format: text | json", "text")
|
|
44
|
+
.action(graphAction);
|
|
43
45
|
|
|
44
46
|
program
|
|
45
|
-
.command("
|
|
46
|
-
.description("
|
|
47
|
-
.
|
|
48
|
-
.option("--
|
|
49
|
-
.option("--
|
|
50
|
-
.option("--
|
|
51
|
-
.option("--
|
|
52
|
-
.
|
|
47
|
+
.command("sync-deps")
|
|
48
|
+
.description("Sync @vnejs/* dependency ranges in current package to latest npm minor versions (~x.y.0)")
|
|
49
|
+
.option("--dry-run", "show changes without writing package.json", false)
|
|
50
|
+
.option("--workspace", "use workspace package.json versions instead of npm registry", false)
|
|
51
|
+
.option("--all", "sync dependencies in all workspace packages", false)
|
|
52
|
+
.option("--expect-version <version>", "wait until npm has this major.minor line, e.g. 0.1")
|
|
53
|
+
.option("--expect-wait <ms>", "delay between npm retries", "10000")
|
|
54
|
+
.option("--expect-attempts <count>", "max npm retries per dependency", "12")
|
|
55
|
+
.action((options) =>
|
|
56
|
+
syncDepsAction({
|
|
57
|
+
...options,
|
|
58
|
+
expectWaitMs: Number(options.expectWait),
|
|
59
|
+
expectMaxAttempts: Number(options.expectAttempts),
|
|
60
|
+
}),
|
|
61
|
+
);
|
|
53
62
|
|
|
54
63
|
program
|
|
55
|
-
.command("
|
|
56
|
-
.description("
|
|
57
|
-
.argument("<
|
|
58
|
-
.option("--
|
|
59
|
-
.option("--
|
|
60
|
-
.option("--
|
|
61
|
-
.option("--
|
|
62
|
-
.
|
|
64
|
+
.command("bump")
|
|
65
|
+
.description("Minor-line bump: graph publish, sync all deps, patch changed")
|
|
66
|
+
.argument("<version>", "target major.minor line, e.g. 0.1")
|
|
67
|
+
.option("--dry-run", "show planned steps without making changes", false)
|
|
68
|
+
.option("--only-version <pattern>", "graph version filter for phase 1 (default: previous minor line)")
|
|
69
|
+
.option("--phase <phase>", "run only one phase: graph | sync-all | patch")
|
|
70
|
+
.option("--ref <ref>", "git ref for phase 3 changed-packages", "HEAD")
|
|
71
|
+
.option("--workspace", "use workspace versions in sync-deps (phase 2)", false)
|
|
72
|
+
.option("--expect-version <version>", "wait until npm has this major.minor line (default: <version>)")
|
|
73
|
+
.option("--expect-wait <ms>", "delay between npm retries", "10000")
|
|
74
|
+
.option("--expect-attempts <count>", "max npm retries per dependency", "12")
|
|
75
|
+
.action((version, options) =>
|
|
76
|
+
bumpAction(version, {
|
|
77
|
+
...options,
|
|
78
|
+
expectWaitMs: Number(options.expectWait),
|
|
79
|
+
expectMaxAttempts: Number(options.expectAttempts),
|
|
80
|
+
}),
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
program
|
|
84
|
+
.command("build")
|
|
85
|
+
.description("Build workspace packages in dependency order (turbo per layer)")
|
|
86
|
+
.option("--script <script>", "npm script to run in each package", "build")
|
|
87
|
+
.option("--only-version <pattern>", "filter by version prefix, e.g. 0.0.x")
|
|
88
|
+
.option("--name <pattern>", "filter by package name substring (includes dependency closure)")
|
|
89
|
+
.option("--sequential", "build one package at a time in flat graph order", false)
|
|
90
|
+
.option("--force", "pass --force to turbo (bypass cache)", false)
|
|
91
|
+
.option("--dry-run", "show build plan without running", false)
|
|
92
|
+
.action((options) => buildAction(options));
|
|
63
93
|
|
|
64
94
|
program
|
|
65
95
|
.command("changed-packages")
|
|
@@ -69,7 +99,9 @@ program
|
|
|
69
99
|
.action((options) => {
|
|
70
100
|
const { packages } = getChangedPackages({ ref: options.ref, script: options.script });
|
|
71
101
|
|
|
72
|
-
packages.forEach((pkg) =>
|
|
102
|
+
packages.forEach((pkg, index) => {
|
|
103
|
+
console.log(`==> [${index + 1}/${packages.length}] ${pkg.name} (${pkg.dir})`);
|
|
104
|
+
});
|
|
73
105
|
console.log("");
|
|
74
106
|
console.log(`Total: ${packages.length}`);
|
|
75
107
|
});
|
|
@@ -82,4 +114,9 @@ program
|
|
|
82
114
|
.option("--dry-run", "list packages without running the script", false)
|
|
83
115
|
.action(runChangedAction);
|
|
84
116
|
|
|
117
|
+
program
|
|
118
|
+
.command("clear")
|
|
119
|
+
.description("Clean node_modules, caches, dist, and lockfiles")
|
|
120
|
+
.action(clearAction);
|
|
121
|
+
|
|
85
122
|
program.parse();
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const resolveGraph = require("../workspace/resolve-graph");
|
|
3
|
+
|
|
4
|
+
module.exports = (options = {}) => {
|
|
5
|
+
const { root, order, layers } = resolveGraph(options);
|
|
6
|
+
|
|
7
|
+
if (!order.length) {
|
|
8
|
+
console.log("No workspace packages matched the provided filters.");
|
|
9
|
+
return { root, packages: [], layers: [], order: [] };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (options.format === "json") {
|
|
13
|
+
console.log(
|
|
14
|
+
JSON.stringify(
|
|
15
|
+
{
|
|
16
|
+
root,
|
|
17
|
+
total: order.length,
|
|
18
|
+
layers: layers.map((layer) =>
|
|
19
|
+
layer.map((pkg) => ({ name: pkg.name, version: pkg.version, dir: pkg.dir })),
|
|
20
|
+
),
|
|
21
|
+
order: order.map((pkg) => ({ name: pkg.name, version: pkg.version, dir: pkg.dir })),
|
|
22
|
+
},
|
|
23
|
+
null,
|
|
24
|
+
2,
|
|
25
|
+
),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return { root, packages: order, layers, order: order.map((pkg) => pkg.name) };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (options.layers) {
|
|
32
|
+
layers.forEach((layer, index) => {
|
|
33
|
+
console.log(`# layer ${index + 1} (${layer.length})`);
|
|
34
|
+
|
|
35
|
+
layer.forEach((pkg) => {
|
|
36
|
+
console.log(`${pkg.name}\t${pkg.version}\t${pkg.dir}`);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (index < layers.length - 1) console.log("");
|
|
40
|
+
});
|
|
41
|
+
} else {
|
|
42
|
+
order.forEach((pkg, index) => {
|
|
43
|
+
console.log(`${index + 1}\t${pkg.name}\t${pkg.version}\t${pkg.dir}`);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log("");
|
|
48
|
+
console.log(`Root: ${path.relative(process.cwd(), root) || "."}`);
|
|
49
|
+
console.log(`Packages: ${order.length}`);
|
|
50
|
+
console.log(`Layers: ${layers.length}`);
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
root,
|
|
54
|
+
packages: order,
|
|
55
|
+
layers,
|
|
56
|
+
order: order.map((pkg) => pkg.name),
|
|
57
|
+
};
|
|
58
|
+
};
|
package/src/index.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
package: require("./package"),
|
|
3
3
|
publish: require("./publish"),
|
|
4
|
-
publishUis: require("./publish-uis"),
|
|
5
|
-
publishHelpers: require("./publish-helpers"),
|
|
6
|
-
publishConfigs: require("./publish-configs"),
|
|
7
4
|
getChangedPackages: require("./changed-packages").getChangedPackages,
|
|
8
5
|
runChanged: require("./run-changed"),
|
|
6
|
+
graph: require("./graph"),
|
|
7
|
+
syncDeps: require("./sync-deps"),
|
|
8
|
+
bump: require("./bump"),
|
|
9
|
+
build: require("./build"),
|
|
10
|
+
clear: require("./clear"),
|
|
11
|
+
resolveGraph: require("./workspace/resolve-graph"),
|
|
12
|
+
listWorkspacePackages: require("./workspace/list-packages"),
|
|
13
|
+
toTildeMinor: require("./workspace/to-tilde-minor"),
|
|
14
|
+
fetchNpmVersion: require("./workspace/fetch-npm-version"),
|
|
15
|
+
expectVersion: require("./workspace/expect-version"),
|
|
9
16
|
};
|
package/src/run-changed/index.js
CHANGED
|
@@ -11,9 +11,9 @@ module.exports = (script, options = {}) => {
|
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
for (const pkg of packages) {
|
|
14
|
+
for (const [index, pkg] of packages.entries()) {
|
|
15
15
|
const pkgDir = path.join(root, pkg.dir);
|
|
16
|
-
console.log(
|
|
16
|
+
console.log(`\n==> [${index + 1}/${packages.length}] ${pkg.name} (${pkg.dir})`);
|
|
17
17
|
|
|
18
18
|
if (options.dryRun) continue;
|
|
19
19
|
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
const { existsSync, writeFileSync } = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const readPackageJson = require("../workspace/read-package-json");
|
|
4
|
+
const listWorkspacePackages = require("../workspace/list-packages");
|
|
5
|
+
const fetchNpmVersion = require("../workspace/fetch-npm-version");
|
|
6
|
+
const toTildeMinor = require("../workspace/to-tilde-minor");
|
|
7
|
+
const { DEPENDENCY_FIELDS } = require("../workspace/build-graph");
|
|
8
|
+
|
|
9
|
+
const resolveVersion = (name, options) => {
|
|
10
|
+
if (options.workspace) {
|
|
11
|
+
return options.workspaceVersions.get(name) ?? null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return fetchNpmVersion(name, {
|
|
15
|
+
expectVersion: options.expectVersion,
|
|
16
|
+
expectWaitMs: options.expectWaitMs,
|
|
17
|
+
expectMaxAttempts: options.expectMaxAttempts,
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const syncPackageDeps = (options = {}) => {
|
|
22
|
+
const pkgDir = path.resolve(options.cwd ?? process.cwd());
|
|
23
|
+
const pkgPath = path.join(pkgDir, "package.json");
|
|
24
|
+
|
|
25
|
+
if (!existsSync(pkgPath)) {
|
|
26
|
+
if (options.exitOnMissing !== false) {
|
|
27
|
+
console.error("package.json not found in current directory");
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const workspaceVersions = options.workspace
|
|
35
|
+
? new Map(listWorkspacePackages({ cwd: pkgDir }).packages.map((pkg) => [pkg.name, pkg.version]))
|
|
36
|
+
: new Map();
|
|
37
|
+
|
|
38
|
+
const pkg = readPackageJson(pkgDir);
|
|
39
|
+
const changes = [];
|
|
40
|
+
const skipped = [];
|
|
41
|
+
const versionSource = options.workspace ? "workspace" : "npm";
|
|
42
|
+
|
|
43
|
+
for (const field of DEPENDENCY_FIELDS) {
|
|
44
|
+
const deps = pkg[field];
|
|
45
|
+
if (!deps) continue;
|
|
46
|
+
|
|
47
|
+
for (const [name, range] of Object.entries(deps)) {
|
|
48
|
+
if (!name.startsWith("@vnejs/")) continue;
|
|
49
|
+
|
|
50
|
+
const version = resolveVersion(name, {
|
|
51
|
+
workspace: options.workspace,
|
|
52
|
+
workspaceVersions,
|
|
53
|
+
expectVersion: options.expectVersion,
|
|
54
|
+
expectWaitMs: options.expectWaitMs,
|
|
55
|
+
expectMaxAttempts: options.expectMaxAttempts,
|
|
56
|
+
});
|
|
57
|
+
if (!version) {
|
|
58
|
+
skipped.push(name);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const next = toTildeMinor(version);
|
|
63
|
+
if (range === next) continue;
|
|
64
|
+
|
|
65
|
+
changes.push({ field, name, from: range, to: next, version });
|
|
66
|
+
deps[name] = next;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (skipped.length) {
|
|
71
|
+
console.warn(`Skipped ${skipped.length} packages not found in ${versionSource}: ${skipped.join(", ")}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (!changes.length) {
|
|
75
|
+
if (!options.quiet) {
|
|
76
|
+
console.log(`${pkg.name ?? path.basename(pkgDir)}: all @vnejs dependencies are up to date`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return { packageName: pkg.name, dir: path.relative(options.root ?? pkgDir, pkgDir), changes, skipped };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
for (const change of changes) {
|
|
83
|
+
console.log(`${change.field}: ${change.name} ${change.from} -> ${change.to} (${versionSource} ${change.version})`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (options.dryRun) {
|
|
87
|
+
console.log(`\nDry run: ${changes.length} dependencies would be updated`);
|
|
88
|
+
return { packageName: pkg.name, dir: path.relative(options.root ?? pkgDir, pkgDir), changes, skipped };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
92
|
+
console.log(`\nUpdated ${changes.length} dependencies in ${pkg.name}`);
|
|
93
|
+
|
|
94
|
+
return { packageName: pkg.name, dir: path.relative(options.root ?? pkgDir, pkgDir), changes, skipped };
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
module.exports = (options = {}) => {
|
|
98
|
+
if (options.all) {
|
|
99
|
+
const { root, packages } = listWorkspacePackages({ cwd: options.cwd });
|
|
100
|
+
const results = [];
|
|
101
|
+
|
|
102
|
+
console.log(`Syncing dependencies in ${packages.length} workspace packages...`);
|
|
103
|
+
|
|
104
|
+
for (const pkg of packages) {
|
|
105
|
+
console.log(`\n==> ${pkg.name} (${pkg.dir})`);
|
|
106
|
+
|
|
107
|
+
if (options.dryRun) {
|
|
108
|
+
console.log(" sync-deps");
|
|
109
|
+
results.push({ packageName: pkg.name, dir: pkg.dir, dryRun: true });
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const result = syncPackageDeps({
|
|
114
|
+
...options,
|
|
115
|
+
cwd: pkg.absDir,
|
|
116
|
+
root,
|
|
117
|
+
exitOnMissing: false,
|
|
118
|
+
all: false,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
if (result) results.push(result);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const updated = results.filter((result) => result.changes?.length);
|
|
125
|
+
console.log(`\nSynced ${packages.length} packages, updated ${updated.length}`);
|
|
126
|
+
return results;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return syncPackageDeps(options);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
module.exports.syncPackageDeps = syncPackageDeps;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const readPackageJson = require("./read-package-json");
|
|
2
|
+
|
|
3
|
+
const DEPENDENCY_FIELDS = ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"];
|
|
4
|
+
|
|
5
|
+
const buildDependencyGraph = (packages) => {
|
|
6
|
+
const byName = new Map(packages.map((pkg) => [pkg.name, pkg]));
|
|
7
|
+
const graph = new Map();
|
|
8
|
+
|
|
9
|
+
for (const pkg of packages) {
|
|
10
|
+
const deps = new Set();
|
|
11
|
+
const pkgJson = readPackageJson(pkg.absDir);
|
|
12
|
+
|
|
13
|
+
for (const field of DEPENDENCY_FIELDS) {
|
|
14
|
+
const fieldDeps = pkgJson[field];
|
|
15
|
+
if (!fieldDeps) continue;
|
|
16
|
+
|
|
17
|
+
for (const depName of Object.keys(fieldDeps)) {
|
|
18
|
+
if (byName.has(depName)) deps.add(depName);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
graph.set(pkg.name, [...deps].sort());
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return { graph, byName };
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const expandDependencyClosure = (packageNames, graph, byName) => {
|
|
29
|
+
const expanded = new Set(packageNames);
|
|
30
|
+
const queue = [...packageNames];
|
|
31
|
+
|
|
32
|
+
while (queue.length) {
|
|
33
|
+
const name = queue.shift();
|
|
34
|
+
|
|
35
|
+
for (const dep of graph.get(name) ?? []) {
|
|
36
|
+
if (!byName.has(dep) || expanded.has(dep)) continue;
|
|
37
|
+
|
|
38
|
+
expanded.add(dep);
|
|
39
|
+
queue.push(dep);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return [...expanded];
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const restrictGraph = (graph, packageNames) => {
|
|
47
|
+
const names = new Set(packageNames);
|
|
48
|
+
const restricted = new Map();
|
|
49
|
+
|
|
50
|
+
for (const name of packageNames) {
|
|
51
|
+
restricted.set(
|
|
52
|
+
name,
|
|
53
|
+
(graph.get(name) ?? []).filter((dep) => names.has(dep)),
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return restricted;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
module.exports = {
|
|
61
|
+
DEPENDENCY_FIELDS,
|
|
62
|
+
buildDependencyGraph,
|
|
63
|
+
expandDependencyClosure,
|
|
64
|
+
restrictGraph,
|
|
65
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module.exports.parseExpectVersion = (value) => {
|
|
2
|
+
if (!value) return null;
|
|
3
|
+
|
|
4
|
+
const normalized = String(value).trim().replace(/\.x$/, "");
|
|
5
|
+
const [major, minor] = normalized.split(".");
|
|
6
|
+
|
|
7
|
+
if (!major || minor === undefined) return null;
|
|
8
|
+
|
|
9
|
+
return `${major}.${minor}`;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
module.exports.versionMatchesExpect = (version, expectVersion) => {
|
|
13
|
+
const parsed = module.exports.parseExpectVersion(expectVersion);
|
|
14
|
+
if (!parsed || !version) return false;
|
|
15
|
+
|
|
16
|
+
const [expectedMajor, expectedMinor] = parsed.split(".");
|
|
17
|
+
const [major, minor] = String(version).split(".");
|
|
18
|
+
|
|
19
|
+
return major === expectedMajor && minor === expectedMinor;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
module.exports.shouldWaitForExpectVersion = (version, expectVersion) => {
|
|
23
|
+
const parsed = module.exports.parseExpectVersion(expectVersion);
|
|
24
|
+
if (!parsed) return false;
|
|
25
|
+
if (!version) return true;
|
|
26
|
+
|
|
27
|
+
const [expectedMajor, expectedMinor] = parsed.split(".").map(Number);
|
|
28
|
+
const [major, minor] = String(version).split(".").map(Number);
|
|
29
|
+
|
|
30
|
+
if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(expectedMajor) || Number.isNaN(expectedMinor)) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (major > expectedMajor || (major === expectedMajor && minor > expectedMinor)) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return !module.exports.versionMatchesExpect(version, parsed);
|
|
39
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const { execSync } = require("child_process");
|
|
2
|
+
const { parseExpectVersion, shouldWaitForExpectVersion } = require("./expect-version");
|
|
3
|
+
|
|
4
|
+
const fetchRaw = (name) => {
|
|
5
|
+
try {
|
|
6
|
+
return execSync(`npm view ${JSON.stringify(name)} version`, {
|
|
7
|
+
encoding: "utf8",
|
|
8
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
9
|
+
}).trim();
|
|
10
|
+
} catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const clearNpmCache = () => {
|
|
16
|
+
execSync("npm cache clean --force", { stdio: "inherit" });
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const sleepSync = (ms) => {
|
|
20
|
+
execSync(`sleep ${Math.max(1, Math.ceil(ms / 1000))}`, { stdio: "ignore" });
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
module.exports = (name, options = {}) => {
|
|
24
|
+
const expectVersion = parseExpectVersion(options.expectVersion);
|
|
25
|
+
|
|
26
|
+
if (!expectVersion) {
|
|
27
|
+
return fetchRaw(name);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const waitMs = options.expectWaitMs ?? 10000;
|
|
31
|
+
const maxAttempts = options.expectMaxAttempts ?? 12;
|
|
32
|
+
|
|
33
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
34
|
+
const version = fetchRaw(name);
|
|
35
|
+
|
|
36
|
+
if (!shouldWaitForExpectVersion(version, expectVersion)) {
|
|
37
|
+
return version;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (attempt === maxAttempts) {
|
|
41
|
+
console.warn(
|
|
42
|
+
`${name}: expected ${expectVersion}.x on npm, last seen: ${version ?? "not found"} — giving up`,
|
|
43
|
+
);
|
|
44
|
+
return version;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.warn(
|
|
48
|
+
`${name}: expected ${expectVersion}.x on npm, got ${version ?? "not found"} — npm cache clean, wait ${waitMs / 1000}s (${attempt}/${maxAttempts})`,
|
|
49
|
+
);
|
|
50
|
+
clearNpmCache();
|
|
51
|
+
sleepSync(waitMs);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return null;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
module.exports.fetchRaw = fetchRaw;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const readPackageJson = require("./read-package-json");
|
|
2
|
+
const matchVersion = require("./match-version");
|
|
3
|
+
|
|
4
|
+
const DEFAULT_EXCLUDED_DIRS = ["cli"];
|
|
5
|
+
|
|
6
|
+
const isExcludedDir = (dir, excludedDirs) =>
|
|
7
|
+
excludedDirs.some((excluded) => dir === excluded || dir.startsWith(`${excluded}/`));
|
|
8
|
+
|
|
9
|
+
module.exports = (packages, options = {}) => {
|
|
10
|
+
let result = packages;
|
|
11
|
+
const excludedDirs = options.excludeDirs ?? DEFAULT_EXCLUDED_DIRS;
|
|
12
|
+
|
|
13
|
+
result = result.filter((pkg) => !isExcludedDir(pkg.dir, excludedDirs));
|
|
14
|
+
|
|
15
|
+
if (options.onlyVersion) {
|
|
16
|
+
result = result.filter((pkg) => matchVersion(pkg.version, options.onlyVersion));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (options.name) {
|
|
20
|
+
const pattern = options.name.toLowerCase();
|
|
21
|
+
result = result.filter((pkg) => pkg.name.toLowerCase().includes(pattern));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (options.script) {
|
|
25
|
+
result = result.filter((pkg) => {
|
|
26
|
+
const pkgJson = readPackageJson(pkg.absDir);
|
|
27
|
+
return Boolean(pkgJson.scripts?.[options.script]);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return result;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
module.exports.DEFAULT_EXCLUDED_DIRS = DEFAULT_EXCLUDED_DIRS;
|
|
35
|
+
module.exports.isExcludedDir = isExcludedDir;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const { existsSync } = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const readPackageJson = require("./read-package-json");
|
|
4
|
+
|
|
5
|
+
module.exports = (start = process.cwd()) => {
|
|
6
|
+
let dir = path.resolve(start);
|
|
7
|
+
|
|
8
|
+
while (true) {
|
|
9
|
+
const pkgPath = path.join(dir, "package.json");
|
|
10
|
+
|
|
11
|
+
if (existsSync(pkgPath)) {
|
|
12
|
+
const pkg = readPackageJson(dir);
|
|
13
|
+
if (pkg.workspaces) return dir;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const parent = path.dirname(dir);
|
|
17
|
+
if (parent === dir) break;
|
|
18
|
+
dir = parent;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return path.resolve(start);
|
|
22
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const { existsSync, readdirSync } = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const readPackageJson = require("./read-package-json");
|
|
4
|
+
const findMonorepoRoot = require("./find-root");
|
|
5
|
+
|
|
6
|
+
const expandWorkspacePattern = (root, pattern) => {
|
|
7
|
+
const results = [];
|
|
8
|
+
const parts = pattern.split("/");
|
|
9
|
+
|
|
10
|
+
const walk = (dir, idx) => {
|
|
11
|
+
if (idx >= parts.length) {
|
|
12
|
+
if (existsSync(path.join(dir, "package.json"))) results.push(dir);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const part = parts[idx];
|
|
17
|
+
|
|
18
|
+
if (part === "**") {
|
|
19
|
+
if (!existsSync(dir)) return;
|
|
20
|
+
|
|
21
|
+
walk(dir, idx + 1);
|
|
22
|
+
|
|
23
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
24
|
+
if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== "dist") {
|
|
25
|
+
const subdir = path.join(dir, entry.name);
|
|
26
|
+
walk(subdir, idx + 1);
|
|
27
|
+
walk(subdir, idx);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (part === "*") {
|
|
35
|
+
if (!existsSync(dir)) return;
|
|
36
|
+
|
|
37
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
38
|
+
if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== "dist") {
|
|
39
|
+
walk(path.join(dir, entry.name), idx + 1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
walk(path.join(dir, part), idx + 1);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
walk(root, 0);
|
|
50
|
+
return results;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const listWorkspacePackages = (options = {}) => {
|
|
54
|
+
const root = options.root ?? findMonorepoRoot(options.cwd);
|
|
55
|
+
const rootPkg = readPackageJson(root);
|
|
56
|
+
const workspaces = rootPkg.workspaces ?? [];
|
|
57
|
+
const dirs = new Set();
|
|
58
|
+
|
|
59
|
+
for (const pattern of workspaces) {
|
|
60
|
+
for (const dir of expandWorkspacePattern(root, pattern)) {
|
|
61
|
+
dirs.add(dir);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const packages = [];
|
|
66
|
+
|
|
67
|
+
for (const absDir of [...dirs].sort()) {
|
|
68
|
+
const pkg = readPackageJson(absDir);
|
|
69
|
+
if (!pkg.name) continue;
|
|
70
|
+
|
|
71
|
+
packages.push({
|
|
72
|
+
name: pkg.name,
|
|
73
|
+
version: pkg.version ?? "0.0.0",
|
|
74
|
+
dir: path.relative(root, absDir) || ".",
|
|
75
|
+
absDir,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return { root, packages };
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
module.exports = listWorkspacePackages;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const listWorkspacePackages = require("./list-packages");
|
|
2
|
+
const filterPackages = require("./filter-packages");
|
|
3
|
+
const { buildDependencyGraph, expandDependencyClosure, restrictGraph } = require("./build-graph");
|
|
4
|
+
const { topoSort, topoSortLayers } = require("./topo-sort");
|
|
5
|
+
|
|
6
|
+
module.exports = (options = {}) => {
|
|
7
|
+
const { root, packages } = listWorkspacePackages({ cwd: options.cwd });
|
|
8
|
+
let selected = filterPackages(packages, options);
|
|
9
|
+
|
|
10
|
+
if (!selected.length) {
|
|
11
|
+
return { root, selected: [], order: [], layers: [], byName: new Map() };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const byName = new Map(packages.map((pkg) => [pkg.name, pkg]));
|
|
15
|
+
const { graph } = buildDependencyGraph(packages);
|
|
16
|
+
let packageNames = selected.map((pkg) => pkg.name);
|
|
17
|
+
|
|
18
|
+
if (options.includeDependencies && packageNames.length) {
|
|
19
|
+
packageNames = expandDependencyClosure(packageNames, graph, byName);
|
|
20
|
+
selected = packageNames.map((name) => byName.get(name)).filter(Boolean);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const restricted = restrictGraph(graph, packageNames);
|
|
24
|
+
const layerNames = topoSortLayers(restricted, packageNames);
|
|
25
|
+
const order = topoSort(restricted, packageNames).map((name) => byName.get(name));
|
|
26
|
+
const layers = layerNames.map((layer) => layer.map((name) => byName.get(name)));
|
|
27
|
+
|
|
28
|
+
return { root, selected, order, layers, byName };
|
|
29
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const topoSortLayers = (graph, packageNames) => {
|
|
2
|
+
const names = [...packageNames].sort();
|
|
3
|
+
const nameSet = new Set(names);
|
|
4
|
+
const inDegree = new Map(names.map((name) => [name, 0]));
|
|
5
|
+
const dependents = new Map(names.map((name) => [name, new Set()]));
|
|
6
|
+
|
|
7
|
+
for (const name of names) {
|
|
8
|
+
for (const dep of graph.get(name) ?? []) {
|
|
9
|
+
if (!nameSet.has(dep)) continue;
|
|
10
|
+
|
|
11
|
+
inDegree.set(name, inDegree.get(name) + 1);
|
|
12
|
+
dependents.get(dep).add(name);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const layers = [];
|
|
17
|
+
let queue = names.filter((name) => inDegree.get(name) === 0);
|
|
18
|
+
|
|
19
|
+
while (queue.length) {
|
|
20
|
+
layers.push(queue);
|
|
21
|
+
|
|
22
|
+
const next = [];
|
|
23
|
+
|
|
24
|
+
for (const name of queue) {
|
|
25
|
+
for (const dependent of dependents.get(name) ?? []) {
|
|
26
|
+
const degree = inDegree.get(dependent) - 1;
|
|
27
|
+
inDegree.set(dependent, degree);
|
|
28
|
+
|
|
29
|
+
if (degree === 0) next.push(dependent);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
queue = next.sort();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (layers.flat().length !== names.length) {
|
|
37
|
+
const remaining = names.filter((name) => !layers.flat().includes(name));
|
|
38
|
+
throw new Error(`Circular dependency detected: ${remaining.join(", ")}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return layers;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const topoSort = (graph, packageNames) => topoSortLayers(graph, packageNames).flat();
|
|
45
|
+
|
|
46
|
+
module.exports = {
|
|
47
|
+
topoSort,
|
|
48
|
+
topoSortLayers,
|
|
49
|
+
};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
const { execSync } = require("child_process");
|
|
2
|
-
const { existsSync } = require("fs");
|
|
3
|
-
const path = require("path");
|
|
4
|
-
|
|
5
|
-
module.exports = (bump, options = {}) => {
|
|
6
|
-
if (!["major", "minor", "patch"].includes(bump)) {
|
|
7
|
-
console.error("bump must be major, minor, or patch");
|
|
8
|
-
process.exit(1);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const root = process.cwd();
|
|
12
|
-
const configsRoot = path.join(root, "configs");
|
|
13
|
-
|
|
14
|
-
if (!existsSync(configsRoot)) {
|
|
15
|
-
console.error(`configs directory not found: ${configsRoot}`);
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const packageDirs = [
|
|
20
|
-
path.join(configsRoot, "ts-common"),
|
|
21
|
-
path.join(configsRoot, "ts-uis"),
|
|
22
|
-
].filter((pkgDir) => existsSync(pkgDir));
|
|
23
|
-
|
|
24
|
-
const access = options.access || "public";
|
|
25
|
-
const publishArgs = [`npx @vnejs/monorepo publish ${bump}`, `--access ${access}`];
|
|
26
|
-
if (options.dryRun) publishArgs.push("--dry-run");
|
|
27
|
-
if (options.otp) publishArgs.push(`--otp ${options.otp}`);
|
|
28
|
-
if (options.tag && options.tag !== "latest") publishArgs.push(`--tag ${options.tag}`);
|
|
29
|
-
|
|
30
|
-
const command = publishArgs.join(" ");
|
|
31
|
-
|
|
32
|
-
for (const pkgDir of packageDirs) {
|
|
33
|
-
console.log(`\n==> ${path.relative(root, pkgDir)}`);
|
|
34
|
-
execSync(command, { cwd: pkgDir, stdio: "inherit" });
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
console.log(`\nPublished ${packageDirs.length} configs packages (${bump}).`);
|
|
38
|
-
};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
const { execSync } = require("child_process");
|
|
2
|
-
const { existsSync } = require("fs");
|
|
3
|
-
const path = require("path");
|
|
4
|
-
const getHelpersLayers = require("../layers/helpers");
|
|
5
|
-
|
|
6
|
-
module.exports = (bump, options = {}) => {
|
|
7
|
-
if (!["major", "minor", "patch"].includes(bump)) {
|
|
8
|
-
console.error("bump must be major, minor, or patch");
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const root = process.cwd();
|
|
13
|
-
const helpersRoot = path.join(root, "helpers");
|
|
14
|
-
|
|
15
|
-
if (!existsSync(helpersRoot)) {
|
|
16
|
-
console.error(`helpers directory not found: ${helpersRoot}`);
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const packageDirs = getHelpersLayers(root).flatMap((layer) => layer.packageDirs);
|
|
21
|
-
|
|
22
|
-
const access = options.access || "public";
|
|
23
|
-
const publishArgs = [`npx @vnejs/monorepo publish ${bump}`, `--access ${access}`];
|
|
24
|
-
if (options.dryRun) publishArgs.push("--dry-run");
|
|
25
|
-
if (options.otp) publishArgs.push(`--otp ${options.otp}`);
|
|
26
|
-
if (options.tag && options.tag !== "latest") publishArgs.push(`--tag ${options.tag}`);
|
|
27
|
-
|
|
28
|
-
const command = publishArgs.join(" ");
|
|
29
|
-
|
|
30
|
-
for (const pkgDir of packageDirs) {
|
|
31
|
-
console.log(`\n==> ${path.relative(root, pkgDir)}`);
|
|
32
|
-
execSync(command, { cwd: pkgDir, stdio: "inherit" });
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
console.log(`\nPublished ${packageDirs.length} helpers packages (${bump}).`);
|
|
36
|
-
};
|
package/src/publish-uis/index.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
const { execSync } = require("child_process");
|
|
2
|
-
const { existsSync } = require("fs");
|
|
3
|
-
const path = require("path");
|
|
4
|
-
const getUisLayers = require("../layers/uis");
|
|
5
|
-
|
|
6
|
-
module.exports = (bump, options = {}) => {
|
|
7
|
-
if (!["major", "minor", "patch"].includes(bump)) {
|
|
8
|
-
console.error("bump must be major, minor, or patch");
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const root = process.cwd();
|
|
13
|
-
const uisRoot = path.join(root, "uis");
|
|
14
|
-
|
|
15
|
-
if (!existsSync(uisRoot)) {
|
|
16
|
-
console.error(`uis directory not found: ${uisRoot}`);
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const packageDirs = getUisLayers(root).flatMap((layer) => layer.packageDirs);
|
|
21
|
-
|
|
22
|
-
const access = options.access || "public";
|
|
23
|
-
const publishArgs = [`npx @vnejs/monorepo publish ${bump}`, `--access ${access}`];
|
|
24
|
-
if (options.dryRun) publishArgs.push("--dry-run");
|
|
25
|
-
if (options.otp) publishArgs.push(`--otp ${options.otp}`);
|
|
26
|
-
if (options.tag && options.tag !== "latest") publishArgs.push(`--tag ${options.tag}`);
|
|
27
|
-
|
|
28
|
-
const command = publishArgs.join(" ");
|
|
29
|
-
|
|
30
|
-
for (const pkgDir of packageDirs) {
|
|
31
|
-
console.log(`\n==> ${path.relative(root, pkgDir)}`);
|
|
32
|
-
execSync(command, { cwd: pkgDir, stdio: "inherit" });
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
console.log(`\nPublished ${packageDirs.length} uis packages (${bump}).`);
|
|
36
|
-
};
|