UNPKG

@hypermod/cli

Version:

To download and run codemods, we provide a CLI tool called @hypermod/cli.

262 lines (261 loc) 13.6 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const path_1 = __importDefault(require("path")); const semver_1 = __importDefault(require("semver")); const chalk_1 = __importDefault(require("chalk")); const find_up_1 = __importDefault(require("find-up")); const inquirer_1 = __importDefault(require("inquirer")); const live_plugin_manager_1 = require("live-plugin-manager"); const core = __importStar(require("@hypermod/core")); const fetcher_1 = require("@hypermod/fetcher"); const errors_1 = require("./errors"); const fetch_package_1 = require("./utils/fetch-package"); const merge_configs_1 = require("./utils/merge-configs"); const file_system_1 = require("./utils/file-system"); const module_loader_1 = __importDefault(require("./utils/module-loader")); const prompt_1 = require("./prompt"); function main(paths, flags) { return __awaiter(this, void 0, void 0, function* () { if (paths.length === 0) { throw new errors_1.InvalidUserInputError('No path provided, please specify which files your codemod should modify'); } const pluginManagerConfig = { pluginsPath: path_1.default.join(__dirname, '..', 'node_modules'), }; // If a registry is provided in the CLI flags, use it for the pluginManagers configuration. if (flags.registry !== undefined) { pluginManagerConfig.npmRegistryUrl = flags.registry; } // If a registryToken is provided in the CLI flags, use it as an authentication token for the pluginManager if (flags.registryToken !== undefined) { pluginManagerConfig.npmRegistryConfig = { auth: { token: flags.registryToken }, }; } const packageManager = flags.experimentalLoader ? (0, module_loader_1.default)({ authToken: flags.registryToken, npmRegistryUrl: flags.registry, }) : new live_plugin_manager_1.PluginManager(pluginManagerConfig); let transforms = []; if (!flags.transform && !flags.packages) { console.log(chalk_1.default.green('No transforms specified, attempting to find local hypermod.config file(s)')); /** * Attempt to locate a root package.json with a workspaces config. * If found, show a prompt with all available codemods */ const localPackageJson = yield (0, file_system_1.getPackageJson)(); if (localPackageJson && localPackageJson.workspaces) { const configs = yield (0, file_system_1.fetchConfigsForWorkspaces)(localPackageJson.workspaces); const answers = yield inquirer_1.default.prompt([(0, prompt_1.getMultiConfigPrompt)(configs)]); const selectedConfig = configs.find(({ filePath }) => answers.codemod.filePath === filePath); if (!selectedConfig) { throw new Error(`Unable to locate config at: ${answers.codemod.filePath}`); } if (selectedConfig.config.transforms && selectedConfig.config.transforms[answers.codemod.selection]) { if (flags.sequence) { Object.entries(selectedConfig.config.transforms) .filter(([key]) => semver_1.default.satisfies(key, `>=${answers.codemod.selection}`)) .forEach(([, path]) => transforms.push(path)); } else { transforms.push(selectedConfig.config.transforms[answers.codemod.selection]); } } else if (selectedConfig.config.presets && selectedConfig.config.presets[answers.codemod.selection]) { transforms.push(selectedConfig.config.presets[answers.codemod.selection]); } } else { /** * Otherwise, locate any config files in parent directories */ const configFilePath = yield (0, find_up_1.default)([ 'hypermod.config.js', 'hypermod.config.mjs', 'hypermod.config.cjs', 'hypermod.config.ts', 'hypermod.config.tsx', 'src/hypermod.config.js', 'src/hypermod.config.mjs', 'src/hypermod.config.cjs', 'src/hypermod.config.ts', 'src/hypermod.config.tsx', 'codemods/hypermod.config.js', 'codemods/hypermod.config.mjs', 'codemods/hypermod.config.cjs', 'codemods/hypermod.config.ts', 'codemods/hypermod.config.tsx', 'codeshift.config.js', 'codeshift.config.mjs', 'codeshift.config.cjs', 'codeshift.config.ts', 'codeshift.config.tsx', 'src/codeshift.config.js', 'src/codeshift.config.mjs', 'src/codeshift.config.cjs', 'src/codeshift.config.ts', 'src/codeshift.config.tsx', 'codemods/codeshift.config.js', 'codemods/codeshift.config.mjs', 'codemods/codeshift.config.cjs', 'codemods/codeshift.config.ts', 'codemods/codeshift.config.tsx', ]); if (!configFilePath) { throw new errors_1.InvalidUserInputError('No transform provided, please specify a transform with either the --transform or --packages flags'); } console.log(chalk_1.default.green('Found local hypermod.config file at:'), configFilePath); const config = yield (0, fetcher_1.fetchConfigAtPath)(configFilePath); const answers = yield inquirer_1.default.prompt([(0, prompt_1.getConfigPrompt)(config)]); if (config.transforms && config.transforms[answers.codemod]) { Object.entries(config.transforms) .filter(([key]) => semver_1.default.satisfies(key, `>=${answers.codemod}`)) .forEach(([, codemod]) => transforms.push(`${configFilePath}@${codemod}`)); } else if (config.presets && config.presets[answers.codemod]) { transforms.push(`${configFilePath}#${answers.codemod}`); } } } if (flags.transform) { if (flags.transform.includes(',')) { flags.transform.split(',').forEach(t => transforms.push(t.trim())); } else { transforms.push(flags.transform); } } if (flags.packages) { const pkgs = flags.packages.split(',').filter(pkg => !!pkg); for (const pkg of pkgs) { const shouldPrependAtSymbol = pkg.startsWith('@') ? '@' : ''; const pkgName = shouldPrependAtSymbol + pkg.split(/[@#]/).filter(str => !!str)[0]; const rawTransformIds = pkg.split(/(?=[@#])/).filter(str => !!str); rawTransformIds.shift(); const transformIds = rawTransformIds .filter(id => id.startsWith('@')) .map(id => id.substring(1)) .sort((idA, idB) => { if (semver_1.default.lt(idA, idB)) return -1; if (semver_1.default.gt(idA, idB)) return 1; return 0; }); const presetIds = rawTransformIds .filter(id => id.startsWith('#')) .map(id => id.substring(1)); const { community, remote } = yield (0, fetch_package_1.fetchPackages)(pkgName, packageManager); const config = (0, merge_configs_1.mergeConfigs)(community, remote); // Validate transforms/presets transformIds.forEach(id => { if (!semver_1.default.valid(semver_1.default.coerce(id.substring(1)))) { throw new errors_1.InvalidUserInputError(`Invalid version provided to the --packages flag. Unable to resolve version "${id}" for package "${pkgName}". Please try: "[scope]/[package]@[version]" for example @mylib/mypackage@10.0.0`); } if (!config.transforms || !config.transforms[id]) { throw new errors_1.InvalidUserInputError(`Invalid version provided to the --packages flag. Unable to resolve version "${id}" for package "${pkgName}"`); } }); presetIds.forEach(id => { if (!config.presets || !config.presets[id]) { throw new errors_1.InvalidUserInputError(`Invalid preset provided to the --packages flag. Unable to resolve preset "${id}" for package "${pkgName}"`); } }); if (presetIds.length === 0 && transformIds.length === 0) { const res = yield inquirer_1.default.prompt([ (0, prompt_1.getConfigPrompt)(config), ]); if (semver_1.default.valid(semver_1.default.coerce(res.codemod))) { transformIds.push(res.codemod); } else { presetIds.push(res.codemod); } } // Get transform file paths if (config.transforms) { if (flags.sequence) { Object.entries(config.transforms) .filter(([key]) => semver_1.default.satisfies(key, `>=${transformIds[0]}`)) .forEach(([, path]) => transforms.push(path)); } else { Object.entries(config.transforms) .filter(([id]) => transformIds.includes(id)) .forEach(([, path]) => transforms.push(path)); } } // Get preset file paths if (config.presets) { Object.entries(config.presets) .filter(([id]) => presetIds.includes(id)) .forEach(([, path]) => transforms.push(path)); } } } if (!transforms.length) { throw new errors_1.InvalidUserInputError('Unable to locate transforms from provided flags.'); } // Dedupe transform array transforms = transforms.filter((transform, i) => transforms.indexOf(transform) === i); for (const transform of transforms) { console.log(chalk_1.default.green('Running transform:'), transform); yield core.run(transform, paths, { verbose: flags.verbose, dry: flags.dry, print: false, babel: true, extensions: flags.extensions, ignorePattern: flags.ignorePattern, cpus: flags.cpus, ignoreConfig: [], runInBand: flags.runInBand, silent: false, parser: flags.parser, stdin: false, parserConfig: '', failOnError: false, }); } }); } exports.default = main;