1const { resolve, relative } = require('path') 2const mapWorkspaces = require('@npmcli/map-workspaces') 3const { minimatch } = require('minimatch') 4const pkgJson = require('@npmcli/package-json') 5 6// minimatch wants forward slashes only for glob patterns 7const globify = pattern => pattern.split('\\').join('/') 8 9// Returns an Map of paths to workspaces indexed by workspace name 10// { foo => '/path/to/foo' } 11const getWorkspaces = async (filters, { path, includeWorkspaceRoot, relativeFrom }) => { 12 // TODO we need a better error to be bubbled up here if this call fails 13 const { content: pkg } = await pkgJson.normalize(path) 14 const workspaces = await mapWorkspaces({ cwd: path, pkg }) 15 let res = new Map() 16 if (includeWorkspaceRoot) { 17 res.set(pkg.name, path) 18 } 19 20 if (!filters.length) { 21 res = new Map([...res, ...workspaces]) 22 } 23 24 for (const filterArg of filters) { 25 for (const [workspaceName, workspacePath] of workspaces.entries()) { 26 let relativePath = relative(relativeFrom, workspacePath) 27 if (filterArg.startsWith('./')) { 28 relativePath = `./${relativePath}` 29 } 30 const relativeFilter = relative(path, filterArg) 31 if (filterArg === workspaceName 32 || resolve(relativeFrom, filterArg) === workspacePath 33 || minimatch(relativePath, `${globify(relativeFilter)}/*`) 34 || minimatch(relativePath, `${globify(filterArg)}/*`) 35 ) { 36 res.set(workspaceName, workspacePath) 37 } 38 } 39 } 40 41 if (!res.size) { 42 let msg = '!' 43 if (filters.length) { 44 msg = `:\n ${filters.reduce( 45 (acc, filterArg) => `${acc} --workspace=${filterArg}`, '')}` 46 } 47 48 throw new Error(`No workspaces found${msg}`) 49 } 50 51 return res 52} 53 54module.exports = getWorkspaces 55