-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
executable file
·83 lines (70 loc) · 2.55 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/usr/bin/env node
import path from 'node:path';
import { loadJsonFile } from 'load-json-file';
import { loadYamlFile } from 'load-yaml-file';
import { findUp } from 'find-up';
import globAll from 'glob-all';
import Graph from 'graph-data-structure';
import { execaSync } from 'execa';
import { isNpm, isNpmOrYarn } from 'is-npm';
const main = async () => {
const argv = process.argv.slice(2);
const command = argv[0];
if (!command) {
console.error('\nPlease specify a command to run\n');
process.exit(1);
}
const rootManifestPath = await findUp('package.json');
const rootManifest = await loadJsonFile(rootManifestPath);
let packageManager;
let workspaces;
if (isNpmOrYarn && Array.isArray(rootManifest.workspaces)) {
packageManager = isNpm ? 'npm' : 'yarn';
workspaces = rootManifest.workspaces;
} else {
try {
const { packages } = await loadYamlFile(path.join(path.dirname(rootManifestPath), 'pnpm-workspace.yaml'));
workspaces = packages;
packageManager = 'pnpm';
} catch (e) {
console.error('No workspaces found');
process.exit(1);
}
}
const packagePaths = globAll.sync(workspaces).map(aPath => path.resolve(aPath));
const packageManifests = await Promise.all(
packagePaths.map(aPath => loadManifest(aPath))
);
const packagesByName = Object.assign({},
...packageManifests.map(manifestInfo => ({ [manifestInfo.manifest.name]: manifestInfo }))
);
const packageNames = Object.keys(packagesByName);
const packageGraph = Graph();
for (const name of packageNames) {
for (const { manifest } of packageManifests) {
if (allDependenciesFromManifest(manifest).includes(name)) {
packageGraph.addEdge(name, manifest.name);
} else {
packageGraph.addNode(name);
}
}
}
const packageNamesSorted = packageGraph.topologicalSort();
console.log(`[mrex] detected workspace packages:\n ${packageNamesSorted.join('\n ')}`);
for (const name of packageNamesSorted) {
const { pathToPackage } = packagesByName[name];
console.log(`\n[mrex] running "${packageManager} run ${argv.join(' ')}" at ${pathToPackage}\n`);
execaSync(packageManager, ['run', ...argv], {
cwd: pathToPackage,
stdio: "inherit",
});
}
}
const loadManifest = async (pathToPackage) => {
const manifest = await loadJsonFile(path.join(pathToPackage, 'package.json'));
return { pathToPackage, manifest };
}
const allDependenciesFromManifest = (manifest) => (
Object.keys(manifest.dependencies || {}).concat(Object.keys(manifest.devDependencies || {}))
);
await main();