mirror of
https://github.com/Afilmory/afilmory
synced 2026-02-01 22:48:17 +00:00
142 lines
4.5 KiB
JavaScript
142 lines
4.5 KiB
JavaScript
// @ts-check
|
|
import fs from 'node:fs'
|
|
import path from 'node:path'
|
|
import process from 'node:process'
|
|
|
|
import fg from 'fast-glob'
|
|
|
|
const dependencyKeys = ['dependencies', 'devDependencies']
|
|
|
|
/** @type {import("eslint").ESLint.Plugin} */
|
|
export default {
|
|
rules: {
|
|
'ensure-package-version': {
|
|
meta: {
|
|
type: 'problem',
|
|
docs: {
|
|
description: 'Ensure that the versions of packages in the workspace are consistent',
|
|
category: 'Possible Errors',
|
|
recommended: true,
|
|
},
|
|
fixable: 'code',
|
|
hasSuggestions: true,
|
|
},
|
|
create(context) {
|
|
if (!context.filename.endsWith('package.json')) return {}
|
|
|
|
const cwd = process.cwd()
|
|
const packageJsonFilePaths = fg.globSync(['packages/*/package.json', 'apps/*/package.json', 'package.json'], {
|
|
cwd,
|
|
ignore: ['**/node_modules/**'],
|
|
})
|
|
|
|
/** @type {Map<string, { version: string, filePath: string }[]>} */
|
|
const packageVersionMap = new Map()
|
|
|
|
packageJsonFilePaths.forEach((filePath) => {
|
|
if (filePath === path.relative(cwd, context.filename)) return
|
|
|
|
const packageJson = JSON.parse(fs.readFileSync(filePath, 'utf-8'))
|
|
|
|
dependencyKeys.forEach((key) => {
|
|
const dependencies = packageJson[key]
|
|
if (!dependencies) return
|
|
|
|
Object.keys(dependencies).forEach((dependency) => {
|
|
if (!packageVersionMap.has(dependency)) {
|
|
packageVersionMap.set(dependency, [])
|
|
}
|
|
packageVersionMap.get(dependency)?.push({
|
|
version: dependencies[dependency],
|
|
filePath,
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
return {
|
|
'Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty > JSONObjectExpression > JSONProperty'(
|
|
node,
|
|
) {
|
|
const parent = node?.parent?.parent
|
|
if (!parent) return
|
|
const packageCategory = parent.key.value
|
|
if (!dependencyKeys.includes(packageCategory)) return
|
|
const packageName = node.key.value
|
|
const packageVersion = node.value.value
|
|
|
|
const versions = packageVersionMap.get(packageName)
|
|
if (!versions || versions.some((v) => v.version === packageVersion)) return
|
|
|
|
context.report({
|
|
node,
|
|
message: `Inconsistent versions of ${packageName}: ${Array.from(new Set(versions.map((v) => v.version))).join(', ')}`,
|
|
suggest: versions.map((version) => ({
|
|
desc: `Follow the version ${version.version} in ${version.filePath}`,
|
|
fix: (fixer) => fixer.replaceText(node.value, `"${version.version}"`),
|
|
})),
|
|
})
|
|
},
|
|
}
|
|
},
|
|
},
|
|
'no-duplicate-package': {
|
|
meta: {
|
|
type: 'problem',
|
|
docs: {
|
|
description: 'Ensure packages are not duplicated in one package.json',
|
|
category: 'Possible Errors',
|
|
recommended: true,
|
|
},
|
|
},
|
|
create(context) {
|
|
if (!context.filename.endsWith('package.json')) return {}
|
|
|
|
let json
|
|
try {
|
|
json = JSON.parse(fs.readFileSync(context.filename, 'utf-8'))
|
|
} catch {
|
|
return {}
|
|
}
|
|
|
|
const dependencyMap = new Map()
|
|
dependencyKeys.forEach((key) => {
|
|
const dependencies = json[key]
|
|
if (!dependencies) return
|
|
|
|
if (!dependencyMap.get(key)) {
|
|
dependencyMap.set(key, new Set())
|
|
}
|
|
|
|
const dependencySet = dependencyMap.get(key)
|
|
Object.keys(dependencies).forEach((dependency) => {
|
|
dependencySet.add(dependency)
|
|
})
|
|
})
|
|
|
|
return {
|
|
'Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty > JSONObjectExpression > JSONProperty'(
|
|
node,
|
|
) {
|
|
const parent = node?.parent?.parent
|
|
if (!parent) return
|
|
const packageCategory = parent.key.value
|
|
if (!dependencyKeys.includes(packageCategory)) return
|
|
const packageName = node.key.value
|
|
|
|
dependencyKeys.forEach((key) => {
|
|
if (key === packageCategory) return
|
|
if (!dependencyMap.get(key)?.has(packageName)) return
|
|
|
|
context.report({
|
|
node,
|
|
message: `Duplicated package ${packageName} in ${key}`,
|
|
})
|
|
})
|
|
},
|
|
}
|
|
},
|
|
},
|
|
},
|
|
}
|