@vnejs/monorepo 0.2.0 → 0.2.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 +4 -2
- package/src/bump/index.js +3 -0
- package/src/clear/index.js +4 -4
- package/src/cli.js +13 -6
- package/src/graph/index.js +1 -3
- package/src/package/index.js +1 -2
- package/src/publish/utils.js +17 -2
- package/src/run-changed/index.js +42 -6
- package/src/run-changed/schedule.js +56 -0
- package/src/run-changed/schedule.test.js +163 -0
- package/src/sync-deps/index.js +1 -3
- package/src/workspace/fetch-npm-version.js +1 -3
- package/src/workspace/filter-packages.js +1 -2
- package/vitest.config.js +10 -0
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vnejs/monorepo",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Monorepo tooling for @vnejs",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"@vnejs/monorepo": "./src/cli.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"test": "
|
|
10
|
+
"test": "npx @vnejs/monorepo test",
|
|
11
11
|
"publish:major": "npm version major && npm publish --access public",
|
|
12
12
|
"publish:minor": "npm version minor && npm publish --access public",
|
|
13
13
|
"publish:patch": "npm version patch && npm publish --access public"
|
|
@@ -15,8 +15,10 @@
|
|
|
15
15
|
"author": "",
|
|
16
16
|
"license": "ISC",
|
|
17
17
|
"dependencies": {
|
|
18
|
+
"@vnejs/configs.vitest": "~0.2.0",
|
|
18
19
|
"commander": "~15.0.0",
|
|
19
20
|
"happy-dom": "~20.10.6",
|
|
21
|
+
"p-limit": "~7.3.0",
|
|
20
22
|
"typescript": "7.0.2",
|
|
21
23
|
"vitest": "~4.1.9"
|
|
22
24
|
}
|
package/src/bump/index.js
CHANGED
package/src/clear/index.js
CHANGED
|
@@ -8,17 +8,17 @@ module.exports = (options = {}) => {
|
|
|
8
8
|
|
|
9
9
|
console.log("==> Removing node_modules...");
|
|
10
10
|
run("rm -rf node_modules", root);
|
|
11
|
-
run(
|
|
11
|
+
run("find . -name node_modules -type d -prune -exec rm -rf {} +", root);
|
|
12
12
|
|
|
13
13
|
console.log("==> Removing Turbo cache...");
|
|
14
14
|
run("rm -rf .turbo", root);
|
|
15
|
-
run(
|
|
15
|
+
run("find . -name .turbo -type d -prune -exec rm -rf {} +", root);
|
|
16
16
|
|
|
17
17
|
console.log("==> Removing dist folders...");
|
|
18
|
-
run(
|
|
18
|
+
run("find . -name dist -type d -prune -exec rm -rf {} +", root);
|
|
19
19
|
|
|
20
20
|
console.log("==> Removing package-lock files...");
|
|
21
|
-
run(
|
|
21
|
+
run("find . -name package-lock.json -type f -delete", root);
|
|
22
22
|
|
|
23
23
|
console.log("\n==> Clear complete.");
|
|
24
24
|
};
|
package/src/cli.js
CHANGED
|
@@ -97,16 +97,23 @@ program
|
|
|
97
97
|
|
|
98
98
|
program
|
|
99
99
|
.command("run-changed")
|
|
100
|
-
.description("Run npm script
|
|
100
|
+
.description("Run npm script in git-changed workspace packages (sequential by default)")
|
|
101
101
|
.option("--script <script>", "npm script name from package.json")
|
|
102
102
|
.option("--ref <ref>", "git ref to compare against", "HEAD")
|
|
103
103
|
.option("--dry-run", "list changed packages without running the script", false)
|
|
104
104
|
.option("--confirm", "ask for confirmation before running the script", false)
|
|
105
|
-
.
|
|
105
|
+
.option("--concurrency <n>", "max parallel package scripts (p-limit)", "1")
|
|
106
|
+
.option("--parallel-ms <ms>", "after this window, drop concurrency to 1")
|
|
107
|
+
.option("--first-serial", "run the first package to completion before the parallel pool", false)
|
|
108
|
+
.action((options) =>
|
|
109
|
+
runChangedAction({
|
|
110
|
+
...options,
|
|
111
|
+
concurrency: Number(options.concurrency),
|
|
112
|
+
parallelMs: options.parallelMs == null ? undefined : Number(options.parallelMs),
|
|
113
|
+
firstSerial: Boolean(options.firstSerial),
|
|
114
|
+
}),
|
|
115
|
+
);
|
|
106
116
|
|
|
107
|
-
program
|
|
108
|
-
.command("clear")
|
|
109
|
-
.description("Clean node_modules, caches, dist, and lockfiles")
|
|
110
|
-
.action(clearAction);
|
|
117
|
+
program.command("clear").description("Clean node_modules, caches, dist, and lockfiles").action(clearAction);
|
|
111
118
|
|
|
112
119
|
program.parse();
|
package/src/graph/index.js
CHANGED
|
@@ -69,9 +69,7 @@ module.exports = (options = {}) => {
|
|
|
69
69
|
if (options.flat) {
|
|
70
70
|
order.forEach((pkg, index) => {
|
|
71
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
|
-
);
|
|
72
|
+
console.log(`${index + 1}\t${meta.layer}/${meta.layerTotal}\t${formatPackageRef(pkg)}\t${pkg.dir}`);
|
|
75
73
|
});
|
|
76
74
|
} else {
|
|
77
75
|
for (let layerIndex = 0; layerIndex < layers.length; layerIndex++) {
|
package/src/package/index.js
CHANGED
|
@@ -19,8 +19,7 @@ module.exports = (options = {}) => {
|
|
|
19
19
|
// TS 7 no longer exports `typescript/bin/tsc`; resolve via package.json `bin`.
|
|
20
20
|
const typescriptPkgPath = require.resolve("typescript/package.json");
|
|
21
21
|
const typescriptPkg = require(typescriptPkgPath);
|
|
22
|
-
const tscRel =
|
|
23
|
-
typeof typescriptPkg.bin === "string" ? typescriptPkg.bin : typescriptPkg.bin.tsc;
|
|
22
|
+
const tscRel = typeof typescriptPkg.bin === "string" ? typescriptPkg.bin : typescriptPkg.bin.tsc;
|
|
24
23
|
const tsc = path.resolve(path.dirname(typescriptPkgPath), tscRel);
|
|
25
24
|
execSync(`node "${tsc}" -p "${config}"`, { cwd: pkgDir, stdio: "inherit" });
|
|
26
25
|
};
|
package/src/publish/utils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { execSync } = require("child_process");
|
|
1
|
+
const { execSync, spawn } = require("child_process");
|
|
2
2
|
const { existsSync, readFileSync, writeFileSync } = require("fs");
|
|
3
3
|
const path = require("path");
|
|
4
4
|
|
|
@@ -28,6 +28,21 @@ const run = (command, pkgDir) => {
|
|
|
28
28
|
execSync(command, { cwd: pkgDir, stdio: "inherit" });
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
+
const runAsync = (command, pkgDir) =>
|
|
32
|
+
new Promise((resolve, reject) => {
|
|
33
|
+
const child = spawn(command, { cwd: pkgDir, stdio: "inherit", shell: true });
|
|
34
|
+
|
|
35
|
+
child.on("error", reject);
|
|
36
|
+
child.on("close", (code) => {
|
|
37
|
+
if (code === 0) {
|
|
38
|
+
resolve();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
reject(new Error(`${command} exited with ${code}`));
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
31
46
|
const prepareForPublish = (pkgDir) => {
|
|
32
47
|
const pkg = readPackageJson(pkgDir);
|
|
33
48
|
if (!pkg.scripts?.build) return;
|
|
@@ -35,4 +50,4 @@ const prepareForPublish = (pkgDir) => {
|
|
|
35
50
|
run("npx @vnejs/monorepo package --clean", pkgDir);
|
|
36
51
|
};
|
|
37
52
|
|
|
38
|
-
module.exports = { readPackageName, readVersion, writeVersion, run, prepareForPublish };
|
|
53
|
+
module.exports = { readPackageName, readVersion, writeVersion, run, runAsync, prepareForPublish };
|
package/src/run-changed/index.js
CHANGED
|
@@ -2,9 +2,10 @@ const path = require("path");
|
|
|
2
2
|
|
|
3
3
|
const { getChangedPackages } = require("../changed-packages");
|
|
4
4
|
const resolveGraph = require("../workspace/resolve-graph");
|
|
5
|
-
const {
|
|
5
|
+
const { runAsync } = require("../publish/utils");
|
|
6
6
|
const confirm = require("../utils/confirm");
|
|
7
7
|
const { formatPackageLine } = require("../utils/format-package");
|
|
8
|
+
const schedulePackages = require("./schedule");
|
|
8
9
|
|
|
9
10
|
const sortByGraphOrder = (root, changedPackages, script) => {
|
|
10
11
|
const changedNames = new Set(changedPackages.map((pkg) => pkg.name));
|
|
@@ -26,8 +27,37 @@ const printPackages = (packages) => {
|
|
|
26
27
|
console.log(`Total: ${packages.length}`);
|
|
27
28
|
};
|
|
28
29
|
|
|
30
|
+
const parseConcurrency = (value) => {
|
|
31
|
+
if (value == null) return 1;
|
|
32
|
+
|
|
33
|
+
const concurrency = Number(value);
|
|
34
|
+
|
|
35
|
+
if (!Number.isInteger(concurrency) || concurrency < 1) {
|
|
36
|
+
console.error('Invalid "--concurrency". Must be an integer >= 1.');
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return concurrency;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const parseParallelMs = (value) => {
|
|
44
|
+
if (value == null) return undefined;
|
|
45
|
+
|
|
46
|
+
const parallelMs = Number(value);
|
|
47
|
+
|
|
48
|
+
if (!Number.isFinite(parallelMs) || parallelMs < 0) {
|
|
49
|
+
console.error('Invalid "--parallel-ms". Must be a number >= 0.');
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return parallelMs;
|
|
54
|
+
};
|
|
55
|
+
|
|
29
56
|
module.exports = async (options = {}) => {
|
|
30
57
|
const script = options.script;
|
|
58
|
+
const concurrency = parseConcurrency(options.concurrency);
|
|
59
|
+
const parallelMs = parseParallelMs(options.parallelMs);
|
|
60
|
+
const firstSerial = Boolean(options.firstSerial);
|
|
31
61
|
|
|
32
62
|
if (!options.dryRun && !script) {
|
|
33
63
|
console.error('Missing required option "--script".');
|
|
@@ -62,9 +92,15 @@ module.exports = async (options = {}) => {
|
|
|
62
92
|
console.log("");
|
|
63
93
|
}
|
|
64
94
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
95
|
+
await schedulePackages({
|
|
96
|
+
packages,
|
|
97
|
+
concurrency,
|
|
98
|
+
parallelMs,
|
|
99
|
+
firstSerial,
|
|
100
|
+
runFn: async (pkg, index) => {
|
|
101
|
+
const pkgDir = path.join(root, pkg.dir);
|
|
102
|
+
console.log(formatPackageLine(pkg, { leadingNewline: true, tag: `[${index + 1}/${packages.length}]` }));
|
|
103
|
+
await runAsync(`npm run ${script}`, pkgDir);
|
|
104
|
+
},
|
|
105
|
+
});
|
|
70
106
|
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const pLimit = require("p-limit").default;
|
|
2
|
+
|
|
3
|
+
const PARALLEL_WINDOW_ENDED = "Parallel window ended; concurrency set to 1";
|
|
4
|
+
|
|
5
|
+
const schedulePackages = async ({ packages, runFn, concurrency = 1, parallelMs, firstSerial = false, log = console.log }) => {
|
|
6
|
+
if (!Number.isInteger(concurrency) || concurrency < 1) {
|
|
7
|
+
throw new Error("concurrency must be an integer >= 1");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (parallelMs != null && (!Number.isFinite(parallelMs) || parallelMs < 0)) {
|
|
11
|
+
throw new Error("parallelMs must be a number >= 0");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (!packages.length) return;
|
|
15
|
+
|
|
16
|
+
let startIndex = 0;
|
|
17
|
+
|
|
18
|
+
if (firstSerial) {
|
|
19
|
+
await runFn(packages[0], 0);
|
|
20
|
+
startIndex = 1;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const remaining = packages.slice(startIndex);
|
|
24
|
+
|
|
25
|
+
if (!remaining.length) return;
|
|
26
|
+
|
|
27
|
+
const limit = pLimit(concurrency);
|
|
28
|
+
let timer;
|
|
29
|
+
|
|
30
|
+
if (parallelMs != null && concurrency > 1) {
|
|
31
|
+
timer = setTimeout(() => {
|
|
32
|
+
limit.concurrency = 1;
|
|
33
|
+
log(PARALLEL_WINDOW_ENDED);
|
|
34
|
+
}, parallelMs);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const results = await Promise.allSettled(remaining.map((pkg, offset) => limit(() => runFn(pkg, startIndex + offset))));
|
|
39
|
+
|
|
40
|
+
const failed = results.filter((result) => result.status === "rejected");
|
|
41
|
+
|
|
42
|
+
if (!failed.length) return;
|
|
43
|
+
|
|
44
|
+
for (const result of failed) {
|
|
45
|
+
const reason = result.reason;
|
|
46
|
+
log(reason?.stack ?? String(reason));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
throw new Error(`${failed.length} package script(s) failed.`);
|
|
50
|
+
} finally {
|
|
51
|
+
if (timer) clearTimeout(timer);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
module.exports = schedulePackages;
|
|
56
|
+
module.exports.PARALLEL_WINDOW_ENDED = PARALLEL_WINDOW_ENDED;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
|
|
3
|
+
import schedulePackages, { PARALLEL_WINDOW_ENDED } from "./schedule.js";
|
|
4
|
+
|
|
5
|
+
const packages = (...names) => names.map((name) => ({ name }));
|
|
6
|
+
|
|
7
|
+
const createDeferred = () => {
|
|
8
|
+
let resolve;
|
|
9
|
+
let reject;
|
|
10
|
+
const promise = new Promise((res, rej) => {
|
|
11
|
+
resolve = res;
|
|
12
|
+
reject = rej;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return { promise, resolve, reject };
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const createTrackedRunner = () => {
|
|
19
|
+
const started = [];
|
|
20
|
+
const deferreds = new Map();
|
|
21
|
+
|
|
22
|
+
const runFn = (pkg) => {
|
|
23
|
+
started.push(pkg.name);
|
|
24
|
+
const deferred = createDeferred();
|
|
25
|
+
deferreds.set(pkg.name, deferred);
|
|
26
|
+
return deferred.promise;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const resolve = (name) => deferreds.get(name).resolve();
|
|
30
|
+
const reject = (name, error) => deferreds.get(name).reject(error);
|
|
31
|
+
|
|
32
|
+
return { started, deferreds, runFn, resolve, reject };
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const flush = async () => {
|
|
36
|
+
await Promise.resolve();
|
|
37
|
+
await Promise.resolve();
|
|
38
|
+
await Promise.resolve();
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
describe("schedulePackages", () => {
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
vi.useRealTimers();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("runs the first package outside the pool when firstSerial is set", async () => {
|
|
47
|
+
const { started, runFn, resolve } = createTrackedRunner();
|
|
48
|
+
const done = schedulePackages({
|
|
49
|
+
packages: packages("a", "b", "c"),
|
|
50
|
+
runFn,
|
|
51
|
+
concurrency: 2,
|
|
52
|
+
firstSerial: true,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
await flush();
|
|
56
|
+
expect(started).toEqual(["a"]);
|
|
57
|
+
|
|
58
|
+
resolve("a");
|
|
59
|
+
await flush();
|
|
60
|
+
expect(started).toEqual(["a", "b", "c"]);
|
|
61
|
+
|
|
62
|
+
resolve("b");
|
|
63
|
+
resolve("c");
|
|
64
|
+
await done;
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("does not start the pool when the first-serial package fails", async () => {
|
|
68
|
+
const { started, runFn, reject } = createTrackedRunner();
|
|
69
|
+
const done = schedulePackages({
|
|
70
|
+
packages: packages("a", "b"),
|
|
71
|
+
runFn,
|
|
72
|
+
concurrency: 2,
|
|
73
|
+
firstSerial: true,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
await flush();
|
|
77
|
+
reject("a", new Error("first failed"));
|
|
78
|
+
|
|
79
|
+
await expect(done).rejects.toThrow("first failed");
|
|
80
|
+
expect(started).toEqual(["a"]);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("drops concurrency to 1 after parallelMs; in-flight tasks keep running", async () => {
|
|
84
|
+
vi.useFakeTimers();
|
|
85
|
+
|
|
86
|
+
const { started, runFn, resolve } = createTrackedRunner();
|
|
87
|
+
const logs = [];
|
|
88
|
+
const done = schedulePackages({
|
|
89
|
+
packages: packages("a", "b", "c", "d", "e"),
|
|
90
|
+
runFn,
|
|
91
|
+
concurrency: 3,
|
|
92
|
+
parallelMs: 100,
|
|
93
|
+
log: (message) => logs.push(message),
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
await flush();
|
|
97
|
+
expect(started).toEqual(["a", "b", "c"]);
|
|
98
|
+
|
|
99
|
+
await vi.advanceTimersByTimeAsync(100);
|
|
100
|
+
expect(logs).toContain(PARALLEL_WINDOW_ENDED);
|
|
101
|
+
expect(started).toEqual(["a", "b", "c"]);
|
|
102
|
+
|
|
103
|
+
resolve("a");
|
|
104
|
+
await flush();
|
|
105
|
+
expect(started).toEqual(["a", "b", "c"]);
|
|
106
|
+
|
|
107
|
+
resolve("b");
|
|
108
|
+
await flush();
|
|
109
|
+
expect(started).toEqual(["a", "b", "c"]);
|
|
110
|
+
|
|
111
|
+
resolve("c");
|
|
112
|
+
await flush();
|
|
113
|
+
expect(started).toEqual(["a", "b", "c", "d"]);
|
|
114
|
+
|
|
115
|
+
resolve("d");
|
|
116
|
+
await flush();
|
|
117
|
+
expect(started).toEqual(["a", "b", "c", "d", "e"]);
|
|
118
|
+
|
|
119
|
+
resolve("e");
|
|
120
|
+
await done;
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("keeps concurrency for the whole run when parallelMs is omitted", async () => {
|
|
124
|
+
const { started, runFn, resolve } = createTrackedRunner();
|
|
125
|
+
const done = schedulePackages({
|
|
126
|
+
packages: packages("a", "b", "c", "d"),
|
|
127
|
+
runFn,
|
|
128
|
+
concurrency: 3,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
await flush();
|
|
132
|
+
expect(started).toEqual(["a", "b", "c"]);
|
|
133
|
+
|
|
134
|
+
resolve("a");
|
|
135
|
+
await flush();
|
|
136
|
+
expect(started).toEqual(["a", "b", "c", "d"]);
|
|
137
|
+
|
|
138
|
+
resolve("b");
|
|
139
|
+
resolve("c");
|
|
140
|
+
resolve("d");
|
|
141
|
+
await done;
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("waits for in-flight failures and then rejects", async () => {
|
|
145
|
+
const { started, runFn, resolve, reject } = createTrackedRunner();
|
|
146
|
+
const logs = [];
|
|
147
|
+
const done = schedulePackages({
|
|
148
|
+
packages: packages("a", "b"),
|
|
149
|
+
runFn,
|
|
150
|
+
concurrency: 2,
|
|
151
|
+
log: (message) => logs.push(message),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
await flush();
|
|
155
|
+
expect(started).toEqual(["a", "b"]);
|
|
156
|
+
|
|
157
|
+
reject("a", new Error("a failed"));
|
|
158
|
+
resolve("b");
|
|
159
|
+
|
|
160
|
+
await expect(done).rejects.toThrow("1 package script(s) failed.");
|
|
161
|
+
expect(logs.some((message) => String(message).includes("a failed"))).toBe(true);
|
|
162
|
+
});
|
|
163
|
+
});
|
package/src/sync-deps/index.js
CHANGED
|
@@ -32,9 +32,7 @@ const syncPackageDeps = (options = {}) => {
|
|
|
32
32
|
return null;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
const workspaceVersions = options.workspace
|
|
36
|
-
? new Map(listWorkspacePackages({ cwd: pkgDir }).packages.map((pkg) => [pkg.name, pkg.version]))
|
|
37
|
-
: new Map();
|
|
35
|
+
const workspaceVersions = options.workspace ? new Map(listWorkspacePackages({ cwd: pkgDir }).packages.map((pkg) => [pkg.name, pkg.version])) : new Map();
|
|
38
36
|
|
|
39
37
|
const pkg = readPackageJson(pkgDir);
|
|
40
38
|
const changes = [];
|
|
@@ -38,9 +38,7 @@ module.exports = (name, options = {}) => {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
if (attempt === maxAttempts) {
|
|
41
|
-
console.warn(
|
|
42
|
-
`${name}: expected ${expectVersion}.x on npm, last seen: ${version ?? "not found"} — giving up`,
|
|
43
|
-
);
|
|
41
|
+
console.warn(`${name}: expected ${expectVersion}.x on npm, last seen: ${version ?? "not found"} — giving up`);
|
|
44
42
|
return version;
|
|
45
43
|
}
|
|
46
44
|
|
|
@@ -4,8 +4,7 @@ const isStubTestScript = require("./is-stub-test-script");
|
|
|
4
4
|
|
|
5
5
|
const DEFAULT_EXCLUDED_DIRS = [];
|
|
6
6
|
|
|
7
|
-
const isExcludedDir = (dir, excludedDirs) =>
|
|
8
|
-
excludedDirs.some((excluded) => dir === excluded || dir.startsWith(`${excluded}/`));
|
|
7
|
+
const isExcludedDir = (dir, excludedDirs) => excludedDirs.some((excluded) => dir === excluded || dir.startsWith(`${excluded}/`));
|
|
9
8
|
|
|
10
9
|
module.exports = (packages, options = {}) => {
|
|
11
10
|
let result = packages;
|
package/vitest.config.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
|
|
4
|
+
import { createVitestConfig } from "@vnejs/configs.vitest/create-config.js";
|
|
5
|
+
|
|
6
|
+
export default createVitestConfig({
|
|
7
|
+
dirname: path.dirname(fileURLToPath(import.meta.url)),
|
|
8
|
+
environment: "node",
|
|
9
|
+
include: ["src/**/*.test.js"],
|
|
10
|
+
});
|