@shopify/shopify-app-session-storage-redis
Version:
Shopify App Session Storage for Redis
125 lines (122 loc) • 4.85 kB
JavaScript
import { Session } from '@shopify/shopify-api';
import { migrationList } from './migrations.mjs';
import { RedisConnection } from './redis-connection.mjs';
import { RedisSessionStorageMigrator } from './redis-migrator.mjs';
/* eslint-disable @shopify/typescript/prefer-pascal-case-enums */
var ShopifyStorageOption;
(function (ShopifyStorageOption) {
ShopifyStorageOption["sessionKeyPrefix"] = "sessionKeyPrefix";
ShopifyStorageOption["migratorOptions"] = "migratorOptions";
ShopifyStorageOption["onError"] = "onError";
})(ShopifyStorageOption || (ShopifyStorageOption = {}));
const defaultRedisSessionStorageOptions = {
sessionKeyPrefix: 'shopify_sessions',
migratorOptions: {
migrationDBIdentifier: 'migrations',
},
};
class RedisSessionStorage {
static withCredentials(host, db, username, password, opts) {
return new RedisSessionStorage(new URL(`redis://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${host}/${db}`), opts);
}
ready;
internalInit;
options;
client;
migrator;
constructor(urlOrClient, opts = {}) {
const allowedClientKeys = Object.keys(ShopifyStorageOption);
const disallowedClientKeys = Object.keys(opts).filter((key) => !allowedClientKeys.includes(key));
if (typeof urlOrClient !== 'string' &&
!(urlOrClient instanceof URL) &&
disallowedClientKeys.length > 0) {
throw new Error('Passing a RedisClient instance is not supported with options. Set the options when creating the client ' +
'instead.');
}
this.options = { ...defaultRedisSessionStorageOptions, ...opts };
this.internalInit = this.init(urlOrClient);
this.migrator = new RedisSessionStorageMigrator(this.client, this.options.migratorOptions, migrationList);
this.ready = this.migrator.applyMigrations(this.internalInit);
}
async storeSession(session) {
await this.ready;
await this.client.set(session.id, JSON.stringify(session.toPropertyArray(true)));
await this.addKeyToShopList(session);
return true;
}
async loadSession(id) {
await this.ready;
let rawResult = await this.client.get(id);
if (!rawResult)
return undefined;
rawResult = JSON.parse(rawResult);
return Session.fromPropertyArray(rawResult, true);
}
async deleteSession(id) {
await this.ready;
const session = await this.loadSession(id);
if (session) {
await this.removeKeyFromShopList(session.shop, id);
await this.client.del(id);
}
return true;
}
async deleteSessions(ids) {
await this.ready;
await Promise.all(ids.map((id) => this.deleteSession(id)));
return true;
}
async findSessionsByShop(shop) {
await this.ready;
const idKeysArrayString = await this.client.get(shop);
if (!idKeysArrayString)
return [];
const idKeysArray = JSON.parse(idKeysArrayString);
const results = [];
for (const idKey of idKeysArray) {
const rawResult = await this.client.get(idKey, false);
if (!rawResult)
continue;
const session = Session.fromPropertyArray(JSON.parse(rawResult), true);
results.push(session);
}
return results;
}
async disconnect() {
await this.client.disconnect();
}
async addKeyToShopList(session) {
const shopKey = session.shop;
const idKey = this.client.generateFullKey(session.id);
const idKeysArrayString = await this.client.get(shopKey);
if (idKeysArrayString) {
const idKeysArray = JSON.parse(idKeysArrayString);
if (!idKeysArray.includes(idKey)) {
idKeysArray.push(idKey);
await this.client.set(shopKey, JSON.stringify(idKeysArray));
}
}
else {
await this.client.set(shopKey, JSON.stringify([idKey]));
}
}
async removeKeyFromShopList(shop, id) {
const shopKey = shop;
const idKey = this.client.generateFullKey(id);
const idKeysArrayString = await this.client.get(shopKey);
if (idKeysArrayString) {
const idKeysArray = JSON.parse(idKeysArrayString);
const index = idKeysArray.indexOf(idKey);
if (index > -1) {
idKeysArray.splice(index, 1);
await this.client.set(shopKey, JSON.stringify(idKeysArray));
}
}
}
async init(urlOrClient) {
this.client = new RedisConnection(urlOrClient, this.options, this.options.sessionKeyPrefix);
await this.client.connect();
}
}
export { RedisSessionStorage };
//# sourceMappingURL=redis.mjs.map