JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 8
  • Score
    100M100P100Q55145F
  • License ISC

Sharing utilities across AWS lambda functions

Package Exports

  • aws-nodejs-kit
  • aws-nodejs-kit/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (aws-nodejs-kit) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Release

Aws Nodejs Kit

This is a collection of generic typescript utilities to use in an aws lambda powered environment

Table of Contents

Installation

npm page: https://www.npmjs.com/package/aws-nodejs-kit

npm i aws-nodejs-kit 

Usage / Reference

Please refer to the /examples folder

NodeJS / Typescript utilities

Monads

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

Logger

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");

Logging Decorators

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() {

    }
}

Dates

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

Exceptions

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";

AWS Helpers

Lambda Core

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();

Lambda Middlewares

// --- 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

DynamoDb

// TODO complete doc

Api Gateway

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();
};

Contributing

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