This is a collection of generic typescript utilities to use in an aws lambda powered environment
npm page: https://www.npmjs.com/package/aws-nodejs-kit
npm i aws-nodejs-kit
Please refer to the /examples folder
import {Optional} from "aws-nodejs-kit";
const value: number | undefined = 10;
// Perform a list of computation without having to check explicitly for null/undefined value
const compute = Optional.fromValue(value)
.map((val: number) => val + 10)
.map((val: number) => val * 2)
// Get the internal value, you can actually apply a default if the value is undefined
.getOrElse(10);
console.log(compute); // 40
import {Logger} from "aws-nodejs-kit";
// Static Logger
const log = Logger.getInstance();
// Standard logs
log.debug("debug");
log.info("info");
log.warn("warn");
log.error("error");
// Log performance
log.time("log");
log.timeEnd("log");
import {CatchExceptionAndThrowIntegrationError} from "aws-nodejs-kit";
import {LogMetric, LogMetricSync} from "aws-nodejs-kit";
class Service {
// Log Metric for async functions
// This will result in the following log row:
// METRIC 1021.351594000007 milliseconds getFeedByName feeds
@LogMetric("getFeedByName", "feeds")
public async getFeedByName() {
}
// Log Metric for sync functions
// This will result in the following log row:
// METRIC 1021.351594000007 milliseconds getFeedById feeds
@LogMetricSync("getFeedById", "feeds")
public getFeedById() {
}
// Catch errors for async functions
// throw an IntegrationError, that, if used in conjuction with "catchErrors" Middleware generate a 429 http error
// Used to propagate an integration error
@CatchExceptionAndThrowIntegrationError()
public async getFeedFromExternal() {
}
}
import {dates} from "aws-nodejs-kit";
dates.datePlusTimeframe(new Date(), 1, dates.TimeUnit.hours);
// 2020-06-15T20:38:14.953Z
dates.dateFromISO(new Date().toISOString());
// 2020-06-15T19:38:14.956Z
dates.dateInHyphens(new Date());
// 2020-06-15
dates.dateInSeconds(new Date());
// 1592249894
dates.dateMinusTimeframe(new Date, 1, dates.TimeUnit.hours);
// 2020-06-15T18:38:14.960Z
dates.isDateGreaterThan(new Date(), 1, dates.TimeUnit.hours);
// true
dates.iSOFromTimestamp(new Date().getTime());
// 2020-06-15T19:41:11.301Z
dates.timestampFromISO(new Date().toISOString());
// 1592250071303
dates.timeframeToSeconds({amount: 1, timeUnit: dates.TimeUnit.hours});
// 3600
import {
ValidationError, // Maps to a 400 Status code
UseCaseError, // Maps to a 422 Status code
IntegrationError, // Maps to a 429 Status code
NotFoundError, // Maps to a 400 Status code
UnAuthorizedError, // Maps to a 401 Status code
NotImplementedError, // Used for abstract classes
} from "aws-nodejs-kit";
import {catchErrors, Lambda} from "aws-nodejs-kit";
import {Logger} from "aws-nodejs-kit";
/**
* Classic handler with business logic
* @param event
*/
const handler = async (event: any) => {
console.log(event);
};
// export a lambda Handler using handler
export const lambdaHandler = new Lambda(handler)
// Add any middleware you need, this one catch errors and respond with standard api gateway responses
.with(catchErrors(Logger.getInstance()))
// Applying Middlewares
.toFn();
// --- Default Middlewares includes:
// Log Lambda input event
.with(logEvent(Logger.getInstance()))
// Log Lambda response
.with(logResponse(Logger.getInstance()))
// Catch errors globally and return a apigw compatible response (map exceptions to status codes)
.with(catchErrors(Logger.getInstance()))
// Validate Lambda input event against a DTO (class decorated with "class-validator" decorators with static method "fromApiGWEvent")
// uses validate function to check- you should pass the "validator" function from "class-validator"
.with(validateDTO(Logger.getInstance(),
(event) => MyDTO.fromApiGWEvent(event),
validate))
// You can create your custom Middleware implementing the "Middleware" type and passing your object to the .with() function
// TODO complete doc
import {ResponseBuilder} from "aws-nodejs-kit";
let handler;
/**
* Return Api Gateway compatible responses
* @param event
*/
handler = async (event: any) => {
/**
* http status code -> 200
* response(enveloped) -> {
* data : {}
* }
*/
return new ResponseBuilder().build().resOk({data: {}});
/**
* http status code -> 204
* response(enveloped) -> {
* data : {}
* }
* used mainly for POST/DELETE/PUT APIs
*/
return new ResponseBuilder().build().resOkNoContent({data: {}});
};
/**
* Return Bad Request responses:
*
* response(enveloped) -> {
* error: {
* errorMessage: errorMessage || "The request could not be understood by the server due to malformed syntax. The client should not repeat the request without modifications",
* errorCode: errorCode || "",
* payload
* }
* }
* @param event
*/
handler = async (event: any) => {
/**
* http status code -> 400
*/
return new ResponseBuilder().build().resBadReq(
{}, // optional payload,
"xxx", // optional errorCode,
"Invalid" // optional errorMessage,
);
/**
* http status code -> 404
* used for missing content
*/
return new ResponseBuilder().build().resNotFound();
/**
* http status code -> 429
* an error while communicating with a third party service happened
*/
return new ResponseBuilder().build().resIntegrationError();
/**
* http status code -> 422
* used for a business logic un-manageable error (better than a 500 aint'it?)
*/
return new ResponseBuilder().build().resUseCaseError();
/**
* http status code -> 403
* you are not allowed to see this content
*/
return new ResponseBuilder().build().resForbidden();
};
npm install
npm run build
npm run test
npm run test:coverage // tests with coverage report
- PRs are welcome
- The release process uses github actions and semantic-release for automatic tagging/versioning/publishing to npm
- The commit messages MUST follow the conventional commit convention