UNPKG

@talend/dynamic-cdn-webpack-plugin

Version:

Dynamically get your dependencies from a cdn rather than bundling them in your app

98 lines (91 loc) 3.92 kB
const fs = require('fs'); const path = require('path'); const readPkgUp = require('read-pkg-up'); const semver = require('semver'); function findPackage(info) { let name = info.name; let scope; if (name.startsWith('@')) { [scope, name] = info.name.split('/'); } // eslint-disable-next-line no-use-before-define return findPackages(scope, name).find(cwd => { const { packageJson: { version }, } = readPkgUp.sync({ cwd }); // check we are at least upper or equal using caret range syntax let range = `^${info.version}`; if (info.peerDependency) { range += `|| ${info.peerDependency}`; } return semver.satisfies(version, range); }); } function findPackagesFromScopeFolder(scope, name, scopeFolderPath) { const isWantedScope = scopeFolderPath.endsWith(`${path.sep}${scope}`); return fs .readdirSync(scopeFolderPath, { withFileTypes: true }) .filter(f => f.isDirectory() || f.isSymbolicLink()) .reduce((accu, subFolder) => { const subFolderPath = path.join(scopeFolderPath, subFolder.name); if (isWantedScope && subFolder.name === name) { // the scope and package name are the ones we look for // just add the path to the found list return accu.concat(subFolderPath); } // the scope or package name is not the one we look for // if there is a nested node modules folder, we dive into it for the search const nestedNodeModulesPath = path.join(subFolderPath, 'node_modules'); if (fs.existsSync(nestedNodeModulesPath)) { // eslint-disable-next-line no-use-before-define return accu.concat(findPackagesFromNonScopeFolder(scope, name, nestedNodeModulesPath, [])); } return accu; }, []); } function findPackagesFromNonScopeFolder(scope, name, nonScopeFolderPath) { return fs .readdirSync(nonScopeFolderPath, { withFileTypes: true }) .filter(f => f.isDirectory() || f.isSymbolicLink()) .reduce((accu, subFolder) => { if (subFolder.name === '.bin') { return accu; } // MAKE IT COMPATIBLE WITH PNPM (especially for test) WHEN deps is @talend/scripts-... let regex = /@talend\/(scripts|babel|eslint)-.*\/node_modules$/; if (subFolder.name.startsWith('@') && !regex.test(subFolder?.path)) { // for scope folders, we need a special treatment to avoid getting scoped packages when we don't want a scoped one. // ex: search for `classnames`, we don't want to find `@types/classnames` in the result return accu.concat( findPackagesFromScopeFolder(scope, name, path.join(nonScopeFolderPath, subFolder.name)), ); } else if (!scope && subFolder.name === name) { // we want a NON scoped package, we are in a non scoped folder, and the names match return accu.concat(path.join(nonScopeFolderPath, subFolder.name)); } const nestedNodeModulesPath = path.join(nonScopeFolderPath, subFolder.name, 'node_modules'); if (fs.existsSync(nestedNodeModulesPath)) { return accu.concat(findPackagesFromNonScopeFolder(scope, name, nestedNodeModulesPath)); } return accu; }, []); } function findPackages(scope, name, buff = []) { // https://nodejs.org/dist/latest-v14.x/docs/api/modules.html#modules_require_resolve_paths_request const roots = require.resolve.paths(name).filter(p => fs.existsSync(p)); if (roots === null) { return buff; } const result = buff.concat( ...roots.map(root => findPackagesFromNonScopeFolder(scope, name, root)), ); // Return a new Set to remove duplicate values: case possible with PNPM in GHA, due to pnpm/action-setup // With the action, a folder setup-pnpm is created to manage the store and the script see it and try to scan it, and this generate duplicate entry // Before we returned directly result of buff.concat... // TODO: Manage pnpm installation manually (not reproduce the issue in this case but need to find solution to install global dep like surge) return [...new Set(result)]; } module.exports = { findPackage, findPackages, };