// See flow-to-typescript-codemod.sh for documentation type FileInfo = { path: string; source: string } export const parser = 'flow' function logger(fileInfo: FileInfo, msg, node) { const lineInfo = node && node.value.loc ? ` line ${node.value.loc.start.line}` : '' console.warn(`warning: (${fileInfo.path}${lineInfo}) ${msg}`) } export default function flowToTypeScript(fileInfo: FileInfo, api: any, options: any) { const j = api.jscodeshift const ast = j(fileInfo.source) const logWarning = (msg: string, node: any) => logger(fileInfo, msg, node) const transforms = [ function updateFunctionTypeParams() { ast.find(j.FunctionTypeParam, { name: null }).forEach((p: any) => { p.value.name = j.identifier('arg') }) }, function fixDuplicateImports() { const fileToImportCount = {} const fileToSpecifiers = {} ast.find(j.ImportDeclaration).forEach((p: any) => { const file = p.value.source.value if (!(file in fileToSpecifiers)) { fileToSpecifiers[file] = [] } fileToSpecifiers[file] = [...fileToSpecifiers[file], ...p.value.specifiers] if (!(file in fileToImportCount)) { fileToImportCount[file] = 0 } else { p.prune() } fileToImportCount[file] += 1 }) Object.keys(fileToImportCount).map(file => { if (fileToImportCount[file] > 1) { ast.find(j.ImportDeclaration, { source: { value: file } }).forEach((p: any) => { p.value.specifiers = fileToSpecifiers[file] }) } }) }, function removeExactTypes() { ast.find(j.ObjectTypeAnnotation, { exact: true }).forEach((p: any) => { p.value.exact = false p.value.inexact = true }) }, ] transforms.forEach(t => t()) return ast.toSource({ arrowParensAlways: true, flowObjectCommas: true, quote: 'single', }) }