UNPKG

@shopify/shopify-app-session-storage-redis

Version:
1 lines 10.3 kB
{"version":3,"file":"redis.mjs","sources":["../../../src/redis.ts"],"sourcesContent":["import {RedisClientOptions, createClient} from 'redis';\nimport {Session} from '@shopify/shopify-api';\nimport {\n SessionStorage,\n SessionStorageMigratorOptions,\n SessionStorageMigrator,\n} from '@shopify/shopify-app-session-storage';\n\nimport {migrationList} from './migrations';\nimport {RedisConnection} from './redis-connection';\nimport {RedisSessionStorageMigrator} from './redis-migrator';\n\ntype RedisClient = ReturnType<typeof createClient>;\n\n/* eslint-disable @shopify/typescript/prefer-pascal-case-enums */\nenum ShopifyStorageOption {\n sessionKeyPrefix = 'sessionKeyPrefix',\n migratorOptions = 'migratorOptions',\n onError = 'onError',\n}\n/* eslint-enable @shopify/typescript/prefer-pascal-case-enums */\n\nexport interface RedisSessionStorageOptions extends RedisClientOptions {\n [ShopifyStorageOption.sessionKeyPrefix]: string;\n [ShopifyStorageOption.migratorOptions]?: SessionStorageMigratorOptions;\n [ShopifyStorageOption.onError]?: (...args: any[]) => void;\n}\n\nconst defaultRedisSessionStorageOptions: RedisSessionStorageOptions = {\n sessionKeyPrefix: 'shopify_sessions',\n migratorOptions: {\n migrationDBIdentifier: 'migrations',\n },\n};\n\nexport class RedisSessionStorage implements SessionStorage {\n static withCredentials(\n host: string,\n db: number,\n username: string,\n password: string,\n opts: Partial<RedisSessionStorageOptions>,\n ) {\n return new RedisSessionStorage(\n new URL(\n `redis://${encodeURIComponent(username)}:${encodeURIComponent(\n password,\n )}@${host}/${db}`,\n ),\n opts,\n );\n }\n\n public readonly ready: Promise<void>;\n private internalInit: Promise<void>;\n private options: RedisSessionStorageOptions;\n private client: RedisConnection;\n private migrator: SessionStorageMigrator;\n\n constructor(\n urlOrClient: URL | string | RedisClient,\n opts: Partial<RedisSessionStorageOptions> = {},\n ) {\n const allowedClientKeys = Object.keys(ShopifyStorageOption);\n const disallowedClientKeys = Object.keys(opts).filter(\n (key) => !allowedClientKeys.includes(key),\n );\n\n if (\n typeof urlOrClient !== 'string' &&\n !(urlOrClient instanceof URL) &&\n disallowedClientKeys.length > 0\n ) {\n throw new Error(\n 'Passing a RedisClient instance is not supported with options. Set the options when creating the client ' +\n 'instead.',\n );\n }\n\n this.options = {...defaultRedisSessionStorageOptions, ...opts};\n this.internalInit = this.init(urlOrClient);\n this.migrator = new RedisSessionStorageMigrator(\n this.client,\n this.options.migratorOptions,\n migrationList,\n );\n this.ready = this.migrator.applyMigrations(this.internalInit);\n }\n\n public async storeSession(session: Session): Promise<boolean> {\n await this.ready;\n\n await this.client.set(\n session.id,\n JSON.stringify(session.toPropertyArray(true)),\n );\n await this.addKeyToShopList(session);\n return true;\n }\n\n public async loadSession(id: string): Promise<Session | undefined> {\n await this.ready;\n\n let rawResult: any = await this.client.get(id);\n\n if (!rawResult) return undefined;\n rawResult = JSON.parse(rawResult);\n\n return Session.fromPropertyArray(rawResult, true);\n }\n\n public async deleteSession(id: string): Promise<boolean> {\n await this.ready;\n const session = await this.loadSession(id);\n if (session) {\n await this.removeKeyFromShopList(session.shop, id);\n await this.client.del(id);\n }\n return true;\n }\n\n public async deleteSessions(ids: string[]): Promise<boolean> {\n await this.ready;\n await Promise.all(ids.map((id) => this.deleteSession(id)));\n return true;\n }\n\n public async findSessionsByShop(shop: string): Promise<Session[]> {\n await this.ready;\n\n const idKeysArrayString = await this.client.get(shop);\n if (!idKeysArrayString) return [];\n\n const idKeysArray = JSON.parse(idKeysArrayString);\n const results: Session[] = [];\n for (const idKey of idKeysArray) {\n const rawResult = await this.client.get(idKey, false);\n if (!rawResult) continue;\n\n const session = Session.fromPropertyArray(JSON.parse(rawResult), true);\n results.push(session);\n }\n\n return results;\n }\n\n public async disconnect(): Promise<void> {\n await this.client.disconnect();\n }\n\n private async addKeyToShopList(session: Session) {\n const shopKey = session.shop;\n const idKey = this.client.generateFullKey(session.id);\n const idKeysArrayString = await this.client.get(shopKey);\n\n if (idKeysArrayString) {\n const idKeysArray = JSON.parse(idKeysArrayString);\n\n if (!idKeysArray.includes(idKey)) {\n idKeysArray.push(idKey);\n await this.client.set(shopKey, JSON.stringify(idKeysArray));\n }\n } else {\n await this.client.set(shopKey, JSON.stringify([idKey]));\n }\n }\n\n private async removeKeyFromShopList(shop: string, id: string) {\n const shopKey = shop;\n const idKey = this.client.generateFullKey(id);\n const idKeysArrayString = await this.client.get(shopKey);\n\n if (idKeysArrayString) {\n const idKeysArray = JSON.parse(idKeysArrayString);\n const index = idKeysArray.indexOf(idKey);\n\n if (index > -1) {\n idKeysArray.splice(index, 1);\n await this.client.set(shopKey, JSON.stringify(idKeysArray));\n }\n }\n }\n\n private async init(urlOrClient: URL | string | RedisClient) {\n this.client = new RedisConnection(\n urlOrClient,\n this.options,\n this.options.sessionKeyPrefix,\n );\n await this.client.connect();\n }\n}\n"],"names":[],"mappings":"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"}