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

eslint-plugin-path

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-path - npm Package Compare versions

Comparing version 0.1.0-rc.3 to 1.0.0-rc.4

lib/utils/constants.js

59

lib/rules/no-relative-imports.js
"use strict";
const {
getImport,
getBaseDirs,
isRelativeToParent,
isExternalPath,
} = require("../utils");
const { getImport } = require("../utils");
const { isRelativeToParent, isExternalPath } = require("../utils/import-types");
const { relative } = require("path");
/**
* @typedef {import("../utils/tsconfig").AliasItem} AliasItem
*/
const { getTSconfigSettings } = require("../utils/tsconfig");
function findAbsolutePath(target, baseDirs = []) {
if (!target || !baseDirs) {
/**
* Creates an absolute path to target using an array of alias items
* @param {string} target
* @param {Array<AliasItem>} aliases
* @returns {string|null} - absolute path import
*/
function getAbsolutePathToTarget(target, aliases = []) {
if (!target || !aliases) {
return null;
}
return baseDirs
const absolutePath = aliases
.map(({ path, alias }) => `${alias || ""}${relative(path, target)}`)
.find((path) => !isRelativeToParent(path));
return absolutePath || null;
}
function getSegmentCount(path) {
/**
* Calculate slash counts
* @param {string} path
* @returns {number} - number of slashes
*/
function getSlashCounts(path) {
if (!path) {

@@ -29,2 +41,8 @@ return 0;

/**
* Checks if the max path depth has been exceeded
* @param {string} current
* @param {RuleSettings} settings
* @returns
*/
function isMaxDepthExceeded(current, settings) {

@@ -39,2 +57,9 @@ if (!current) {

/**
*
* @param {string} current
* @param {string} expected
* @param {RuleSettings} settings
* @returns
*/
function isWrongRelativeImport(current, expected, settings) {

@@ -55,3 +80,3 @@ if (

return settings.suggested
? getSegmentCount(current) > getSegmentCount(expected)
? getSlashCounts(current) > getSlashCounts(expected)
: false;

@@ -91,10 +116,16 @@ }

/**
* @typedef {Object} RuleSettings
* @property {number} maxDepth
* @property {boolean} suggested
*/
module.exports.create = (context) => {
const baseDirs = getBaseDirs();
const filename = context.getFilename();
const { maxDepth = 2, suggested = false } = context.options[0] || {};
/** @type {RuleSettings} */
const settings = { maxDepth, suggested };
const tsconfigSettings = getTSconfigSettings();
return getImport(filename, ({ node, start, value: current, end, path }) => {
const expected = findAbsolutePath(path, baseDirs);
const expected = getAbsolutePathToTarget(path, tsconfigSettings);

@@ -101,0 +132,0 @@ if (isWrongRelativeImport(current, expected, settings)) {

"use strict";
const { dirname, join, normalize, resolve, relative } = require("path");
const { existsSync, readFileSync } = require("fs");
const { dirname, join, normalize } = require("path");
const FILES = {
package: "package.json",
tsconfig: "tsconfig.json",
};
/**
* @typedef {Object} ImportHandlerParams
* @property {any} node - context node from eslint
* @property {string} value - import value
* @property {string} path - path to import value
* @property {number} start - star of line where import is declared
* @property {number} end - end of line where import is declared
*/
function hasKey(map, path) {
let inner = map;
for (let step of path.split(".")) {
inner = inner[step];
if (inner === undefined) {
return false;
}
}
return true;
}
function getContextPackagePath() {
let dir = resolve(FILES.package);
do {
dir = dirname(dir);
} while (!existsSync(join(dir, FILES.package)) && dir !== "/");
if (!existsSync(join(dir, FILES.package))) {
return;
}
return dir;
}
function isRelativeToParent(name) {
return /^\.\.$|^\.\.[\\/]/.test(name);
}
function loadFile(baseDir, filename) {
return JSON.parse(readFileSync(join(baseDir, filename), "utf-8"));
}
function isFileExists(baseDir, filename) {
return existsSync(join(baseDir, filename));
}
function isExternalPath(path) {
if (!path) {
return false;
}
const packagePath = getContextPackagePath();
if (relative(packagePath, path).startsWith("..")) {
return true;
}
const folders = ["node_modules"];
return folders.some((folder) => {
const folderPath = resolve(packagePath, folder);
const relativePath = relative(folderPath, path);
return !relativePath.startsWith("..");
});
}
function getTSconfigDirs() {
const rootDir = getContextPackagePath();
const urls = [];
if (isFileExists(rootDir, FILES.tsconfig)) {
const config = loadFile(rootDir, FILES.tsconfig);
if (hasKey(config, "compilerOptions.paths")) {
Object.entries(config.compilerOptions.paths).forEach(([key, items]) =>
items.forEach((item) =>
urls.push({
path: item.replace("*", ""),
alias: key.replace("*", ""),
})
)
);
}
if (hasKey(config, "include")) {
config.include.forEach((item) => urls.push({ path: item, alias: null }));
}
if (hasKey(config, "compilerOptions.baseUrl")) {
urls.push({
path: config.compilerOptions.baseUrl,
alias: null,
});
}
}
return urls.map((item) => ({
...item,
path: join(rootDir, item.path),
}));
}
const configureParams = (filename, node, { value, range }) => {
/**
* Params configurator
* @param {string} filename
* @param {any} node
* @param {{value: string; range: [number, number]}} source
* @returns {ImportHandlerParams}
*/
function configureParams(filename, node, { value, range }) {
const path = normalize(join(dirname(filename), value));
const [start, end] = range;
const [start, end] = range || [];
return { node, value, path, start, end };
};
}
const getImport = (filename, callback) => ({
ImportDeclaration: (node) => {
callback(configureParams(filename, node, node.source));
},
CallExpression: (node) => {
if (
node.arguments.length > 0 &&
node.arguments[0].type === "Literal" &&
(node.callee.type === "Import" ||
(node.callee.type === "Identifier" && node.callee.name === "require"))
) {
callback(configureParams(filename, node, node.arguments[0]));
}
},
ImportExpression: (node) => {
if (node.source.type === "Literal") {
/**
* ESLint rule handler
* @param {string} filename
* @param {(params: ImportHandlerParams) => void} callback
* @returns {any} eslint rule handler
*/
function getImport(filename, callback) {
return {
ImportDeclaration: (node) => {
callback(configureParams(filename, node, node.source));
}
},
});
},
CallExpression: (node) => {
if (
node.arguments.length > 0 &&
node.arguments[0].type === "Literal" &&
(node.callee.type === "Import" ||
(node.callee.type === "Identifier" && node.callee.name === "require"))
) {
callback(configureParams(filename, node, node.arguments[0]));
}
},
ImportExpression: (node) => {
if (node.source.type === "Literal") {
callback(configureParams(filename, node, node.source));
}
},
};
}
module.exports = {
getBaseDirs: getTSconfigDirs,
getImport,
isRelativeToParent,
isExternalPath,
};
{
"name": "eslint-plugin-path",
"version": "0.1.0-rc.3",
"version": "1.0.0-rc.4",
"main": "lib/index.js",

@@ -5,0 +5,0 @@ "author": "qDanik <qdanik@yandex.ru>",

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