UNPKG

ntts

Version:

A CLI tool for refactoring an existing NodeJs application to a fully functional TypeScript application.

144 lines (133 loc) 5.39 kB
import { BindingElement, Identifier, ImportDeclaration, Node, ObjectBindingPattern, SourceFile, SyntaxKind, } from 'ts-morph'; import VariableNameGenerator from '../variable-name-generator/variable-name-generator'; import ImportFinder from '../import-finder/import-finder'; class ImportCreator { static addEmptyImport = (moduleSpecifier: string, sourceFile: SourceFile) => { const importDeclaration = sourceFile.getImportDeclaration(moduleSpecifier); if (!importDeclaration) { sourceFile.addImportDeclaration({ moduleSpecifier }); } }; static addSimpleImport = (importName: string, moduleSpecifier: string, sourceFile: SourceFile): string => { const importDeclaration = ImportFinder.getNonNamespaceImportDeclaration(moduleSpecifier, sourceFile); const defaultImport = importDeclaration?.getDefaultImport()?.getText(); if (importDeclaration && defaultImport) { return defaultImport; } if (importDeclaration && !defaultImport) { importDeclaration.setDefaultImport(importName); return importName; } sourceFile.addImportDeclaration({ defaultImport: importName, moduleSpecifier, }); return importName; }; static addNamedImport = (importName: string, moduleSpecifier: string, usedNames: string[], sourceFile: SourceFile): string => { const importDeclaration = ImportFinder.getNonNamespaceImportDeclaration(moduleSpecifier, sourceFile); const importSpecifier = importDeclaration?.getNamedImports().find((named) => importName === named.getName()); if (importDeclaration && importSpecifier) { return importSpecifier.getAliasNode()?.getText() || importSpecifier.getName(); } const newImportName = VariableNameGenerator.getUsableVariableName(importName, usedNames); const namedImport = newImportName === importName ? importName : `${importName} as ${newImportName}`; if (importDeclaration) { importDeclaration.addNamedImport(namedImport); return newImportName; } sourceFile.addImportDeclaration({ namedImports: [namedImport], moduleSpecifier, }); return newImportName; }; static addImport = (nameNode: ObjectBindingPattern | Identifier, moduleSpecifier: string, sourceFile: SourceFile) => { const importDeclaration = ImportFinder.getNonNamespaceImportDeclaration(moduleSpecifier, sourceFile); if (Node.isIdentifier(nameNode)) { this.addDefaultImportStatement(importDeclaration, nameNode, moduleSpecifier, sourceFile); } else { this.addNamedImportStatement(importDeclaration, nameNode, moduleSpecifier, sourceFile); } }; static addNamespaceImport = (importName: string, moduleSpecifier: string, sourceFile: SourceFile): string => { sourceFile.addImportDeclaration({ namespaceImport: importName, moduleSpecifier, }); return importName; }; private static getPropertyName = (element: BindingElement): string | undefined => { const nameNode = element.getPropertyNameNode(); if (Node.isIdentifier(nameNode)) { return nameNode.getText(); } if (Node.isStringLiteral(nameNode)) { return nameNode.getLiteralValue(); } if (Node.isComputedPropertyName(nameNode)) { const literal = nameNode.getFirstChildByKind(SyntaxKind.StringLiteral) || nameNode.getFirstChildByKind(SyntaxKind.NoSubstitutionTemplateLiteral); return literal?.getLiteralValue(); } return undefined; }; private static getNamedImports = (objectBinding: ObjectBindingPattern): string[] => objectBinding .getElements() .map((binding) => { const propertyName = this.getPropertyName(binding); const bindingName = binding.getNameNode().getText(); if (propertyName) { return `${propertyName} as ${bindingName}`; } return bindingName; }); private static addNamedImportStatement = ( importDeclaration: ImportDeclaration | undefined, objectBinding: ObjectBindingPattern, moduleSpecifier: string, sourceFile: SourceFile, ) => { const existingNamedImports = importDeclaration?.getNamedImports().map((named) => named.getNameNode().getText()); const namedImports = this.getNamedImports(objectBinding); if (namedImports.length <= 0) { return; } else if (importDeclaration && existingNamedImports) { const filteredImports = namedImports.filter((named) => !existingNamedImports.includes(named)); importDeclaration.addNamedImports(filteredImports); } else if (importDeclaration && !existingNamedImports) { importDeclaration.addNamedImports(namedImports); } else { sourceFile.addImportDeclaration({ namedImports, moduleSpecifier, }); } }; private static addDefaultImportStatement = ( importDeclaration: ImportDeclaration | undefined, identifier: Identifier, moduleSpecifier: string, sourceFile: SourceFile, ) => { const defaultImport = importDeclaration?.getDefaultImport()?.getText(); if (importDeclaration && defaultImport) { identifier.rename(defaultImport); } else if (importDeclaration && !defaultImport) { importDeclaration.setDefaultImport(identifier.getText()); } else { sourceFile.addImportDeclaration({ defaultImport: identifier.getText(), moduleSpecifier, }); } }; } export default ImportCreator;