All files / src/auth/session/storage custom.ts

30.3% Statements 30/99
4.35% Branches 2/46
29.41% Functions 5/17
30.93% Lines 30/97

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 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127  24x 24x 24x 24x 24x 24x 24x   1x 1x 1x 1x 1x 1x 1x 1x 1x 1x   24x 1x   1x 2x   1x 1x 1x                 24x                                                                                     24x                                 24x                                               24x          
import {Session} from '../session';
import {SessionInterface} from '../types';
import {SessionStorage} from '../session_storage';
import * as ShopifyErrors from '../../../error';
import {sanitizeShop} from '../../../utils/shop-validator';
 
export class CustomSessionStorage implements SessionStorage {
  constructor(
    readonly storeCallback: (session: SessionInterface) => Promise<boolean>,
    readonly loadCallback: (
      id: string,
    ) => Promise<SessionInterface | {[key: string]: unknown} | undefined>,
    readonly deleteCallback: (id: string) => Promise<boolean>,
    readonly deleteSessionsCallback?: (ids: string[]) => Promise<boolean>,
    readonly findSessionsByShopCallback?: (
      shop: string,
    ) => Promise<SessionInterface[]>,
  ) {
    this.storeCallback = storeCallback;
    this.loadCallback = loadCallback;
    this.deleteCallback = deleteCallback;
    this.deleteSessionsCallback = deleteSessionsCallback;
    this.findSessionsByShopCallback = findSessionsByShopCallback;
  }
 
  public async storeSession(session: SessionInterface): Promise<boolean> {
    try {
      return await this.storeCallback(session);
    } catch (error) {
      throw new ShopifyErrors.SessionStorageError(
        `CustomSessionStorage failed to store a session. Error Details: ${error}`,
      );
    }
  }
 
  public async loadSession(id: string): Promise<SessionInterface | undefined> {
    let result: SessionInterface | {[key: string]: unknown} | undefined;
    try {
      result = await this.loadCallback(id);
    } catch (error) {
      throw new ShopifyErrors.SessionStorageError(
        `CustomSessionStorage failed to load a session. Error Details: ${error}`,
      );
    }
    if (result) {
      if (result instanceof Session) {
        if (result.expires && typeof result.expires === 'string') {
          result.expires = new Date(result.expires);
        }

        return result as SessionInterface;
      } else if (result instanceof Object && 'id' in result) {
        let session = new Session(
          result.id as string,
          result.shop as string,
          result.state as string,
          result.isOnline as boolean,
        );
        session = {...session, ...(result as SessionInterface)};

        if (session.expires && typeof session.expires === 'string') {
          session.expires = new Date(session.expires);
        }

        Object.setPrototypeOf(session, Session.prototype);
        return session as SessionInterface;
      } else {
        throw new ShopifyErrors.SessionStorageError(
          `Expected return to be instanceof Session, but received instanceof ${
            result!.constructor.name
          }.`,
        );
      }
    } else {
      return undefined;
    }
  }
 
  public async deleteSession(id: string): Promise<boolean> {
    try {
      return await this.deleteCallback(id);
    } catch (error) {
      throw new ShopifyErrors.SessionStorageError(
        `CustomSessionStorage failed to delete a session. Error Details: ${error}`,
      );
    }
  }

  public async deleteSessions(ids: string[]): Promise<boolean> {
    if (this.deleteSessionsCallback) {
      try {
        return await this.deleteSessionsCallback(ids);
      } catch (error) {
        throw new ShopifyErrors.SessionStorageError(
          `CustomSessionStorage failed to delete array of sessions. Error Details: ${error}`,
        );
      }
    } else {
      console.warn(
        `CustomSessionStorage failed to delete array of sessions. Error Details: deleteSessionsCallback not defined.`,
      );
    }
    return false;
  }

  public async findSessionsByShop(shop: string): Promise<SessionInterface[]> {
    const cleanShop = sanitizeShop(shop, true)!;

    let sessions: SessionInterface[] = [];
 
    if (this.findSessionsByShopCallback) {
      try {
        sessions = await this.findSessionsByShopCallback(cleanShop);
      } catch (error) {
        throw new ShopifyErrors.SessionStorageError(
          `CustomSessionStorage failed to find sessions by shop. Error Details: ${error}`,
        );
      }
    } else {
      console.warn(
        `CustomSessionStorage failed to find sessions by shop. Error Details: findSessionsByShopCallback not defined.`,
      );
    }
    return sessions;
  }
}