New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@knit/depcheck

Package Overview
Dependencies
Maintainers
2
Versions
50
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@knit/depcheck - npm Package Compare versions

Comparing version 0.0.0-5bd66a9 to 0.0.0-812e2aa

41

__tests__/unit.test.js

@@ -0,4 +1,8 @@

"use strict";
var _ = _interopRequireDefault(require(".."));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* flow */
import depcheck from "..";
jest.mock("@knit/needle", () => {

@@ -13,34 +17,7 @@ const path = require("path");

});
describe("eslint", () => {
it("returns presets and plugins", async () => {
const m = await depcheck("configs");
expect(Object.keys(m.using)).toEqual([
"@typescript-eslint/parser",
"eslint-plugin-shorthand-pl",
"eslint-plugin-test",
"@ns/eslint-plugin",
"@ns/eslint-plugin-shorthand-pl",
"@ns/eslint-plugin-test",
"@typescript-eslint/eslint-plugin",
"eslint-config-shorthand-ex",
"eslint-config-test",
"@ns/eslint-config",
"@ns/eslint-config-shorthand-ex",
"@ns/eslint-config-test",
"eslint-config-module",
"@ns/eslint-config-module",
"eslint-plugin-module",
"@ns/eslint-plugin-module",
"@foo/eslint-plugin-foo",
"@bar/eslint-plugin",
"eslint-plugin-prettier",
"eslint-config-prettier"
]);
const m = await (0, _.default)("configs");
expect(Object.keys(m.using)).toEqual(["@typescript-eslint/parser", "eslint-plugin-shorthand-pl", "eslint-plugin-test", "@ns/eslint-plugin", "@ns/eslint-plugin-shorthand-pl", "@ns/eslint-plugin-test", "@typescript-eslint/eslint-plugin", "eslint-config-shorthand-ex", "eslint-config-test", "@ns/eslint-config", "@ns/eslint-config-shorthand-ex", "@ns/eslint-config-test", "eslint-config-module", "@ns/eslint-config-module", "eslint-plugin-module", "@ns/eslint-plugin-module", "@foo/eslint-plugin-foo", "@bar/eslint-plugin", "eslint-plugin-prettier", "eslint-config-prettier"]);
});
});
});

@@ -1,2 +0,2 @@

/* @flow weak */
"use strict";

@@ -6,11 +6,3 @@ const lodash = require("lodash");

module.exports = function detectRequireResolve(node) {
return node.type === "CallExpression" &&
node.callee &&
node.callee.type === "MemberExpression" &&
node.callee.object.name === "require" &&
node.callee.property.name === "resolve" &&
node.arguments[0] &&
lodash.isString(node.arguments[0].value)
? [node.arguments[0].value]
: [];
};
return node.type === "CallExpression" && node.callee && node.callee.type === "MemberExpression" && node.callee.object.name === "require" && node.callee.property.name === "resolve" && node.arguments[0] && lodash.isString(node.arguments[0].value) ? [node.arguments[0].value] : [];
};

@@ -1,91 +0,57 @@

