UNPKG

ts-import-types-cli

Version:

Autofix TypeScript types to be imported using `import type`

157 lines (156 loc) 8.03 kB
"use strict"; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spread = (this && this.__spread) || function () { for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); return ar; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; exports.__esModule = true; exports.tsImportTypes = void 0; var chalk_1 = __importDefault(require("chalk")); var os_1 = require("os"); var path_1 = require("path"); var ts_morph_1 = require("ts-morph"); var info = function () { var messages = []; for (var _i = 0; _i < arguments.length; _i++) { messages[_i] = arguments[_i]; } console.log(chalk_1["default"].blue.apply(chalk_1["default"], __spread(['i'], messages))); }; var getRelativePath = function (sourceFile) { return path_1.relative(process.cwd(), sourceFile.getFilePath()); }; var getSourceFiles = function (sourcePatterns, project) { return sourcePatterns.length ? project.getSourceFiles(sourcePatterns) : project.getSourceFiles(); }; function tsImportTypes(_a) { var dryRun = _a.dryRun, organiseImports = _a.organiseImports, sourcePatterns = _a.sourcePatterns, tsConfigFilePath = _a.tsConfigFilePath; info('Analysing', path_1.relative(process.cwd(), tsConfigFilePath)); var project = new ts_morph_1.Project({ tsConfigFilePath: tsConfigFilePath }); var sourceFiles = getSourceFiles(sourcePatterns, project); var filesWithRewrittenDirectives = []; info('Found', sourceFiles.length, 'files'); sourceFiles.forEach(function (sourceFile, i) { try { var hasChanged_1 = false; var importDeclarations = sourceFile.getImportDeclarations(); var imports_1 = {}; var rewrittenImports_1 = []; var rewrittenDirectives_1 = []; sourceFile.getPathReferenceDirectives().forEach(function (directive) { rewrittenDirectives_1.push("/// <reference path=\"" + directive.getText() + "\" />"); }); sourceFile.getTypeReferenceDirectives().forEach(function (directive) { rewrittenDirectives_1.push("/// <reference type=\"" + directive.getText() + "\" />"); }); sourceFile.getLibReferenceDirectives().forEach(function (directive) { rewrittenDirectives_1.push("/// <reference lib=\"" + directive.getText() + "\" />"); }); /** import Default, { named1, named2 as alias } from './file' */ importDeclarations.forEach(function (importDeclaration) { /** Default */ var defaultImport = importDeclaration.getDefaultImport(); /** { named1, named2 as alias } */ var namedImports = importDeclaration.getNamedImports(); /** eg './file' or 'some-dependency' */ var modulePath = importDeclaration.getModuleSpecifierValue(); imports_1[modulePath] = imports_1[modulePath] || { codeImports: [], defaultImport: '', typeImports: [] }; if (defaultImport) { imports_1[modulePath].defaultImport = defaultImport.getText(); hasChanged_1 = true; } namedImports.forEach(function (namedImport) { var _a; /** import { named2 as alias } */ var alias = (_a = namedImport.getAliasNode()) === null || _a === void 0 ? void 0 : _a.getText(); var definitions = namedImport.getNameNode().getDefinitions(); /** determine whether this import is a type or an implementation */ definitions.forEach(function (definition) { var definitionName = definition.getName(); var finalName = alias ? definitionName + " as " + alias : definitionName; var definitionKind = definition.getKind(); if (['type', 'interface'].includes(definitionKind)) { hasChanged_1 = true; imports_1[modulePath].typeImports.push(finalName); } else { hasChanged_1 = true; imports_1[modulePath].codeImports.push(finalName); } }); }); if (hasChanged_1) { importDeclaration.remove(); } }); // write new imports for those we've collected and removed Object.entries(imports_1).forEach(function (_a) { var _b = __read(_a, 2), identifier = _b[0], _c = _b[1], codeImports = _c.codeImports, defaultImport = _c.defaultImport, typeImports = _c.typeImports; if (defaultImport && codeImports.length) { rewrittenImports_1.push("import " + defaultImport + ", { " + codeImports.join(', ') + " } from '" + identifier + "'"); } if (defaultImport && !codeImports.length) { rewrittenImports_1.push("import " + defaultImport + " from '" + identifier + "'"); } if (!defaultImport && codeImports.length) { rewrittenImports_1.push("import { " + codeImports.join(', ') + " } from '" + identifier + "'"); } if (typeImports.length) { rewrittenImports_1.push("import type { " + typeImports.join(', ') + " } from '" + identifier + "'"); } }); // nothing to do if (rewrittenImports_1.length === 0) { console.log(chalk_1["default"].gray('-', getRelativePath(sourceFile))); return; } console.log(chalk_1["default"].green('✓', getRelativePath(sourceFile))); if (rewrittenDirectives_1.length > 0) { filesWithRewrittenDirectives.push(getRelativePath(sourceFile)); console.log(chalk_1["default"].yellow('! contains triple-slash directives')); } sourceFile.insertText(0, rewrittenImports_1.join(os_1.EOL) + os_1.EOL + os_1.EOL); if (organiseImports !== false) { sourceFile.organizeImports(); } if (dryRun === true) { console.log(sourceFile.getText()); } else { sourceFile.saveSync(); } } catch (err) { console.log(chalk_1["default"].red('×', getRelativePath(sourceFile))); } }); console.log(''); console.log(chalk_1["default"].bgGreen.black(' Complete ')); console.log(''); if (filesWithRewrittenDirectives.length > 0) { console.log(chalk_1["default"].yellow(("\n* Moving triple-slash directives such as /// <reference lib=\"webworker\" /> back\n to the top of the file is not yet supported. If you know how to do this using\n https://ts-morph.com please open a PR or otherwise let me know.\n\n https://github.com/JamieMason/ts-import-types-cli/pulls\n\n Unfortunately until then, the following files will need their triple-slash\n directives manually moving back to the top of the file:\n" + filesWithRewrittenDirectives.map(function (filePath) { return "\n - " + filePath; }).join('') + "\n").trim())); } } exports.tsImportTypes = tsImportTypes;