Add .npmrc and ESLint rule for version prefix validation

Co-authored-by: hyoban <38493346+hyoban@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-01-20 09:42:10 +00:00
parent 20b53464ba
commit bab1b87017
5 changed files with 96 additions and 0 deletions

1
web/.npmrc Normal file
View File

@ -0,0 +1 @@
save-exact=true

View File

@ -1,6 +1,7 @@
import noAsAnyInT from './rules/no-as-any-in-t.js'
import noExtraKeys from './rules/no-extra-keys.js'
import noLegacyNamespacePrefix from './rules/no-legacy-namespace-prefix.js'
import noVersionPrefix from './rules/no-version-prefix.js'
import requireNsOption from './rules/require-ns-option.js'
import validI18nKeys from './rules/valid-i18n-keys.js'
@ -14,6 +15,7 @@ const plugin = {
'no-as-any-in-t': noAsAnyInT,
'no-extra-keys': noExtraKeys,
'no-legacy-namespace-prefix': noLegacyNamespacePrefix,
'no-version-prefix': noVersionPrefix,
'require-ns-option': requireNsOption,
'valid-i18n-keys': validI18nKeys,
},

View File

@ -0,0 +1,82 @@
/** @type {import('eslint').Rule.RuleModule} */
export default {
meta: {
type: 'problem',
docs: {
description: 'Ensure package.json dependencies and devDependencies do not use version prefixes (^ or ~)',
},
fixable: 'code',
},
create(context) {
return {
Program(node) {
const { filename, sourceCode } = context
// Only check package.json files
if (!filename.endsWith('package.json'))
return
let packageJson = {}
try {
packageJson = JSON.parse(sourceCode.text)
}
catch (error) {
context.report({
node,
message: `Error parsing package.json: ${error instanceof Error ? error.message : String(error)}`,
})
return
}
const dependencyTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies']
const fixes = {}
for (const depType of dependencyTypes) {
if (!packageJson[depType])
continue
const dependencies = packageJson[depType]
for (const [name, version] of Object.entries(dependencies)) {
// Check if version starts with ^ or ~
if (typeof version === 'string' && (version.startsWith('^') || version.startsWith('~'))) {
const cleanVersion = version.substring(1)
context.report({
node,
message: `Dependency "${name}" in "${depType}" should not use version prefix. Use "${cleanVersion}" instead of "${version}"`,
fix(fixer) {
// Store fix for later
if (!fixes[depType])
fixes[depType] = {}
fixes[depType][name] = cleanVersion
return null
},
})
}
}
}
// Apply all fixes at once if there are any
if (Object.keys(fixes).length > 0) {
context.report({
node,
message: 'Some dependencies have version prefixes that should be removed',
fix(fixer) {
const newPackageJson = { ...packageJson }
for (const [depType, deps] of Object.entries(fixes)) {
newPackageJson[depType] = { ...newPackageJson[depType] }
for (const [name, version] of Object.entries(deps)) {
newPackageJson[depType][name] = version
}
}
const newText = `${JSON.stringify(newPackageJson, null, 2)}\n`
return fixer.replaceText(node, newText)
},
})
}
},
}
},
}

View File

@ -133,4 +133,14 @@ export default antfu(
'dify-i18n/no-extra-keys': 'error',
},
},
// package.json version prefix validation
{
files: ['**/package.json'],
plugins: {
'dify-i18n': difyI18n,
},
rules: {
'dify-i18n/no-version-prefix': 'error',
},
},
)