react-monaco-editor
Version:
Monaco Editor for React
205 lines (194 loc) • 5.31 kB
JavaScript
;
const fs = require("fs");
const path = require("path");
const chalk = require("chalk");
const diff = require("diff");
const inquirer = require("inquirer");
const PLazy = require("p-lazy");
const Listr = require("listr");
const { validate } = require("webpack");
const { WebpackOptionsValidationError } = require("webpack");
const runPrettier = require("../utils/run-prettier");
/**
*
* Runs migration on a given configuration using AST's and promises
* to sequentially transform a configuration file.
*
* @param {Array} args - Migrate arguments such as input and
* output path
* @returns {Function} Runs the migration using the 'runMigrate'
* function.
*/
module.exports = function migrate(...args) {
const filePaths = args.slice(3);
if (!filePaths.length) {
const errMsg = "\n ✖ Please specify a path to your webpack config \n ";
console.error(chalk.red(errMsg));
return;
}
const currentConfigPath = path.resolve(process.cwd(), filePaths[0]);
let outputConfigPath;
if (!filePaths[1]) {
return inquirer
.prompt([
{
type: "confirm",
name: "confirmPath",
message:
"Migration output path not specified. " +
"Do you want to use your existing webpack " +
"configuration?",
default: "Y"
}
])
.then(ans => {
if (!ans["confirmPath"]) {
console.error(chalk.red("✖ ︎Migration aborted due no output path"));
return;
}
outputConfigPath = path.resolve(process.cwd(), filePaths[0]);
return runMigration(currentConfigPath, outputConfigPath);
})
.catch(err => {
console.error(err);
});
}
outputConfigPath = path.resolve(process.cwd(), filePaths[1]);
return runMigration(currentConfigPath, outputConfigPath);
};
/**
*
* Runs migration on a given configuration using AST's and promises
* to sequentially transform a configuration file.
*
* @param {String} currentConfigPath - input path for config
* @param {String} outputConfigPath - output path for config
* @returns {Promise} Runs the migration using a promise that
* will throw any errors during each transform or output if the
* user decides to abort the migration
*/
function runMigration(currentConfigPath, outputConfigPath) {
const recastOptions = {
quote: "single"
};
const tasks = new Listr([
{
title: "Reading webpack config",
task: ctx =>
new PLazy((resolve, reject) => {
fs.readFile(currentConfigPath, "utf8", (err, content) => {
if (err) {
reject(err);
}
try {
const jscodeshift = require("jscodeshift");
ctx.source = content;
ctx.ast = jscodeshift(content);
resolve();
} catch (err) {
reject("Error generating AST", err);
}
});
})
},
{
title: "Migrating config to newest version",
task: ctx => {
const transformations = require("../migrate").transformations;
return new Listr(
Object.keys(transformations).map(key => {
const transform = transformations[key];
return {
title: key,
task: _ => transform(ctx.ast, ctx.source)
};
})
);
}
}
]);
tasks
.run()
.then(ctx => {
const result = ctx.ast.toSource(recastOptions);
const diffOutput = diff.diffLines(ctx.source, result);
diffOutput.forEach(diffLine => {
if (diffLine.added) {
process.stdout.write(chalk.green(`+ ${diffLine.value}`));
} else if (diffLine.removed) {
process.stdout.write(chalk.red(`- ${diffLine.value}`));
}
});
return inquirer
.prompt([
{
type: "confirm",
name: "confirmMigration",
message: "Are you sure these changes are fine?",
default: "Y"
}
])
.then(answers => {
if (answers["confirmMigration"]) {
return inquirer.prompt([
{
type: "confirm",
name: "confirmValidation",
message:
"Do you want to validate your configuration? " +
"(If you're using webpack merge, validation isn't useful)",
default: "Y"
}
]);
} else {
console.log(chalk.red("✖ Migration aborted"));
}
})
.then(answer => {
if (!answer) return;
runPrettier(outputConfigPath, result, err => {
if (err) {
throw err;
}
});
if (answer["confirmValidation"]) {
const webpackOptionsValidationErrors = validate(
require(outputConfigPath)
);
if (webpackOptionsValidationErrors.length) {
console.log(
chalk.red(
"\n✖ Your configuration validation wasn't successful \n"
)
);
console.error(
new WebpackOptionsValidationError(
webpackOptionsValidationErrors
).message
);
}
}
console.log(
chalk.green(
`\n✔︎ New webpack config file is at ${outputConfigPath}.`
)
);
console.log(
chalk.green(
"✔︎ Heads up! Updating to the latest version could contain breaking changes."
)
);
console.log(
chalk.green(
"✔︎ Plugin and loader dependencies may need to be updated."
)
);
});
})
.catch(err => {
const errMsg = "\n ✖ ︎Migration aborted due to some errors: \n";
console.error(chalk.red(errMsg));
console.error(err);
process.exitCode = 1;
});
}