dts-bundle-generator
Version:
DTS Bundle Generator
114 lines (113 loc) • 5.74 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var ts = require("typescript");
var compile_dts_1 = require("./compile-dts");
var types_usage_evaluator_1 = require("./types-usage-evaluator");
var logger_1 = require("./logger");
var skippedNodes = [
ts.SyntaxKind.ExportDeclaration,
ts.SyntaxKind.ExportAssignment,
ts.SyntaxKind.ImportDeclaration,
ts.SyntaxKind.ImportEqualsDeclaration,
];
function generateDtsBundle(filePath, options) {
if (options === void 0) { options = {}; }
if (!ts.sys.fileExists(filePath)) {
throw new Error("File \"" + filePath + "\" does not exist");
}
var program = compile_dts_1.compileDts(filePath);
var typeChecker = program.getTypeChecker();
// we do not need any types from node_modules dir
var sourceFiles = program.getSourceFiles().filter(function (file) { return file.fileName.indexOf('node_modules') === -1; });
var typesUsageEvaluator = new types_usage_evaluator_1.TypesUsageEvaluator(sourceFiles, typeChecker);
var rootSourceFileSymbol = typeChecker.getSymbolAtLocation(getRootSourceFile(program));
var rootFileExports = typeChecker.getExportsOfModule(rootSourceFileSymbol).map(function (symbol) {
if (symbol.flags & ts.SymbolFlags.Alias) {
// so we need to have original symbols from source file
symbol = typeChecker.getAliasedSymbol(symbol);
}
return symbol;
});
var resultOutput = '';
for (var _i = 0, sourceFiles_1 = sourceFiles; _i < sourceFiles_1.length; _i++) {
var sourceFile = sourceFiles_1[_i];
logger_1.verboseLog("\n\n======= Preparing file: " + sourceFile.fileName + " =======");
var fileOutput = '';
for (var _a = 0, _b = sourceFile.statements; _a < _b.length; _a++) {
var node = _b[_a];
// we should skip import and exports statements
if (skippedNodes.indexOf(node.kind) !== -1) {
continue;
}
var isNodeUsed = false;
if (types_usage_evaluator_1.isNodeDeclaration(node)) {
isNodeUsed = rootFileExports.some(typesUsageEvaluator.isTypeUsedBySymbol.bind(typesUsageEvaluator, node));
}
else if (node.kind === ts.SyntaxKind.VariableStatement) {
var declarations = node.declarationList.declarations;
isNodeUsed = declarations.some(isDeclarationExported.bind(null, rootFileExports, typeChecker));
}
if (!isNodeUsed) {
logger_1.verboseLog("Skip file member: " + node.getText().replace(/(\n|\r)/g, '').slice(0, 50) + "...");
continue;
}
var nodeText = node.getText();
var hasNodeExportKeyword = hasNodeModifier(node, ts.SyntaxKind.ExportKeyword);
if (node.kind === ts.SyntaxKind.ClassDeclaration || node.kind === ts.SyntaxKind.EnumDeclaration) {
if (options.failOnClass === true && node.kind === ts.SyntaxKind.ClassDeclaration) {
var classDecl = node;
var className = classDecl.name ? classDecl.name.text : '';
var errorMessage = "Class was found in generated dts.\n " + className + " from " + sourceFile.fileName;
throw new Error(errorMessage);
}
// not all classes and enums can be exported - only exported from root file
var shouldNodeHasExportKeyword = isDeclarationExported(rootFileExports, typeChecker, node);
if (node.kind === ts.SyntaxKind.EnumDeclaration) {
// but const enum always can be exported
shouldNodeHasExportKeyword = shouldNodeHasExportKeyword || hasNodeModifier(node, ts.SyntaxKind.ConstKeyword);
}
nodeText = getTextAccordingExport(nodeText, hasNodeExportKeyword, shouldNodeHasExportKeyword);
}
else {
nodeText = getTextAccordingExport(nodeText, hasNodeExportKeyword, true);
}
fileOutput += nodeText + "\n";
}
if (fileOutput.length === 0) {
logger_1.normalLog("No output for file: " + sourceFile.fileName);
}
if (options.outputFilenames) {
fileOutput = "// File: " + sourceFile.fileName + "\n\n" + fileOutput + "\n";
}
resultOutput += fileOutput;
}
return resultOutput;
}
exports.generateDtsBundle = generateDtsBundle;
function getRootSourceFile(program) {
var rootFiles = program.getRootFileNames();
if (rootFiles.length !== 1) {
logger_1.verboseLog("Root files:\n " + rootFiles.join('\n '));
throw new Error("There is not one root file - " + rootFiles.length);
}
return program.getSourceFile(rootFiles[0]);
}
function isDeclarationExported(exportedSymbols, typeChecker, declaration) {
if (!declaration.name) {
return false;
}
var declarationSymbol = typeChecker.getSymbolAtLocation(declaration.name);
return exportedSymbols.some(function (rootExport) { return rootExport === declarationSymbol; });
}
function getTextAccordingExport(nodeText, isNodeExported, shouldNodeBeExported) {
if (shouldNodeBeExported && !isNodeExported) {
return 'export ' + nodeText;
}
else if (isNodeExported && !shouldNodeBeExported) {
return nodeText.slice('export '.length);
}
return nodeText;
}
function hasNodeModifier(node, modifier) {
return Boolean(node.modifiers && node.modifiers.some(function (nodeModifier) { return nodeModifier.kind === modifier; }));
}