All files / lib/lambda/middleware fetchPackage.ts

100% Statements 17/17
94.11% Branches 16/17
100% Functions 2/2
100% Lines 17/17

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63                          16x                               16x 10x   10x     24x     24x 24x 19x 12x     5x   5x 5x   5x 3x       21x 1x     20x        
import { MiddlewareObj, Request } from "@middy/core";
import { createError } from "@middy/util";
import { getPackage, isActiveMainNonDraftPackage } from "libs/api/package";
 
import { storePackageInRequest } from "./utils";
 
export type FetchPackageOptions = {
  allowNotFound?: boolean;
  setToContext?: boolean;
  rethrowErrors?: boolean;
  requireActiveMainNonDraft?: boolean;
};
 
const defaults: FetchPackageOptions = {
  allowNotFound: false,
  setToContext: false,
  rethrowErrors: false,
  requireActiveMainNonDraft: true,
};
 
/**
 * Fetches a package and adds it to internal storage.
 * @param {object} opts Options for running the middleware
 * @param {boolean} opts.allowNotFound [false] if true, do not error if the package is not found
 * @param {boolean} opts.setToContext [false] if true, also stores the package in context, so it can be accessed in the handler
 * @param {boolean} opts.rethrowErrors [false] if true, rethrow non-404 errors from the package lookup even when allowNotFound is true
 * @param {boolean} opts.requireActiveMainNonDraft [true] if true, treat deleted, draft, and incomplete shell records as not found
 * @returns {MiddlewareObj} middleware to fetch a package before the handler runs
 */
export const fetchPackage = (opts: FetchPackageOptions = {}): MiddlewareObj => {
  const options = { ...defaults, ...opts };
 
  return {
    before: async (request: Request) => {
      // the event body should already have been validated by `validator` before this handler runs
      const { id } = request.event.body as { id: string };
 
      let packageResult;
      try {
        packageResult = await getPackage(id);
        if (options.requireActiveMainNonDraft && !isActiveMainNonDraftPackage(packageResult)) {
          packageResult = undefined;
        }
      } catch (err) {
        const statusCode = (err as { statusCode?: number; meta?: { statusCode?: number } })
          ?.statusCode;
        const metaStatusCode = (err as { meta?: { statusCode?: number } })?.meta?.statusCode;
        const isNotFoundError = statusCode === 404 || metaStatusCode === 404;
 
        if (!options.allowNotFound || (options.rethrowErrors && !isNotFoundError)) {
          throw err;
        }
      }
 
      if (!options.allowNotFound && (packageResult === undefined || !packageResult.found)) {
        throw createError(404, JSON.stringify({ message: "No record found for the given id" }));
      }
 
      storePackageInRequest(packageResult, request, options.setToContext);
    },
  };
};