如何使用 FP-TS 改进此打字稿代码?
How can I improve this typescript code using FP-TS?
我正在尝试使用 fp-ts 编写一些打字稿代码
算法应执行的任务如下:
从命令行接收路径应该
- 验证路径是否存在
- 搜索目录中的所有文件和 select 一个包含名称
cratb.import
和扩展名“.json”的文件 | “.yaml” | “.yml”
- if is ".json" 使用 js-yaml 包将纯文本解析为对象
JSON.parse
else if is ".yaml" 将纯文本解析为对象 YAML.load
这是我的主要代码:
if(FpFs.pathExists(targetPath)){
const res = await pipe(
FpFs.readDir(targetPath),
TE.map((files) =>
O.fromNullable(files.find(e => e === `${dFileName}.yaml` || e === `${dFileName}.yml` || e === `${dFileName}.json`))
),
TE.map(
O.map(fileName =>
['json', 'JSON', 'yaml', 'YAML', 'yml', 'YML'].includes(getFileExtension(fileName))
? O.fromNullable(fileName)
: O.fromNullable(null)
)
),
TE.map(O.flatten),
TE.map(
O.map(
fileName =>
['json', 'JSON'].includes(getFileExtension(fileName))
? pipe(
FpFs.readFile(path.join(targetPath, fileName)),
TE.map(x => JSON.parse(x.toString()))
)
: pipe(
FpFs.readFile(path.join(targetPath, fileName)),
TE.map(x => YAML.load(x.toString()))
)
)
)
)()
if(E.isRight(res)){
if(O.isSome(res.right)){
res.right.value()
.then(res => {
if(E.isRight(res)){
return console.log(res.right)
}
})
}
}
console.log('Error in some point XD')
}else{
console.log(color.red(['ERROR']), `directory "${ importFilePath }" not found`)
}
但我觉得这可能会更好
任何想法都会有所帮助
谢谢
经过更多的研究和 de community 的帮助,我想到了这个
helpers.ts
import * as O from 'fp-ts/lib/Option'
export const appendStrBefore = (appending: string) => (appended: string) => `${appending}${appended}`
export const isOneOfOptions =
(...options: string[]) =>
(searched: string) =>
options.includes(searched)
export const candidatesContainingSomeOfOptions =
(options: string[]) =>
(candidates: string[]): O.Option<string> => {
const result = options.reduce((prev, curr) => prev === '' ? candidates.includes(curr) ? curr : prev : prev, '')
return result === '' ? O.none : O.some(result)
}
export const getFileExtension = (fileName: string): string => {
const lastPeriod = fileName.lastIndexOf('.')
return fileName.substring(lastPeriod + 1, fileName.length)
}
主文件
(importFilePath = '', { test }) => {
const targetPath = path.join(process.cwd(), importFilePath)
const dFileName = 'cratb.import'
const extOptions = ['json', 'JSON', 'yaml', 'YAML', 'yml', 'YML']
const readFileAndParse =
(path: string) =>
(parser: Function) =>
pipe(
FpFs.readFile(path),
TE.map(x => parser(x.toString()))
)
FpFs.pathExists(targetPath)
? pipe(
FpFs.readDir(targetPath),
TE.map(
files => pipe(
extOptions.map(appendStrBefore(`${dFileName}.`)),
(candidates) => candidatesContainingSomeOfOptions(candidates)(files)
)
),
TE.map(
fileNameOption =>
O.isSome(fileNameOption)
? pipe(
readFileAndParse(path.join(targetPath, fileNameOption.value)),
parsing => parsing(
isOneOfOptions('json', 'JSON')(getFileExtension(fileNameOption.value)) //choose a parser
? JSON.parse
: YAML.load
),
)
: TE.of('File not found')
),
TE.fold(
err => T.of(handleFSError(err)),
TE.fold(
err => T.of(handleFSError(err)),
T.of
)
)
)().then(parseConfigObject)
: console.log(color.red(['ERROR']), `directory "${ importFilePath }" not found`)
现在我觉得更好
我正在尝试使用 fp-ts 编写一些打字稿代码
算法应执行的任务如下:
从命令行接收路径应该
- 验证路径是否存在
- 搜索目录中的所有文件和 select 一个包含名称
cratb.import
和扩展名“.json”的文件 | “.yaml” | “.yml” - if is ".json" 使用 js-yaml 包将纯文本解析为对象
JSON.parse
else if is ".yaml" 将纯文本解析为对象YAML.load
这是我的主要代码:
if(FpFs.pathExists(targetPath)){
const res = await pipe(
FpFs.readDir(targetPath),
TE.map((files) =>
O.fromNullable(files.find(e => e === `${dFileName}.yaml` || e === `${dFileName}.yml` || e === `${dFileName}.json`))
),
TE.map(
O.map(fileName =>
['json', 'JSON', 'yaml', 'YAML', 'yml', 'YML'].includes(getFileExtension(fileName))
? O.fromNullable(fileName)
: O.fromNullable(null)
)
),
TE.map(O.flatten),
TE.map(
O.map(
fileName =>
['json', 'JSON'].includes(getFileExtension(fileName))
? pipe(
FpFs.readFile(path.join(targetPath, fileName)),
TE.map(x => JSON.parse(x.toString()))
)
: pipe(
FpFs.readFile(path.join(targetPath, fileName)),
TE.map(x => YAML.load(x.toString()))
)
)
)
)()
if(E.isRight(res)){
if(O.isSome(res.right)){
res.right.value()
.then(res => {
if(E.isRight(res)){
return console.log(res.right)
}
})
}
}
console.log('Error in some point XD')
}else{
console.log(color.red(['ERROR']), `directory "${ importFilePath }" not found`)
}
但我觉得这可能会更好
任何想法都会有所帮助
谢谢
经过更多的研究和 de community 的帮助,我想到了这个
helpers.ts
import * as O from 'fp-ts/lib/Option'
export const appendStrBefore = (appending: string) => (appended: string) => `${appending}${appended}`
export const isOneOfOptions =
(...options: string[]) =>
(searched: string) =>
options.includes(searched)
export const candidatesContainingSomeOfOptions =
(options: string[]) =>
(candidates: string[]): O.Option<string> => {
const result = options.reduce((prev, curr) => prev === '' ? candidates.includes(curr) ? curr : prev : prev, '')
return result === '' ? O.none : O.some(result)
}
export const getFileExtension = (fileName: string): string => {
const lastPeriod = fileName.lastIndexOf('.')
return fileName.substring(lastPeriod + 1, fileName.length)
}
主文件
(importFilePath = '', { test }) => {
const targetPath = path.join(process.cwd(), importFilePath)
const dFileName = 'cratb.import'
const extOptions = ['json', 'JSON', 'yaml', 'YAML', 'yml', 'YML']
const readFileAndParse =
(path: string) =>
(parser: Function) =>
pipe(
FpFs.readFile(path),
TE.map(x => parser(x.toString()))
)
FpFs.pathExists(targetPath)
? pipe(
FpFs.readDir(targetPath),
TE.map(
files => pipe(
extOptions.map(appendStrBefore(`${dFileName}.`)),
(candidates) => candidatesContainingSomeOfOptions(candidates)(files)
)
),
TE.map(
fileNameOption =>
O.isSome(fileNameOption)
? pipe(
readFileAndParse(path.join(targetPath, fileNameOption.value)),
parsing => parsing(
isOneOfOptions('json', 'JSON')(getFileExtension(fileNameOption.value)) //choose a parser
? JSON.parse
: YAML.load
),
)
: TE.of('File not found')
),
TE.fold(
err => T.of(handleFSError(err)),
TE.fold(
err => T.of(handleFSError(err)),
T.of
)
)
)().then(parseConfigObject)
: console.log(color.red(['ERROR']), `directory "${ importFilePath }" not found`)
现在我觉得更好