Skip to content
This repository has been archived by the owner on Aug 7, 2020. It is now read-only.

[WIP] Use yargs #1

Merged
merged 3 commits into from Dec 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
@@ -1,9 +1,9 @@
# f2t
CLI tool for converting Flow code into Typescript
CLI tool for converting Flow code into Typescript

## Usage
```
$ f2t ./src
$ npx f2t ./src
```

## Dependency
Expand Down
11 changes: 8 additions & 3 deletions package.json
Expand Up @@ -5,7 +5,7 @@
"main": "dist/index.js",
"license": "MIT",
"scripts": {
"build": "rm -rf dist && tsc -w",
"build": "rm -rf dist && tsc",
"test": "echo \"Error: no test specified\" && exit 1"
},
"bin": {
Expand All @@ -30,16 +30,21 @@
"homepage": "https://github.com/nd-02110114/f2t#readme",
"dependencies": {
"@babel/core": "^7.1.2",
"@babel/plugin-syntax-object-rest-spread": "^7.0.0",
"@babel/plugin-syntax-class-properties": "^7.0.0",
"@babel/plugin-syntax-flow": "^7.0.0",
"@babel/plugin-syntax-jsx": "^7.0.0",
"@babel/plugin-syntax-object-rest-spread": "^7.0.0",
"@cureapp/babel-plugin-flow-to-typescript": "^0.3.7",
"prettier": "^1.14.3"
"chalk": "^2.4.1",
"ms": "^2.1.1",
"prettier": "^1.14.3",
"yargs": "^12.0.5"
},
"devDependencies": {
"@types/chalk": "^2.2.0",
"@types/node": "^10.11.7",
"@types/prettier": "^1.13.2",
"@types/yargs": "^12.0.1",
"tslint": "^5.11.0",
"typescript": "^3.1.3"
}
Expand Down
22 changes: 22 additions & 0 deletions src/args.ts
@@ -0,0 +1,22 @@
import * as yargs from "yargs";
// @ts-ignore
import * as pkg from "../package.json";

export type CLIOptions = {
input: string
}

const args = yargs
.version(pkg.version)
.option("input", {
alias: "i",
demandOption: true,
describe: "Set the directory path you want to convert",
type: "string",
})
.help("help")
.detectLocale(false)

const { _: [target], ...flags } = args.argv;

export { flags };
56 changes: 56 additions & 0 deletions src/cli.ts
@@ -0,0 +1,56 @@
#!/usr/bin/env node
import * as fs from 'fs'
import * as path from 'path'
import * as babel from '@babel/core'
import * as prettier from 'prettier'
import * as chalk from 'chalk'
import * as babelConfig from './config/.babelrc.js'
import * as prettierDefaultConfig from './config/.prettierrc.js'
import { walk, isJsxFile, deleteAtFlow } from './utils'
import { flags } from './args'

const fsThrowError = (err: NodeJS.ErrnoException) => {
if(err) throw err
}

// convert (babel, prettier, rename)
const converter = async (fullPath: string): Promise<void> => {
try {
const isJsFile = fullPath.match(/(js|jsx)$/)
if (isJsFile == null) {
return
}

const config = { cwd: path.join(__dirname, '../'), ...babelConfig }
// flow code is compiled by babel
const result = await babel.transformFileAsync(fullPath, config)
const babeledCode = result.code
const deletedAtFlowCode = deleteAtFlow(babeledCode)
// prettier
// @ts-ignore
const formattedCode = prettier.format(deletedAtFlowCode, prettierDefaultConfig)
fs.writeFile(fullPath, formattedCode, fsThrowError)
// js → ts,tsx
const extension = isJsxFile(formattedCode) ? 'tsx' : 'ts'
const newPath = fullPath.replace(/(js|jsx)$/, '') + extension
fs.rename(fullPath, newPath, fsThrowError)
const cwdPath = path.resolve('.')
console.log(`${path.relative(cwdPath, fullPath)} -> ${path.relative(cwdPath, newPath)}`)
} catch (e) {
throw e
}
}

// main process
const main = async () => {
const filePath = flags.input
const absPath = path.resolve(filePath)
await walk(absPath, converter)
// @ts-ignore
// console.log(chalk.bold.underline('\n🔥 Finish coverting from flow code to typescript!!'))
}

main().catch((e: Error) => {
// @ts-ignore
console.error(chalk.red(e.stack))
})
2 changes: 1 addition & 1 deletion src/babel.config.js → src/config/.babelrc.js
Expand Up @@ -4,7 +4,7 @@ module.exports = {
"@babel/plugin-syntax-class-properties",
"@babel/plugin-syntax-flow",
"@babel/plugin-syntax-jsx",
"./dist/babel-plugin-flow-to-typescript-react.js",
"./dist/babel-plugin-flow-to-typescript-react/index.js",
"@cureapp/babel-plugin-flow-to-typescript"
]
}
File renamed without changes.
92 changes: 0 additions & 92 deletions src/index.ts

This file was deleted.

47 changes: 47 additions & 0 deletions src/utils.ts
@@ -0,0 +1,47 @@
import * as fs from 'fs'
import * as path from 'path'

// judge whether the file is a jsx file or not
export const isJsxFile = (code: string): boolean => {
const lines = code.split('\n').filter((line: string) =>
line.match(/^\/\//) == null && line.match(/from ("|')react("|')/),
)
if (lines.length > 0) {
return true
}
return false
}

// delete @flow & $Flow
export const deleteAtFlow = (code: string): string => {
const lines = code.split('\n')
const newLines = lines.filter((line: string) => line.match(/(@flow|\$Flow)/) == null)
return newLines.join('\n')
}

// searching files recursively
// ref:https://qiita.com/amay077/items/cc6ee3e66040a5097230
type fileCallbackType = (path: string) => Promise<void>

export const walk = async (inputPath: string, fileCallback: fileCallbackType): Promise<void> => {
return await fs.readdir(inputPath, async (err, files) => {
if (err) {
throw err
}

await files.forEach(async (f: string) => {
try {
const fullPath = path.join(inputPath, f)
if (fs.statSync(fullPath).isDirectory()) {
// This recursion happens if the path indicates a directory
return await walk(fullPath, fileCallback)
} else {
return await fileCallback(fullPath)
}
} catch(e) {
throw e
}
})
})
}

5 changes: 4 additions & 1 deletion tsconfig.json
Expand Up @@ -4,15 +4,18 @@
"module": "commonjs",
"moduleResolution": "node",
"outDir": "./dist",
"lib": ["esnext"],
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noImplicitThis": true,
"alwaysStrict": true,
"noUnusedParameters": true,
"allowJs": true,
"baseUrl": "./src",
"baseUrl": ".",
"paths": {"@babel/core": ["types/base-core"]},
"typeRoots": ["types", "node_modules/@types"],
// "resolveJsonModule": true
},
"include": ["src"]
}