fp-ts: functions inside pipe are getting skipped

58 views Asked by At

I am new to function programming and I am running into strange behavior. I am calling a function containing a tryCatch function within a pipe function for fp-ts. It appears as if the function containing the tryCatch is never actually called even though, with breakpoints, I am making it to the next line, past the function containing the tryCatch, just not inside the tryCatch function or the chain or the fold as well.

Additionally, if I isolate this function and call it like validateRegistrationForm(user) to a console.log it seems to print a function instead of a return value. For the examples I found online, it seems as if tryCatch return a TaskEither and not a function.

What am I doing wrong syntactically to create this issue and how can I fix it?

Here is an example of the function in the pipe where the tryCatch is never called:

const validateRegistrationForm = (user: User): TaskEither<Error, User> => tryCatch(
    async () => {
        const schema = Joi.object().keys({
            userName: Joi.string().min(4).max(255).required(),
            firstName: Joi.string().pattern(new RegExp(/^[a-z\d\-_\s]+$/i)).min(1).max(50).required(),
            lastName: Joi.string().pattern(new RegExp(/^[a-z\d\-_\s]+$/i)).min(1).max(50).required(),
            emailAddress: Joi.string().email().required(),
            password: Joi.alternatives().try(Joi.string(), Joi.number()).required(),
            confirmPassword: Joi.alternatives().try(Joi.string(), Joi.number()).disallow(Joi.ref('password')).required()
        });

        // If post exists, wrap it in a 'some', otherwise return 'none'
        let {error} = await schema.validateAsync(user);

        if (error && error.length > 0)
            throw new ValidationError(error.message);

        return user;
    },
    (reason: any) => reason instanceof Error ? reason : new Error(reason.message)
);

Here is the function containing the pipe and chain:

const createUser = (user: User): TaskEither<Error, User> => {
    return pipe(
        user,    
        validateRegistrationForm, 
        chain((validContent: User) => {  <-- the breakpoint goes here and stops
            const user: User = {
                confirmPassword: validContent.confirmPassword,
                firstName: validContent.firstName,
                lastName: validContent.lastName,
                emailAddress: validContent.emailAddress,
                password: validContent.password,
                userName: validContent.userName
            };

            return repository.saveUser(user);
        })
    );
};

Here is the code that calls the function containing the pipe:

postUser: (req, res) => {
        pipe(
            req.body,
            interactor.createUser,
            fold(<-- this is where the breakpoint jumps to immediately, it calls createUser however
                (error) => async () => {
                    console.error(error);
                    res.status(500).send({ error: 'Failed to retrieve user' });
                },
                (user) => async () => {
                    if (user) {
                        res.status(200).send(user);
                    } else {
                        res.status(404).send({ error: 'User not found' });
                    }
                }
            )
        );
    }
1

There are 1 answers

0
Danielo515 On

tryCatch returns a new function, which your function then returns. You either remove the wrapping function or call it directly