1 | "use strict";
|
2 | var __assign = (this && this.__assign) || function () {
|
3 | __assign = Object.assign || function(t) {
|
4 | for (var s, i = 1, n = arguments.length; i < n; i++) {
|
5 | s = arguments[i];
|
6 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
7 | t[p] = s[p];
|
8 | }
|
9 | return t;
|
10 | };
|
11 | return __assign.apply(this, arguments);
|
12 | };
|
13 | Object.defineProperty(exports, "__esModule", { value: true });
|
14 | exports.generateDtsBundle = void 0;
|
15 | var ts = require("typescript");
|
16 | var path = require("path");
|
17 | var compile_dts_1 = require("./compile-dts");
|
18 | var types_usage_evaluator_1 = require("./types-usage-evaluator");
|
19 | var typescript_1 = require("./helpers/typescript");
|
20 | var fix_path_1 = require("./helpers/fix-path");
|
21 | var module_info_1 = require("./module-info");
|
22 | var generate_output_1 = require("./generate-output");
|
23 | var logger_1 = require("./logger");
|
24 | function generateDtsBundle(entries, options) {
|
25 | if (options === void 0) { options = {}; }
|
26 | logger_1.normalLog('Compiling input files...');
|
27 | var _a = compile_dts_1.compileDts(entries.map(function (entry) { return entry.filePath; }), options.preferredConfigPath, options.followSymlinks), program = _a.program, rootFilesRemapping = _a.rootFilesRemapping;
|
28 | var typeChecker = program.getTypeChecker();
|
29 | var typeRoots = ts.getEffectiveTypeRoots(program.getCompilerOptions(), {});
|
30 | var sourceFiles = program.getSourceFiles().filter(function (file) {
|
31 | return !isSourceFileDefaultLibrary(program, file);
|
32 | });
|
33 | logger_1.verboseLog("Input source files:\n " + sourceFiles.map(function (file) { return file.fileName; }).join('\n '));
|
34 | var typesUsageEvaluator = new types_usage_evaluator_1.TypesUsageEvaluator(sourceFiles, typeChecker);
|
35 |
|
36 | return entries.map(function (entry) {
|
37 | logger_1.normalLog("Processing " + entry.filePath);
|
38 | var newRootFilePath = rootFilesRemapping.get(entry.filePath);
|
39 | if (newRootFilePath === undefined) {
|
40 | throw new Error("Cannot remap root source file " + entry.filePath);
|
41 | }
|
42 | var rootSourceFile = getRootSourceFile(program, newRootFilePath);
|
43 | var rootSourceFileSymbol = typeChecker.getSymbolAtLocation(rootSourceFile);
|
44 | if (rootSourceFileSymbol === undefined) {
|
45 | throw new Error("Symbol for root source file " + newRootFilePath + " not found");
|
46 | }
|
47 | var librariesOptions = entry.libraries || {};
|
48 | var criteria = {
|
49 | allowedTypesLibraries: librariesOptions.allowedTypesLibraries,
|
50 | importedLibraries: librariesOptions.importedLibraries,
|
51 | inlinedLibraries: librariesOptions.inlinedLibraries || [],
|
52 | typeRoots: typeRoots,
|
53 | };
|
54 | var rootFileExports = typescript_1.getExportsForSourceFile(typeChecker, rootSourceFileSymbol);
|
55 | var rootFileExportSymbols = rootFileExports.map(function (exp) { return exp.symbol; });
|
56 | var collectionResult = {
|
57 | typesReferences: new Set(),
|
58 | imports: new Map(),
|
59 | statements: [],
|
60 | renamedExports: [],
|
61 | };
|
62 | var outputOptions = entry.output || {};
|
63 | var updateResultCommonParams = {
|
64 | isStatementUsed: function (statement) { return isNodeUsed(statement, rootFileExportSymbols, typesUsageEvaluator, typeChecker); },
|
65 | shouldStatementBeImported: function (statement) {
|
66 | return shouldNodeBeImported(statement, rootFileExportSymbols, typesUsageEvaluator, typeChecker, isSourceFileDefaultLibrary.bind(null, program));
|
67 | },
|
68 | shouldDeclareGlobalBeInlined: function (currentModule) { return Boolean(outputOptions.inlineDeclareGlobals) && currentModule.type === 0 ; },
|
69 | shouldDeclareExternalModuleBeInlined: function () { return Boolean(outputOptions.inlineDeclareExternals); },
|
70 | getModuleInfo: function (fileName) { return module_info_1.getModuleInfo(fileName, criteria); },
|
71 | resolveIdentifier: function (identifier) {
|
72 | var symbol = getDeclarationNameSymbol(identifier, typeChecker);
|
73 | if (symbol === null) {
|
74 | return undefined;
|
75 | }
|
76 | var declarations = typescript_1.getDeclarationsForSymbol(symbol);
|
77 | if (declarations.length === 0) {
|
78 | return undefined;
|
79 | }
|
80 | var decl = declarations[0];
|
81 | if (!typescript_1.isNodeNamedDeclaration(decl)) {
|
82 | return undefined;
|
83 | }
|
84 | return decl.name;
|
85 | },
|
86 | getDeclarationsForExportedAssignment: function (exportAssignment) {
|
87 | var symbolForExpression = typeChecker.getSymbolAtLocation(exportAssignment.expression);
|
88 | if (symbolForExpression === undefined) {
|
89 | return [];
|
90 | }
|
91 | var symbol = typescript_1.getActualSymbol(symbolForExpression, typeChecker);
|
92 | return typescript_1.getDeclarationsForSymbol(symbol);
|
93 | },
|
94 | getDeclarationUsagesSourceFiles: function (declaration) {
|
95 | return getDeclarationUsagesSourceFiles(declaration, rootFileExportSymbols, typesUsageEvaluator, typeChecker);
|
96 | },
|
97 | areDeclarationSame: function (left, right) {
|
98 | var leftSymbols = typescript_1.splitTransientSymbol(getNodeSymbol(left, typeChecker), typeChecker);
|
99 | var rightSymbols = typescript_1.splitTransientSymbol(getNodeSymbol(right, typeChecker), typeChecker);
|
100 | return leftSymbols.some(function (leftSymbol) { return rightSymbols.includes(leftSymbol); });
|
101 | },
|
102 | };
|
103 | for (var _i = 0, sourceFiles_1 = sourceFiles; _i < sourceFiles_1.length; _i++) {
|
104 | var sourceFile = sourceFiles_1[_i];
|
105 | logger_1.verboseLog("\n\n======= Preparing file: " + sourceFile.fileName + " =======");
|
106 | var prevStatementsCount = collectionResult.statements.length;
|
107 | var updateFn = sourceFile === rootSourceFile ? updateResultForRootSourceFile : updateResult;
|
108 | var currentModule = module_info_1.getModuleInfo(sourceFile.fileName, criteria);
|
109 | var params = __assign(__assign({}, updateResultCommonParams), { currentModule: currentModule, statements: sourceFile.statements });
|
110 | updateFn(params, collectionResult);
|
111 |
|
112 | if (currentModule.type === 1 && updateResultCommonParams.isStatementUsed(sourceFile)) {
|
113 | updateImportsForStatement(sourceFile, params, collectionResult);
|
114 | }
|
115 | if (collectionResult.statements.length === prevStatementsCount) {
|
116 | logger_1.verboseLog("No output for file: " + sourceFile.fileName);
|
117 | }
|
118 | }
|
119 | if (entry.failOnClass) {
|
120 | var classes = collectionResult.statements.filter(ts.isClassDeclaration);
|
121 | if (classes.length !== 0) {
|
122 | var classesNames = classes.map(function (c) { return c.name === undefined ? 'anonymous class' : c.name.text; });
|
123 | throw new Error(classes.length + " class statement(s) are found in generated dts: " + classesNames.join(', '));
|
124 | }
|
125 | }
|
126 | return generate_output_1.generateOutput(__assign(__assign({}, collectionResult), { needStripDefaultKeywordForStatement: function (statement) {
|
127 | var statementExports = typescript_1.getExportsForStatement(rootFileExports, typeChecker, statement);
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 | return statementExports.find(function (exp) { return exp.exportedName === 'default'; }) === undefined;
|
134 | }, shouldStatementHasExportKeyword: function (statement) {
|
135 | var statementExports = typescript_1.getExportsForStatement(rootFileExports, typeChecker, statement);
|
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 | var result = statementExports.length === 0 || statementExports.find(function (exp) { return exp.exportedName === exp.symbol.escapedName; }) !== undefined;
|
142 | if (ts.isClassDeclaration(statement)
|
143 | || ts.isEnumDeclaration(statement)
|
144 | || ts.isFunctionDeclaration(statement)
|
145 | || ts.isVariableStatement(statement)) {
|
146 |
|
147 |
|
148 | result = result && statementExports.length !== 0;
|
149 | if (ts.isEnumDeclaration(statement)) {
|
150 |
|
151 | result = result || typescript_1.hasNodeModifier(statement, ts.SyntaxKind.ConstKeyword);
|
152 | }
|
153 | }
|
154 | else if (typescript_1.isAmbientModule(statement) || ts.isExportDeclaration(statement)) {
|
155 | result = false;
|
156 | }
|
157 | return result;
|
158 | }, needStripConstFromConstEnum: function (constEnum) {
|
159 | if (!program.getCompilerOptions().preserveConstEnums || !outputOptions.respectPreserveConstEnum) {
|
160 | return false;
|
161 | }
|
162 | var enumSymbol = getNodeSymbol(constEnum, typeChecker);
|
163 | if (enumSymbol === null) {
|
164 | return false;
|
165 | }
|
166 | return rootFileExportSymbols.includes(enumSymbol);
|
167 | } }), {
|
168 | sortStatements: outputOptions.sortNodes,
|
169 | umdModuleName: outputOptions.umdModuleName,
|
170 | noBanner: outputOptions.noBanner,
|
171 | });
|
172 | });
|
173 | }
|
174 | exports.generateDtsBundle = generateDtsBundle;
|
175 | var skippedNodes = [
|
176 | ts.SyntaxKind.ExportDeclaration,
|
177 | ts.SyntaxKind.ImportDeclaration,
|
178 | ts.SyntaxKind.ImportEqualsDeclaration,
|
179 | ];
|
180 |
|
181 | function updateResult(params, result) {
|
182 | for (var _i = 0, _a = params.statements; _i < _a.length; _i++) {
|
183 | var statement = _a[_i];
|
184 |
|
185 | if (skippedNodes.indexOf(statement.kind) !== -1) {
|
186 | continue;
|
187 | }
|
188 | if (typescript_1.isDeclareModuleStatement(statement)) {
|
189 | updateResultForModuleDeclaration(statement, params, result);
|
190 | continue;
|
191 | }
|
192 | if (params.currentModule.type === 3 ) {
|
193 | continue;
|
194 | }
|
195 | if (typescript_1.isDeclareGlobalStatement(statement) && params.shouldDeclareGlobalBeInlined(params.currentModule, statement)) {
|
196 | result.statements.push(statement);
|
197 | continue;
|
198 | }
|
199 | if (ts.isExportAssignment(statement) && statement.isExportEquals && params.currentModule.type === 1 ) {
|
200 | updateResultForImportedEqExportAssignment(statement, params, result);
|
201 | continue;
|
202 | }
|
203 | if (!params.isStatementUsed(statement)) {
|
204 | logger_1.verboseLog("Skip file member: " + statement.getText().replace(/(\n|\r)/g, '').slice(0, 50) + "...");
|
205 | continue;
|
206 | }
|
207 | switch (params.currentModule.type) {
|
208 | case 2 :
|
209 | addTypesReference(params.currentModule.typesLibraryName, result.typesReferences);
|
210 | break;
|
211 | case 1 :
|
212 | updateImportsForStatement(statement, params, result);
|
213 | break;
|
214 | case 0 :
|
215 | result.statements.push(statement);
|
216 | break;
|
217 | }
|
218 | }
|
219 | }
|
220 |
|
221 | function updateResultForRootSourceFile(params, result) {
|
222 | function isReExportFromImportableModule(statement) {
|
223 | if (!ts.isExportDeclaration(statement) || statement.moduleSpecifier === undefined || !ts.isStringLiteral(statement.moduleSpecifier)) {
|
224 | return false;
|
225 | }
|
226 | var moduleFileName = resolveModuleFileName(statement.getSourceFile().fileName, statement.moduleSpecifier.text);
|
227 | return params.getModuleInfo(moduleFileName).type === 1 ;
|
228 | }
|
229 | updateResult(params, result);
|
230 |
|
231 | for (var _i = 0, _a = params.statements; _i < _a.length; _i++) {
|
232 | var statement = _a[_i];
|
233 |
|
234 | var isExportAssignment = ts.isExportAssignment(statement);
|
235 | var isReExportFromImportable = isReExportFromImportableModule(statement);
|
236 | if (isExportAssignment || isReExportFromImportable) {
|
237 | result.statements.push(statement);
|
238 | }
|
239 |
|
240 | if (ts.isExportDeclaration(statement) && statement.exportClause !== undefined && ts.isNamedExports(statement.exportClause)) {
|
241 | for (var _b = 0, _c = statement.exportClause.elements; _b < _c.length; _b++) {
|
242 | var exportItem = _c[_b];
|
243 | if (exportItem.name.getText() === 'default' && exportItem.propertyName === undefined) {
|
244 |
|
245 |
|
246 |
|
247 | continue;
|
248 | }
|
249 | if (exportItem.propertyName !== undefined && exportItem.propertyName.getText() === 'default') {
|
250 | var resolvedIdentifier = params.resolveIdentifier(exportItem.propertyName);
|
251 |
|
252 | result.renamedExports.push(((resolvedIdentifier === null || resolvedIdentifier === void 0 ? void 0 : resolvedIdentifier.getText()) || '') + " as " + exportItem.name.getText());
|
253 | continue;
|
254 | }
|
255 |
|
256 | if (exportItem.propertyName !== undefined) {
|
257 | result.renamedExports.push(exportItem.getText());
|
258 | }
|
259 | }
|
260 | }
|
261 | }
|
262 | }
|
263 | function updateResultForImportedEqExportAssignment(exportAssignment, params, result) {
|
264 | var moduleDeclarations = params.getDeclarationsForExportedAssignment(exportAssignment)
|
265 | .filter(typescript_1.isNamespaceStatement)
|
266 | .filter(function (s) { return s.getSourceFile() === exportAssignment.getSourceFile(); });
|
267 |
|
268 |
|
269 |
|
270 | for (var _i = 0, moduleDeclarations_1 = moduleDeclarations; _i < moduleDeclarations_1.length; _i++) {
|
271 | var moduleDeclaration = moduleDeclarations_1[_i];
|
272 | if (moduleDeclaration.body === undefined || !ts.isModuleBlock(moduleDeclaration.body)) {
|
273 | continue;
|
274 | }
|
275 | updateResult(__assign(__assign({}, params), { statements: moduleDeclaration.body.statements }), result);
|
276 | }
|
277 | }
|
278 | function updateResultForModuleDeclaration(moduleDecl, params, result) {
|
279 | if (moduleDecl.body === undefined || !ts.isModuleBlock(moduleDecl.body)) {
|
280 | return;
|
281 | }
|
282 | var moduleName = moduleDecl.name.text;
|
283 | var moduleFileName = resolveModuleFileName(params.currentModule.fileName, moduleName);
|
284 | var moduleInfo = params.getModuleInfo(moduleFileName);
|
285 |
|
286 | if (!params.currentModule.isExternal && moduleInfo.isExternal) {
|
287 |
|
288 | if (params.shouldDeclareExternalModuleBeInlined()) {
|
289 | result.statements.push(moduleDecl);
|
290 | }
|
291 | return;
|
292 | }
|
293 | updateResult(__assign(__assign({}, params), { currentModule: moduleInfo, statements: moduleDecl.body.statements }), result);
|
294 | }
|
295 | function resolveModuleFileName(currentFileName, moduleName) {
|
296 | return moduleName.startsWith('.') ? fix_path_1.fixPath(path.join(currentFileName, '..', moduleName)) : "node_modules/" + moduleName + "/";
|
297 | }
|
298 | function addTypesReference(library, typesReferences) {
|
299 | if (!typesReferences.has(library)) {
|
300 | logger_1.normalLog("Library \"" + library + "\" will be added via reference directive");
|
301 | typesReferences.add(library);
|
302 | }
|
303 | }
|
304 | function updateImportsForStatement(statement, params, result) {
|
305 | if (params.currentModule.type !== 1 ) {
|
306 | return;
|
307 | }
|
308 | var statementsToImport = ts.isVariableStatement(statement) ? statement.declarationList.declarations : [statement];
|
309 | for (var _i = 0, statementsToImport_1 = statementsToImport; _i < statementsToImport_1.length; _i++) {
|
310 | var statementToImport = statementsToImport_1[_i];
|
311 | if (params.shouldStatementBeImported(statementToImport)) {
|
312 | addImport(statementToImport, params, result.imports);
|
313 | }
|
314 | }
|
315 | }
|
316 | function getDeclarationUsagesSourceFiles(declaration, rootFileExports, typesUsageEvaluator, typeChecker) {
|
317 | return new Set(getExportedSymbolsUsingStatement(declaration, rootFileExports, typesUsageEvaluator, typeChecker)
|
318 | .map(function (symbol) { return typescript_1.getDeclarationsForSymbol(symbol); })
|
319 | .reduce(function (acc, val) { return acc.concat(val); }, [])
|
320 | .map(function (declaration) { return declaration.getSourceFile(); }));
|
321 | }
|
322 | function addImport(statement, params, imports) {
|
323 | if (statement.name === undefined) {
|
324 | throw new Error("Import/usage unnamed declaration: " + statement.getText());
|
325 | }
|
326 | params.getDeclarationUsagesSourceFiles(statement).forEach(function (sourceFile) {
|
327 | sourceFile.statements
|
328 | .filter(ts.isImportDeclaration)
|
329 | .forEach(function (importDeclaration) {
|
330 | var importClause = importDeclaration.importClause;
|
331 | if (importClause === undefined) {
|
332 | return;
|
333 | }
|
334 | var importModuleSpecifier = importDeclaration.moduleSpecifier.text;
|
335 | var importItem = imports.get(importModuleSpecifier);
|
336 | if (importItem === undefined) {
|
337 | importItem = {
|
338 | defaultImports: new Set(),
|
339 | namedImports: new Set(),
|
340 | starImports: new Set(),
|
341 | };
|
342 | imports.set(importModuleSpecifier, importItem);
|
343 | }
|
344 | if (importClause.name !== undefined && params.areDeclarationSame(statement, importClause)) {
|
345 |
|
346 | importItem.defaultImports.add(importClause.name.text);
|
347 | }
|
348 | if (importClause.namedBindings !== undefined) {
|
349 | if (ts.isNamedImports(importClause.namedBindings)) {
|
350 |
|
351 | importClause.namedBindings.elements
|
352 | .filter(params.areDeclarationSame.bind(params, statement))
|
353 | .forEach(function (specifier) { return importItem.namedImports.add(specifier.getText()); });
|
354 | }
|
355 | else {
|
356 |
|
357 | importItem.starImports.add(importClause.namedBindings.name.getText());
|
358 | }
|
359 | }
|
360 | });
|
361 | });
|
362 | }
|
363 | function getRootSourceFile(program, rootFileName) {
|
364 | if (program.getRootFileNames().indexOf(rootFileName) === -1) {
|
365 | throw new Error("There is no such root file " + rootFileName);
|
366 | }
|
367 | var sourceFile = program.getSourceFile(rootFileName);
|
368 | if (sourceFile === undefined) {
|
369 | throw new Error("Cannot get source file for root file " + rootFileName);
|
370 | }
|
371 | return sourceFile;
|
372 | }
|
373 | function isNodeUsed(node, rootFileExports, typesUsageEvaluator, typeChecker) {
|
374 | if (typescript_1.isNodeNamedDeclaration(node)) {
|
375 | var nodeSymbol_1 = getNodeSymbol(node, typeChecker);
|
376 | if (nodeSymbol_1 === null) {
|
377 | return false;
|
378 | }
|
379 | return rootFileExports.some(function (rootExport) { return typesUsageEvaluator.isSymbolUsedBySymbol(nodeSymbol_1, rootExport); });
|
380 | }
|
381 | else if (ts.isVariableStatement(node)) {
|
382 | return node.declarationList.declarations.some(function (declaration) {
|
383 | return isNodeUsed(declaration, rootFileExports, typesUsageEvaluator, typeChecker);
|
384 | });
|
385 | }
|
386 | return false;
|
387 | }
|
388 | function shouldNodeBeImported(node, rootFileExports, typesUsageEvaluator, typeChecker, isDefaultLibrary) {
|
389 | var nodeSymbol = getNodeSymbol(node, typeChecker);
|
390 | if (nodeSymbol === null) {
|
391 | return false;
|
392 | }
|
393 | var symbolDeclarations = typescript_1.getDeclarationsForSymbol(nodeSymbol);
|
394 | var isSymbolDeclaredInDefaultLibrary = symbolDeclarations.some(function (declaration) { return isDefaultLibrary(declaration.getSourceFile()); });
|
395 | if (isSymbolDeclaredInDefaultLibrary) {
|
396 |
|
397 |
|
398 |
|
399 |
|
400 |
|
401 |
|
402 |
|
403 |
|
404 |
|
405 |
|
406 |
|
407 | return false;
|
408 | }
|
409 | return getExportedSymbolsUsingStatement(node, rootFileExports, typesUsageEvaluator, typeChecker).length !== 0;
|
410 | }
|
411 | function getExportedSymbolsUsingStatement(node, rootFileExports, typesUsageEvaluator, typeChecker) {
|
412 | var nodeSymbol = getNodeSymbol(node, typeChecker);
|
413 | if (nodeSymbol === null) {
|
414 | return [];
|
415 | }
|
416 | var symbolsUsingNode = typesUsageEvaluator.getSymbolsUsingSymbol(nodeSymbol);
|
417 | if (symbolsUsingNode === null) {
|
418 | throw new Error('Something went wrong - value cannot be null');
|
419 | }
|
420 |
|
421 | return Array.from(symbolsUsingNode).filter(function (symbol) {
|
422 | var symbolsDeclarations = typescript_1.getDeclarationsForSymbol(symbol);
|
423 | if (symbolsDeclarations.length === 0 || symbolsDeclarations.every(typescript_1.isDeclarationFromExternalModule)) {
|
424 | return false;
|
425 | }
|
426 | return rootFileExports.some(function (rootSymbol) { return typesUsageEvaluator.isSymbolUsedBySymbol(symbol, rootSymbol); });
|
427 | });
|
428 | }
|
429 | function isSourceFileDefaultLibrary(program, file) {
|
430 |
|
431 | return program.isSourceFileDefaultLibrary(file);
|
432 | }
|
433 | function getNodeSymbol(node, typeChecker) {
|
434 | var nodeName = node.name;
|
435 | if (nodeName === undefined) {
|
436 | return null;
|
437 | }
|
438 | return getDeclarationNameSymbol(nodeName, typeChecker);
|
439 | }
|
440 | function getDeclarationNameSymbol(name, typeChecker) {
|
441 | var symbol = typeChecker.getSymbolAtLocation(name);
|
442 | if (symbol === undefined) {
|
443 | return null;
|
444 | }
|
445 | return typescript_1.getActualSymbol(symbol, typeChecker);
|
446 | }
|