Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

eslint-plugin-feature-modules

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-feature-modules - npm Package Compare versions

Comparing version 1.0.0 to 1.0.1

225

lib/rules/no-deep-module-require/index.js

@@ -0,118 +1,121 @@

const path = require('path');
const isRequireFunction = node => {
return (
node.callee.type === 'Identifier' &&
node.callee.name === 'require' &&
node.arguments.length === 1 &&
node.arguments[0].type === 'Literal'
return (
node.callee.type === 'Identifier' &&
node.callee.name === 'require' &&
node.arguments.length === 1 &&
node.arguments[0].type === 'Literal'
);
};
const isDotPath = filePath => {
return filePath.startsWith('.');
};
const isDeepNonIndexImport = modulePathParts => {
if (modulePathParts.length <= 2) return false;
const thirdPathPart = modulePathParts[2];
return thirdPathPart !== 'index' && thirdPathPart !== 'index.js';
};
const getRelevantPathParts = filePath => {
return filePath.split(path.sep).filter(part => !part.startsWith('.'));
};
const getModuleName = (pathParts, moduleFolderName) => {
const moduleFolderNameIndex = pathParts.indexOf(moduleFolderName);
if (moduleFolderNameIndex === -1) return null;
return pathParts[moduleFolderNameIndex + 1]; //get moduleName, one after moduleFolderName
};
const trimPathsToModuleFolder = (pathParts, moduleFolderName) => {
const moduleFolderNameIndex = pathParts.indexOf(moduleFolderName);
return pathParts.slice(moduleFolderNameIndex);
};
const lintingRule = function(context) {
const verifyValidImport = (node, requirePath) => {
if (!isDotPath(requirePath)) return; //dont check against node_modules or alias paths
const fileName = context.getFilename();
const { moduleFolderName } = context.options[0];
const fullRequirePath = path.resolve(path.parse(fileName).dir, requirePath);
const dependencyPathParts = getRelevantPathParts(fullRequirePath);
const importingModulePathParts = getRelevantPathParts(fileName);
// //are we requiring a file that is in same module?
const dependencyModuleName = getModuleName(
dependencyPathParts,
moduleFolderName
);
const importingModuleName = getModuleName(
importingModulePathParts,
moduleFolderName
);
//if we arent requiring something from module folders
// OR the requiring module is the same as our importing module, bail
if (
dependencyModuleName == null ||
dependencyModuleName === importingModuleName
) {
return;
}
//if not, are we digging more than one level deep?
const modulePathParts = trimPathsToModuleFolder(
dependencyPathParts,
moduleFolderName
);
if (isDeepNonIndexImport(modulePathParts)) {
context.report(node, 'Cannot request module thats too deep!');
}
};
const isRelativePath = path => {
return path.startsWith('.');
};
const isDeepNonIndexImport = modulePathParts => {
if (modulePathParts.length <= 2) return false;
const thirdPathPart = modulePathParts[2];
return thirdPathPart !== 'index' && thirdPathPart !== 'index.js';
};
const getRelevantPathParts = path => {
return path.split('/').filter(part => !part.startsWith('.'));
};
const getModuleName = (pathParts, moduleFolderName) => {
const moduleFolderNameIndex = pathParts.indexOf(moduleFolderName);
if (moduleFolderNameIndex === -1) return null;
return pathParts[moduleFolderNameIndex + 1]; //get moduleName, one after moduleFolderName
};
const trimPathsToModuleFolder = (pathParts, moduleFolderName) => {
const moduleFolderNameIndex = pathParts.indexOf(moduleFolderName);
return pathParts.slice(moduleFolderNameIndex);
};
const lintingRule = function(context) {
const verifyValidImport = (node, requirePath) => {
if (!isRelativePath(requirePath)) return; //dont check against node_modules or alias paths
const fileName = context.getFilename();
const { moduleFolderName } = context.options[0];
const dependencyPathParts = getRelevantPathParts(requirePath);
const importingModulePathParts = getRelevantPathParts(fileName);
// //are we requiring a file that is in same module?
const dependencyModuleName = getModuleName(
dependencyPathParts,
moduleFolderName
);
const importingModuleName = getModuleName(
importingModulePathParts,
moduleFolderName
);
//if we arent requiring something from module folders
// OR the requiring module is the same as our importing module, bail
if (
dependencyModuleName == null ||
dependencyModuleName === importingModuleName
) {
return {
ImportDeclaration(node) {
const importSource = node.source.value;
verifyValidImport(node.source, importSource);
},
CallExpression(node) {
if (!isRequireFunction(node)) {
return;
}
//if not, are we digging more than one level deep?
const modulePathParts = trimPathsToModuleFolder(
dependencyPathParts,
moduleFolderName
);
if (isDeepNonIndexImport(modulePathParts)) {
context.report(node, 'Cannot request module thats too deep!');
}
};
return {
ImportDeclaration(node) {
const importSource = node.source.value;
verifyValidImport(node.source, importSource);
},
CallExpression(node) {
if (!isRequireFunction(node)) {
return;
}
const fileName = context.getFilename();
const source = node.arguments[0].value;
verifyValidImport(node.arguments[0], source);
}
};
const fileName = context.getFilename();
const source = node.arguments[0].value;
verifyValidImport(node.arguments[0], source);
}
};
module.exports = {
meta: {
docs: {
description: 'Disallow digging too deep into feature modules',
category: 'best practices'
},
schema: [
{
type: 'object',
properties: {
moduleBasePath: {
type: 'string'
},
moduleFolderName: {
type: 'string'
}
};
module.exports = {
meta: {
docs: {
description: 'Disallow digging too deep into feature modules',
category: 'best practices'
},
schema: [
{
type: 'object',
properties: {
moduleBasePath: {
type: 'string'
},
required: ['moduleFolderName']
}
]
},
create: lintingRule
};
moduleFolderName: {
type: 'string'
}
},
required: ['moduleFolderName']
}
]
},
create: lintingRule
};
{
"name": "eslint-plugin-feature-modules",
"version": "1.0.0",
"version": "1.0.1",
"description": "Plugin for eslint rules that apply to feature modules directory structure",

@@ -5,0 +5,0 @@ "keywords": [

const { RuleTester } = require('eslint');
const rule = require('../../../../lib/rules/no-deep-module-require');
const path = require('path')

@@ -11,2 +12,6 @@ const config = {

const normalizePath = filePath => {
return path.resolve(filePath)
}
const ruleOptions = [{ moduleFolderName: 'module' }];

@@ -34,3 +39,3 @@

code: 'import foo from "./module/story"',
filename: 'src/app',
filename: normalizePath('src/app'),
options: ruleOptions

@@ -40,3 +45,3 @@ },

code: 'import foo from "../../module/story"',
filename: 'module/party/index.js',
filename: normalizePath('module/party/index.js'),
options: ruleOptions

@@ -46,8 +51,8 @@ },

code: 'const foo = require("../../module/story")',
filename: 'module/party/index.js',
filename: normalizePath('module/party/index.js'),
options: ruleOptions
},
{
code: 'const foo = require("../module/party/foo")',
filename: 'module/party/index.js',
code: 'const foo = require("../../module/party/foo")',
filename: normalizePath('module/party/index.js'),
options: ruleOptions

@@ -57,8 +62,8 @@ },

code: 'const foo = require("./reducer/test/test.js")',
filename: 'module/party/index.js',
filename: normalizePath('module/party/index.js'),
options: ruleOptions
},
{
code: 'const foo = require("../feature/party")',
filename: 'feature/something/index.js',
code: 'const foo = require("../../feature/party")',
filename: normalizePath('feature/something/index.js'),
options: [{ moduleFolderName: 'feature' }]

@@ -68,3 +73,3 @@ },

code: 'const foo = require("module/this/is/long/but/fine")',
filename: 'module/something',
filename: normalizePath('module/something'),
options: ruleOptions

@@ -74,3 +79,3 @@ },

code: 'const foo = require("./module")',
filename: 'src',
filename: normalizePath('src'),
options: ruleOptions

@@ -80,3 +85,3 @@ },

code: 'const foo = require("./module/party/index.js")',
filename: 'src',
filename: normalizePath('src'),
options: ruleOptions

@@ -86,3 +91,3 @@ },

code: 'const foo = require("./module/party/index")',
filename: 'src',
filename: normalizePath('src'),
options: ruleOptions

@@ -94,3 +99,3 @@ }

code: 'const foo = require("../../module/story/foo")',
filename: 'module/party/index.js',
filename: normalizePath('module/party/index.js'),
options: ruleOptions

@@ -100,3 +105,3 @@ }),

code: 'const reducer = require("./module/story/foo")',
filename: 'src/app',
filename: normalizePath('src/app'),
options: ruleOptions

@@ -106,3 +111,3 @@ }),

code: 'const foo = require("../feature/party/reducer")',
filename: 'feature/something/index.js',
filename: normalizePath('feature/something/index.js'),
options: [{ moduleFolderName: 'feature' }]

@@ -112,6 +117,11 @@ }),

code: 'const foo = require("../feature/party/inde")',
filename: 'feature/something/index.js',
filename: normalizePath('feature/something/index.js'),
options: [{ moduleFolderName: 'feature' }]
}),
invalid({
code: 'const foo = require("../party/foo")',
filename: normalizePath('src/module/awesome/index.js'),
options: ruleOptions
})
]
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc