@angular-eslint/schematics
Version:
Angular Schematics for angular-eslint
120 lines (119 loc) • 6.02 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertTSLintDisableCommentsForProject = exports.createConvertToESLintConfig = void 0;
const core_1 = require("@angular-devkit/core");
const child_process_1 = require("child_process");
const tmp_1 = require("tmp");
const utils_1 = require("../utils");
const tslintToEslintConfigVersion =
// eslint-disable-next-line @typescript-eslint/no-var-requires
require('../../package.json').devDependencies['tslint-to-eslint-config'];
let tslintToEslintConfigLibrary;
function getTslintToEslintConfigLibrary(context) {
if (tslintToEslintConfigLibrary) {
return tslintToEslintConfigLibrary;
}
try {
// This is usually not available at runtime but makes it easier to work with in our tests
return require('tslint-to-eslint-config');
// eslint-disable-next-line no-empty
}
catch (e) { }
context.logger.info('\nINFO: We are now installing the "tslint-to-eslint-config" package into a tmp directory to aid with the conversion');
context.logger.info('\nThis may take a minute or two...\n');
/**
* In order to avoid all users of angular-eslint needing to have tslint-to-eslint-config (and therefore tslint)
* in their node_modules, we dynamically install and uninstall the library as part of the conversion
* process.
*/
const tempDir = (0, tmp_1.dirSync)().name;
(0, child_process_1.execSync)(`npm i -D tslint-to-eslint-config@${tslintToEslintConfigVersion}`, {
cwd: tempDir,
stdio: 'ignore',
});
tslintToEslintConfigLibrary = require(require.resolve('tslint-to-eslint-config', {
paths: [tempDir],
}));
return tslintToEslintConfigLibrary;
}
function createConvertToESLintConfig(context) {
return async function convertToESLintConfig(pathToTslintJson, tslintJson) {
const { findReportedConfiguration, createESLintConfiguration, joinConfigConversionResults, } = getTslintToEslintConfigLibrary(context);
const reportedConfiguration = await findReportedConfiguration('npx tslint --print-config', pathToTslintJson);
if (reportedConfiguration instanceof Error) {
if (reportedConfiguration.message.includes('unknown option `--print-config')) {
throw new Error('\nError: TSLint v5.18 required in order to run this schematic. Please update your version and try again.\n');
}
/**
* Make a print-config issue easier to understand for the end user.
* This error could occur if, for example, the user does not have a TSLint plugin installed correctly that they
* reference in their config.
*/
const printConfigFailureMessageStart = 'Command failed: npx tslint --print-config "tslint.json"';
if (reportedConfiguration.message.startsWith(printConfigFailureMessageStart)) {
throw new Error(`\nThere was a critical error when trying to inspect your tslint.json: \n${reportedConfiguration.message.replace(printConfigFailureMessageStart, '')}`);
}
throw new Error(`Unexpected error: ${reportedConfiguration.message}`);
}
const originalConfigurations = {
tslint: {
full: reportedConfiguration,
raw: tslintJson,
},
};
const summarizedConfiguration = await createESLintConfiguration(originalConfigurations);
const expectedESLintPlugins = [
// These are added to support the ng-cli-compat configs
'eslint-plugin-jsdoc',
'eslint-plugin-prefer-arrow',
'eslint-plugin-import',
// These are already covered by our recommended config, and are installed by the `ng add` schematic
'@angular-eslint/eslint-plugin',
'@angular-eslint/eslint-plugin-template',
];
const convertedESLintConfig = joinConfigConversionResults(summarizedConfiguration, originalConfigurations);
return {
convertedESLintConfig,
unconvertedTSLintRules: summarizedConfiguration.missing,
ensureESLintPlugins: Array.from(summarizedConfiguration.plugins).filter((pluginName) => !expectedESLintPlugins.includes(pluginName)),
};
};
}
exports.createConvertToESLintConfig = createConvertToESLintConfig;
function likelyContainsTSLintComment(fileContent) {
return fileContent.includes('tslint:');
}
function convertTSLintDisableCommentsForProject(projectName) {
return (tree, context) => {
/**
* We need to avoid a direct dependency on tslint-to-eslint-config
* and ensure we are only resolving the dependency from the user's
* node_modules on demand (it will be installed as part of the
* conversion schematic).
*/
const { convertFileComments } = getTslintToEslintConfigLibrary(context);
const workspaceJson = (0, utils_1.readJsonInTree)(tree, 'angular.json');
const existingProjectConfig = workspaceJson.projects[projectName];
let pathRoot = '';
// Default Angular CLI project at the root of the workspace
if (existingProjectConfig.root === '') {
pathRoot = 'src';
}
else {
pathRoot = existingProjectConfig.root;
}
return (0, utils_1.visitNotIgnoredFiles)((filePath, host) => {
if (!filePath.endsWith('.ts')) {
return;
}
const fileContent = host.read(filePath).toString('utf-8');
// Avoid updating files if we don't have to
if (!likelyContainsTSLintComment(fileContent)) {
return;
}
const updatedFileContent = convertFileComments({ fileContent, filePath });
host.overwrite(filePath, updatedFileContent);
}, (0, core_1.normalize)(pathRoot));
};
}
exports.convertTSLintDisableCommentsForProject = convertTSLintDisableCommentsForProject;