Validation
Learn about validating different events in our application.
We'll cover the following...
Let’s start with the entrypoint.ts
files. The name tells us that these are the entry points to all the code in this specific folder. Note that naming is extremely difficult and the names we picked represent our best effort.
import * as TE from 'fp-ts/TaskEither';import * as T from 'fp-ts/Task'import {APIGatewayProxyEventV2} from "aws-lambda/trigger/api-gateway-proxy";import {pipe} from "fp-ts/function";import {preparePetGet, preparePetPost} from "./anticorruption";import {putInDatabase, retrieveFromDatabase} from "./database";import {createdResponse, handleError, okResponse} from "../common/responses";import {Response} from "../common/types";export const getPet = async (event: APIGatewayProxyEventV2): Promise<Response> =>pipe(preparePetGet(event),TE.fromEither,TE.chain(retrieveFromDatabase),TE.map(JSON.stringify),TE.bimap(handleError, okResponse),TE.getOrElse(T.of))();export const postPet = async (event: APIGatewayProxyEventV2): Promise<Response> =>pipe(preparePetPost(event),TE.fromEither,TE.chain(putInDatabase),TE.bimap(handleError, createdResponse),TE.getOrElse(T.of))();
import {APIGatewayProxyEventV2} from "aws-lambda/trigger/api-gateway-proxy";import {pipe} from "fp-ts/function";import * as TE from "fp-ts/TaskEither";import * as T from "fp-ts/Task";import {prepareWildAnimalGet, prepareWildAnimalPost} from "./anticorruption";import {createdResponse, handleError, okResponse} from "../common/responses";import {putInDatabase, retrieveFromDatabase} from "./database";import {Response} from "../common/types";export const getWildAnimal = async (event: APIGatewayProxyEventV2): Promise<Response> =>pipe(prepareWildAnimalGet(event),TE.fromEither,TE.chain(retrieveFromDatabase),TE.map(JSON.stringify),TE.bimap(handleError, okResponse),TE.getOrElse(T.of))();export const postWildAnimal = async (event: APIGatewayProxyEventV2): Promise<Response> =>pipe(prepareWildAnimalPost(event),TE.fromEither,TE.chain(putInDatabase),TE.bimap(handleError, createdResponse),TE.getOrElse(T.of))();
Why do we need entry points
Now, take a look at the example of the pet. We can see functions for GET and POST. If we wanted a DELETE, we’d add a delete
here that would be called by the outside code (that is, anything outside the pets folder). The first reason for entry points is that they limit the surface area of our pets module. Sadly, other parts of the application can still import from all the other files, as there’s currently no way to force a more local export in JavaScript or TypeScript. To enforce this, rely on agreement within the team or write some code to do it automatically.
In any case, this surface area limitation is especially useful for functional applications since a large number of functions combined with a large number of files and importing from anywhere can quickly create confusion. There are similar, well-known rules for structuring layered (controller-service-database) applications.
The second reason for entry points is that we need ...