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

ts-unused-exports

Package Overview
Dependencies
Maintainers
1
Versions
59
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ts-unused-exports - npm Package Compare versions

Comparing version 6.1.2 to 6.2.0

11

CHANGELOG.md

@@ -0,1 +1,12 @@

## [6.2.0] - 11 May 2020
### Changed
- (Internal) Using TypeScript 3.8
### Added
- Handle dynamic imports within a TSX div or fragment
- Add basic support for export * as namespace.
## [6.1.2] - 1 Apr 2020

@@ -2,0 +13,0 @@

30

lib/analyzer.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var util_1 = require("./parser/util");
var isExportArray = function (e) {

@@ -39,6 +40,21 @@ return e.startsWith('[') && e.endsWith(']');

};
var processImportsOfExportedAsNamespace = function (file, exportMap) {
/* Basic support for export-as-namespace.
* If a file is exported as a namespace, and that namespace is imported,
* then we mark *all* exports of that file as used.
* A more accurate analysis would require scanning for all usages of the exports, via that namespace.
*/
file.pathsExportedAsNamespace.forEach(function (exportedAsNamespace) {
var _a;
var what = (_a = exportMap[exportedAsNamespace]) === null || _a === void 0 ? void 0 : _a.exports;
if (what) {
Object.keys(what).forEach(function (exported) { return what[exported].usageCount++; });
}
});
};
var processImports = function (file, exportMap) {
processImportsOfExportedAsNamespace(file, exportMap);
Object.keys(file.imports).forEach(function (key) {
var _a;
var ex = exportMap[key] && exportMap[key].exports;
var _a, _b;
var ex = (_a = exportMap[key]) === null || _a === void 0 ? void 0 : _a.exports;
// Handle imports from an index file

@@ -49,3 +65,3 @@ if (!ex && key === '.') {

var indexKey = indexCandidates[c];
ex = ((_a = exportMap[indexKey]) === null || _a === void 0 ? void 0 : _a.exports) || undefined;
ex = ((_b = exportMap[indexKey]) === null || _b === void 0 ? void 0 : _b.exports) || undefined;
if (ex)

@@ -92,3 +108,3 @@ break;

delete fileExports.exports[ex];
var exports = (_a = exportMap[ex.slice(2)]) === null || _a === void 0 ? void 0 : _a.exports;
var exports = (_a = exportMap[util_1.cleanRelativePath(ex)]) === null || _a === void 0 ? void 0 : _a.exports;
if (exports) {

@@ -121,7 +137,7 @@ Object.keys(exports)

var filterFiles = function (files, extraOptions) {
var _a, _b;
if (!((_a = extraOptions) === null || _a === void 0 ? void 0 : _a.ignoreFilesRegex)) {
var _a;
if (!(extraOptions === null || extraOptions === void 0 ? void 0 : extraOptions.ignoreFilesRegex)) {
return files;
}
var regexes = (_b = extraOptions.ignoreFilesRegex) === null || _b === void 0 ? void 0 : _b.map(function (rex) { return new RegExp(rex); });
var regexes = (_a = extraOptions.ignoreFilesRegex) === null || _a === void 0 ? void 0 : _a.map(function (rex) { return new RegExp(rex); });
var shouldIgnoreFile = function (fileName) {

@@ -128,0 +144,0 @@ return regexes.some(function (reg) {

@@ -16,3 +16,2 @@ "use strict";

var tsconfig = _a[0], tsFiles = _a.slice(1);
var _b, _c, _d;
if (!argsParser_1.hasValidArgs(showError, tsconfig, tsFiles)) {

@@ -33,3 +32,3 @@ showError(usage_1.USAGE);

var options = argsParser_1.extractOptionsFromFiles(tsFiles).options;
if ((_b = options) === null || _b === void 0 ? void 0 : _b.showLineNumber) {
if (options === null || options === void 0 ? void 0 : options.showLineNumber) {
files.forEach(function (path) {

@@ -46,7 +45,7 @@ analysis_1[path].forEach(function (unusedExport) {

}
if ((_c = options) === null || _c === void 0 ? void 0 : _c.exitWithCount) {
if (options === null || options === void 0 ? void 0 : options.exitWithCount) {
// Max allowed exit code is 127 (single signed byte)
return exitWith(Math.min(127, files.length));
}
var maxIssues = ((_d = options) === null || _d === void 0 ? void 0 : _d.maxIssues) || 0;
var maxIssues = (options === null || options === void 0 ? void 0 : options.maxIssues) || 0;
return exitWith(files.length <= maxIssues

@@ -53,0 +52,0 @@ ? ExitCode.NoUnusedExportsFound

@@ -6,4 +6,5 @@ import * as ts from 'typescript';

what: string[];
isExportStarAs?: boolean;
}
export declare const getFromText: (moduleSpecifier: string) => string;
export declare const getFrom: (moduleSpecifier: ts.Expression) => string;

@@ -5,2 +5,3 @@ "use strict";

var common_1 = require("./common");
var util_1 = require("./util");
var namespaceBlacklist_1 = require("./namespaceBlacklist");

@@ -15,27 +16,6 @@ // Parse Dynamic Imports

}
function isWithArguments(node) {
var myInterface = node;
return !!myInterface.arguments;
}
// A whitelist, to over-ride namespaceBlacklist.
//
// We need to search some structures that would not have a namespace.
var whitelist = [ts.SyntaxKind.MethodDeclaration];
var runForChildren = function (next, fun) {
next
.getChildren()
.filter(function (c) { return !namespaceBlacklist_1.namespaceBlacklist.includes(c.kind) || whitelist.includes(c.kind); })
.forEach(function (node) { return fun(node); });
};
var recurseIntoChildren = function (next, fun) {
var alsoProcessChildren = fun(next);
if (alsoProcessChildren) {
runForChildren(next, function (node) { return recurseIntoChildren(node, fun); });
}
return alsoProcessChildren;
};
var parseDereferencedLambdaParamsToTypes = function (paramName, lambda) {
var types = [];
var usagePrefix = paramName + ".";
recurseIntoChildren(lambda, function (child) {
util_1.recurseIntoChildren(lambda, function (child) {
if (child.getText().startsWith(usagePrefix)) {

@@ -82,39 +62,76 @@ var usage = child.getText().substring(usagePrefix.length);

};
recurseIntoChildren(node, function (child) {
if (child.kind === ts.SyntaxKind.ArrowFunction) {
processLambda(child);
var firstArrow = util_1.findFirstChildOfKind(node, ts.SyntaxKind.ArrowFunction);
if (firstArrow) {
processLambda(firstArrow);
}
return what;
};
var addImportViaLambda = function (node, from, addImport) {
var whatFromLambda = findLambdasWithDereferencing(node);
var what = ['default'].concat(whatFromLambda);
addImport({
from: common_1.getFromText(from),
what: what,
});
return whatFromLambda.length !== 0;
};
var tryParseExpression = function (expr, addImport) {
if (expr.getText().startsWith('import')) {
var callExpression = util_1.findFirstChildOfKind(expr, ts.SyntaxKind.CallExpression);
if (!(callExpression === null || callExpression === void 0 ? void 0 : callExpression.getText().startsWith('import'))) {
return false;
}
return true;
var syntaxListWithFrom = util_1.findFirstChildOfKind(callExpression, ts.SyntaxKind.SyntaxList);
if (!syntaxListWithFrom) {
return false;
}
var from = syntaxListWithFrom.getText();
return addImportViaLambda(expr, from, addImport);
}
return false;
};
var handleImportWithJsxAttributes = function (attributes, addImport) {
attributes.properties.forEach(function (prop) {
if (ts.isJsxAttribute(prop)) {
if (prop.initializer &&
ts.isJsxExpression(prop.initializer) &&
prop.initializer.expression) {
tryParseExpression(prop.initializer.expression, addImport);
}
}
});
return what;
};
var handleImportWithinExpression = function (node, addImport) {
var expr = node;
while (isWithExpression(expr)) {
var newExpr = expr.expression;
if (!tryParseExpression(newExpr, addImport)) {
if (ts.isJsxElement(newExpr) || ts.isJsxFragment(newExpr)) {
var jsxExpressions = util_1.findAllChildrenOfKind(newExpr, ts.SyntaxKind.JsxExpression);
jsxExpressions.forEach(function (j) {
var jsxExpr = j;
if (jsxExpr.expression) {
tryParseExpression(jsxExpr.expression, addImport);
}
});
}
var selfClosingElements = util_1.findAllChildrenOfKind(newExpr, ts.SyntaxKind.JsxSelfClosingElement);
selfClosingElements.forEach(function (elem) {
if (ts.isJsxSelfClosingElement(elem)) {
handleImportWithJsxAttributes(elem.attributes, addImport);
}
});
}
if (isWithExpression(newExpr)) {
expr = newExpr;
}
else {
break;
}
}
};
exports.addDynamicImports = function (node, addImport) {
var addImportsInAnyExpression = function (node) {
var getArgumentFrom = function (node) {
if (isWithArguments(node)) {
return node.arguments[0].getText();
}
};
if (isWithExpression(node)) {
var expr = node;
while (isWithExpression(expr)) {
var newExpr = expr.expression;
if (newExpr.getText() === 'import') {
var importing = getArgumentFrom(expr);
if (!!importing) {
var what = ['default'].concat(findLambdasWithDereferencing(node));
addImport({
from: common_1.getFromText(importing),
what: what,
});
}
}
if (isWithExpression(newExpr)) {
expr = newExpr;
}
else {
break;
}
}
handleImportWithinExpression(node, addImport); // can be a ParenthesizedExpression with a JSX element inside it
}

@@ -124,4 +141,4 @@ return true;

// Recurse, since dynamic imports can occur at nested levels within the code
recurseIntoChildren(node, addImportsInAnyExpression);
util_1.recurseIntoChildren(node, addImportsInAnyExpression);
};
//# sourceMappingURL=dynamic.js.map
import * as ts from 'typescript';
import { LocationInFile, ExtraCommandLineOptions } from '../types';
import { ExtraCommandLineOptions, LocationInFile } from '../types';
import { FromWhat } from './common';

@@ -4,0 +4,0 @@ export declare const extractExportStatement: (decl: ts.ExportDeclaration) => string[];

@@ -7,5 +7,17 @@ "use strict";

var extractAliasFirstFromElements = function (elements) { return elements.map(function (e) { return e.name.text; }); };
var extractPropertyOrAliasFirstFromElements = function (elements) { return elements.map(function (e) { return (e.propertyName || e.name).text; }); };
var extractFromBindingsWith = function (bindings, extract) {
if (ts.isNamedExports(bindings))
return extract(bindings.elements);
return [bindings.name.text];
};
var extractAliasFirstFromBindings = function (bindings) {
return extractFromBindingsWith(bindings, extractAliasFirstFromElements);
};
var extractPropertyOrAliasFromBindings = function (bindings) {
return extractFromBindingsWith(bindings, extractPropertyOrAliasFirstFromElements);
};
exports.extractExportStatement = function (decl) {
return decl.exportClause
? extractAliasFirstFromElements(decl.exportClause.elements)
? extractAliasFirstFromBindings(decl.exportClause)
: [];

@@ -17,7 +29,7 @@ };

? // The alias 'name' or the original type is exported
extractAliasFirstFromElements(exportClause.elements)
extractAliasFirstFromBindings(exportClause)
: common_1.STAR;
var whatImported = exportClause
? // The original type 'propertyName' is imported
exportClause.elements.map(function (e) { return (e.propertyName || e.name).text; })
extractPropertyOrAliasFromBindings(exportClause)
: common_1.STAR;

@@ -32,2 +44,3 @@ return {

what: whatImported,
isExportStarAs: (exportClause === null || exportClause === void 0 ? void 0 : exportClause.kind) === ts.SyntaxKind.NamespaceExport,
},

@@ -65,4 +78,3 @@ };

var shouldNodeTypeBeIgnored = function (node, extraOptions) {
var _a;
var allowUnusedTypes = !!((_a = extraOptions) === null || _a === void 0 ? void 0 : _a.allowUnusedTypes);
var allowUnusedTypes = !!(extraOptions === null || extraOptions === void 0 ? void 0 : extraOptions.allowUnusedTypes);
if (!allowUnusedTypes)

@@ -69,0 +81,0 @@ return false;

@@ -0,3 +1,3 @@

import * as ts from 'typescript';
import * as tsconfigPaths from 'tsconfig-paths';
import * as ts from 'typescript';
import { FromWhat } from './common';

@@ -4,0 +4,0 @@ import { Imports } from '../types';

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var common_1 = require("./common");
var path_1 = require("path");
var fs_1 = require("fs");
var common_1 = require("./common");
var util_1 = require("./util");

@@ -7,0 +7,0 @@ // Parse Imports

@@ -8,2 +8,3 @@ "use strict";

var import_1 = require("./import");
var util_1 = require("./util");
var comment_1 = require("./comment");

@@ -29,3 +30,7 @@ var nodeProcessor_1 = require("./nodeProcessor");

var tsconfigPathsMatcher = (!!paths && tsconfigPaths.createMatchPath(baseDir, paths)) || undefined;
var pathsExportedAsNamespace = [];
var addImport = function (fw) {
if (fw.isExportStarAs) {
pathsExportedAsNamespace.push(util_1.cleanRelativePath(fw.from));
}
return import_1.addImportCore(fw, rootDir, path, imports, baseDir, baseUrl, tsconfigPathsMatcher);

@@ -48,2 +53,3 @@ };

exportLocations: exportLocations,
pathsExportedAsNamespace: pathsExportedAsNamespace,
};

@@ -57,4 +63,3 @@ };

var baseUrl = _a.baseUrl, filePaths = _a.files, paths = _a.paths;
var _b;
var includeDeclarationFiles = !((_b = extraOptions) === null || _b === void 0 ? void 0 : _b.excludeDeclarationFiles);
var includeDeclarationFiles = !(extraOptions === null || extraOptions === void 0 ? void 0 : extraOptions.excludeDeclarationFiles);
var files = filePaths

@@ -61,0 +66,0 @@ .filter(function (p) { return includeDeclarationFiles || !p.includes('.d.'); })

@@ -45,5 +45,4 @@ "use strict";

.forEach(function (name) {
var _a;
addExport(namespace.namespace + name, node);
if ((_a = extraOptions) === null || _a === void 0 ? void 0 : _a.searchNamespaces) {
if (extraOptions === null || extraOptions === void 0 ? void 0 : extraOptions.searchNamespaces) {
// performance: halves the time taken on large codebase (150k loc)

@@ -68,3 +67,2 @@ var isNamespace = node

if (namespace === void 0) { namespace = ''; }
var _a;
var kind = node.kind;

@@ -92,3 +90,3 @@ var processSubNode = function (subNode, namespace) {

// so for performance should only be done when necessary.
if ((_a = extraOptions) === null || _a === void 0 ? void 0 : _a.searchNamespaces) {
if (extraOptions === null || extraOptions === void 0 ? void 0 : extraOptions.searchNamespaces) {
imports_from_namespace_1.addImportsFromNamespace(node, imports, addImport);

@@ -95,0 +93,0 @@ }

@@ -0,1 +1,6 @@

import ts = require('typescript');
export declare function isUnique<T>(value: T, index: number, self: T[]): boolean;
export declare function cleanRelativePath(path: string): string;
export declare function recurseIntoChildren(next: ts.Node, fun: (node: ts.Node) => boolean): boolean;
export declare function findAllChildrenOfKind(node: ts.Node, kind: ts.SyntaxKind): ts.Node[];
export declare function findFirstChildOfKind(node: ts.Node, kind: ts.SyntaxKind): ts.Node | null;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ts = require("typescript");
var namespaceBlacklist_1 = require("./namespaceBlacklist");
function isUnique(value, index, self) {

@@ -7,2 +9,56 @@ return self.indexOf(value) === index;

exports.isUnique = isUnique;
function cleanRelativePath(path) {
return path.slice(2);
}
exports.cleanRelativePath = cleanRelativePath;
// A whitelist, to over-ride namespaceBlacklist.
//
// We need to search some structures that would not have a namespace.
var whitelist = [
ts.SyntaxKind.MethodDeclaration,
ts.SyntaxKind.PropertyAssignment,
ts.SyntaxKind.JsxElement,
ts.SyntaxKind.JsxSelfClosingElement,
];
function runForChildren(next, fun) {
next
.getChildren()
.filter(function (c) { return !namespaceBlacklist_1.namespaceBlacklist.includes(c.kind) || whitelist.includes(c.kind); })
.forEach(function (node) {
fun(node);
});
}
function recurseIntoChildren(next, fun) {
var alsoProcessChildren = fun(next);
if (alsoProcessChildren) {
runForChildren(next, function (node) { return recurseIntoChildren(node, fun); });
}
return alsoProcessChildren;
}
exports.recurseIntoChildren = recurseIntoChildren;
function findAllChildrenOfKind(node, kind) {
var childrenFound = [];
var innerFindFirstChildOfKind = function (childNode) {
if (childNode.kind === kind) {
childrenFound.push(childNode);
}
return true;
};
recurseIntoChildren(node, innerFindFirstChildOfKind);
return childrenFound;
}
exports.findAllChildrenOfKind = findAllChildrenOfKind;
function findFirstChildOfKind(node, kind) {
var childFound = null;
var innerFindFirstChildOfKind = function (childNode) {
if (!childFound && childNode.kind === kind) {
childFound = childNode;
return false;
}
return true;
};
recurseIntoChildren(node, innerFindFirstChildOfKind);
return childFound;
}
exports.findFirstChildOfKind = findFirstChildOfKind;
//# sourceMappingURL=util.js.map

@@ -10,2 +10,3 @@ export interface Imports {

exportLocations: LocationInFile[];
pathsExportedAsNamespace: string[];
}

@@ -12,0 +13,0 @@ export interface LocationInFile {

{
"name": "ts-unused-exports",
"version": "6.1.2",
"version": "6.2.0",
"description": "ts-unused-exports finds unused exported symbols in your Typescript project",

@@ -42,14 +42,14 @@ "main": "lib/app.js",

"@istanbuljs/nyc-config-typescript": "^1.0.1",
"@types/node": "^13.1.6",
"@typescript-eslint/eslint-plugin": "^2.15.0",
"@typescript-eslint/parser": "^2.15.0",
"codecov": "^3.6.1",
"coveralls": "^3.0.9",
"@types/node": "^13.9.8",
"@typescript-eslint/eslint-plugin": "^2.26.0",
"@typescript-eslint/parser": "^2.26.0",
"codecov": "^3.6.5",
"coveralls": "^3.0.11",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.9.0",
"eslint-config-prettier": "^6.10.1",
"eslint-plugin-prettier": "^3.1.2",
"nyc": "^15.0.0",
"pickled-cucumber": "^2.0.13",
"pickled-cucumber": "^2.0.14",
"prettier": "^1.19.1",
"ts-node": "^8.6.1"
"ts-node": "^8.8.1"
},

@@ -59,4 +59,4 @@ "dependencies": {

"tsconfig-paths": "^3.9.0",
"typescript": "^3.7.4"
"typescript": "^3.8.3"
}
}

@@ -62,3 +62,3 @@ # ts-unused-exports

| `exitWithCount` | Set the process exit code to be the count of files that have unused exports. | `--exitWithCount` |
| `ignoreFiles` | Ignore files with filenames that match the given regex. Use this to exclude groups of files - for example test files and their utilities. | `--ignoreFiles=\.(spec|test)` |
| `ignoreFiles` | Ignore files with filenames that match the given regex. Use this to exclude groups of files - for example test files and their utilities. | `--ignoreFiles=.*spec` |
| `ignoreProductionFiles` | Only scan **test** files (so ignore non-test 'production' files). | `--ignoreProductionFiles` |

@@ -65,0 +65,0 @@ | `ignoreTestFiles` | Only scan **production** files (ignore all test files, like `spec.ts(x)` or `test.ts(x)` or `TestUtils.ts`). Use this to detect production code that is only used in tests (so is dead code). Note: this will NOT detect unused exports in test code - for that, you can run `ts-unused-exports` separately with the `--ignoreProductionFiles` option. | `--ignoreTestFiles` |

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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