import * as ts from 'typescript' ; import * as tsconfigPaths from 'tsconfig-paths' ; import { FromWhat , STAR , getFrom } from './common' ; import { dirname , join , relative , resolve , sep } from 'path' ; import { Imports } from '../types' ; import { existsSync } from 'fs' ; import { isUnique } from './util' ; const EXTENSIONS = [ '.d.ts' , '.ts' , '.tsx' , '.js' , '.jsx' ] ; const relativeTo = ( rootDir , file , path ) : string => relative ( rootDir , resolve ( dirname ( file ) , path ) ) ; const isRelativeToBaseDir = ( baseDir , from ) : boolean => existsSync ( resolve ( baseDir , `${ from }.js` ) ) || existsSync ( resolve ( baseDir , `${ from }.ts` ) ) || existsSync ( resolve ( baseDir , `${ from }.d.ts` ) ) || existsSync ( resolve ( baseDir , `${ from }.tsx` ) ) || existsSync ( resolve ( baseDir , from , 'index.js' ) ) || existsSync ( resolve ( baseDir , from , 'index.ts' ) ) || existsSync ( resolve ( baseDir , from , 'index.tsx' ) ) ; export const extractImport = ( decl ) : FromWhat => { const from = getFrom ( decl . moduleSpecifier ) ; const { importClause } = decl ; if ( ! importClause ) return { from , what : STAR , } ; const { namedBindings } = importClause ; const importDefault = ! ! importClause . name ? [ 'default' ] : [ ] ; if ( ! namedBindings ) { return { from , what : importDefault , } ; } const isStar = ! ! ( namedBindings as ts . NamespaceImport ) . name ; const importNames = isStar ? STAR : ( namedBindings as ts . NamedImports ) . elements . map ( ( e ) => ( e . propertyName || e . name ) . text ) ; return { from , what : importDefault . concat ( importNames ) , } ; } ; const declarationFilePatch = ( matchedPath ) : string => { return matchedPath . endsWith ( '.d' ) && existsSync ( `${ matchedPath }.ts` ) ? matchedPath . slice ( 0 , - 2 ) : matchedPath ; } ; export const addImportCore = ( fw , rootDir , path , imports , baseDir , baseUrl , tsconfigPathsMatcher ? ) : string | undefined => { const { from , what } = fw ; const getKey = ( from ) : string => { if ( from [ 0 ] == '.' ) { return relativeTo ( rootDir , path , from ) || '.' ; } else { let matchedPath ; if ( isRelativeToBaseDir ( baseDir , from ) ) { return join ( baseUrl , from ) ; } if ( tsconfigPathsMatcher && ( matchedPath = tsconfigPathsMatcher ( from , undefined , undefined , EXTENSIONS ) ) ) { const absoluteRootDir = resolve ( rootDir ) ; return join ( declarationFilePatch ( matchedPath ) . replace ( `${ absoluteRootDir }${ sep }` , '' ) . replace ( `${ baseDir }${ sep }` , '' ) ) ; } return from ; } } ; const key = getKey ( from ) ; const items = imports [ key ] || [ ] ; imports [ key ] = items . concat ( what ) . filter ( isUnique ) ; return key ; } ;