diff --git a/core/project/__fixtures__/basic/packages/pkg-1/package.json b/core/project/__fixtures__/basic/packages/pkg-1/package.json new file mode 100644 index 0000000000..8b0c3e7dc2 --- /dev/null +++ b/core/project/__fixtures__/basic/packages/pkg-1/package.json @@ -0,0 +1,4 @@ +{ + "name": "pkg-1", + "version": "1.0.0" +} diff --git a/core/project/__fixtures__/basic/packages/pkg-2/package.json b/core/project/__fixtures__/basic/packages/pkg-2/package.json new file mode 100644 index 0000000000..bc90fce816 --- /dev/null +++ b/core/project/__fixtures__/basic/packages/pkg-2/package.json @@ -0,0 +1,7 @@ +{ + "name": "pkg-2", + "version": "1.0.0", + "dependencies": { + "pkg-1": "^1.0.0" + } +} diff --git a/core/project/__tests__/project.test.js b/core/project/__tests__/project.test.js index d4f6e9d91c..69619b73bf 100644 --- a/core/project/__tests__/project.test.js +++ b/core/project/__tests__/project.test.js @@ -258,6 +258,31 @@ Object { }); }); + describe(".getPackagesSync()", () => { + it("returns a list of package instances synchronously", () => { + const project = new Project(testDir); + expect(project.getPackagesSync()).toMatchInlineSnapshot(` + Array [ + Object { + "name": "pkg-1", + "version": "1.0.0", + }, + Object { + "dependencies": Object { + "pkg-1": "^1.0.0", + }, + "name": "pkg-2", + "version": "1.0.0", + }, + ] + `); + }); + + it("is available from a static named export", () => { + expect(Project.getPackagesSync(testDir)).toMatchObject(new Project(testDir).getPackagesSync()); + }); + }); + describe("get .manifest", () => { it("returns a Package instance", () => { const project = new Project(testDir); diff --git a/core/project/index.js b/core/project/index.js index a647473321..94d0b530c9 100644 --- a/core/project/index.js +++ b/core/project/index.js @@ -14,7 +14,7 @@ const ValidationError = require("@lerna/validation-error"); const Package = require("@lerna/package"); const applyExtends = require("./lib/apply-extends"); const deprecateConfig = require("./lib/deprecate-config"); -const { makeFileFinder } = require("./lib/make-file-finder"); +const { makeFileFinder, makeSyncFileFinder } = require("./lib/make-file-finder"); class Project { constructor(cwd) { @@ -175,6 +175,16 @@ class Project { return this.fileFinder("package.json", filePaths => pMap(filePaths, mapper, { concurrency: 50 })); } + getPackagesSync() { + return makeSyncFileFinder(this.rootPath, this.packageConfigs)("package.json", packageConfigPath => { + return new Package( + loadJsonFile.sync(packageConfigPath), + path.dirname(packageConfigPath), + this.rootPath + ); + }); + } + getPackageLicensePaths() { return this.fileFinder(Project.LICENSE_GLOB, null, { case: false }); } @@ -196,3 +206,4 @@ Project.LICENSE_GLOB = "LICEN{S,C}E{,.*}"; module.exports = Project; module.exports.getPackages = cwd => new Project(cwd).getPackages(); +module.exports.getPackagesSync = cwd => new Project(cwd).getPackagesSync(); diff --git a/core/project/lib/make-file-finder.js b/core/project/lib/make-file-finder.js index 79360b1d2a..9d1b40a177 100644 --- a/core/project/lib/make-file-finder.js +++ b/core/project/lib/make-file-finder.js @@ -6,6 +6,7 @@ const path = require("path"); const ValidationError = require("@lerna/validation-error"); module.exports.makeFileFinder = makeFileFinder; +module.exports.makeSyncFileFinder = makeSyncFileFinder; function getGlobOpts(rootPath, packageConfigs) { const globOpts = { @@ -61,3 +62,21 @@ function makeFileFinder(rootPath, packageConfigs) { return promise.then(results => results.reduce((acc, result) => acc.concat(result), [])); }; } + +function makeSyncFileFinder(rootPath, packageConfigs) { + const globOpts = getGlobOpts(rootPath, packageConfigs); + + return (fileName, fileMapper, customGlobOpts) => { + const options = Object.assign({}, customGlobOpts, globOpts); + const patterns = packageConfigs.map(globPath => path.join(globPath, fileName)).sort(); + + let results = globby.sync(patterns, options); + + /* istanbul ignore else */ + if (fileMapper) { + results = results.map(fileMapper); + } + + return results; + }; +}