import { run } from 'jscodeshift/src/Runner'; import { filterFiles, getTransformFile, initTempDir, readTempData } from './utils/file'; import { TransformerPath, MigrateReport, ValidateReport, LayoutReport, TransformModule, RunnerConfig, Rules, } from './types/runner'; import { FILE_FILTERS, TEMP_DIR_PREFIX } from './constants'; import { VersionCompatibilityResult } from './types/transformer'; import { checkDependencyVersionCompatibility } from './transformers/validate/versions'; import { filterAPIRules } from './utils/helper'; /** * Run JSCodeshift Core Runner with Transform and input files * @param transformer Transform type * @param files Paths to input files * @param config Runner config * @returns Temp directory where the result will be stored in multiple files */ const runner = async (transformers: TransformModule[], config?: RunnerConfig): Promise => { const reportDir = await initTempDir(TEMP_DIR_PREFIX); const runners = transformers.map(async (t) => { const { files, transformer, parser, rules } = t; const module = getTransformFile(transformer); return run(module, files, { parser: parser || 'tsx', reportDir, ...(config?.options || {}), rules, }); }); await Promise.all(runners); return reportDir; }; /** * Migrates Flex Plugin to use Declarative Component APIs * @param filePaths Path of the files on which the migration is performed * @param config Runner config * @returns */ export const migrate = async (filePaths: string[], config?: RunnerConfig): Promise => { const reportDir = await runner([{ transformer: TransformerPath.Migrate, files: filePaths }], config); return readTempData(reportDir); }; /** * Validates the Flex Plugin for violation of rules passed to it. * @param filePaths Path of the Flex Plugin files on which the validation is performed * @param rules List of rules against which the Flex Plugin needs to be validated * @param config Runner config * @returns */ export const validate = async (filePaths: string[], rules?: Rules, config?: RunnerConfig): Promise => { const [cssFiles, scssFiles, jsonFiles, files] = filterFiles(filePaths, FILE_FILTERS); const packageJsonFile = jsonFiles.find((file) => file.endsWith('package.json')); const [cssRules, apiRules] = filterAPIRules(rules?.apiCompatibility?.rules, 'css'); const tempFilePath = await runner( [ { transformer: TransformerPath.Validate, files, rules: apiRules, }, { transformer: TransformerPath.Validate, files: cssFiles.concat(scssFiles), rules: cssRules, parser: 'flow', }, ], config, ); const runnerPromise = readTempData(tempFilePath); const versionPromise = packageJsonFile ? checkDependencyVersionCompatibility(packageJsonFile, rules?.versionCompatibility?.rules) : Promise.resolve({ warnings: [] } as VersionCompatibilityResult); const [runnerResult, versionCompatibilityResult] = await Promise.all([runnerPromise, versionPromise]); if (packageJsonFile) { runnerResult.errors = [ ...runnerResult.errors, ...(versionCompatibilityResult?.error ? [{ file: packageJsonFile, message: versionCompatibilityResult.error }] : []), ]; runnerResult.versionCompatibility = versionCompatibilityResult.warnings ? [ { file: packageJsonFile, warnings: versionCompatibilityResult.warnings, }, ] : []; } return runnerResult; }; /** * Returns the UI Config snippet for a given Flex Plugin which is using Declarative Components API * @param filePaths Path of the files for which the UI Config snippet needs to be generated * @param config Runner config * @returns */ // eslint-disable-next-line @typescript-eslint/no-unused-vars export const layout = async (filePaths: string[], config?: RunnerConfig): Promise => { const tempFilePath = await runner([{ transformer: TransformerPath.Layout, files: filePaths }], config); return readTempData(tempFilePath); };