{"version":3,"file":"prisma.mjs","sources":["../../../src/prisma.ts"],"sourcesContent":["import {Session} from '@shopify/shopify-api';\nimport {SessionStorage} from '@shopify/shopify-app-session-storage';\nimport type {PrismaClient, Session as Row} from '@prisma/client';\nimport {Prisma} from '@prisma/client';\n\ninterface PrismaSessionStorageOptions {\n  tableName?: string;\n  connectionRetries?: number;\n  connectionRetryIntervalMs?: number;\n}\n\nconst UNIQUE_KEY_CONSTRAINT_ERROR_CODE = 'P2002';\n\n// eslint-disable-next-line no-warning-comments\n// TODO: Remove this when all session storages have implemented the isReady method\nexport interface PrismaSessionStorageInterface extends SessionStorage {\n  isReady(): Promise<boolean>;\n}\n\nexport class PrismaSessionStorage<T extends PrismaClient>\n  implements PrismaSessionStorageInterface\n{\n  private ready: Promise<boolean>;\n  private readonly tableName: string = 'session';\n  private connectionRetries = 2;\n  private connectionRetryIntervalMs = 5000;\n\n  constructor(\n    private prisma: T,\n    {\n      tableName,\n      connectionRetries,\n      connectionRetryIntervalMs,\n    }: PrismaSessionStorageOptions = {},\n  ) {\n    if (tableName) {\n      this.tableName = tableName;\n    }\n\n    if (connectionRetries !== undefined) {\n      this.connectionRetries = connectionRetries;\n    }\n\n    if (connectionRetryIntervalMs !== undefined) {\n      this.connectionRetryIntervalMs = connectionRetryIntervalMs;\n    }\n\n    if (this.getSessionTable() === undefined) {\n      throw new Error(`PrismaClient does not have a ${this.tableName} table`);\n    }\n\n    this.ready = this.pollForTable()\n      .then(() => true)\n      .catch((cause) => {\n        throw new MissingSessionTableError(\n          `Prisma ${this.tableName} table does not exist. This could happen for a few reasons, see https://github.com/Shopify/shopify-app-js/tree/main/packages/apps/session-storage/shopify-app-session-storage-prisma#troubleshooting for more information`,\n          cause,\n        );\n      });\n  }\n\n  public async storeSession(session: Session): Promise<boolean> {\n    await this.ensureReady();\n    const data = this.sessionToRow(session);\n\n    try {\n      await this.getSessionTable().upsert({\n        where: {id: session.id},\n        update: data,\n        create: data,\n      });\n    } catch (error) {\n      if (\n        error instanceof Prisma.PrismaClientKnownRequestError &&\n        error.code === UNIQUE_KEY_CONSTRAINT_ERROR_CODE\n      ) {\n        console.log(\n          'Caught PrismaClientKnownRequestError P2002 - Unique Key Key Constraint, retrying upsert.',\n        );\n        await this.getSessionTable().upsert({\n          where: {id: session.id},\n          update: data,\n          create: data,\n        });\n        return true;\n      }\n      throw error;\n    }\n\n    return true;\n  }\n\n  public async loadSession(id: string): Promise<Session | undefined> {\n    await this.ensureReady();\n    const row = await this.getSessionTable().findUnique({\n      where: {id},\n    });\n\n    if (!row) {\n      return undefined;\n    }\n\n    return this.rowToSession(row);\n  }\n\n  public async deleteSession(id: string): Promise<boolean> {\n    await this.ensureReady();\n    try {\n      await this.getSessionTable().delete({where: {id}});\n    } catch {\n      return true;\n    }\n\n    return true;\n  }\n\n  public async deleteSessions(ids: string[]): Promise<boolean> {\n    await this.ensureReady();\n    await this.getSessionTable().deleteMany({where: {id: {in: ids}}});\n\n    return true;\n  }\n\n  public async findSessionsByShop(shop: string): Promise<Session[]> {\n    await this.ensureReady();\n    const sessions = await this.getSessionTable().findMany({\n      where: {shop},\n      take: 25,\n      orderBy: [{expires: 'desc'}],\n    });\n\n    return sessions.map((session) => this.rowToSession(session));\n  }\n\n  public async isReady(): Promise<boolean> {\n    try {\n      await this.pollForTable();\n      this.ready = Promise.resolve(true);\n    } catch (_error) {\n      this.ready = Promise.resolve(false);\n    }\n    return this.ready;\n  }\n\n  private async ensureReady(): Promise<void> {\n    if (!(await this.ready))\n      throw new MissingSessionStorageError(\n        'Prisma session storage is not ready. Use the `isReady` method to poll for the table.',\n      );\n  }\n\n  private async pollForTable(): Promise<void> {\n    for (let i = 0; i < this.connectionRetries; i++) {\n      try {\n        await this.getSessionTable().count();\n        return;\n      } catch (error) {\n        console.log(`Error obtaining session table: ${error}`);\n      }\n      await sleep(this.connectionRetryIntervalMs);\n    }\n    throw Error(\n      `The table \\`${this.tableName}\\` does not exist in the current database.`,\n    );\n  }\n\n  private sessionToRow(session: Session): Row {\n    const sessionParams = session.toObject();\n\n    return {\n      id: session.id,\n      shop: session.shop,\n      state: session.state,\n      isOnline: session.isOnline,\n      scope: session.scope || null,\n      expires: session.expires || null,\n      accessToken: session.accessToken || '',\n      userId:\n        (sessionParams.onlineAccessInfo?.associated_user\n          .id as unknown as bigint) || null,\n      firstName:\n        sessionParams.onlineAccessInfo?.associated_user.first_name || null,\n      lastName:\n        sessionParams.onlineAccessInfo?.associated_user.last_name || null,\n      email: sessionParams.onlineAccessInfo?.associated_user.email || null,\n      accountOwner:\n        sessionParams.onlineAccessInfo?.associated_user.account_owner || false,\n      locale: sessionParams.onlineAccessInfo?.associated_user.locale || null,\n      collaborator:\n        sessionParams.onlineAccessInfo?.associated_user.collaborator || false,\n      emailVerified:\n        sessionParams.onlineAccessInfo?.associated_user.email_verified || false,\n    };\n  }\n\n  private rowToSession(row: Row): Session {\n    const sessionParams: Record<string, boolean | string | number> = {\n      id: row.id,\n      shop: row.shop,\n      state: row.state,\n      isOnline: row.isOnline,\n      userId: String(row.userId),\n      firstName: String(row.firstName),\n      lastName: String(row.lastName),\n      email: String(row.email),\n      locale: String(row.locale),\n    };\n\n    if (row.accountOwner !== null) {\n      sessionParams.accountOwner = row.accountOwner;\n    }\n\n    if (row.collaborator !== null) {\n      sessionParams.collaborator = row.collaborator;\n    }\n\n    if (row.emailVerified !== null) {\n      sessionParams.emailVerified = row.emailVerified;\n    }\n\n    if (row.expires) {\n      sessionParams.expires = row.expires.getTime();\n    }\n\n    if (row.scope) {\n      sessionParams.scope = row.scope;\n    }\n\n    if (row.accessToken) {\n      sessionParams.accessToken = row.accessToken;\n    }\n\n    return Session.fromPropertyArray(Object.entries(sessionParams), true);\n  }\n\n  private getSessionTable(): T['session'] {\n    return (this.prisma as any)[this.tableName];\n  }\n}\n\nexport class MissingSessionTableError extends Error {\n  constructor(\n    message: string,\n    public readonly cause: Error,\n  ) {\n    super(message);\n  }\n}\n\nexport class MissingSessionStorageError extends Error {\n  constructor(message: string) {\n    super(message);\n  }\n}\n\nasync function sleep(ms: number) {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n"],"names":[],"mappings":"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"}