eslint-plugin-workspaces
Advanced tools
Comparing version
@@ -0,1 +1,13 @@ | ||
## [v0.7.0] - 2021-10-08 | ||
- Fixed a bug where imports were incorrectly flagged as relative imports ([#11](https://github.com/joshuajaco/eslint-plugin-workspaces/issues/11)) | ||
- It is no longer necessary to add the plugin when also extending one of the presets: | ||
```patch | ||
{ | ||
- "plugins": ["workspaces"], | ||
"extends": ["plugin:workspaces/recommended"] | ||
} | ||
``` | ||
## [v0.6.2] - 2020-10-16 | ||
@@ -14,4 +26,5 @@ | ||
[v0.7.0]: https://github.com/joshuajaco/eslint-plugin-workspaces/compare/v0.6.2...v0.7.0 | ||
[v0.6.2]: https://github.com/joshuajaco/eslint-plugin-workspaces/compare/v0.6.1...v0.6.2 | ||
[v0.6.1]: https://github.com/joshuajaco/eslint-plugin-workspaces/compare/v0.6.0...v0.6.1 | ||
[v0.6.0]: https://github.com/joshuajaco/eslint-plugin-workspaces/compare/v0.5.5...v0.6.0 |
'use strict'; | ||
const { dirname, relative } = require('path'); | ||
const { isSubPath, packages, getImport, pathToImport } = require('../utils'); | ||
const { findWorkspaces } = require('find-workspaces'); | ||
const { isSubPath, getImport, pathToImport } = require('../utils'); | ||
@@ -21,6 +22,8 @@ module.exports.meta = { | ||
module.exports.create = (context) => | ||
getImport(context, ({ node, path, start, end }) => { | ||
packages.forEach(({ name, location }) => { | ||
if (isSubPath(location, context.getFilename()) && isSubPath(name, path)) { | ||
module.exports.create = (context) => { | ||
const filename = context.getFilename(); | ||
const workspaces = findWorkspaces(filename); | ||
return getImport(workspaces, filename, ({ node, path, start, end }) => { | ||
workspaces.forEach(({ package: { name }, location }) => { | ||
if (isSubPath(location, filename) && isSubPath(name, path)) { | ||
context.report({ | ||
@@ -33,6 +36,3 @@ node, | ||
pathToImport( | ||
relative( | ||
dirname(context.getFilename()), | ||
path.replace(name, location), | ||
), | ||
relative(dirname(filename), path.replace(name, location)), | ||
), | ||
@@ -44,1 +44,2 @@ ), | ||
}); | ||
}; |
'use strict'; | ||
const { isSubPath, packages, getImport } = require('../utils'); | ||
const { findWorkspaces } = require('find-workspaces'); | ||
const { isSubPath, getImport } = require('../utils'); | ||
@@ -69,26 +70,37 @@ module.exports.meta = { | ||
const forbidden = packages.filter(({ name }) => !allowed.includes(name)); | ||
const filename = context.getFilename(); | ||
const workspaces = findWorkspaces(filename); | ||
return getImport(context, ({ node, value, path, currentPackage }) => { | ||
forbidden | ||
.filter( | ||
filterSharedPackagesInCurrentScope( | ||
currentPackage, | ||
scopedEnabled, | ||
scopedSharingFolderName, | ||
), | ||
) | ||
.forEach(({ name, location }) => { | ||
if ( | ||
name !== currentPackage.name && | ||
(isSubPath(name, value) || isSubPath(location, path)) | ||
) { | ||
context.report({ | ||
node, | ||
messageId: 'noCrossImports', | ||
data: { name }, | ||
}); | ||
} | ||
}); | ||
}); | ||
if (!workspaces) return {}; | ||
const forbidden = workspaces.filter( | ||
({ package: { name } }) => !allowed.includes(name), | ||
); | ||
return getImport( | ||
workspaces, | ||
filename, | ||
({ node, value, path, currentWorkspace }) => { | ||
forbidden | ||
.filter( | ||
filterSharedPackagesInCurrentScope( | ||
currentWorkspace, | ||
scopedEnabled, | ||
scopedSharingFolderName, | ||
), | ||
) | ||
.forEach(({ package: { name }, location }) => { | ||
if ( | ||
name !== currentWorkspace.package.name && | ||
(isSubPath(name, value) || isSubPath(location, path)) | ||
) { | ||
context.report({ | ||
node, | ||
messageId: 'noCrossImports', | ||
data: { name }, | ||
}); | ||
} | ||
}); | ||
}, | ||
); | ||
}; |
'use strict'; | ||
const { isSubPath, packages, getImport } = require('../utils'); | ||
const { findWorkspaces } = require('find-workspaces'); | ||
const { isSubPath, getImport } = require('../utils'); | ||
@@ -19,21 +20,28 @@ module.exports.meta = { | ||
module.exports.create = (context) => | ||
getImport(context, ({ node, path, start, end, currentPackage }) => { | ||
packages.forEach(({ name, location }) => { | ||
if ( | ||
name !== path && | ||
name !== currentPackage.name && | ||
isSubPath(location, path) | ||
) { | ||
context.report({ | ||
node, | ||
messageId: 'noRelativeImports', | ||
fix: (fixer) => | ||
fixer.replaceTextRange( | ||
[start + 1, end - 1], | ||
path.replace(location, name), | ||
), | ||
}); | ||
} | ||
}); | ||
}); | ||
module.exports.create = (context) => { | ||
const filename = context.getFilename(); | ||
const workspaces = findWorkspaces(filename); | ||
return getImport( | ||
workspaces, | ||
filename, | ||
({ node, path, start, end, currentWorkspace }) => { | ||
workspaces.forEach(({ package: { name }, location }) => { | ||
if ( | ||
name !== path && | ||
name !== currentWorkspace.package.name && | ||
isSubPath(location, path) | ||
) { | ||
context.report({ | ||
node, | ||
messageId: 'noRelativeImports', | ||
fix: (fixer) => | ||
fixer.replaceTextRange( | ||
[start + 1, end - 1], | ||
path.replace(location, name), | ||
), | ||
}); | ||
} | ||
}); | ||
}, | ||
); | ||
}; |
'use strict'; | ||
const { isSubPath, packages, getImport } = require('../utils'); | ||
const { findWorkspaces } = require('find-workspaces'); | ||
const { isSubPath, getImport } = require('../utils'); | ||
@@ -19,19 +20,27 @@ module.exports.meta = { | ||
module.exports.create = (context) => | ||
getImport(context, ({ node, value, path, currentPackage }) => { | ||
packages.forEach(({ name, location }) => { | ||
const { dependencies, devDependencies } = currentPackage; | ||
module.exports.create = (context) => { | ||
const filename = context.getFilename(); | ||
const workspaces = findWorkspaces(filename); | ||
return getImport( | ||
workspaces, | ||
filename, | ||
({ node, value, path, currentWorkspace }) => { | ||
workspaces.forEach(({ package: { name }, location }) => { | ||
const { dependencies = {}, devDependencies = {} } = | ||
currentWorkspace.package; | ||
if ( | ||
name !== currentPackage.name && | ||
(isSubPath(name, value) || isSubPath(location, path)) && | ||
!Object.keys(dependencies).includes(name) && | ||
!Object.keys(devDependencies).includes(name) | ||
) { | ||
context.report({ | ||
node, | ||
messageId: 'requireDependency', | ||
}); | ||
} | ||
}); | ||
}); | ||
if ( | ||
name !== currentWorkspace.package.name && | ||
(isSubPath(name, value) || isSubPath(location, path)) && | ||
!Object.keys(dependencies).includes(name) && | ||
!Object.keys(devDependencies).includes(name) | ||
) { | ||
context.report({ | ||
node, | ||
messageId: 'requireDependency', | ||
}); | ||
} | ||
}); | ||
}, | ||
); | ||
}; |
'use strict'; | ||
const getPackages = require('@joshuajaco/get-monorepo-packages'); | ||
const fs = require('fs'); | ||
const { | ||
dirname, | ||
join, | ||
relative, | ||
sep, | ||
normalize, | ||
isAbsolute, | ||
resolve, | ||
} = require('path'); | ||
const { dirname, join, relative, sep, normalize, isAbsolute } = require('path'); | ||
@@ -20,42 +10,2 @@ const isSubPath = (parent, path) => { | ||
const directoryContainsRootPackageJson = (path) => { | ||
const pathToCheck = resolve(path, 'package.json'); | ||
if (!fs.existsSync(pathToCheck)) return false; | ||
const pkg = require(pathToCheck); | ||
if (pkg && {}.hasOwnProperty.call(pkg, 'workspaces')) { | ||
return true; | ||
} | ||
return false; | ||
}; | ||
const getRepositoryRoot = (path = process.cwd()) => { | ||
let pathForCheck = path; | ||
if (directoryContainsRootPackageJson(pathForCheck)) { | ||
return pathForCheck; | ||
} | ||
while (pathForCheck !== resolve(pathForCheck, '..')) { | ||
pathForCheck = resolve(pathForCheck, '..'); | ||
if (directoryContainsRootPackageJson(pathForCheck)) { | ||
return pathForCheck; | ||
} | ||
} | ||
return path; | ||
}; | ||
const packages = getPackages(getRepositoryRoot()).map( | ||
({ | ||
package: { name, dependencies = {}, devDependencies = {} }, | ||
location, | ||
}) => ({ | ||
name, | ||
location, | ||
dependencies, | ||
devDependencies, | ||
}), | ||
); | ||
const resolvePath = (parent, path) => { | ||
@@ -67,6 +17,6 @@ if (path[0] !== '.') return path; | ||
const resolveImport = (context, node, { value, range }, currentPackage) => { | ||
const path = resolvePath(dirname(context.getFilename()), value); | ||
const resolveImport = (filename, node, { value, range }, currentWorkspace) => { | ||
const path = resolvePath(dirname(filename), value); | ||
const [start, end] = range; | ||
return { node, value, path, start, end, currentPackage }; | ||
return { node, value, path, start, end, currentWorkspace }; | ||
}; | ||
@@ -84,13 +34,14 @@ | ||
const findCurrentPackage = (context) => | ||
packages.find(({ location }) => isSubPath(location, context.getFilename())); | ||
const getImport = (workspaces, filename, callback) => { | ||
if (!workspaces) return {}; | ||
const getImport = (context, callback) => { | ||
const currentPackage = findCurrentPackage(context); | ||
const currentWorkspace = workspaces.find(({ location }) => | ||
isSubPath(location, filename), | ||
); | ||
if (!currentPackage) return {}; | ||
if (!currentWorkspace) return {}; | ||
return { | ||
ImportDeclaration: (node) => { | ||
callback(resolveImport(context, node, node.source, currentPackage)); | ||
callback(resolveImport(filename, node, node.source, currentWorkspace)); | ||
}, | ||
@@ -105,3 +56,3 @@ CallExpression: (node) => { | ||
callback( | ||
resolveImport(context, node, node.arguments[0], currentPackage), | ||
resolveImport(filename, node, node.arguments[0], currentWorkspace), | ||
); | ||
@@ -112,3 +63,3 @@ } | ||
if (node.source.type === 'Literal') { | ||
callback(resolveImport(context, node, node.source, currentPackage)); | ||
callback(resolveImport(filename, node, node.source, currentWorkspace)); | ||
} | ||
@@ -121,6 +72,4 @@ }, | ||
isSubPath, | ||
packages, | ||
getImport, | ||
pathToImport, | ||
getRepositoryRoot, | ||
}; |
{ | ||
"name": "eslint-plugin-workspaces", | ||
"version": "0.7.0", | ||
"version": "0.8.0-rc1", | ||
"main": "lib/index.js", | ||
@@ -33,3 +33,3 @@ "license": "MIT", | ||
"format": "prettier --write \"**/*.{js,json,md,yml}\" --ignore-path .gitignore", | ||
"mocha": "mocha tests --recursive --file tests/setup.js", | ||
"mocha": "mocha tests --recursive", | ||
"test": "yarn lint && nyc yarn mocha", | ||
@@ -41,3 +41,3 @@ "coverage": "mkdir -p coverage && touch ./coverage/lcov.info && nyc report --reporter=text-lcov > ./coverage/lcov.info", | ||
"dependencies": { | ||
"@joshuajaco/get-monorepo-packages": "^1.2.1" | ||
"find-workspaces": "^0.0.1" | ||
}, | ||
@@ -52,6 +52,6 @@ "devDependencies": { | ||
"mocha": "^9.1.2", | ||
"mock-require": "^3.0.3", | ||
"nyc": "^15.1.0", | ||
"prettier": "^2.4.1" | ||
"prettier": "^2.4.1", | ||
"proxyquire": "^2.1.3" | ||
} | ||
} |
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
15894
1.36%1
-66.67%299
-5.08%1
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed