0

I'd like to ignore certain errors using fp-ts (if they happen, it means everything went well, i.e. missing account during signup process).

I have the following code:

export const handleSignup = async (server: FastifyInstance): Promise<void> => {
  server.post('/signup', async (req, res) => {
    const {email} = req.body as SignupPostData
    const {redirectUri} = req.query as Record<'redirectUri', string>

    return pipe(
      withDb(lookupAccountByEmail)(email),
      TE.chain(() => flow(generateMagicLinkToken, TE.fromEither)(email)),
      TE.chain(sendSignupEmail(email, redirectUri))
    )().then(foldReply<SignupApiResponse>(res))
  })
}

The lookupAccountByEmail function will either return an Account, or will return an error object. If an account is returned, I need to return an error with code 'account-exists'. If an error object with the code 'account-not-found' is returned, I'd like everything to continue as if there were no problem. If an error object with any other code is returned, it should still error.

What's the best way to handle this in fp-ts?

1 Answers1

2

You can use TE.fold.

const doSignup = pipe(
  generateMagicLinkToken(email),
  TE.fromEither,
  TE.chain(sendSignupEmail(email, redirectUri))
)
return pipe(
  email,
  withDb(lookupAccountByEmail),
  TE.fold(
    left => left.error === 'account-not-found' ? doSignup : TE.left(left)
    right => TE.left({error: 'account-exits'})
  ),
  T.map(foldReply<SignupApiResponse>(res))
)()
Dan Fey
  • 56
  • 1
  • 4
  • Thanks, this helped a ton! for the final bit, the foldReply basically returns an E.fold(). How can I change that to return a Task (so that it satisfies T.chain)? – Alexander Mattoni Sep 02 '20 at 00:16
  • 1
    Ah, I see the issue @AlexanderMattoni. Can you try T.map instead of T.chain? – Dan Fey Sep 03 '20 at 01:15
  • I tried T.map, unfortunately the fold that was returned did not get executed and I'm unsure why. Here is the signature: `export const foldReply = ( reply: FastifyReply, successCode?: number ): ((ma: E.Either) => void) => { return E.fold(replyWithError(reply), replyWithSuccess(reply, successCode)) }` – Alexander Mattoni Sep 03 '20 at 15:00
  • 1
    I think you need to add an invocation after the pipe. I'm going to update the answer above. I did my best to recreate your logic here. Please let me know if I'm missing anything. https://github.com/feydan/te-fold-example ``` ts-node example.ts undefined: call successful ``` – Dan Fey Sep 03 '20 at 20:55