Skip to content

Commit eb63f1e

Browse files
joshblackdakahn
andauthored
feat(cli): add generic support to cli for workspaces (#9761)
Co-authored-by: DAK <40970507+dakahn@users.noreply.github.com>
1 parent 49c0c93 commit eb63f1e

File tree

1 file changed

+67
-17
lines changed

1 file changed

+67
-17
lines changed

packages/cli/src/workspace.js

Lines changed: 67 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,26 @@ const execa = require('execa');
1111
const fs = require('fs-extra');
1212
const glob = require('fast-glob');
1313
const path = require('path');
14-
const packageJson = require('../../../package.json');
15-
16-
const WORKSPACE_ROOT = path.resolve(__dirname, '../../../');
17-
const packagePaths = glob
18-
.sync(packageJson.workspaces.map((pattern) => `${pattern}/package.json`))
19-
.map((match) => {
20-
const packageJsonPath = path.join(WORKSPACE_ROOT, match);
21-
return {
22-
packageJsonPath,
23-
packageJson: fs.readJsonSync(packageJsonPath),
24-
packagePath: path.dirname(packageJsonPath),
25-
packageFolder: path.relative(
26-
WORKSPACE_ROOT,
27-
path.dirname(packageJsonPath)
28-
),
29-
};
30-
});
14+
15+
const { root: ROOT_DIR } = path.parse(__dirname);
16+
const WORKSPACE_ROOT = getProjectRoot(__dirname);
17+
const packageJson = fs.readJsonSync(path.join(WORKSPACE_ROOT, 'package.json'));
18+
const packagePaths = Array.isArray(packageJson.workspaces)
19+
? glob
20+
.sync(packageJson.workspaces.map((pattern) => `${pattern}/package.json`))
21+
.map((match) => {
22+
const packageJsonPath = path.join(WORKSPACE_ROOT, match);
23+
return {
24+
packageJsonPath,
25+
packageJson: fs.readJsonSync(packageJsonPath),
26+
packagePath: path.dirname(packageJsonPath),
27+
packageFolder: path.relative(
28+
WORKSPACE_ROOT,
29+
path.dirname(packageJsonPath)
30+
),
31+
};
32+
})
33+
: [];
3134

3235
const env = {
3336
root: {
@@ -54,6 +57,53 @@ async function getPackages() {
5457
return JSON.parse(lernaListOutput).filter((pkg) => !pkg.private);
5558
}
5659

60+
/**
61+
* Returns the root directory of a project, either as a workspace root with a
62+
* collection of packages or a single project with a `package.json`
63+
* @param {string} directory
64+
* @returns {string}
65+
*/
66+
function getProjectRoot(directory) {
67+
const packageJsonPaths = ancestors(directory).filter((directory) => {
68+
return fs.existsSync(path.join(directory, 'package.json'));
69+
});
70+
71+
const rootDirectory =
72+
packageJsonPaths.length > 0
73+
? packageJsonPaths[packageJsonPaths.length - 1]
74+
: null;
75+
76+
if (!rootDirectory) {
77+
throw new Error(
78+
`Unable to find a \`package.json\` file from directory: ${directory}`
79+
);
80+
}
81+
82+
return rootDirectory;
83+
}
84+
85+
/**
86+
* Returns an array of the the directory and its ancestors
87+
* @param {string} directory
88+
* @returns {Array<string>}
89+
*/
90+
function ancestors(directory) {
91+
const result = [directory];
92+
let current = directory;
93+
94+
while (current !== '') {
95+
result.push(current);
96+
97+
if (current !== ROOT_DIR) {
98+
current = path.dirname(current);
99+
} else {
100+
current = '';
101+
}
102+
}
103+
104+
return result;
105+
}
106+
57107
module.exports = {
58108
workspace,
59109
getPackages,

0 commit comments

Comments
 (0)