function getPackageJson(filePath) {
/**
* If the cheapest faster path gives us one result, we can skip the complicated code
* for finding which package belongs to a file
*
* (this is all so we don't need to hit the disk and cause I/O delays for every linted file)
*/
const candidates = projects.filter((project) => filePath.startsWith(project.dir));
if (candidates.length === 1) {
return candidates[0].packageJson;
}
// Find with longest matching path
// (since project diretories can nest)
/**
* We can have multiple candidates when project directaries nest
* e.g.:
* - foo/
* package.json
* - foo/tests/
* package.json
*
* If we have a file in foo/tests, we don't want to match foo,
* but it will match in the above.
*
* We also run in to this situation when we have similarly named projects:
* e.g.:
* - foo/
* - foo-other/
*
* If we have a file in foo-other, foo will also match
*/
let bestMatch = null;
const fParts = filePath.split('/');
findBestCandidate: for (const project of candidates) {
const candidate = project.dir.split('/');
/**
* If the candidate project has a longer path than our file,
* our file cannot possibly be within that project
*/
if (candidate.length > fParts.length) {
continue;
}
for (let i = 0; i < candidate.length; i++) {
const cPart = candidate[i];
const fPart = fParts[i];
/**
* If a folder/segment of the candidate ever does not match
* the filePath part, the whole candidate is not worth checking
*/
if (cPart !== fPart) {
continue findBestCandidate;
}
}
/**
* If execution makes it past the above loop, the *entire* candidate path is within
* the file path.
*
* If we make it here, we know that we don't have a situation like "foo" vs "foo-other"
*/
if (!bestMatch || bestMatch.dir.length < candidate.dir.length) {
bestMatch = project;
}
}
return bestMatch.packageJson;
}
for example, using
@manypkg/get-packages