NullVoxPopuli / ember-apply

Automatic integration and configuration from the EmberJS community
https://ember-apply.pages.dev
MIT License
38 stars 9 forks source link

Add utility for getting the most relevant package.json from an array of packages #572

Open NullVoxPopuli opened 4 months ago

NullVoxPopuli commented 4 months ago

for example, using @manypkg/get-packages


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;
}
NullVoxPopuli commented 4 months ago

This would also be a good opportunity to switch the workspace discovery code to @manypkg