Business logic (regardless of the type of resource, such as an API, a cron job, etc.) should perform a specific action and not worry about everything else like errors, formatting or logging.
Wrappers are functions that “wrap” the original function and are responsible for handling all the repetitive actions to avoid having to write them each time. This way, the business logic remains clean and focused, consistent with the DRY methodology.
The main function in the handler is the function that will be invoked by API Gateway (in my case, I work with AWS), but the business logic is actually contained in the main function, but executed by the wrapper.
export const main = Util.handler(async (event) => {
// this is my business logic, clean and focused.
await dynamoDb.send(new PutCommand(params))
return JSON.stringify(params.Item)
}) // everything else is handled by the Util.handler wrapperThese wrappers can be placed before (checking permissions, preparing the environment) or after (catching errors, formatting the result, logging).
export namespace Util {
export function handler(
lambda: (evt: APIGatewayProxyEvent, context: Context) => Promise<string>,
) {
return async function (event: APIGatewayProxyEvent, context: Context) {
// 1. logging
console.log(`[START] ${context.functionName}`)
// 2. pre-auth check
const token = event.headers?.["authorization"]
if (!token || !token.startsWith("Bearer valid_token")) {
throw new AuthError()
}
let body: string, statusCode: number
try {
// run the Lambda (pure business logic)
body = await lambda(event, context)
statusCode = 200
} catch (error) {
// 3. custom error
if (error instanceof AuthError) {
statusCode = 401
body = JSON.stringify({ error: error.message })
} else {
statusCode = 500
body = JSON.stringify({ error: "Internal error." })
}
} finally {
// 4. logging
console.log(`[END] End. Status: ${statusCode}`)
// 5. HTTP response
return { statusCode, body }
}
}
}
}- The business logic takes care of what to do
- The wrapper takes care of how to manage execution
This is a use case for higher-order functions.