Bringing it Together

Understand the project’s code that we’ve written so far.

Creating a unified response type

Let’s combine all the things we’ve learned so far. The one element we should add is a unified response. We’ll use the following HTTP/REST-inspired type:

Press + to interact
type Response = {
status: number,
message: string,
};

In the type above, the status will be a 2xx, 4xx, or 5xx number signifying success or failure (similar to HTTP response code), and a message will give additional information. Let’s look at them below. We’ll also add some pure helper functions to create responses.

Press + to interact
const createdResponse = (message: string): Response => ({
status: 201,
message,
});
const badRequest = (exception: string): Response => ({
status: 400,
message: exception,
});
const internalServerError = (): Response => ({
status: 500,
message: 'failed to create',
});

We could factor out some duplication here, but this example is good enough for now. Let’s review an example where we use these functions:

Press + to interact
function userResponse(u: UserRegistrationDto) {
return pipe(
u,
e => sequenceForOption(
O.some(firstNameIso.wrap(e.firstName)),
O.some(lastNameIso.wrap(e.lastName)),
prismPositiveInteger.getOption(e.age),
findGender(e.sex),
findRegion(e.country),
),
O.map(([f, l, a, g, c]) => createUser(f, l, a, g, c)),
O.map(u => {
console.log(`Created ${JSON.stringify(u)}. Could now save in db`);
return createdResponse(`Created ${JSON.stringify(u)}`);
}),
O.getOrElse(internalServerError),
);
}
function flow(u: UserRegistrationDto) {
return pipe(
fieldsNotEmpty(u),
E.chain(validateAge),
E.chain(validateGender),
E.map(userResponse),
E.getOrElse(badRequest),
);
}
console.log(flow(exampleEvent));

Let’s explain what we did in the code above:

  • Lines 1–18: The userResponse function builds our user. It logs a message, which is a stand-in for a call to a database, and builds a response. The response is either a 201 in case of success or a
...