/* @flow weak */
"use strict";
import path from "path";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
import depcheck from "depcheck";
import pify from "pify";
import needle from "@knit/needle";
var _path = _interopRequireDefault(require("path"));
export type TParser = (
content: string,
filePath: string,
deps: Array<string>,
rootDir: string
) => Array<string>;
var _depcheck = _interopRequireDefault(require("depcheck"));
export type TOptions = {|
ignoreBinPackage: boolean,
ignoreDirs: Array<string>,
ignoreMatches: Array<string>,
parsers: {
[k: string]: mixed
},
detectors: Array<mixed>,
specials: Array<mixed>
|};
var _pify = _interopRequireDefault(require("pify"));
export type TResults = {|
dependencies: Array<string>,
devDependencies: Array<string>,
missing: { [k: string]: Array<string> },
using: { [k: string]: Array<string> },
unused: { [k: string]: Array<string> },
invalidFiles: { [k: string]: string },
invalidDirs: { [k: string]: string }
|};
var _needle = _interopRequireDefault(require("@knit/needle"));
export type TDepcheck = (dir: string) => Promise<TResults>;
var _eslint = _interopRequireDefault(require("./specials/eslint"));
const options: TOptions = {
ignoreBinPackage: false, // ignore the packages with bin entry
ignoreDirs: [needle.paths.outputDir],
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const options = {
ignoreBinPackage: false,
// ignore the packages with bin entry
ignoreDirs: [_needle.default.paths.outputDir, ...(_needle.default.paths.ignoreDirPattern || [])],
ignoreMatches: [],
parsers: {
"*.js": depcheck.parser.es7,
"*.jsx": depcheck.parser.jsx,
"*.ts": depcheck.parser.typescript,
"*.tsx": depcheck.parser.typescript
"*.js": _depcheck.default.parser.es7,
"*.jsx": _depcheck.default.parser.jsx,
"*.ts": _depcheck.default.parser.typescript,
"*.tsx": _depcheck.default.parser.typescript
},
detectors: [
depcheck.detector.requireResolveCallExpression,
depcheck.detector.requireCallExpression,
depcheck.detector.importCallExpression,
depcheck.detector.importDeclaration,
depcheck.detector.exportDeclaration,
depcheck.detector.typescriptImportEqualsDeclaration,
depcheck.detector.typescriptImportType
],
specials: [
depcheck.special.babel,
depcheck.special.eslint,
depcheck.special.jest,
depcheck.special.prettier,
depcheck.special.ttypesciprt,
depcheck.special.webpack
]
detectors: [_depcheck.default.detector.requireResolveCallExpression, _depcheck.default.detector.requireCallExpression, _depcheck.default.detector.importCallExpression, _depcheck.default.detector.importDeclaration, _depcheck.default.detector.exportDeclaration, _depcheck.default.detector.typescriptImportEqualsDeclaration, _depcheck.default.detector.typescriptImportType],
specials: [_depcheck.default.special.babel, _eslint.default, _depcheck.default.special.jest, _depcheck.default.special.prettier, _depcheck.default.special.ttypescript, _depcheck.default.special.webpack]
};
const dc: TDepcheck = d => {
const dc = d => {
// depcheck needs an absolute path
const dir = path.isAbsolute(d) ? d : path.join(needle.paths.rootDir, d);
return (
// a lookup indicating each dependency is used by which files
pify(depcheck)(dir, options)
.then({
dependencies: [],
devDependencies: [],
missing: {},
using: {},
unused: {},
invalidFiles: {},
invalidDirs: {}
})
.catch(res => {
// weird library that only returns errors
if (res.code) throw new Error(res);
return res;
})
const dir = _path.default.isAbsolute(d) ? d : _path.default.join(_needle.default.paths.rootDir, d);
return (// a lookup indicating each dependency is used by which files
(0, _pify.default)(_depcheck.default)(dir, options).then({
dependencies: [],
devDependencies: [],
missing: {},
using: {},
unused: {},
invalidFiles: {},
invalidDirs: {}
}).catch(res => {
// weird library that only returns errors
if (res.code) throw new Error(res);
return res;
})
);
};
export default dc;
var _default = dc;
exports.default = _default;
module.exports = exports.default;
{
"homepage": "https://github.com/knitjs/knit#readme",
"license": "MIT",
"author": {
"name": "Shane Wilson"
},
"bugs": {
"url": "https://github.com/knitjs/knit/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/knitjs/knit.git"
},
"engines": {
"node": ">=10",
"npm": ">=5"
},
"private": false,
"name": "@knit/depcheck",
"description": "Depcheck parsers for knit",
"version": "0.0.0-5bd66a9"
"description": "Depcheck parsers for monorepo packages",
"version": "0.0.0-812e2aa",
"dependencies": {
"@knit/needle": "0.0.0-812e2aa",
"depcheck": "^0.9.1",
"lodash": "^4.17.15",
"pify": "4.0.1",
"require-package-name": "2.0.1"
}
}

@@ -1,18 +0,149 @@

import path from "path";
import lodash from "lodash";
import requirePackageName from "require-package-name";
import { wrapToArray } from "depcheck/dist/utils/index";
"use strict";
const requireConfig = (preset, rootDir) => {
const presetPath = path.isAbsolute(preset)
? preset
: path.resolve(rootDir, "node_modules", preset);
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = parseESLint;
var _path = _interopRequireDefault(require("path"));
var _lodash = _interopRequireDefault(require("lodash"));
var _requirePackageName = _interopRequireDefault(require("require-package-name"));
var _vm = _interopRequireDefault(require("vm"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* eslint-disable require-jsdoc */
function evaluate(code) {
const exports = {};
const sandbox = {
exports,
module: {
exports
}
};
_vm.default.runInNewContext(code, sandbox);
return sandbox.module.exports;
}
function parse(content) {
try {
return require(presetPath); // eslint-disable-line global-require
return JSON.parse(content);
} catch (error) {// not JSON format
}
try {
return evaluate(content);
} catch (error) {} // not valid JavaScript code
// parse fail, return nothing
return null;
}
function getCustomConfig(binName, filename, content, rootDir) {
const scripts = getScripts(filename, content);
if (scripts.length === 0) {
return null;
}
const script = scripts.find(s => s.split(/\s+/).indexOf(binName) !== -1);
if (script) {
const commands = script.split("&&");
const command = commands.find(c => c.startsWith(binName));
const optionsKeys = optionKeysForConfig[binName];
if (command && optionsKeys) {
const args = command.split(/\s+/);
const configIdx = args.findIndex(arg => optionsKeys.indexOf(arg) !== -1);
if (configIdx !== -1 && args[configIdx + 1]) {
const configFile = args[configIdx + 1];
const configPath = _path.default.resolve(rootDir, configFile);
const configContent = fs.readFileSync(configPath);
return parse(configContent);
}
}
}
return null;
}
function loadConfig(binName, filenameRegex, filename, content, rootDir) {
const basename = _path.default.basename(filename);
if (filenameRegex.test(basename)) {
const config = parse(content);
return config;
}
const custom = getCustomConfig(binName, filename, content, rootDir);
if (custom) {
return custom;
}
return null;
}
function loadModuleData(moduleName, rootDir) {
try {
const file = require.resolve(`${moduleName}/package.json`, {
paths: [rootDir]
});
return {
path: _path.default.dirname(file),
metadata: readJSON(file)
};
} catch (error) {
return {}; // silently return nothing
return {
path: null,
metadata: null
};
}
};
}
function wrapToArray(obj) {
if (!obj) {
return [];
}
if (Array.isArray(obj)) {
return obj;
}
return [obj];
}
function resolveConfigModule(preset, rootDir) {
const presetParts = preset.split("/");
let moduleName = presetParts.shift();
if (moduleName.startsWith("@")) {
moduleName += `/${presetParts.shift()}`;
}
const moduleData = loadModuleData(moduleName, rootDir);
const includedDeps = moduleData.metadata && moduleData.metadata.dependencies && typeof moduleData.metadata.dependencies === "object" ? Object.keys(moduleData.metadata.dependencies) : [];
return [moduleData.path && _path.default.resolve(moduleData.path, ...presetParts), includedDeps];
}
function requireConfig(preset, rootDir) {
const [presetPath, includedDeps] = _path.default.isAbsolute(preset) ? [preset, []] : resolveConfigModule(preset, rootDir);
try {
return [require(presetPath), includedDeps]; // eslint-disable-line global-require
} catch (error) {
return [{}, []]; // silently return nothing
}
}
/**

@@ -26,6 +157,8 @@ * Brings package name to correct format based on prefix

*/
function normalizePackageName(name, prefix) {
let normalizedName = name;
const convertPathToPosix = p => path.normalize(p).replace(/\\/g, "/");
const convertPathToPosix = p => _path.default.normalize(p).replace(/\\/g, "/");
/**

@@ -36,2 +169,4 @@ * On Windows, name can come in with Windows slashes instead of Unix slashes.

*/
if (normalizedName.indexOf("\\") > -1) {

@@ -46,12 +181,7 @@ normalizedName = convertPathToPosix(normalizedName);

*/
const scopedPackageShortcutRegex = new RegExp(
`^(@[^/]+)(?:/(?:${prefix})?)?$`
);
const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`);
const scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`);
if (scopedPackageShortcutRegex.test(normalizedName)) {
normalizedName = normalizedName.replace(
scopedPackageShortcutRegex,
`$1/${prefix}`
);
normalizedName = normalizedName.replace(scopedPackageShortcutRegex, `$1/${prefix}`);
} else if (!scopedPackageNameRegex.test(normalizedName.split("/")[1])) {

@@ -62,6 +192,3 @@ /**

*/
normalizedName = normalizedName.replace(
/^@([^/]+)\/(.*)$/,
`@$1/${prefix}-$2`
);
normalizedName = normalizedName.replace(/^@([^/]+)\/(.*)$/, `@$1/${prefix}-$2`);
}

@@ -75,9 +202,10 @@ } else if (normalizedName.indexOf(`${prefix}-`) !== 0) {

const resolvePresetPackage = (preset, rootDir) => {
function resolvePresetPackage(preset, rootDir) {
// inspired from https://github.com/eslint/eslint/blob/5b4a94e26d0ef247fe222dacab5749805d9780dd/lib/config/config-file.js#L347
if (path.isAbsolute(preset)) {
if (_path.default.isAbsolute(preset)) {
return preset;
}
if (preset.startsWith("./") || preset.startsWith("../")) {
return path.resolve(rootDir, preset);
return _path.default.resolve(rootDir, preset);
}

@@ -87,3 +215,2 @@

const pluginName = preset.slice(7, preset.lastIndexOf("/"));
return normalizePackageName(pluginName, "eslint-plugin");

@@ -93,38 +220,44 @@ }

return normalizePackageName(preset, "eslint-config");
};
}
const checkConfig = (config, rootDir) => {
function checkConfig(config, rootDir, includedDeps = []) {
const parser = wrapToArray(config.parser);
const plugins = wrapToArray(config.plugins).map(plugin =>
normalizePackageName(plugin, "eslint-plugin")
);
const plugins = wrapToArray(config.plugins).map(plugin => normalizePackageName(plugin, "eslint-plugin"));
const extendsArray = wrapToArray(config.extends);
const presets = extendsArray.filter(preset => !(["eslint:recommended", "eslint:all"].indexOf(preset) !== -1)).map(preset => resolvePresetPackage(preset, rootDir)); // prettier/recommended extends eslint-config-prettier
// https://github.com/prettier/eslint-plugin-prettier#recommended-configuration
const presets = wrapToArray(config.extends)
.filter(preset => !["eslint:recommended", "eslint:all"].includes(preset))
.map(preset => resolvePresetPackage(preset, rootDir));
if (extendsArray.indexOf("plugin:prettier/recommended") !== -1) {
presets.push("eslint-config-prettier");
}
const presetPackages = presets
.filter(preset => !path.isAbsolute(preset))
.map(requirePackageName);
const presetPackages = presets.filter(preset => !_path.default.isAbsolute(preset)).map(_requirePackageName.default);
const presetDeps = (0, _lodash.default)(presets).map(preset => requireConfig(preset, rootDir)).map(([presetConfig, deps]) => checkConfig(presetConfig, rootDir, deps)).flatten().value();
return _lodash.default.union(parser, plugins, presetPackages, presetDeps).filter(dep => !(includedDeps.indexOf(dep) !== -1));
}
const presetDeps = lodash(presets)
.map(preset => requireConfig(preset, rootDir))
.map(presetConfig => checkConfig(presetConfig, rootDir))
.flatten()
.value();
const configNameRegex = /^\.eslintrc(\.(json|js|yml|yaml))?$/;
return lodash.union(parser, plugins, presetPackages, presetDeps);
};
function parseESLint(content, filename, _, rootDir) {
const config = loadConfig("eslint", configNameRegex, filename, content, rootDir);
export default (content, filename, deps, rootDir) => {
if (
path.basename(rootDir).includes("eslint-config") &&
path.extname(filename) === ".js"
) {
const config = require(filename) || {};
if (config) {
return checkConfig(config, rootDir);
}
const packageJsonPath = _path.default.resolve(rootDir, "package.json");
const resolvedFilePath = _path.default.resolve(rootDir, filename);
if (resolvedFilePath === packageJsonPath) {
const parsed = JSON.parse(content);
if (parsed.eslintConfig) {
return checkConfig(parsed.eslintConfig, rootDir);
}
}
return [];
};
}
module.exports = exports.default;

@@ -1,30 +0,15 @@

/* @flow */
"use strict";
import path from "path";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
import type { TParser } from "..";
var _path = _interopRequireDefault(require("path"));
export type TLoader = {|
loader?: string,
loaders?: Array<string>
|};
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
export type TRule = {|
loader?: string,
use?: Array<string>
|};
const extractLoaders = item => {
let loaders = [];
export type TConfig = {|
module?: {
rules?: Array<TRule>,
preLoaders?: Array<TLoader>,
loaders?: Array<TLoader>,
postLoaders?: Array<TLoader>,
noParse?: Array<RegExp>
}
|};
type TExtractLoaders = (i: TLoader | TRule) => Array<string>;
const extractLoaders: TExtractLoaders = item => {
let loaders = [];
if (item.loader) {

@@ -41,74 +26,34 @@ loaders = loaders.concat(item.loader.split("!"));

type TStripQueryParameter = (l: string) => string;
const stripQueryParameter: TStripQueryParameter = loader =>
loader.split("?")[0];
const stripQueryParameter = loader => loader.split("?")[0]; // webpack v1 auto-loads loaders with the `-loader` suffix
// webpack v1 auto-loads loaders with the `-loader` suffix
type TNormalizeLoader = (l: string) => string;
const normalizeLoader: TNormalizeLoader = loader =>
`${loader.split("-")[0]}-loader`;
type TGetLoaders = (d: Array<string>, l: ?Array<TLoader>) => Array<string>;
const getLoaders: TGetLoaders = (deps, loaders) =>
(loaders || [])
.map(extractLoaders)
.reduce((acc, x) => acc.concat(x), [])
.map(stripQueryParameter)
.map(normalizeLoader)
.filter(Boolean)
.reduce((acc, x) => (acc.includes(x) ? acc : acc.concat(x)), []);
const normalizeLoader = loader => `${loader.split("-")[0]}-loader`;
// webpack v2 does not auto-loads loaders with the `-loader` suffix
const getLoaders = (deps, loaders) => (loaders || []).map(extractLoaders).reduce((acc, x) => acc.concat(x), []).map(stripQueryParameter).map(normalizeLoader).filter(Boolean).reduce((acc, x) => acc.indexOf(x) !== -1 ? acc : acc.concat(x), []); // webpack v2 does not auto-loads loaders with the `-loader` suffix
// but allows the user to set an array of suffixes
type TNormalizeRule = (r: string, e: ?Array<string>) => Array<string>;
const normalizeRule: TNormalizeRule = (rule, exts) => {
const normalizeRule = (rule, exts) => {
const loaders = [rule];
(exts || []).forEach(e => {
loaders.push([rule, e].join("-"));
});
return loaders;
};
type TGetRules = (
ds: Array<string>,
rs: ?Array<TRule>,
es: ?Array<string>
) => Array<string>;
const getRules: TGetRules = (deps, rules, exts) =>
(rules || [])
.map(extractLoaders)
.reduce((acc, x) => acc.concat(x), [])
.map(stripQueryParameter)
.map(rule => normalizeRule(rule, exts))
.reduce((acc, x) => acc.concat(x), [])
.filter(Boolean)
.reduce((acc, x) => (acc.includes(x) ? acc : acc.concat(x)), []);
const getRules = (deps, rules, exts) => (rules || []).map(extractLoaders).reduce((acc, x) => acc.concat(x), []).map(stripQueryParameter).map(rule => normalizeRule(rule, exts)).reduce((acc, x) => acc.concat(x), []).filter(Boolean).reduce((acc, x) => acc.indexOf(x) !== -1 ? acc : acc.concat(x), []);
const parser: TParser = (content, filename, deps, rootDir) => {
if (
path.basename(rootDir).includes("webpack-config") &&
path.extname(filename) === ".js"
) {
const parser = (content, filename, deps, rootDir) => {
if (_path.default.basename(rootDir).indexOf("webpack-config") !== -1 && _path.default.extname(filename) === ".js") {
// $FlowIgnore
const webpackConfig: TConfig = require(filename);
const module = webpackConfig.module || {};
const webpackConfig = require(filename);
// v1
const module = webpackConfig.module || {}; // v1
const loaders = getLoaders(deps, module.loaders);
const preLoaders = getLoaders(deps, module.preLoaders);
const postLoaders = getLoaders(deps, module.postLoaders);
const postLoaders = getLoaders(deps, module.postLoaders); // v2
// v2
const rules = getRules(
deps,
module.rules,
(webpackConfig.resolveLoader || {}).moduleExtensions
);
return rules
.concat(loaders)
.concat(preLoaders)
.concat(postLoaders);
const rules = getRules(deps, module.rules, (webpackConfig.resolveLoader || {}).moduleExtensions);
return rules.concat(loaders).concat(preLoaders).concat(postLoaders);
}

@@ -119,2 +64,4 @@

export default parser;
var _default = parser;
exports.default = _default;
module.exports = exports.default;
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