From b7fda8ea1f27605168b1563073eb29a90e34bba7 Mon Sep 17 00:00:00 2001 From: Gareth Elwell <41474928+g-elwell@users.noreply.github.com> Date: Mon, 20 Jan 2025 09:45:55 +0000 Subject: [PATCH] refactor: extract package fetching logic into shared utility --- src/commands/build.js | 63 ++-------------- src/commands/installer/installer.js | 27 +------ src/utils/get-packages-for-command.js | 102 ++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 82 deletions(-) create mode 100644 src/utils/get-packages-for-command.js diff --git a/src/commands/build.js b/src/commands/build.js index 6dfea08..1d0e493 100644 --- a/src/commands/build.js +++ b/src/commands/build.js @@ -1,4 +1,3 @@ -const path = require('path'); const webpack = require('webpack'); const { terminal } = require('terminal-kit'); // eslint-disable-next-line import/no-extraneous-dependencies @@ -7,11 +6,9 @@ const webpackConfig = require('./build/webpack'); const spinner = ora(); -const { findAllProjectPaths, validateProject } = require('./../utils/projectpaths'); -const { getPackage } = require('./../utils/get-package'); const { getFilteredEntryPoints } = require('./../utils/get-filtered-entrypoints'); -const dirsExist = require('../utils/dirs-exist'); const getProjectConfig = require('../utils/get-project-config'); +const getPackagesForCommand = require('../utils/get-packages-for-command'); global.buildCount = 0; @@ -56,66 +53,16 @@ exports.handler = async ({ once = false, quiet = false, }) => { - const currentLocation = path.basename(process.cwd()); - const mode = production ? 'production' : 'development'; - // Use env variables if working on Webpack >=5. - const projectsList = projects.split(',').map((item) => item.split('@')[0]).filter((item) => item.length > 0); - const hasTargetDirs = dirsExist(targetDirs); - const isAllProjects = (site || hasTargetDirs) && (!projects || projectsList.length === 0); - - let packages = []; - - try { - if (projectsList.length === 0 && !isAllProjects) { - // Is project root - a standalone build. - terminal(`\x1b[1mCompiling \x1b[4msingle\x1b[0m\x1b[1m project in ${mode} mode.\x1b[0m\n`); - packages.push(getPackage(path.resolve('./'))); - } else if (isAllProjects) { - // Find all projects through-out the site. - terminal(`\x1b[1mCompiling \x1b[4mall\x1b[0m\x1b[1m projects in ${mode} mode.\x1b[0m\n`); - packages = findAllProjectPaths(targetDirs).map((path) => getPackage(path)); - } else { - // List of projects. - terminal(`\x1b[1mCompiling \x1b[4mlist\x1b[0m\x1b[1m of projects in ${mode} mode.\x1b[0m\n`); - packages = findAllProjectPaths(targetDirs, projectsList).map((path) => getPackage(path)); - - const packageNames = packages.map((pkg) => pkg.name); - projectsList.map((projectName) => { - if (!packageNames.includes(projectName)) { - terminal.red(`Error: Project ${projectName} does not exist.\n`); - } - packageNames.includes(projectName); - }); - } - } catch (e) { - terminal.red(e); - process.exit(1); - } - - const validProjects = packages.filter((pkg) => validateProject(pkg)); - - if (!quiet) { - const invalidProjects = packages.filter((pkg) => !validateProject(pkg)); - invalidProjects.map((invalidProject) => - terminal.red(`[${invalidProject.relativePath}] no entrypoints\n`), - ); - } - - if (validProjects.length === 0) { - terminal.red(`Error: No projects found\n`); - process.exit(1); - } - terminal('Processing the following projects:\n'); - validProjects.forEach((pkg) => { - terminal.defaultColor(` * %s `, pkg.name).dim(`[%s]\n`, pkg.relativePath); + const packages = getPackagesForCommand({ + projects, + site, }); - terminal('\n'); spinner.start('Building webpack configs.\n'); - const configMap = validProjects.map((packageObject) => { + const configMap = packages.map((packageObject) => { // Empty array means all entrypoints. let filteredEntrypoints = []; diff --git a/src/commands/installer/installer.js b/src/commands/installer/installer.js index 8133bd7..35d575b 100644 --- a/src/commands/installer/installer.js +++ b/src/commands/installer/installer.js @@ -3,37 +3,16 @@ const { execSync } = require('child_process'); const yargs = require('yargs'); const args = yargs.argv._; -const { findAllProjectPaths } = require('./../../utils/projectpaths'); -const { getPackage } = require('./../../utils/get-package'); -const dirsExist = require('./../../utils/dirs-exist'); +const getPackagesForCommand = require('./../../utils/get-packages-for-command'); module.exports = (commandType) => { if (!['ci', 'install'].includes(commandType)) { throw new Error('Not a valid comment type.'); } - const hasTargetDirs = dirsExist(targetDirs); - - if (!hasTargetDirs) { - throw new Error('Recursive install only works from the site root directory.'); - } - - let paths = findAllProjectPaths(targetDirs); - - let packages = []; - - try { - packages = paths.map((item) => getPackage(item, false)).filter((item) => item); - } catch (e) { - terminal.red(e); - process.exit(1); - } - - terminal('Installing packages for the following projects:\n'); - packages.forEach((pkg) => { - terminal.defaultColor(` * %s `, pkg.name).dim(`[%s]\n`, pkg.relativePath); + const packages = getPackagesForCommand({ + requireSiteRoot: true, }); - terminal('\n'); const gluedArgs = args.join(' '); diff --git a/src/utils/get-packages-for-command.js b/src/utils/get-packages-for-command.js new file mode 100644 index 0000000..26dc5d9 --- /dev/null +++ b/src/utils/get-packages-for-command.js @@ -0,0 +1,102 @@ +const path = require('path'); +const { terminal } = require('terminal-kit'); + +const dirsExist = require('./dirs-exist'); +const { getPackage } = require('./get-package'); +const { findAllProjectPaths, validateProject } = require('./projectpaths'); + +/** + * Get valid packages to run a command against. + * + * Bases results on the following logic: + * - If the `site` flag is set, or the command was ran from within wp-content, all projects are targeted. + * - If the `projects` flag is set, only those projects are targeted. + * - If neither the `site` or `projects` flags are set, only the current project is targeted. + * + * @param {Object} args + * @param {string} [args.projects] Comma separated list of projects to target. + * @param {boolean} [args.site] Run the process from the root of a site, such as from wp-content. + * @param {boolean} [args.requireSiteRoot] Require the process to be run from the site root directory. + * @param {boolean} [args.quiet] Limit the amount of noise by removing webpack output. + * @param {'development'|'production'} [args.mode] The mode to run the command in. + * + * @return {Array} An array of valid projects to run the command against. + */ +function getPackagesForCommand({ + projects = '', + site = false, + requireSiteRoot = false, + quiet = false, + mode = 'development', +}) { + const targetDirs = global.targetDirs; + + const projectsList = projects + .split(',') + .map((item) => item.split('@')[0]) + .filter((item) => item.length > 0); + + const hasTargetDirs = dirsExist(targetDirs); + + if (requireSiteRoot && !hasTargetDirs) { + terminal.red(`Command only works from the site root directory.\n`); + } + + const isAllProjects = (site || hasTargetDirs) && (!projects || projectsList.length === 0); + + let packages = []; + + try { + if (projectsList.length === 0 && !isAllProjects) { + // Is project root - a standalone build. + terminal(`\x1b[1mCompiling \x1b[4msingle\x1b[0m\x1b[1m project in ${mode} mode.\x1b[0m\n`); + + packages.push(getPackage(path.resolve('./'))); + } else if (isAllProjects) { + // Find all projects through-out the site. + terminal(`\x1b[1mCompiling \x1b[4mall\x1b[0m\x1b[1m projects in ${mode} mode.\x1b[0m\n`); + + packages = findAllProjectPaths(targetDirs).map((path) => getPackage(path)); + } else { + // List of projects. + terminal(`\x1b[1mCompiling \x1b[4mlist\x1b[0m\x1b[1m of projects in ${mode} mode.\x1b[0m\n`); + + packages = findAllProjectPaths(targetDirs, projectsList).map((path) => getPackage(path)); + const packageNames = packages.map((pkg) => pkg.name); + projectsList.map((projectName) => { + if (!packageNames.includes(projectName)) { + terminal.red(`Error: Project ${projectName} does not exist.\n`); + } else { + packageNames.includes(projectName); + } + }); + } + } catch (e) { + terminal.red(e); + process.exit(1); + } + + const validProjects = packages.filter((pkg) => validateProject(pkg)); + + if (!quiet) { + const invalidProjects = packages.filter((pkg) => !validateProject(pkg)); + invalidProjects.map((invalidProject) => + terminal.red(`[${invalidProject.relativePath}] no entrypoints\n`), + ); + } + + if (validProjects.length === 0) { + terminal.red(`Error: No projects found\n`); + process.exit(1); + } + + terminal('Processing the following projects:\n'); + validProjects.forEach((pkg) => { + terminal.defaultColor(` * %s `, pkg.name).dim(`[%s]\n`, pkg.relativePath); + }); + terminal('\n'); + + return validProjects; +} + +module.exports = getPackagesForCommand;