@o3r/eslint-plugin
Version:
The module provides in-house eslint plugins to use in your own eslint configuration.
128 lines (127 loc) • 6.41 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("node:path");
const semver = require("semver");
const version_harmonize_1 = require("../../json/json-dependency-versions-harmonize/version-harmonize");
const utils_1 = require("../../utils");
const utils_2 = require("../utils");
const isYAMLScalar = (node) => node?.type === 'YAMLScalar';
const getStaticYAMLValue = (node) => {
return isYAMLScalar(node)
? node.value?.toString()
: undefined;
};
const defaultOptions = [{
ignoredDependencies: [],
excludePackages: [],
yarnrcDependencyTypes: ['peerDependencies', 'dependencies'],
dependencyTypesInPackages: ['optionalDependencies', 'dependencies', 'devDependencies', 'peerDependencies', 'generatorDependencies']
}];
exports.default = (0, utils_1.createRule)({
name: 'yarnrc-package-extensions-harmonize',
meta: {
hasSuggestions: true,
type: 'problem',
docs: {
description: 'Ensure that the package extension versions are aligned with the range defined in the packages.'
},
schema: [
{
type: 'object',
properties: {
excludePackages: {
type: 'array',
description: 'List of package.json to ignore when determining the dependencies versions',
items: {
type: 'string'
}
},
yarnrcDependencyTypes: {
type: 'array',
description: 'List of dependency types to validate in .yarnrc.yml',
default: defaultOptions[0].yarnrcDependencyTypes,
items: {
type: 'string'
}
},
dependencyTypesInPackages: {
type: 'array',
description: 'List of dependency types in package.json to parse',
default: defaultOptions[0].dependencyTypesInPackages,
items: {
type: 'string'
}
},
ignoredDependencies: {
type: 'array',
description: 'List of dependencies to ignore',
items: {
type: 'string'
}
}
},
additionalProperties: false
}
],
messages: {
versionUpdate: 'Set version {{version}}',
error: '{{depName}} should be updated to version {{version}} (from: {{packageJsonFile}})'
},
fixable: 'code'
},
defaultOptions,
create: (context, [options]) => {
const parserServices = (0, utils_2.getYamlParserServices)(context);
const dirname = path.dirname(context.filename);
const workspace = (0, version_harmonize_1.findWorkspacePackageJsons)(dirname);
const bestRanges = workspace
? (0, version_harmonize_1.getBestRanges)(options.dependencyTypesInPackages, workspace.packages.filter(({ content }) => !content.name || !options.excludePackages.includes(content.name)))
: {};
const ignoredDependencies = options.ignoredDependencies.map((dep) => new RegExp(dep.replace(/[$()+.?[\\\]^{|}]/g, '\\$&').replace(/\*/g, '.*')));
if (parserServices.isYAML) {
return {
// eslint-disable-next-line @typescript-eslint/naming-convention -- name required by Yaml Eslint parser
YAMLPair: (node) => {
if (node.value) {
const range = getStaticYAMLValue(node.value)?.toString();
const parent = node.parent.parent && node.parent.parent.type === 'YAMLPair' && getStaticYAMLValue(node.parent.parent.key)?.toString();
const baseNode = node.parent.parent.parent.parent?.parent?.parent;
const isCorrectNode = baseNode && baseNode.type === 'YAMLPair' && getStaticYAMLValue(baseNode.key)?.toString() === 'packageExtensions';
if (isCorrectNode && semver.validRange(range) && parent && options.yarnrcDependencyTypes.includes(parent)) {
const depName = node.key && getStaticYAMLValue(node.key)?.toString();
if (!depName || !bestRanges[depName] || ignoredDependencies.some((ignore) => ignore.test(depName))) {
return;
}
const minYarnrcVersion = semver.minVersion(range);
const minBestRangeVersion = semver.minVersion(bestRanges[depName].range);
if (minYarnrcVersion && minBestRangeVersion && semver.lt(minYarnrcVersion, minBestRangeVersion)) {
const version = bestRanges[depName].range;
const packageJsonFile = bestRanges[depName].path;
context.report({
loc: node.value.loc,
messageId: 'error',
data: {
depName,
version,
packageJsonFile
},
fix: (fixer) => fixer.replaceTextRange(node.value.range, `${version}`),
suggest: [
{
messageId: 'versionUpdate',
data: {
version
},
fix: (fixer) => fixer.replaceTextRange(node.value.range, `${version}`)
}
]
});
}
}
}
}
};
}
return {};
}
});