UNPKG

@repka-kit/ts

Version:

Next generation build tools for monorepo: lint, bundle and package your TypeScript projects

1,276 lines (1,253 loc) 534 kB
#!/usr/bin/env node 'use strict'; var ts = require('typescript'); var path = require('node:path'); var node_util = require('node:util'); var process$1 = require('node:process'); var fs = require('node:fs'); function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var ts__namespace = /*#__PURE__*/_interopNamespaceDefault(ts); var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path); var process__namespace = /*#__PURE__*/_interopNamespaceDefault(process$1); var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs); function verboseLog(message) { logMessage(message, 0 /* Verbose */); } function normalLog(message) { logMessage(message, 1 /* Normal */); } function warnLog(message) { logMessage(message, 2 /* Warning */); } function errorLog(message) { logMessage(message, 3 /* Error */); } let currentLogLevel = 3 /* Error */; function enableVerbose() { currentLogLevel = 0 /* Verbose */; normalLog("Verbose log enabled"); } function enableNormalLog() { currentLogLevel = 1 /* Normal */; } function logMessage(message, level = 0 /* Verbose */) { if (level < currentLogLevel) { return; } switch (level) { case 3 /* Error */: console.error(`\x1B[0;31m${message}\x1B[0m`); break; case 2 /* Warning */: console.warn(`\x1B[1;33m${message}\x1B[0m`); break; case 1 /* Normal */: case 0 /* Verbose */: console.log(message); } } function fixPath(path) { return path.replace(/\\/g, "/"); } function getAbsolutePath(fileName, cwd) { if (!path__namespace.isAbsolute(fileName)) { fileName = path__namespace.join(cwd !== void 0 ? cwd : process__namespace.cwd(), fileName); } return fixPath(fileName); } const formatDiagnosticsHost = { getCanonicalFileName: (fileName) => ts__namespace.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(), getCurrentDirectory: ts__namespace.sys.getCurrentDirectory, getNewLine: () => ts__namespace.sys.newLine }; function checkProgramDiagnosticsErrors(program) { checkDiagnosticsErrors(ts__namespace.getPreEmitDiagnostics(program), "Compiled with errors"); checkDiagnosticsErrors(program.getDeclarationDiagnostics(), "Compiled with errors"); } function checkDiagnosticsErrors(diagnostics, failMessage) { if (diagnostics.length === 0) { return; } errorLog(ts__namespace.formatDiagnostics(diagnostics, formatDiagnosticsHost).trim()); throw new Error(failMessage); } const parseConfigHost = { useCaseSensitiveFileNames: ts__namespace.sys.useCaseSensitiveFileNames, readDirectory: ts__namespace.sys.readDirectory, fileExists: ts__namespace.sys.fileExists, readFile: ts__namespace.sys.readFile }; function getCompilerOptions(opts) { const configFileName = opts.preferredConfigPath ? opts.preferredConfigPath : findConfig(opts); if (configFileName) { verboseLog(`Using config: ${configFileName}`); } if (opts.compilerOptions) { verboseLog(`Using custom compiler options ${node_util.format(opts.compilerOptions)}`); } if (!configFileName && !opts.compilerOptions) { throw new Error("No config file or compiler options specified in the options"); } const configParseResult = configFileName ? ts__namespace.readConfigFile(configFileName, ts__namespace.sys.readFile) : { config: { compilerOptions: opts.compilerOptions }, error: void 0 }; checkDiagnosticsErrors(configParseResult.error !== void 0 ? [configParseResult.error] : [], "Error while processing tsconfig file"); const compilerOptionsParseResult = ts__namespace.parseJsonConfigFileContent( configParseResult.config, parseConfigHost, configFileName ? path__namespace.resolve(path__namespace.dirname(configFileName)) : path__namespace.resolve(path__namespace.dirname(opts.inputFileNames[0])), void 0, configFileName ? getAbsolutePath(configFileName) : void 0 ); const diagnostics = compilerOptionsParseResult.errors.filter((d) => d.code !== 18003 /* NoInputsWereFoundDiagnosticCode */); checkDiagnosticsErrors(diagnostics, "Error while processing tsconfig compiler options"); return { ...compilerOptionsParseResult.options, ...opts.compilerOptions }; } function findConfig(opts) { if (!opts.compilerOptions) { if (opts.inputFileNames.length > 1) { throw new Error("Cannot find tsconfig for multiple files, please specify preferred tsconfig file"); } if (opts.inputFileNames.length <= 0) { throw new Error("No input files or preferred tsconfig in the options"); } } const searchPath = getAbsolutePath(opts.inputFileNames[0]); const configFileName = ts__namespace.findConfigFile(searchPath, ts__namespace.sys.fileExists); if (!configFileName && !opts.compilerOptions) { throw new Error(`Cannot find config file for file ${opts.inputFileNames[0]}`); } return configFileName; } const declarationExtsRemapping = { [ts__namespace.Extension.Js]: ts__namespace.Extension.Js, [ts__namespace.Extension.Jsx]: ts__namespace.Extension.Jsx, [ts__namespace.Extension.Json]: ts__namespace.Extension.Json, [ts__namespace.Extension.TsBuildInfo]: ts__namespace.Extension.TsBuildInfo, [ts__namespace.Extension.Mjs]: ts__namespace.Extension.Mjs, [ts__namespace.Extension.Cjs]: ts__namespace.Extension.Cjs, [ts__namespace.Extension.Ts]: ts__namespace.Extension.Dts, [ts__namespace.Extension.Tsx]: ts__namespace.Extension.Dts, [ts__namespace.Extension.Dts]: ts__namespace.Extension.Dts, [ts__namespace.Extension.Mts]: ts__namespace.Extension.Dmts, [ts__namespace.Extension.Dmts]: ts__namespace.Extension.Dmts, [ts__namespace.Extension.Cts]: ts__namespace.Extension.Dcts, [ts__namespace.Extension.Dcts]: ts__namespace.Extension.Dcts }; function compileDts(opts) { const rootFiles = opts.inputFileNames; const followSymlinks = opts.followSymlinks ?? true; const compilerOptions = getCompilerOptions(opts); compilerOptions.outDir = void 0; compilerOptions.incremental = void 0; compilerOptions.tsBuildInfoFile = void 0; compilerOptions.declarationDir = void 0; if (compilerOptions.composite) { warnLog(`Composite projects aren't supported at the time. Prefer to use non-composite project to generate declarations instead or just ignore this message if everything works fine. See https://github.com/timocov/dts-bundle-generator/issues/93`); compilerOptions.composite = void 0; } const dtsFiles = getDeclarationFiles(rootFiles, compilerOptions); verboseLog(`dts cache: ${Object.keys(dtsFiles).join("\n ")} `); const host = ts__namespace.createCompilerHost(compilerOptions); if (!followSymlinks) { host.realpath = (p) => p; } host.resolveModuleNameLiterals = (moduleLiterals, containingFile) => { return moduleLiterals.map((moduleLiteral) => { const resolvedModule = ts__namespace.resolveModuleName(moduleLiteral.text, containingFile, compilerOptions, host).resolvedModule; if (resolvedModule && !resolvedModule.isExternalLibraryImport) { const newExt = declarationExtsRemapping[resolvedModule.extension]; if (newExt !== resolvedModule.extension) { verboseLog(`Changing module from ${resolvedModule.extension} to ${newExt} for ${resolvedModule.resolvedFileName}`); resolvedModule.extension = newExt; resolvedModule.resolvedFileName = changeExtensionToDts(resolvedModule.resolvedFileName); } } return { resolvedModule }; }); }; const originalGetSourceFile = host.getSourceFile; host.getSourceFile = (fileName, languageVersion, onError) => { const absolutePath = getAbsolutePath(fileName); const storedValue = dtsFiles.get(absolutePath); if (storedValue !== void 0) { verboseLog(`dts cache match: ${absolutePath}`); return ts__namespace.createSourceFile(fileName, storedValue, languageVersion); } verboseLog(`dts cache mismatch: ${absolutePath} (${fileName})`); return originalGetSourceFile(fileName, languageVersion, onError); }; const rootFilesRemapping = /* @__PURE__ */ new Map(); const inputFiles = rootFiles.map((rootFile) => { const rootDtsFile = changeExtensionToDts(rootFile); rootFilesRemapping.set(rootFile, rootDtsFile); return rootDtsFile; }); const program = ts__namespace.createProgram(inputFiles, compilerOptions, host); checkProgramDiagnosticsErrors(program); warnAboutTypeScriptFilesInProgram(program); return { program, rootFilesRemapping }; } function changeExtensionToDts(fileName) { let ext; if (fileName.endsWith(ts__namespace.Extension.Dts)) { return fileName; } if (fileName.endsWith(ts__namespace.Extension.Cts)) { ext = ts__namespace.Extension.Cts; } else if (fileName.endsWith(ts__namespace.Extension.Mts)) { ext = ts__namespace.Extension.Mts; } else if (fileName.endsWith(ts__namespace.Extension.Ts)) { ext = ts__namespace.Extension.Ts; } else if (fileName.endsWith(ts__namespace.Extension.Tsx)) { ext = ts__namespace.Extension.Tsx; } if (ext === void 0) { return fileName; } return fileName.slice(0, -ext.length) + declarationExtsRemapping[ext]; } function getDeclarationFiles(rootFiles, compilerOptions) { compilerOptions = { ...compilerOptions, noEmit: false, declaration: true, emitDeclarationOnly: true }; const program = ts__namespace.createProgram(rootFiles, compilerOptions); const allFilesAreDeclarations = program.getSourceFiles().every((s) => s.isDeclarationFile); const declarations = /* @__PURE__ */ new Map(); if (allFilesAreDeclarations) { verboseLog("Skipping compiling the project to generate d.ts because all files in it are d.ts already"); return declarations; } checkProgramDiagnosticsErrors(program); const emitResult = program.emit( void 0, (fileName, data) => declarations.set(getAbsolutePath(fileName), data), void 0, true ); checkDiagnosticsErrors(emitResult.diagnostics, "Errors while emitting declarations"); return declarations; } function warnAboutTypeScriptFilesInProgram(program) { const nonDeclarationFiles = program.getSourceFiles().filter((file) => !file.isDeclarationFile); if (nonDeclarationFiles.length !== 0) { warnLog(`WARNING: It seems that some files in the compilation still are not declaration files. For more information see https://github.com/timocov/dts-bundle-generator/issues/53. If you think this is a mistake, feel free to open new issue or just ignore this warning. ${nonDeclarationFiles.map((file) => file.fileName).join("\n ")} `); } } const namedDeclarationKinds = [ ts__namespace.SyntaxKind.InterfaceDeclaration, ts__namespace.SyntaxKind.ClassDeclaration, ts__namespace.SyntaxKind.EnumDeclaration, ts__namespace.SyntaxKind.TypeAliasDeclaration, ts__namespace.SyntaxKind.ModuleDeclaration, ts__namespace.SyntaxKind.FunctionDeclaration, ts__namespace.SyntaxKind.VariableDeclaration, ts__namespace.SyntaxKind.PropertySignature ]; function isNodeNamedDeclaration(node) { return namedDeclarationKinds.indexOf(node.kind) !== -1; } function hasNodeModifier(node, modifier) { const modifiers = getModifiers(node); return Boolean(modifiers && modifiers.some((nodeModifier) => nodeModifier.kind === modifier)); } function getNodeName(node) { const nodeName = node.name; if (nodeName === void 0) { const modifiers = getModifiers(node); const defaultModifier = modifiers == null ? void 0 : modifiers.find((mod) => mod.kind === ts__namespace.SyntaxKind.DefaultKeyword); if (defaultModifier !== void 0) { return defaultModifier; } } return nodeName; } function getActualSymbol(symbol, typeChecker) { if (symbol.flags & ts__namespace.SymbolFlags.Alias) { symbol = typeChecker.getAliasedSymbol(symbol); } return symbol; } function getDeclarationNameSymbol(name, typeChecker) { const symbol = typeChecker.getSymbolAtLocation(name); if (symbol === void 0) { return null; } return getActualSymbol(symbol, typeChecker); } function splitTransientSymbol(symbol, typeChecker) { if ((symbol.flags & ts__namespace.SymbolFlags.Transient) === 0) { return [symbol]; } const declarations = getDeclarationsForSymbol(symbol); const result = []; for (const declaration of declarations) { if (!isNodeNamedDeclaration(declaration) || declaration.name === void 0) { continue; } const sym = typeChecker.getSymbolAtLocation(declaration.name); if (sym === void 0) { continue; } result.push(getActualSymbol(sym, typeChecker)); } return result; } function isGlobalScopeAugmentation(module) { return Boolean(module.flags & ts__namespace.NodeFlags.GlobalAugmentation); } function isAmbientModule(node) { return ts__namespace.isModuleDeclaration(node) && (node.name.kind === ts__namespace.SyntaxKind.StringLiteral || isGlobalScopeAugmentation(node)); } function isDeclareModule(node) { return ts__namespace.isModuleDeclaration(node) && !(node.flags & ts__namespace.NodeFlags.Namespace) && !isGlobalScopeAugmentation(node); } function isDeclareGlobalStatement(statement) { return ts__namespace.isModuleDeclaration(statement) && isGlobalScopeAugmentation(statement); } function isNamespaceStatement(node) { return ts__namespace.isModuleDeclaration(node) && Boolean(node.flags & ts__namespace.NodeFlags.Namespace); } function getDeclarationsForSymbol(symbol) { const result = []; if (symbol.declarations !== void 0) { result.push(...symbol.declarations); } if (symbol.valueDeclaration !== void 0) { if (!result.includes(symbol.valueDeclaration)) { result.push(symbol.valueDeclaration); } } return result; } function getExportsForSourceFile(typeChecker, sourceFileSymbol) { if (sourceFileSymbol.exports !== void 0) { const commonJsExport = sourceFileSymbol.exports.get(ts__namespace.InternalSymbolName.ExportEquals); if (commonJsExport !== void 0) { const symbol = getActualSymbol(commonJsExport, typeChecker); return [ { symbol, type: 0 /* CommonJS */, exportedName: "", originalName: symbol.escapedName } ]; } } const result = typeChecker.getExportsOfModule(sourceFileSymbol).map((symbol) => ({ symbol, exportedName: symbol.escapedName, type: 1 /* ES6Named */, originalName: "" })); if (sourceFileSymbol.exports !== void 0) { const defaultExportSymbol = sourceFileSymbol.exports.get(ts__namespace.InternalSymbolName.Default); if (defaultExportSymbol !== void 0) { const defaultExport = result.find((exp) => exp.symbol === defaultExportSymbol); if (defaultExport !== void 0) { defaultExport.type = 2 /* ES6Default */; } else { result.push({ symbol: defaultExportSymbol, type: 2 /* ES6Default */, exportedName: "default", originalName: "" }); } } } result.forEach((exp) => { exp.symbol = getActualSymbol(exp.symbol, typeChecker); const resolvedIdentifier = resolveIdentifierBySymbol(exp.symbol); exp.originalName = (resolvedIdentifier == null ? void 0 : resolvedIdentifier.name) !== void 0 ? resolvedIdentifier.name.getText() : exp.symbol.escapedName; }); return result; } function resolveIdentifier(typeChecker, identifier) { const symbol = getDeclarationNameSymbol(identifier, typeChecker); if (symbol === null) { return void 0; } return resolveIdentifierBySymbol(symbol); } function resolveIdentifierBySymbol(identifierSymbol) { const declarations = getDeclarationsForSymbol(identifierSymbol); if (declarations.length === 0) { return void 0; } const decl = declarations[0]; if (!isNodeNamedDeclaration(decl)) { return void 0; } return decl; } function getExportsForStatement(exportedSymbols, typeChecker, statement) { if (ts__namespace.isVariableStatement(statement)) { if (statement.declarationList.declarations.length === 0) { return []; } const firstDeclarationExports = getExportsForName( exportedSymbols, typeChecker, statement.declarationList.declarations[0].name ); const allDeclarationsHaveSameExportType = statement.declarationList.declarations.every((variableDecl) => { var _a, _b; return ((_a = getExportsForName(exportedSymbols, typeChecker, variableDecl.name)[0]) == null ? void 0 : _a.type) === ((_b = firstDeclarationExports[0]) == null ? void 0 : _b.type); }); if (!allDeclarationsHaveSameExportType) { return []; } return firstDeclarationExports; } const nodeName = getNodeName(statement); if (nodeName === void 0) { return []; } return getExportsForName(exportedSymbols, typeChecker, nodeName); } function getExportsForName(exportedSymbols, typeChecker, name) { if (ts__namespace.isArrayBindingPattern(name) || ts__namespace.isObjectBindingPattern(name)) { return []; } const declarationSymbol = typeChecker.getSymbolAtLocation(name); return exportedSymbols.filter((rootExport) => rootExport.symbol === declarationSymbol); } const modifiersPriority = { [ts__namespace.SyntaxKind.ExportKeyword]: 4, [ts__namespace.SyntaxKind.DefaultKeyword]: 3, [ts__namespace.SyntaxKind.DeclareKeyword]: 2, [ts__namespace.SyntaxKind.AsyncKeyword]: 1, [ts__namespace.SyntaxKind.ConstKeyword]: 1 }; function modifiersToMap(modifiers) { modifiers = modifiers || []; return modifiers.reduce( (result, modifier) => { result[modifier.kind] = true; return result; }, // eslint-disable-next-line @typescript-eslint/consistent-type-assertions {} ); } function modifiersMapToArray(modifiersMap) { return Object.entries(modifiersMap).filter(([kind, include]) => include).map(([kind]) => { return ts__namespace.factory.createModifier(Number(kind)); }).sort((a, b) => { const aValue = modifiersPriority[a.kind] || 0; const bValue = modifiersPriority[b.kind] || 0; return bValue - aValue; }); } function recreateRootLevelNodeWithModifiers(node, modifiersMap, newName, keepComments = true) { const newNode = recreateRootLevelNodeWithModifiersImpl(node, modifiersMap, newName); if (keepComments) { ts__namespace.setCommentRange(newNode, ts__namespace.getCommentRange(node)); } return newNode; } function recreateRootLevelNodeWithModifiersImpl(node, modifiersMap, newName) { const modifiers = modifiersMapToArray(modifiersMap); if (ts__namespace.isArrowFunction(node)) { return ts__namespace.factory.createArrowFunction( modifiers, node.typeParameters, node.parameters, node.type, node.equalsGreaterThanToken, node.body ); } if (ts__namespace.isClassDeclaration(node)) { return ts__namespace.factory.createClassDeclaration( modifiers, newName || node.name, node.typeParameters, node.heritageClauses, node.members ); } if (ts__namespace.isClassExpression(node)) { return ts__namespace.factory.createClassExpression( modifiers, newName || node.name, node.typeParameters, node.heritageClauses, node.members ); } if (ts__namespace.isEnumDeclaration(node)) { return ts__namespace.factory.createEnumDeclaration( modifiers, newName || node.name, node.members ); } if (ts__namespace.isExportAssignment(node)) { return ts__namespace.factory.createExportAssignment( modifiers, node.isExportEquals, node.expression ); } if (ts__namespace.isExportDeclaration(node)) { return ts__namespace.factory.createExportDeclaration( modifiers, node.isTypeOnly, node.exportClause, node.moduleSpecifier, node.assertClause ); } if (ts__namespace.isFunctionDeclaration(node)) { return ts__namespace.factory.createFunctionDeclaration( modifiers, node.asteriskToken, newName || node.name, node.typeParameters, node.parameters, node.type, node.body ); } if (ts__namespace.isFunctionExpression(node)) { return ts__namespace.factory.createFunctionExpression( modifiers, node.asteriskToken, newName || node.name, node.typeParameters, node.parameters, node.type, node.body ); } if (ts__namespace.isImportDeclaration(node)) { return ts__namespace.factory.createImportDeclaration( modifiers, node.importClause, node.moduleSpecifier, node.assertClause ); } if (ts__namespace.isImportEqualsDeclaration(node)) { return ts__namespace.factory.createImportEqualsDeclaration( modifiers, node.isTypeOnly, newName || node.name, node.moduleReference ); } if (ts__namespace.isInterfaceDeclaration(node)) { return ts__namespace.factory.createInterfaceDeclaration( modifiers, newName || node.name, node.typeParameters, node.heritageClauses, node.members ); } if (ts__namespace.isModuleDeclaration(node)) { return ts__namespace.factory.createModuleDeclaration( modifiers, node.name, node.body, node.flags ); } if (ts__namespace.isTypeAliasDeclaration(node)) { return ts__namespace.factory.createTypeAliasDeclaration( modifiers, newName || node.name, node.typeParameters, node.type ); } if (ts__namespace.isVariableStatement(node)) { return ts__namespace.factory.createVariableStatement( modifiers, node.declarationList ); } throw new Error(`Unknown top-level node kind (with modifiers): ${ts__namespace.SyntaxKind[node.kind]}. If you're seeing this error, please report a bug on https://github.com/timocov/dts-bundle-generator/issues`); } function getModifiers(node) { if (!ts__namespace.canHaveModifiers(node)) { return void 0; } return ts__namespace.getModifiers(node); } class TypesUsageEvaluator { typeChecker; nodesParentsMap = /* @__PURE__ */ new Map(); constructor(files, typeChecker) { this.typeChecker = typeChecker; this.computeUsages(files); } isSymbolUsedBySymbol(symbol, by) { return this.isSymbolUsedBySymbolImpl(this.getActualSymbol(symbol), this.getActualSymbol(by), /* @__PURE__ */ new Set()); } getSymbolsUsingSymbol(symbol) { return this.nodesParentsMap.get(this.getActualSymbol(symbol)) || null; } isSymbolUsedBySymbolImpl(fromSymbol, toSymbol, visitedSymbols) { if (fromSymbol === toSymbol) { return true; } const reachableNodes = this.nodesParentsMap.get(fromSymbol); if (reachableNodes !== void 0) { for (const symbol of Array.from(reachableNodes)) { if (visitedSymbols.has(symbol)) { continue; } visitedSymbols.add(symbol); if (this.isSymbolUsedBySymbolImpl(symbol, toSymbol, visitedSymbols)) { return true; } } } visitedSymbols.add(fromSymbol); return false; } computeUsages(files) { this.nodesParentsMap.clear(); for (const file of files) { ts__namespace.forEachChild(file, this.computeUsageForNode.bind(this)); } } computeUsageForNode(node) { if (isDeclareModule(node) && node.body !== void 0 && ts__namespace.isModuleBlock(node.body)) { for (const statement of node.body.statements) { this.computeUsageForNode(statement); } } if (isNodeNamedDeclaration(node) && node.name) { const childSymbol = this.getSymbol(node.name); this.computeUsagesRecursively(node, childSymbol); } if (ts__namespace.isVariableStatement(node)) { for (const varDeclaration of node.declarationList.declarations) { this.computeUsageForNode(varDeclaration); } } } computeUsagesRecursively(parent, parentSymbol) { const queue = parent.getChildren(); for (const child of queue) { if (child.kind === ts__namespace.SyntaxKind.JSDoc) { continue; } queue.push(...child.getChildren()); if (ts__namespace.isIdentifier(child)) { if (ts__namespace.isNamedTupleMember(child.parent) && child.parent.name === child) { continue; } if (ts__namespace.isBindingElement(child.parent) && child.parent.propertyName === child) { continue; } const childSymbols = splitTransientSymbol(this.getSymbol(child), this.typeChecker); for (const childSymbol of childSymbols) { let symbols = this.nodesParentsMap.get(childSymbol); if (symbols === void 0) { symbols = /* @__PURE__ */ new Set(); this.nodesParentsMap.set(childSymbol, symbols); } if (childSymbol !== parentSymbol) { symbols.add(parentSymbol); } } } } } getSymbol(node) { const nodeSymbol = this.typeChecker.getSymbolAtLocation(node); if (nodeSymbol === void 0) { throw new Error(`Cannot find symbol for node "${node.getText()}" in "${node.parent.getText()}" from "${node.getSourceFile().fileName}"`); } return this.getActualSymbol(nodeSymbol); } getActualSymbol(symbol) { return getActualSymbol(symbol, this.typeChecker); } } const nodeModulesFolderName = "node_modules/"; const libraryNameRegex = /node_modules\/((?:(?=@)[^/]+\/[^/]+|[^/]+))\//; function getLibraryName(fileName) { const lastNodeModulesIndex = fileName.lastIndexOf(nodeModulesFolderName); if (lastNodeModulesIndex === -1) { return null; } const match = libraryNameRegex.exec(fileName.slice(lastNodeModulesIndex)); if (match === null) { return null; } return match[1]; } function getTypesLibraryName(path) { const libraryName = getLibraryName(path); if (libraryName === null) { return null; } const typesFolderPrefix = "@types/"; if (!libraryName.startsWith(typesFolderPrefix)) { return null; } return libraryName.substring(typesFolderPrefix.length); } var ModuleType = /* @__PURE__ */ ((ModuleType2) => { ModuleType2[ModuleType2["ShouldBeInlined"] = 0] = "ShouldBeInlined"; ModuleType2[ModuleType2["ShouldBeImported"] = 1] = "ShouldBeImported"; ModuleType2[ModuleType2["ShouldBeReferencedAsTypes"] = 2] = "ShouldBeReferencedAsTypes"; ModuleType2[ModuleType2["ShouldBeUsedForModulesOnly"] = 3] = "ShouldBeUsedForModulesOnly"; return ModuleType2; })(ModuleType || {}); function getModuleInfo(fileName, criteria) { return getModuleInfoImpl(fileName, fileName, criteria); } function getModuleInfoImpl(currentFilePath, originalFileName, criteria) { const npmLibraryName = getLibraryName(currentFilePath); if (npmLibraryName === null) { if (criteria.typeRoots !== void 0) { for (const root of criteria.typeRoots) { const relativePath = fixPath(path__namespace.relative(root, originalFileName)); if (!relativePath.startsWith("../")) { return getModuleInfoImpl(remapToTypesFromNodeModules(relativePath), originalFileName, criteria); } } } return { type: 0 /* ShouldBeInlined */, fileName: originalFileName, isExternal: false }; } const typesLibraryName = getTypesLibraryName(currentFilePath); if (shouldLibraryBeInlined(npmLibraryName, typesLibraryName, criteria.inlinedLibraries)) { return { type: 0 /* ShouldBeInlined */, fileName: originalFileName, isExternal: true }; } if (shouldLibraryBeImported(npmLibraryName, typesLibraryName, criteria.importedLibraries, criteria.allowedTypesLibraries)) { return { type: 1 /* ShouldBeImported */, fileName: originalFileName, isExternal: true }; } if (typesLibraryName !== null && isLibraryAllowed(typesLibraryName, criteria.allowedTypesLibraries)) { return { type: 2 /* ShouldBeReferencedAsTypes */, fileName: originalFileName, typesLibraryName, isExternal: true }; } return { type: 3 /* ShouldBeUsedForModulesOnly */, fileName: originalFileName, isExternal: true }; } function shouldLibraryBeInlined(npmLibraryName, typesLibraryName, inlinedLibraries) { return isLibraryAllowed(npmLibraryName, inlinedLibraries) || typesLibraryName !== null && isLibraryAllowed(typesLibraryName, inlinedLibraries); } function shouldLibraryBeImported(npmLibraryName, typesLibraryName, importedLibraries, allowedTypesLibraries) { if (typesLibraryName === null) { return isLibraryAllowed(npmLibraryName, importedLibraries); } if (allowedTypesLibraries === void 0 || !isLibraryAllowed(typesLibraryName, allowedTypesLibraries)) { return isLibraryAllowed(typesLibraryName, importedLibraries); } return false; } function isLibraryAllowed(libraryName, allowedArray) { return allowedArray === void 0 || allowedArray.indexOf(libraryName) !== -1; } function remapToTypesFromNodeModules(pathRelativeToTypesRoot) { return `node_modules/@types/${pathRelativeToTypesRoot}`; } function packageVersion() { let dirName = __dirname; while (dirName.length !== 0) { const packageJsonFilePath = path__namespace.join(dirName, "package.json"); if (fs__namespace.existsSync(packageJsonFilePath)) { return require(packageJsonFilePath).version; } dirName = path__namespace.join(dirName, ".."); } throw new Error(`Cannot find up package.json in ${__dirname}`); } function generateOutput(params, options = {}) { let resultOutput = ""; if (!options.noBanner) { resultOutput += `// Generated by dts-bundle-generator v${packageVersion()} `; } if (params.typesReferences.size !== 0) { const header = generateReferenceTypesDirective(Array.from(params.typesReferences)); resultOutput += `${header} `; } if (params.imports.size !== 0) { const sortedEntries = Array.from(params.imports.entries()).sort((firstEntry, secondEntry) => { return firstEntry[0].localeCompare(secondEntry[0]); }); const importsArray = []; for (const [libraryName, libraryImports] of sortedEntries) { importsArray.push(...generateImports(libraryName, libraryImports)); } if (importsArray.length !== 0) { resultOutput += `${importsArray.join("\n")} `; } } const statements = params.statements.map((statement) => getStatementText( statement, Boolean(options.sortStatements), params )); if (options.sortStatements) { statements.sort(compareStatementText); } resultOutput += statementsTextToString(statements); if (params.renamedExports.length !== 0) { resultOutput += ` export { ${params.renamedExports.sort().join(",\n ")}, };`; } if (options.umdModuleName !== void 0) { resultOutput += ` export as namespace ${options.umdModuleName};`; } resultOutput += ` export {}; `; return resultOutput; } function statementsTextToString(statements) { const statementsText = statements.map((statement) => statement.text).join("\n"); return spacesToTabs(prettifyStatementsText(statementsText)); } function prettifyStatementsText(statementsText) { const sourceFile = ts__namespace.createSourceFile("output.d.ts", statementsText, ts__namespace.ScriptTarget.Latest, false, ts__namespace.ScriptKind.TS); const printer = ts__namespace.createPrinter( { newLine: ts__namespace.NewLineKind.LineFeed, removeComments: false } ); return printer.printFile(sourceFile).trim(); } function compareStatementText(a, b) { if (a.sortingValue > b.sortingValue) { return 1; } else if (a.sortingValue < b.sortingValue) { return -1; } return 0; } function getStatementText(statement, includeSortingValue, helpers) { const shouldStatementHasExportKeyword = helpers.shouldStatementHasExportKeyword(statement); const printer = ts__namespace.createPrinter( { newLine: ts__namespace.NewLineKind.LineFeed, removeComments: false }, { // eslint-disable-next-line complexity substituteNode: (hint, node) => { if (ts__namespace.isImportTypeNode(node) && node.qualifier !== void 0 && helpers.needStripImportFromImportTypeNode(node)) { if (node.isTypeOf) { return ts__namespace.factory.createTypeQueryNode(node.qualifier); } return ts__namespace.factory.createTypeReferenceNode(node.qualifier, node.typeArguments); } if (node !== statement) { return node; } const modifiersMap = modifiersToMap(getModifiers(node)); if (ts__namespace.isEnumDeclaration(node) && modifiersMap[ts__namespace.SyntaxKind.ConstKeyword] && helpers.needStripConstFromConstEnum(node)) { modifiersMap[ts__namespace.SyntaxKind.ConstKeyword] = false; } let newName; if (modifiersMap[ts__namespace.SyntaxKind.DefaultKeyword]) { const needStripDefaultKeywordResult = helpers.needStripDefaultKeywordForStatement(statement); if (needStripDefaultKeywordResult.needStrip) { modifiersMap[ts__namespace.SyntaxKind.DefaultKeyword] = false; if (ts__namespace.isClassDeclaration(node)) { modifiersMap[ts__namespace.SyntaxKind.DeclareKeyword] = true; } newName = needStripDefaultKeywordResult.newName; } } if (!shouldStatementHasExportKeyword) { modifiersMap[ts__namespace.SyntaxKind.ExportKeyword] = false; } else { modifiersMap[ts__namespace.SyntaxKind.ExportKeyword] = true; } if (!modifiersMap[ts__namespace.SyntaxKind.ExportKeyword] && (ts__namespace.isClassDeclaration(node) || ts__namespace.isFunctionDeclaration(node) || ts__namespace.isVariableStatement(node) || ts__namespace.isEnumDeclaration(node) || ts__namespace.isModuleDeclaration(node))) { modifiersMap[ts__namespace.SyntaxKind.DeclareKeyword] = true; } return recreateRootLevelNodeWithModifiers(node, modifiersMap, newName, shouldStatementHasExportKeyword); } } ); const statementText = printer.printNode(ts__namespace.EmitHint.Unspecified, statement, statement.getSourceFile()).trim(); let sortingValue = ""; if (includeSortingValue) { const tempSourceFile = ts__namespace.createSourceFile("temp.d.ts", statementText, ts__namespace.ScriptTarget.ESNext); sortingValue = tempSourceFile.getChildren()[0].getText(); } return { text: statementText, sortingValue }; } function generateImports(libraryName, imports) { const fromEnding = `from '${libraryName}';`; const result = []; Array.from(imports.starImports).sort().forEach((importName) => result.push(`import * as ${importName} ${fromEnding}`)); Array.from(imports.requireImports).sort().forEach((importName) => result.push(`import ${importName} = require('${libraryName}');`)); Array.from(imports.defaultImports).sort().forEach((importName) => result.push(`import ${importName} ${fromEnding}`)); if (imports.namedImports.size !== 0) { result.push(`import { ${Array.from(imports.namedImports).sort().join(", ")} } ${fromEnding}`); } return result; } function generateReferenceTypesDirective(libraries) { return libraries.sort().map((library) => { return `/// <reference types="${library}" />`; }).join("\n"); } function spacesToTabs(text) { return text.replace(/^( )+/gm, (substring) => { return " ".repeat(substring.length / 4); }); } function generateOutFileName(inputFilePath) { const inputFileName = path__namespace.parse(inputFilePath).name; return fixPath(path__namespace.join(inputFilePath, "..", inputFileName + ".d.ts")); } function generateAndSaveDtsBundle(bundlerConfig) { var _a; const generatedDts = generateDtsBundle(bundlerConfig.entries, bundlerConfig.compilationOptions); const outFilesToCheck = []; for (let i = 0; i < bundlerConfig.entries.length; ++i) { const entry = bundlerConfig.entries[i]; const outFile = entry.outFile !== void 0 ? entry.outFile : generateOutFileName(entry.filePath); normalLog(`Writing ${entry.filePath} -> ${outFile}`); ts__namespace.sys.writeFile(outFile, generatedDts[i]); if (!entry.noCheck) { outFilesToCheck.push(outFile); } } if (outFilesToCheck.length === 0) { normalLog("File checking is skipped (due nothing to check)"); return; } normalLog("Checking generated files..."); const preferredConfigPath = bundlerConfig.compilationOptions !== void 0 ? bundlerConfig.compilationOptions.preferredConfigPath : void 0; const compilerOptions = getCompilerOptions({ inputFileNames: outFilesToCheck, preferredConfigPath, compilerOptions: (_a = bundlerConfig.compilationOptions) == null ? void 0 : _a.compilerOptions }); if (compilerOptions.skipLibCheck) { compilerOptions.skipLibCheck = false; warnLog('Compiler option "skipLibCheck" is disabled to properly check generated output'); } const program = ts__namespace.createProgram(outFilesToCheck, compilerOptions); checkProgramDiagnosticsErrors(program); } function generateDtsBundle(entries, options = {}) { normalLog("Compiling input files..."); const { program, rootFilesRemapping } = compileDts({ inputFileNames: entries.map((entry) => entry.filePath), preferredConfigPath: options.preferredConfigPath, compilerOptions: options.compilerOptions, followSymlinks: options.followSymlinks }); const typeChecker = program.getTypeChecker(); const typeRoots = ts__namespace.getEffectiveTypeRoots(program.getCompilerOptions(), {}); const sourceFiles = program.getSourceFiles().filter((file) => { return !program.isSourceFileDefaultLibrary(file); }); verboseLog(`Input source files: ${sourceFiles.map((file) => file.fileName).join("\n ")}`); const typesUsageEvaluator = new TypesUsageEvaluator(sourceFiles, typeChecker); let uniqueNameCounter = 1; return entries.map((entry) => { normalLog(`Processing ${entry.filePath}`); const newRootFilePath = rootFilesRemapping.get(entry.filePath); if (newRootFilePath === void 0) { throw new Error(`Cannot remap root source file ${entry.filePath}`); } const rootSourceFile = getRootSourceFile(program, newRootFilePath); const rootSourceFileSymbol = typeChecker.getSymbolAtLocation(rootSourceFile); if (rootSourceFileSymbol === void 0) { throw new Error(`Symbol for root source file ${newRootFilePath} not found`); } const librariesOptions = entry.libraries || {}; const criteria = { allowedTypesLibraries: librariesOptions.allowedTypesLibraries, importedLibraries: librariesOptions.importedLibraries, inlinedLibraries: librariesOptions.inlinedLibraries || [], typeRoots }; const rootFileExports = getExportsForSourceFile(typeChecker, rootSourceFileSymbol); const rootFileExportSymbols = rootFileExports.map((exp) => exp.symbol); const collectionResult = { typesReferences: /* @__PURE__ */ new Set(), imports: /* @__PURE__ */ new Map(), statements: [], renamedExports: [], declarationsRenaming: /* @__PURE__ */ new Map() }; const outputOptions = entry.output || {}; const inlineDeclareGlobals = Boolean(outputOptions.inlineDeclareGlobals); const needStripDefaultKeywordForStatement = (statement) => { const statementExports = getExportsForStatement(rootFileExports, typeChecker, statement); const defaultExport = statementExports.find((exp) => exp.exportedName === "default"); return { needStrip: defaultExport === void 0 || defaultExport.originalName !== "default" && statement.getSourceFile() !== rootSourceFile, newName: isNodeNamedDeclaration(statement) ? collectionResult.declarationsRenaming.get(statement) : void 0 }; }; const updateResultCommonParams = { isStatementUsed: (statement) => isNodeUsed( statement, rootFileExportSymbols, typesUsageEvaluator, typeChecker, criteria, inlineDeclareGlobals ), shouldStatementBeImported: (statement) => { return shouldNodeBeImported( statement, rootFileExportSymbols, typesUsageEvaluator, typeChecker, program.isSourceFileDefaultLibrary.bind(program), criteria, inlineDeclareGlobals ); }, shouldDeclareGlobalBeInlined: (currentModule) => inlineDeclareGlobals && currentModule.type === ModuleType.ShouldBeInlined, shouldDeclareExternalModuleBeInlined: () => Boolean(outputOptions.inlineDeclareExternals), getModuleInfo: (fileNameOrModuleLike) => { if (typeof fileNameOrModuleLike !== "string") { return getModuleLikeInfo(fileNameOrModuleLike, criteria); } return getModuleInfo(fileNameOrModuleLike, criteria); }, resolveIdentifier: (identifier) => { var _a; const resolvedDeclaration = resolveIdentifier(typeChecker, identifier); if (resolvedDeclaration === void 0) { return void 0; } const storedValue = collectionResult.declarationsRenaming.get(resolvedDeclaration); if (storedValue !== void 0) { return storedValue; } let identifierName = (_a = resolvedDeclaration.name) == null ? void 0 : _a.getText(); if (hasNodeModifier(resolvedDeclaration, ts__namespace.SyntaxKind.DefaultKeyword) && resolvedDeclaration.name === void 0 && needStripDefaultKeywordForStatement(resolvedDeclaration).needStrip) { identifierName = `__DTS_BUNDLE_GENERATOR__GENERATED_NAME$${uniqueNameCounter++}`; collectionResult.declarationsRenaming.set(resolvedDeclaration, identifierName); } return identifierName; }, getDeclarationsForExportedAssignment: (exportAssignment) => { const symbolForExpression = typeChecker.getSymbolAtLocation(exportAssignment.expression); if (symbolForExpression === void 0) { return []; } const symbol = getActualSymbol(symbolForExpression, typeChecker); return getDeclarationsForSymbol(symbol); }, getDeclarationUsagesSourceFiles: (declaration) => { return getDeclarationUsagesSourceFiles( declaration, rootFileExportSymbols, typesUsageEvaluator, typeChecker, criteria, inlineDeclareGlobals ); }, areDeclarationSame: (left, right) => { const leftSymbols = splitTransientSymbol(getNodeSymbol(left, typeChecker), typeChecker); const rightSymbols = splitTransientSymbol(getNodeSymbol(right, typeChecker), typeChecker); return leftSymbols.some((leftSymbol) => rightSymbols.includes(leftSymbol)); }, resolveReferencedModule: (node) => { let moduleName; if (ts__namespace.isExportDeclaration(node) || ts__namespace.isImportDeclaration(node)) { moduleName = node.moduleSpecifier; } else if (ts__namespace.isModuleDeclaration(node)) { moduleName = node.name; } else if (ts__namespace.isImportEqualsDeclaration(node)) { if (ts__namespace.isExternalModuleReference(node.moduleReference)) { moduleName = node.moduleReference.expression; } } else if (ts__namespace.isLiteralTypeNode(node.argument) && ts__namespace.isStringLiteral(node.argument.literal)) { moduleName = node.argument.literal; } if (moduleName === void 0) { return null; } const moduleSymbol = typeChecker.getSymbolAtLocation(moduleName); if (moduleSymbol === void 0) { return null; } const symbol = getActualSymbol(moduleSymbol, typeChecker); if (symbol.valueDeclaration === void 0) { return null; } if (ts__namespace.isSourceFile(symbol.valueDeclaration) || ts__namespace.isModuleDeclaration(symbol.valueDeclaration)) { return symbol.valueDeclaration; } return null; } }; for (const sourceFile of sourceFiles) { verboseLog(` ======= Preparing file: ${sourceFile.fileName} =======`); const prevStatementsCount = collectionResult.statements.length; const updateFn = sourceFile === rootSourceFile ? updateResultForRootSourceFile : updateResult; const currentModule = getModuleInfo(sourceFile.fileName, criteria); const params = { ...updateResultCommonParams, currentModule, statements: sourceFile.statements }; updateFn(params, collectionResult); if (currentModule.type === ModuleType.ShouldBeImported && updateResultCommonParams.isStatementUsed(sourceFile)) { updateImportsForStatement(sourceFile, params, collectionResult); } if (collectionResult.statements.length === prevStatementsCount) { verboseLog(`No output for file: ${sourceFile.fileName}`); } } if (entry.failOnClass) { const classes = collectionResult.statements.filter(ts__namespace.isClassDeclaration); if (classes.length !== 0) { const classesNames = classes.map((c) => c.name === void 0 ? "anonymous class" : c.name.text); throw new Error(`${classes.length} class statement(s) are found in generated dts: ${classesNames.join(", ")}`); } } const exportReferencedTypes = outputOptions.exportReferencedTypes !== false; return generateOutput( { ...collectionResult, needStripDefaultKeywordForStatement, shouldStatementHasExportKeyword: (statement) => { const statementExports = getExportsForStatement(rootFileExports, typeChecker, statement); const hasStatementDefaultKeyword = hasNodeModifier(statement, ts__namespace.SyntaxKind.DefaultKeyword); let result = statementExports.length === 0 || statementExports.find((exp) => { const shouldBeDefaultExportedDirectly = exp.exportedName === "default" && hasStatementDefaultKeyword && statement.getSourceFile() === rootSourceFile; return shouldBeDefaultExportedDirectly || exp.exportedName === exp.originalName; }) !== void 0; const onlyDirectlyExportedShouldBeExported = !exportReferencedTypes || ts__namespace.isClassDeclaration(statement) || ts__namespace.isEnumDeclaration(statement) && !hasNodeModifier(statement, ts__namespace.SyntaxKind.ConstKeyword) || ts__namespace.isFunctionDeclaration(statement) || ts__namespace.isVariableStatement(statement) || ts__namespace.isModuleDeclaration(statement); if (onlyDirectlyExportedShouldBeExported) { result = result && statementExports.length !== 0; } else if (isAmbientModule(statement) || ts__namespace.isExportDeclaration(statement)) { result = false; } return result; }, needStripConstFromConstEnum: (constEnum) => { if (!program.getCompilerOptions().preserveConstEnums || !outputOptions.respectPreserveConstEnum) { return false; } const enumSymbol = getNodeSymbol(constEnum, typeChecker); if (enumSymbol === null) { return false; } return rootFileExportSymbols.includes(enumSymbol); }, needStripImportFromImportTypeNode: (node) => { if (node.qualifier === void 0) { return false; } if (!ts__namespace.isLiteralTypeNode(node.argument) || !ts__namespace.isStringLiteral(node.argument.literal)) { return false; } const resolvedModule = updateResultCommonParams.resolveReferencedModule(node); if (resolvedModule === null) { return false; } return updateResultCommonParams.getModuleInfo(resolvedModule).type === ModuleType.ShouldBeInlined; } }, { sortStatements: outputOptions.sortNodes, umdModuleName: outputOptions.umdModuleName, noBanner: outputOptions.noBanner } ); }); } const skippedNodes = [ ts__namespace.SyntaxKind.ExportDeclaration, ts__namespace.SyntaxKind.ImportDeclaration, ts__namespace.SyntaxKind.ImportEqualsDeclaration ]; function updateResult(params, result) { for (const statement of params.statements) { if (skippedNodes.indexOf(statement.kind) !== -1) { continue; } if (isDeclareModule(statement)) { updateResultForModuleDeclaration(statement, params, result); if (ts__namespace.isStringLiteral(statement.name)) { continue; } } if (params.currentModule.type === ModuleType.ShouldBeUsedForModulesOnly) { continue; } if (isDeclareGlobalStatement(statement) && params.shouldDeclareGlobalBeInlined(params.currentModule, statement)) { result.statements.push(statement); continue; } if (ts__namespace.isExportAssignment(statement) && statement.isExportEquals && params.currentModule.isExternal) { updateResultForExternalEqExportAssignment(statement, params, result); continue; } if (!params.isStatementUsed(statement)) { verboseLog(`Skip file member: ${statement.getText().replace(/(\n|\r)/g, "").slice(0, 50)}...`); continue; } switch (params.currentModule.type) { case ModuleType.ShouldBeReferencedAsTypes: addTypesReference(params.currentModule.typesLibraryName, result.typesReferences); break; case ModuleType.ShouldBeImported: updateImportsForStatement(statement, params, result); break; case ModuleType.ShouldBeInlined: result.statements.push(statement); break; } } } function updateResultForRootSourceFile(params, result) { function isReExportFromImportableModule(statement) { if (!ts__namespace.isExportDeclaration(statement)) { return false; } const resolvedModule = params.resolveReferencedModule(statement); if (resolvedModule === null) { return false; } return params.getModuleInfo(resolvedModule).type === ModuleType.ShouldBeImported; } updateResult(params, result); for (const statement of params.stat