All files / src/utils graphql_proxy.ts

87.5% Statements 35/40
75% Branches 9/12
100% Functions 4/4
86.49% Lines 32/37

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 64 65 66 67 68    2x 2x   2x   2x 5x 5x 1x 4x 1x     3x 3x 3x     3x 3x 2x     3x   3x 3x         3x 3x     3x     3x 3x 2x   1x   1x 1x                   1x   3x 3x   3x     3x    
import http from 'http';
 
import {GraphqlClient} from '../clients/graphql';
import * as ShopifyErrors from '../error';
 
import loadCurrentSession from './load-current-session';
 
export default async function graphqlProxy(userReq: http.IncomingMessage, userRes: http.ServerResponse): Promise<void> {
  const session = await loadCurrentSession(userReq, userRes);
  if (!session) {
    throw new ShopifyErrors.SessionNotFound('Cannot proxy query. No session found.');
  } else if (!session.accessToken) {
    throw new ShopifyErrors.InvalidSession('Cannot proxy query. Session not authenticated.');
  }
 
  const shopName: string = session.shop;
  const token: string = session.accessToken;
  let reqBodyString = '';
 
  // eslint-disable-next-line promise/param-names
  const promise: Promise<void> = new Promise((resolve, _reject) => {
    userReq.on('data', (chunk) => {
      reqBodyString += chunk;
    });
 
    userReq.on('end', async () => {
      let reqBodyObject: Record<string, unknown> | undefined;
      try {
        reqBodyObject = JSON.parse(reqBodyString);
      } catch (err) {
        // we can just continue and attempt to pass the string
      }
 
      let status = 200;
      let body: unknown = '';
 
      try {
        const options = {
          data: reqBodyObject ? reqBodyObject : reqBodyString,
        };
        const client = new GraphqlClient(shopName, token);
        const response = await client.query(options);
        body = response.body;
      } catch (err) {
        switch (err.constructor.name) {
          case 'MissingRequiredArgument':
            status = 400;
            break;
          case 'HttpResponseError':
            status = err.code;
            break;
          case 'HttpThrottlingError':
            status = 429;
            break;
          default:
            status = 500;
        }
        body = err.message;
      } finally {
        userRes.statusCode = status;
        userRes.end(JSON.stringify(body));
      }
      return resolve();
    });
  });
  return promise;
}