@shopify/shopify-app-session-storage-redis 5.0.5 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/dist/cjs/redis.js +1 -1
- package/dist/cjs/redis.js.map +1 -1
- package/dist/esm/redis.mjs +1 -1
- package/dist/esm/redis.mjs.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +9 -6
- package/src/migrations.ts +36 -0
- package/src/redis-connection.ts +73 -0
- package/src/redis-migrator.ts +58 -0
- package/src/redis.ts +192 -0
package/README.md
CHANGED
|
@@ -59,4 +59,28 @@ const shopify = shopifyApp({
|
|
|
59
59
|
});
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
+
## Refresh Token Support
|
|
63
|
+
|
|
64
|
+
This package supports storing refresh tokens for apps using expiring offline access tokens. No migration or schema changes are required - Redis storage automatically preserves all Session fields through JSON serialization.
|
|
65
|
+
|
|
66
|
+
> [!NOTE]
|
|
67
|
+
> The `future.expiringOfflineAccessTokens` flag is available in `@shopify/shopify-app-remix` and `@shopify/shopify-app-react-router` only. It does not apply to `@shopify/shopify-app-express`.
|
|
68
|
+
|
|
69
|
+
To enable expiring offline access tokens in your app (React Router or Remix):
|
|
70
|
+
|
|
71
|
+
```js
|
|
72
|
+
import {shopifyApp} from '@shopify/shopify-app-react-router';
|
|
73
|
+
import {RedisSessionStorage} from '@shopify/shopify-app-session-storage-redis';
|
|
74
|
+
|
|
75
|
+
const shopify = shopifyApp({
|
|
76
|
+
sessionStorage: new RedisSessionStorage(
|
|
77
|
+
'redis://username:password@host/database',
|
|
78
|
+
),
|
|
79
|
+
future: {
|
|
80
|
+
expiringOfflineAccessTokens: true,
|
|
81
|
+
},
|
|
82
|
+
// ...
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
62
86
|
If you prefer to use your own implementation of a session storage mechanism that is compatible with the `@shopify/shopify-app-express` package, see the [implementing session storage guide](../shopify-app-session-storage/implementing-session-storage.md).
|
package/dist/cjs/redis.js
CHANGED
|
@@ -5,7 +5,7 @@ var migrations = require('./migrations.js');
|
|
|
5
5
|
var redisConnection = require('./redis-connection.js');
|
|
6
6
|
var redisMigrator = require('./redis-migrator.js');
|
|
7
7
|
|
|
8
|
-
/* eslint-disable @shopify/typescript
|
|
8
|
+
/* eslint-disable @shopify/typescript-prefer-pascal-case-enums */
|
|
9
9
|
var ShopifyStorageOption;
|
|
10
10
|
(function (ShopifyStorageOption) {
|
|
11
11
|
ShopifyStorageOption["sessionKeyPrefix"] = "sessionKeyPrefix";
|
package/dist/cjs/redis.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis.js","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":["RedisSessionStorageMigrator","migrationList","Session","RedisConnection"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"redis.js","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":["RedisSessionStorageMigrator","migrationList","Session","RedisConnection"],"mappings":"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"}
|
package/dist/esm/redis.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { migrationList } from './migrations.mjs';
|
|
|
3
3
|
import { RedisConnection } from './redis-connection.mjs';
|
|
4
4
|
import { RedisSessionStorageMigrator } from './redis-migrator.mjs';
|
|
5
5
|
|
|
6
|
-
/* eslint-disable @shopify/typescript
|
|
6
|
+
/* eslint-disable @shopify/typescript-prefer-pascal-case-enums */
|
|
7
7
|
var ShopifyStorageOption;
|
|
8
8
|
(function (ShopifyStorageOption) {
|
|
9
9
|
ShopifyStorageOption["sessionKeyPrefix"] = "sessionKeyPrefix";
|
package/dist/esm/redis.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"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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"}
|
|
1
|
+
{"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":";;;;;AAcA;AACA,IAAK,oBAIJ;AAJD,CAAA,UAAK,oBAAoB,EAAA;AACvB,IAAA,oBAAA,CAAA,kBAAA,CAAA,GAAA,kBAAqC;AACrC,IAAA,oBAAA,CAAA,iBAAA,CAAA,GAAA,iBAAmC;AACnC,IAAA,oBAAA,CAAA,SAAA,CAAA,GAAA,SAAmB;AACrB,CAAC,EAJI,oBAAoB,KAApB,oBAAoB,GAAA,EAAA,CAAA,CAAA;AAazB,MAAM,iCAAiC,GAA+B;AACpE,IAAA,gBAAgB,EAAE,kBAAkB;AACpC,IAAA,eAAe,EAAE;AACf,QAAA,qBAAqB,EAAE,YAAY;AACpC,KAAA;CACF;MAEY,mBAAmB,CAAA;IAC9B,OAAO,eAAe,CACpB,IAAY,EACZ,EAAU,EACV,QAAgB,EAChB,QAAgB,EAChB,IAAyC,EAAA;QAEzC,OAAO,IAAI,mBAAmB,CAC5B,IAAI,GAAG,CACL,CAAA,QAAA,EAAW,kBAAkB,CAAC,QAAQ,CAAC,CAAA,CAAA,EAAI,kBAAkB,CAC3D,QAAQ,CACT,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,EAAI,EAAE,CAAA,CAAE,CAClB,EACD,IAAI,CACL;IACH;AAEgB,IAAA,KAAK;AACb,IAAA,YAAY;AACZ,IAAA,OAAO;AACP,IAAA,MAAM;AACN,IAAA,QAAQ;IAEhB,WAAA,CACE,WAAuC,EACvC,IAAA,GAA4C,EAAE,EAAA;QAE9C,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC;QAC3D,MAAM,oBAAoB,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CACnD,CAAC,GAAG,KAAK,CAAC,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAC1C;QAED,IACE,OAAO,WAAW,KAAK,QAAQ;AAC/B,YAAA,EAAE,WAAW,YAAY,GAAG,CAAC;AAC7B,YAAA,oBAAoB,CAAC,MAAM,GAAG,CAAC,EAC/B;YACA,MAAM,IAAI,KAAK,CACb,yGAAyG;AACvG,gBAAA,UAAU,CACb;QACH;QAEA,IAAI,CAAC,OAAO,GAAG,EAAC,GAAG,iCAAiC,EAAE,GAAG,IAAI,EAAC;QAC9D,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;AAC1C,QAAA,IAAI,CAAC,QAAQ,GAAG,IAAI,2BAA2B,CAC7C,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,OAAO,CAAC,eAAe,EAC5B,aAAa,CACd;AACD,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC;IAC/D;IAEO,MAAM,YAAY,CAAC,OAAgB,EAAA;QACxC,MAAM,IAAI,CAAC,KAAK;QAEhB,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CACnB,OAAO,CAAC,EAAE,EACV,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAC9C;AACD,QAAA,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;AACpC,QAAA,OAAO,IAAI;IACb;IAEO,MAAM,WAAW,CAAC,EAAU,EAAA;QACjC,MAAM,IAAI,CAAC,KAAK;QAEhB,IAAI,SAAS,GAAQ,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AAE9C,QAAA,IAAI,CAAC,SAAS;AAAE,YAAA,OAAO,SAAS;AAChC,QAAA,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;QAEjC,OAAO,OAAO,CAAC,iBAAiB,CAAC,SAAS,EAAE,IAAI,CAAC;IACnD;IAEO,MAAM,aAAa,CAAC,EAAU,EAAA;QACnC,MAAM,IAAI,CAAC,KAAK;QAChB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC1C,IAAI,OAAO,EAAE;YACX,MAAM,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;YAClD,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B;AACA,QAAA,OAAO,IAAI;IACb;IAEO,MAAM,cAAc,CAAC,GAAa,EAAA;QACvC,MAAM,IAAI,CAAC,KAAK;QAChB,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC;AAC1D,QAAA,OAAO,IAAI;IACb;IAEO,MAAM,kBAAkB,CAAC,IAAY,EAAA;QAC1C,MAAM,IAAI,CAAC,KAAK;QAEhB,MAAM,iBAAiB,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;AACrD,QAAA,IAAI,CAAC,iBAAiB;AAAE,YAAA,OAAO,EAAE;QAEjC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC;QACjD,MAAM,OAAO,GAAc,EAAE;AAC7B,QAAA,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE;AAC/B,YAAA,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC;AACrD,YAAA,IAAI,CAAC,SAAS;gBAAE;AAEhB,YAAA,MAAM,OAAO,GAAG,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC;AACtE,YAAA,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;QACvB;AAEA,QAAA,OAAO,OAAO;IAChB;AAEO,IAAA,MAAM,UAAU,GAAA;AACrB,QAAA,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE;IAChC;IAEQ,MAAM,gBAAgB,CAAC,OAAgB,EAAA;AAC7C,QAAA,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI;AAC5B,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QACrD,MAAM,iBAAiB,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;QAExD,IAAI,iBAAiB,EAAE;YACrB,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC;YAEjD,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;AAChC,gBAAA,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC;AACvB,gBAAA,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;YAC7D;QACF;aAAO;AACL,YAAA,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACzD;IACF;AAEQ,IAAA,MAAM,qBAAqB,CAAC,IAAY,EAAE,EAAU,EAAA;QAC1D,MAAM,OAAO,GAAG,IAAI;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC;QAC7C,MAAM,iBAAiB,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;QAExD,IAAI,iBAAiB,EAAE;YACrB,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC;YACjD,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC;AAExC,YAAA,IAAI,KAAK,GAAG,EAAE,EAAE;AACd,gBAAA,WAAW,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;AAC5B,gBAAA,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;YAC7D;QACF;IACF;IAEQ,MAAM,IAAI,CAAC,WAAuC,EAAA;AACxD,QAAA,IAAI,CAAC,MAAM,GAAG,IAAI,eAAe,CAC/B,WAAW,EACX,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAC9B;AACD,QAAA,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;IAC7B;AACD;;;;"}
|