Last active
May 3, 2022 17:00
-
-
Save cybersiddhu/1d877d07ca9f7c2d386fcb877262237b to your computer and use it in GitHub Desktop.
Functional pipeline to return markdown content from wiki
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"dependencies": { | |
"@isomorphic-git/lightning-fs": "~4.6.0", | |
"fp-ts": "~2.12.0", | |
"fp-ts-std": "~0.13.1", | |
"isomorphic-git": "~1.17.1", | |
"monocle-ts": "~2.3.13", | |
"newtype-ts": "~0.3.5", | |
"next": "12.1.5", | |
"react": "17.0.2", | |
"react-dom": "17.0.2", | |
"react-markdown": "~8.0.3" | |
}, |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { pipe, flow } from "fp-ts/lib/function" | |
import * as E from "fp-ts/lib/Either" | |
import * as TE from "fp-ts/lib/TaskEither" | |
import { clone } from "isomorphic-git" | |
import * as S from "fp-ts/string" | |
import { intercalate } from "fp-ts/Semigroup" | |
import http from "isomorphic-git/http/web" | |
import FS from "@isomorphic-git/lightning-fs" | |
export interface DirFileProps { | |
dir: string | |
file: string | |
url: string | |
browserFS: FS | |
} | |
export function cloneGithubWiki(props: DirFileProps) { | |
const defaultCloneParams = { | |
http: http, | |
fs: props.browserFS, | |
corsProxy: "https://cors.isomorphic-git.org", | |
} | |
const defaultSep = "/" | |
const wrapper = (props: DirFileProps) => TE.of(props) | |
const executeCloneRepo = ({ dir, url, file }: DirFileProps) => | |
TE.tryCatch(async () => { | |
await clone({ dir, url, ...defaultCloneParams }) | |
return { dir, url, file } as DirFileProps | |
}, E.toError) | |
// const errLogger = TE.fromIOK(Console.error) | |
// const infoLogger = TE.fromIOK(Console.info) | |
const errMsgExtract = (err: Error) => err.message | |
const addPath = ({ dir, file }: DirFileProps) => { | |
const pathDelimGroup = pipe(S.Semigroup, intercalate(defaultSep)) | |
return pathDelimGroup.concat(dir, file) | |
} | |
const readFileFromRepo = (path: string) => | |
TE.tryCatch(async () => { | |
const buffer = await props.browserFS.promises.readFile(path, { | |
encoding: "utf8", | |
}) | |
return buffer.toString() | |
}, E.toError) | |
const payload = flow( | |
wrapper, | |
TE.chain(executeCloneRepo), | |
// TE.chainFirstIOK(infoLogger), | |
TE.map(addPath), | |
// TE.chainFirstIOK(infoLogger), | |
TE.chain(readFileFromRepo), | |
// TE.chainFirstIOK(infoLogger), | |
TE.mapLeft(errMsgExtract), | |
) | |
return payload(props) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useRouter } from "next/router" | |
import { useState, useEffect, useMemo } from "react" | |
import * as E from "fp-ts/Either" | |
import * as TE from "fp-ts/TaskEither" | |
import { pipe } from "fp-ts/lib/function" | |
import { cloneGithubWiki } from "../../hooks/useGithubWiki" | |
import { toOutput, WikiContentEither } from "../../components/WikiDisplay" | |
import FS from "@isomorphic-git/lightning-fs" | |
export default function Gene() { | |
const router = useRouter() | |
const geneFile = `${router.query.id}.md` | |
const [content, setContent] = useState<WikiContentEither>( | |
E.right({ loading: true }), | |
) | |
const errSet = (err: string) => setContent(E.left(err)) | |
const contentSet = (cont: string) => | |
setContent(E.right({ markdown: cont, loading: false })) | |
const wikiFn = useMemo(() => { | |
return cloneGithubWiki({ | |
dir: "/wiki", | |
file: geneFile, | |
browserFS: new FS("github-wiki"), | |
url: "https://github.com/dictybase-playground/ontomania.wiki.git", | |
}) | |
}, [geneFile]) | |
useEffect(() => { | |
const prog = async (fn: TE.TaskEither<string, string>) => | |
pipe(await fn(), E.fold(errSet, contentSet)) | |
prog(wikiFn) | |
}, [wikiFn]) | |
return pipe(content, toOutput) | |
} | |
Gene.getInitialProps = () => ({ foo: "bar" }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// group of functions that maps the markdown content/error to the corresponding react component | |
import * as E from "fp-ts/Either" | |
import * as F from "fp-ts-std/Function" | |
import ReactMarkDown from "react-markdown" | |
interface WikiContentProps { | |
markdown?: string | |
loading: boolean | |
} | |
// type for Either monad | |
export type WikiContentEither = E.Either<string, WikiContentProps> | |
// predicate function that checks is the fetching is under process | |
const isLoading = (ma: WikiContentEither) => E.isRight(ma) && ma.right.loading | |
// predicate function to indicate if the fetching is completed | |
const isNotLoading = (ma: WikiContentEither) => | |
E.isRight(ma) && !ma.right.loading | |
// react component for loading state | |
const loaderDisplay = () => <h1>Loading....</h1> | |
// react component for error display | |
const errDisplay = (ma: WikiContentEither) => | |
E.isLeft(ma) && <h2>error {ma.left}</h2> | |
// react component for display markdown content | |
const nameDisplay = (ma: WikiContentEither) => | |
E.isRight(ma) && <ReactMarkDown>{ma.right.markdown as string}</ReactMarkDown> | |
// react component when something unexpected happened | |
const defaultDisplay = () => <h2>Not sure what happened</h2> | |
// this function maps three conditions, error,success or loading to a react component | |
export const toOutput = F.guard([ | |
[isLoading, loaderDisplay], | |
[E.isLeft, errDisplay], | |
[isNotLoading, nameDisplay], | |
])(defaultDisplay) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment