@kendallgassner/eslint-plugin-package-json
Version:
Rules for valid, consistent, and readable package.json files
117 lines (107 loc) • 4.26 kB
JavaScript
/**
* @fileoverview Checks existence of local dependencies in the package.json
* @author Kendall Gassner
*/
;
const fs = require('fs');
const path = require('path');
const {
isPackageJson,
extractPackageObjectFromAST
} = require('../processors/PackageJsonProcessor');
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
function fileExistsWithCaseSync(filepath) {
var dir = path.dirname(filepath);
if (dir === path.dirname(dir)) {
return true;
}
var filenames = fs.readdirSync(dir);
if (filenames.indexOf(path.basename(filepath)) === -1) {
return false;
}
return fileExistsWithCaseSync(dir);
}
module.exports = {
meta: {
docs: {
description:
'Checks existence of local dependencies in the package.json',
category: 'Best Practices',
recommended: true
},
fixable: null // or "code" or "whitespace"
},
create: function(context) {
return {
'Program:exit': node => {
if (!isPackageJson(context.getFilename())) {
return;
}
const sourceCode = context.getSourceCode();
const packageRoot = extractPackageObjectFromAST(node);
const original = JSON.parse(sourceCode.getText(packageRoot));
const {
dependencies,
peerDependencies,
devDependencies
} = original;
const depObjs = [
{
type: 'dependencies',
value: Object.entries(dependencies || {})
},
{
type: 'peerDependencies',
value: Object.entries(peerDependencies || {})
},
{
type: 'devDependencies',
value: Object.entries(devDependencies || {})
}
];
depObjs.map(obj =>
obj.value.map(([key, value]) => {
const response = localPath => {
const filePath = path.join(
context
.getFilename()
.replace(/package\.json/g, '/'),
value.replace(new RegExp(localPath, 'g'), ''),
'/package.json'
);
try {
if (!fileExistsWithCaseSync(filePath)) {
context.report({
node: packageRoot,
message: `The package ${key} does not exist given the specified path: ${value}.`
});
}
} catch (e) {
context.report({
node: packageRoot,
message: `The package ${key} does not exist given the specified path: ${value}.`
});
}
};
if (value.includes('link:')) {
if (obj.type === 'peerDependencies') {
// if this is a peerDependency
context.report({
node: packageRoot,
message: `Peer Dependencies cannot be listed as local dependencies.`
});
} else {
response('link:');
}
}
if (value.includes('file:')) {
response('file:');
}
})
);
}
};
}
};