baileys-redis-auth 1.1.0 → 2.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/LOGOUT_GUIDE.md CHANGED
@@ -22,7 +22,7 @@ Your application MUST manually clear the Redis session when it detects a logout.
22
22
 
23
23
  ```typescript
24
24
  import {deleteKeysWithPattern, useRedisAuthState} from 'baileys-redis-auth'
25
- import {DisconnectReason} from '@whiskeysockets/baileys'
25
+ import {DisconnectReason} from 'baileys'
26
26
 
27
27
  const {state, saveCreds, redis} = await useRedisAuthState(redisOptions, 'my-session')
28
28
 
@@ -36,7 +36,7 @@ sock.ev.on('connection.update', async (update) => {
36
36
  // User logged out - clear the session
37
37
  await deleteKeysWithPattern({
38
38
  redis,
39
- pattern: 'my-session:*', // Must match your session prefix
39
+ sessionId: 'my-session', // Must match your session prefix
40
40
  logger: console.log // Optional: pass logger for debugging
41
41
  })
42
42
  console.log('Session cleared after logout')
@@ -76,7 +76,7 @@ sock.ev.on('connection.update', async (update) => {
76
76
  // Clear HSet-based session
77
77
  await deleteHSetKeys({
78
78
  redis,
79
- key: 'my-session',
79
+ sessionId: 'my-session',
80
80
  logger: console.log // Optional: pass logger for debugging
81
81
  })
82
82
  console.log('Session cleared after logout')
@@ -89,7 +89,7 @@ sock.ev.on('connection.update', async (update) => {
89
89
 
90
90
  ```typescript
91
91
  import {deleteKeysWithPattern, useRedisAuthState} from 'baileys-redis-auth'
92
- import makeWASocket, {DisconnectReason} from '@whiskeysockets/baileys'
92
+ import makeWASocket, {DisconnectReason} from 'baileys'
93
93
  import type {Boom} from '@hapi/boom'
94
94
 
95
95
  async function startWhatsApp() {
@@ -119,7 +119,7 @@ async function startWhatsApp() {
119
119
  // THIS IS CRITICAL: Clear Redis session on logout
120
120
  await deleteKeysWithPattern({
121
121
  redis,
122
- pattern: `${sessionPrefix}:*`,
122
+ sessionId: sessionPrefix,
123
123
  logger: console.log // Optional: pass logger for debugging
124
124
  })
125
125
  console.log('✅ Session cleared successfully')
@@ -164,7 +164,7 @@ await sock.logout()
164
164
 
165
165
  ```typescript
166
166
  await sock.logout()
167
- await deleteKeysWithPattern({redis, pattern: 'session:*'})
167
+ await deleteKeysWithPattern({redis, sessionId: 'session'})
168
168
  // Race condition - might clear before logout message is sent
169
169
  ```
170
170
 
@@ -173,7 +173,7 @@ await deleteKeysWithPattern({redis, pattern: 'session:*'})
173
173
  ```typescript
174
174
  sock.ev.on('connection.update', async (update) => {
175
175
  if (connection === 'close' && statusCode === DisconnectReason.loggedOut) {
176
- await deleteKeysWithPattern({redis, pattern: 'session:*'})
176
+ await deleteKeysWithPattern({redis, sessionId: 'session'})
177
177
  }
178
178
  })
179
179
 
@@ -188,7 +188,7 @@ await sock.logout() // Cleanup happens automatically
188
188
  ```typescript
189
189
  deleteKeysWithPattern({
190
190
  redis: RedisClient, // Redis client from useRedisAuthState
191
- pattern: string, // Pattern to match (e.g., 'session:*')
191
+ sessionId: string, // Session ID (e.g., 'session')
192
192
  logger?: (message: string, ...args: unknown[]) => void // Optional logger function
193
193
  }): Promise<void>
194
194
  ```
@@ -198,7 +198,7 @@ deleteKeysWithPattern({
198
198
  ```typescript
199
199
  deleteHSetKeys({
200
200
  redis: RedisClient, // Redis client from useRedisAuthStateWithHSet
201
- key: string, // Session prefix (e.g., 'session')
201
+ sessionId: string, // Session prefix (e.g., 'session')
202
202
  logger?: (message: string, ...args: unknown[]) => void // Optional logger function
203
203
  }): Promise<void>
204
204
  ```
package/README.md CHANGED
@@ -1,16 +1,22 @@
1
1
  # baileys-redis-auth
2
2
 
3
+ ✅ **Baileys v7.0.0-rc.9 Compatible** - aligned with current latest npm release
4
+
3
5
  `baileys-redis-auth` is a library designed to seamlessly integrate Redis as an authentication state storage solution for [Baileys](https://github.com/WhiskeySockets/Baileys), the powerful WhatsApp Web API library. By leveraging Redis, this module allows you to persist Baileys sessions, enabling your application to resume connections without needing to re-scan QR codes frequently. This is particularly useful for applications requiring robust and scalable session management.
4
6
 
5
7
  This library provides flexible ways to store authentication data in Redis, using either simple key-value pairs or Redis Hashes for optimized storage.
6
8
 
9
+ ## NPM Package
10
+
11
+ - Package page: https://www.npmjs.com/package/baileys-redis-auth
12
+
7
13
  ## Prerequisites
8
14
 
9
15
  Before using `baileys-redis-auth`, ensure you have the following installed and configured:
10
16
 
11
- * **Node.js:** Version 18.x or higher is recommended.
12
- * **Redis:** A running Redis server instance. You'll need its connection details (host, port, password if any).
13
- * **Baileys:** This library is an auth handler for Baileys, so you should have Baileys as part of your project.
17
+ - **Node.js:** Version 18.x or higher is recommended.
18
+ - **Redis:** A running Redis server instance. You'll need its connection details (host, port, password if any).
19
+ - **Baileys:** This library is an auth handler for Baileys, so you should have Baileys as part of your project.
14
20
 
15
21
  ## Installation
16
22
 
@@ -22,168 +28,295 @@ npm install baileys-redis-auth
22
28
 
23
29
  ### Using `useRedisAuthStateWithHSet` (Recommended)
24
30
 
25
- This is the recommended method for storing Baileys authentication data in Redis. It utilizes Redis Hashes (HSET) to store all authentication credentials and keys under a single Redis key per session prefix. This approach is generally more efficient and organized, especially when managing multiple Baileys sessions.
31
+ This is the recommended method for storing Baileys authentication data in Redis. It utilizes Redis Hashes (HSET) to store all authentication credentials and keys under a single Redis key per session. This approach is generally more efficient and organized, especially when managing multiple Baileys sessions.
26
32
 
27
33
  **Parameters:**
28
- * `redisOptions`: An object containing your Redis server connection details (e.g., `host`, `port`, `password`). This is passed directly to the `ioredis` constructor.
29
- * `prefix`: A string used to namespace your Baileys session data in Redis. For example, if your `prefix` is `'DB1'`, all data for this session will be stored under a Redis key like `authState:DB1`. This allows you to manage multiple independent Baileys sessions in the same Redis database.
30
- * `logger` (optional): A function `(message: string, ...args: unknown[]) => void` for logging Redis connection events. Pass `console.log` or your custom logger function.
34
+
35
+ - `redisOptions`: An object containing your Redis server connection details (e.g., `host`, `port`, `password`). This is passed directly to the `ioredis` constructor.
36
+ - `sessionId`: A string used to identify and namespace your Baileys session data in Redis. For example, if your `sessionId` is `'user-123'`, all data for this session will be stored under a Redis key like `user-123:auth`. This allows you to manage multiple independent Baileys sessions in the same Redis database.
37
+ - `logger` (optional): A function `(message: string, ...args: unknown[]) => void` for logging Redis connection events. Pass `console.log` or your custom logger function.
31
38
 
32
39
  ```typescript
33
- import {useRedisAuthStateWithHSet, deleteHSetKeys} from 'baileys-redis-auth';
34
- import Redis, { RedisOptions } from 'ioredis'; // Assuming ioredis is used like this
40
+ import { useRedisAuthStateWithHSet, deleteHSetKeys } from 'baileys-redis-auth'
41
+ import Redis, { RedisOptions } from 'ioredis'
35
42
 
36
43
  // Define your Redis connection options
37
44
  const redisOptions: RedisOptions = {
38
- host: 'localhost',
39
- port: 6379,
40
- // password: 'your_redis_password', // Uncomment if your Redis has a password
41
- };
45
+ host: 'localhost',
46
+ port: 6379
47
+ // password: 'your_redis_password', // Uncomment if your Redis has a password
48
+ }
42
49
 
43
- // Define a unique prefix for this Baileys session
44
- const sessionPrefix = 'baileys_session_1';
50
+ // Define a unique session identifier for this Baileys session
51
+ const sessionId = 'baileys_session_1'
45
52
 
46
53
  async function initializeBaileysWithHSet() {
47
- // Initialize a new Redis client instance if you need to pass it around or use it elsewhere
48
- // const redis = new Redis(redisOptions);
49
- // redis.on('connect', () => console.log('Connected to Redis for HSet method!'));
50
- // Note: useRedisAuthStateWithHSet creates its own Redis instance internally based on redisOptions.
51
- // If you pass an existing ioredis instance, it should be the first argument,
52
- // and redisOptions the second, though the current library signature seems to expect options first.
53
- // For simplicity, we'll let the function create its own connection.
54
-
55
- const {state, saveCreds, redis: authRedisInstance} = await useRedisAuthStateWithHSet(
56
- redisOptions,
57
- sessionPrefix,
58
- console.log // Optional: pass logger for Redis connection events
59
- );
60
-
61
- // 'state' will be used to initialize Baileys
62
- // 'saveCreds' is a function to periodically save the authentication state
63
- // 'authRedisInstance' is the Redis client instance used by the auth state hook
64
-
65
- console.log('Baileys state loaded using HSet method.');
66
-
67
- // Example: Listen for Redis connection events on the instance returned by the hook
68
- authRedisInstance.on('connect', () => console.log(`Redis (from hook) connected for session: ${sessionPrefix}`));
69
- authRedisInstance.on('error', (err) => console.error(`Redis (from hook) error for session ${sessionPrefix}:`, err));
70
-
71
- // ... your Baileys setup code using 'state' and 'saveCreds'
72
-
73
- // Example of how to delete all keys for this specific session prefix if needed:
74
- // await deleteHSetKeys({redis: authRedisInstance, key: sessionPrefix});
75
- // console.log(`Authentication data for session ${sessionPrefix} deleted.`);
54
+ // useRedisAuthStateWithHSet creates its own Redis instance internally based on redisOptions
55
+
56
+ const {
57
+ state,
58
+ saveCreds,
59
+ redis: authRedisInstance
60
+ } = await useRedisAuthStateWithHSet(
61
+ redisOptions,
62
+ sessionId,
63
+ console.log // Optional: pass logger for Redis connection events
64
+ )
65
+
66
+ // 'state' will be used to initialize Baileys
67
+ // 'saveCreds' is a function to periodically save the authentication state
68
+ // 'authRedisInstance' is the Redis client instance used by the auth state hook
69
+
70
+ console.log('Baileys state loaded using HSet method.')
71
+
72
+ // Example: Listen for Redis connection events on the instance returned by the hook
73
+ authRedisInstance.on('connect', () =>
74
+ console.log(`Redis (from hook) connected for session: ${sessionId}`)
75
+ )
76
+ authRedisInstance.on('error', (err) =>
77
+ console.error(`Redis (from hook) error for session ${sessionId}:`, err)
78
+ )
79
+
80
+ // ... your Baileys setup code using 'state' and 'saveCreds'
81
+
82
+ // Example of how to delete all data for this specific session if needed:
83
+ // await deleteHSetKeys({redis: authRedisInstance, sessionId: sessionId});
84
+ // console.log(`Authentication data for session ${sessionId} deleted.`);
76
85
  }
77
86
 
78
- initializeBaileysWithHSet().catch(console.error);
87
+ initializeBaileysWithHSet().catch(console.error)
79
88
  ```
80
89
 
81
90
  #### Deleting Session Data (`deleteHSetKeys`)
82
91
 
83
- To remove all authentication data associated with a specific session prefix used with `useRedisAuthStateWithHSet`, you can use the `deleteHSetKeys` utility function.
92
+ To remove all authentication data associated with a specific session used with `useRedisAuthStateWithHSet`, you can use the `deleteHSetKeys` utility function.
84
93
 
85
94
  **Usage:**
86
95
 
87
96
  ```typescript
88
- import { deleteHSetKeys } from 'baileys-redis-auth';
89
- import Redis, { RedisOptions } from 'ioredis'; // Or use the instance from useRedisAuthStateWithHSet
97
+ import { deleteHSetKeys } from 'baileys-redis-auth'
98
+ import Redis, { RedisOptions } from 'ioredis' // Or use the instance from useRedisAuthStateWithHSet
90
99
 
91
100
  // Assuming 'authRedisInstance' is the Redis instance from useRedisAuthStateWithHSet
92
101
  // or a new instance configured with the same options.
93
102
  // const redisClient = new Redis(redisOptions);
94
- // const sessionPrefixToDelete = 'baileys_session_1';
103
+ // const sessionIdToDelete = 'baileys_session_1';
95
104
 
96
- // await deleteHSetKeys({redis: authRedisInstance, key: sessionPrefixToDelete});
97
- // console.log(`All HSet data for prefix '${sessionPrefixToDelete}' deleted.`);
105
+ // await deleteHSetKeys({redis: authRedisInstance, sessionId: sessionIdToDelete});
106
+ // console.log(`All HSet data for session '${sessionIdToDelete}' deleted.`);
98
107
  ```
99
108
 
100
109
  **Parameters:**
101
- * `options`: An object with the following properties:
102
- * `redis`: An active `ioredis` client instance.
103
- * `key`: The session `prefix` string (e.g., `'baileys_session_1'`) whose data needs to be deleted. This corresponds to the `prefix` you used with `useRedisAuthStateWithHSet`.
104
- * `logger` (optional): A function for logging deletion operations.
110
+
111
+ - `options`: An object with the following properties:
112
+ - `redis`: An active `ioredis` client instance.
113
+ - `sessionId`: The session identifier string (e.g., `'baileys_session_1'`) whose data needs to be deleted. This corresponds to the `sessionId` you used with `useRedisAuthStateWithHSet`.
114
+ - `logger` (optional): A function for logging deletion operations.
105
115
 
106
116
  ### Using `useRedisAuthState`
107
117
 
108
- This method stores each piece of authentication data as a separate key-value pair in Redis, prefixed by the `prefix` string. While functional, it can lead to a larger number of individual keys in your Redis database compared to the HSET method.
118
+ This method stores each piece of authentication data as a separate key-value pair in Redis, prefixed by the `sessionId` string. While functional, it can lead to a larger number of individual keys in your Redis database compared to the HSET method.
109
119
 
110
120
  **Parameters:**
111
- * `redisOptions`: An object containing your Redis server connection details (e.g., `host`, `port`, `password`). This is passed directly to the `ioredis` constructor.
112
- * `prefix`: A string used to prefix all Redis keys for this Baileys session. For example, if your `prefix` is `'DB1'`, keys will be stored like `DB1:creds`, `DB1:pre-key-1`, etc.
113
- * `logger` (optional): A function `(message: string, ...args: unknown[]) => void` for logging Redis connection events. Pass `console.log` or your custom logger function.
121
+
122
+ - `redisOptions`: An object containing your Redis server connection details (e.g., `host`, `port`, `password`). This is passed directly to the `ioredis` constructor.
123
+ - `sessionId`: A string used to identify and prefix all Redis keys for this Baileys session. For example, if your `sessionId` is `'user-456'`, keys will be stored like `user-456:creds`, `user-456:pre-key-1`, etc.
124
+ - `logger` (optional): A function `(message: string, ...args: unknown[]) => void` for logging Redis connection events. Pass `console.log` or your custom logger function.
114
125
 
115
126
  ```typescript
116
- import {useRedisAuthState, deleteKeysWithPattern} from 'baileys-redis-auth';
117
- import Redis, { RedisOptions } from 'ioredis'; // Assuming ioredis is used like this
127
+ import { useRedisAuthState, deleteKeysWithPattern } from 'baileys-redis-auth'
128
+ import Redis, { RedisOptions } from 'ioredis'
118
129
 
119
130
  // Define your Redis connection options
120
131
  const redisOptions: RedisOptions = {
121
- host: 'localhost',
122
- port: 6379,
123
- // password: 'your_redis_password', // Uncomment if your Redis has a password
124
- };
132
+ host: 'localhost',
133
+ port: 6379
134
+ // password: 'your_redis_password', // Uncomment if your Redis has a password
135
+ }
125
136
 
126
- // Define a unique prefix for this Baileys session
127
- const sessionPrefix = 'baileys_session_2';
137
+ // Define a unique session identifier for this Baileys session
138
+ const sessionId = 'baileys_session_2'
128
139
 
129
140
  async function initializeBaileysSimple() {
130
- // Initialize a new Redis client instance if you need to pass it around
131
- // const redis = new Redis(redisOptions);
132
- // redis.on('connect', () => console.log('Connected to Redis for simple method!'));
133
- // As with HSet, useRedisAuthState creates its own Redis instance.
134
-
135
- const {state, saveCreds, redis: authRedisInstance} = await useRedisAuthState(
136
- redisOptions,
137
- sessionPrefix,
138
- console.log // Optional: pass logger for Redis connection events
139
- );
140
-
141
- // 'state' will be used to initialize Baileys
142
- // 'saveCreds' is a function to periodically save the authentication state
143
- // 'authRedisInstance' is the Redis client instance used by the auth state hook
144
-
145
- console.log('Baileys state loaded using simple key-value method.');
146
-
147
- // Example: Listen for Redis connection events on the instance returned by the hook
148
- authRedisInstance.on('connect', () => console.log(`Redis (from hook) connected for session: ${sessionPrefix}`));
149
- authRedisInstance.on('error', (err) => console.error(`Redis (from hook) error for session ${sessionPrefix}:`, err));
150
-
151
- // ... your Baileys setup code using 'state' and 'saveCreds'
152
-
153
- // Example of how to delete all keys for this specific session prefix if needed:
154
- // The pattern should match the prefix used.
155
- // await deleteKeysWithPattern({redis: authRedisInstance, pattern: `${sessionPrefix}:*`});
156
- // console.log(`Authentication data for session ${sessionPrefix} (pattern: ${sessionPrefix}:*) deleted.`);
141
+ // useRedisAuthState creates its own Redis instance internally based on redisOptions
142
+
143
+ const {
144
+ state,
145
+ saveCreds,
146
+ redis: authRedisInstance
147
+ } = await useRedisAuthState(
148
+ redisOptions,
149
+ sessionId,
150
+ console.log // Optional: pass logger for Redis connection events
151
+ )
152
+
153
+ // 'state' will be used to initialize Baileys
154
+ // 'saveCreds' is a function to periodically save the authentication state
155
+ // 'authRedisInstance' is the Redis client instance used by the auth state hook
156
+
157
+ console.log('Baileys state loaded using simple key-value method.')
158
+
159
+ // Example: Listen for Redis connection events on the instance returned by the hook
160
+ authRedisInstance.on('connect', () =>
161
+ console.log(`Redis (from hook) connected for session: ${sessionId}`)
162
+ )
163
+ authRedisInstance.on('error', (err) =>
164
+ console.error(`Redis (from hook) error for session ${sessionId}:`, err)
165
+ )
166
+
167
+ // ... your Baileys setup code using 'state' and 'saveCreds'
168
+
169
+ // Example of how to delete all keys for this specific session if needed:
170
+ // await deleteKeysWithPattern({redis: authRedisInstance, sessionId: sessionId});
171
+ // console.log(`Authentication data for session ${sessionId} deleted.`);
157
172
  }
158
173
 
159
- initializeBaileysSimple().catch(console.error);
174
+ initializeBaileysSimple().catch(console.error)
160
175
  ```
161
176
 
162
177
  #### Deleting Session Data (`deleteKeysWithPattern`)
163
178
 
164
- To remove all authentication data associated with a specific session prefix used with `useRedisAuthState`, you can use the `deleteKeysWithPattern` utility function. This function deletes all Redis keys matching a given pattern.
179
+ To remove all authentication data associated with a specific session used with `useRedisAuthState`, you can use the `deleteKeysWithPattern` utility function. This function deletes all Redis keys for the given session.
165
180
 
166
181
  **Usage:**
167
182
 
168
183
  ```typescript
169
- import { deleteKeysWithPattern } from 'baileys-redis-auth';
170
- import Redis, { RedisOptions } from 'ioredis'; // Or use the instance from useRedisAuthState
184
+ import { deleteKeysWithPattern } from 'baileys-redis-auth'
185
+ import Redis, { RedisOptions } from 'ioredis' // Or use the instance from useRedisAuthState
171
186
 
172
187
  // Assuming 'authRedisInstance' is the Redis instance from useRedisAuthState
173
188
  // or a new instance configured with the same options.
174
189
  // const redisClient = new Redis(redisOptions);
175
- // const sessionPrefixToDelete = 'baileys_session_2';
190
+ // const sessionIdToDelete = 'baileys_session_2';
176
191
 
177
- // The pattern must match how useRedisAuthState stores keys, typically `prefix:*`
178
- // await deleteKeysWithPattern({redis: authRedisInstance, pattern: `${sessionPrefixToDelete}:*`});
179
- // console.log(`All keys matching pattern '${sessionPrefixToDelete}:*' deleted.`);
192
+ // await deleteKeysWithPattern({redis: authRedisInstance, sessionId: sessionIdToDelete});
193
+ // console.log(`All keys for session '${sessionIdToDelete}' deleted.`);
180
194
  ```
181
195
 
182
196
  **Parameters:**
183
- * `options`: An object with the following properties:
184
- * `redis`: An active `ioredis` client instance.
185
- * `pattern`: The key pattern to delete (e.g., `'baileys_session_2:*'`). This should align with the `prefix` used in `useRedisAuthState`, followed by `:*` to match all related keys.
186
- * `logger` (optional): A function for logging deletion operations.
197
+
198
+ - `options`: An object with the following properties:
199
+ - `redis`: An active `ioredis` client instance.
200
+ - `sessionId`: The session identifier string (e.g., `'baileys_session_2'`) whose data needs to be deleted. This corresponds to the `sessionId` you used with `useRedisAuthState`.
201
+ - `logger` (optional): A function for logging deletion operations.
202
+
203
+ ## Listing Active Sessions
204
+
205
+ The library provides utility functions to discover all active sessions stored in Redis. This is useful for managing multiple WhatsApp connections or performing administrative tasks.
206
+
207
+ ### `listHSetSessions` - List Hash-Based Sessions
208
+
209
+ Lists all session identifiers stored using the `useRedisAuthStateWithHSet` method.
210
+
211
+ **Usage:**
212
+
213
+ ```typescript
214
+ import { listHSetSessions } from 'baileys-redis-auth'
215
+ import Redis from 'ioredis'
216
+
217
+ const redis = new Redis({ host: 'localhost', port: 6379 })
218
+
219
+ async function showAllHashSessions() {
220
+ const sessions = await listHSetSessions({
221
+ redis,
222
+ logger: console.log // Optional: pass logger for debugging
223
+ })
224
+
225
+ console.log('Active Hash-based sessions:', sessions)
226
+ // Output: ['baileys_session_1', 'user-123', 'bot-789']
227
+
228
+ // You can now iterate and manage these sessions
229
+ for (const sessionId of sessions) {
230
+ console.log(`Found session: ${sessionId}`)
231
+ }
232
+ }
233
+
234
+ showAllHashSessions().catch(console.error)
235
+ ```
236
+
237
+ **Parameters:**
238
+
239
+ - `options`: An object with the following properties:
240
+ - `redis`: An active `ioredis` client instance.
241
+ - `logger` (optional): A function for logging scan operations.
242
+
243
+ **Returns:** `Promise<string[]>` - An array of session identifiers.
244
+
245
+ ### `listSessions` - List Key-Value Based Sessions
246
+
247
+ Lists all session identifiers stored using the `useRedisAuthState` method.
248
+
249
+ **Usage:**
250
+
251
+ ```typescript
252
+ import { listSessions } from 'baileys-redis-auth'
253
+ import Redis from 'ioredis'
254
+
255
+ const redis = new Redis({ host: 'localhost', port: 6379 })
256
+
257
+ async function showAllKeyValueSessions() {
258
+ const sessions = await listSessions({
259
+ redis,
260
+ logger: console.log // Optional: pass logger for debugging
261
+ })
262
+
263
+ console.log('Active key-value based sessions:', sessions)
264
+ // Output: ['baileys_session_2', 'user-456', 'bot-012']
265
+
266
+ // You can now iterate and manage these sessions
267
+ for (const sessionId of sessions) {
268
+ console.log(`Found session: ${sessionId}`)
269
+ }
270
+ }
271
+
272
+ showAllKeyValueSessions().catch(console.error)
273
+ ```
274
+
275
+ **Parameters:**
276
+
277
+ - `options`: An object with the following properties:
278
+ - `redis`: An active `ioredis` client instance.
279
+ - `logger` (optional): A function for logging scan operations.
280
+
281
+ **Returns:** `Promise<string[]>` - An array of unique session identifiers.
282
+
283
+ ### Practical Example: Managing Multiple Sessions
284
+
285
+ ```typescript
286
+ import {
287
+ listHSetSessions,
288
+ listSessions,
289
+ deleteHSetKeys,
290
+ deleteKeysWithPattern
291
+ } from 'baileys-redis-auth'
292
+ import Redis from 'ioredis'
293
+
294
+ const redis = new Redis({ host: 'localhost', port: 6379 })
295
+
296
+ async function manageAllSessions() {
297
+ // List all Hash-based sessions
298
+ const hashSessions = await listHSetSessions({ redis })
299
+ console.log('Hash-based sessions:', hashSessions)
300
+
301
+ // List all key-value based sessions
302
+ const kvSessions = await listSessions({ redis })
303
+ console.log('Key-value based sessions:', kvSessions)
304
+
305
+ // Delete a specific Hash session
306
+ if (hashSessions.includes('old-session')) {
307
+ await deleteHSetKeys({ redis, sessionId: 'old-session' })
308
+ console.log('Deleted old-session')
309
+ }
310
+
311
+ // Delete a specific key-value session
312
+ if (kvSessions.includes('inactive-session')) {
313
+ await deleteKeysWithPattern({ redis, sessionId: 'inactive-session' })
314
+ console.log('Deleted inactive-session')
315
+ }
316
+ }
317
+
318
+ manageAllSessions().catch(console.error)
319
+ ```
187
320
 
188
321
  ## Logout and Session Cleanup
189
322
 
@@ -192,18 +325,22 @@ import Redis, { RedisOptions } from 'ioredis'; // Or use the instance from useRe
192
325
  ### Proper Logout Implementation
193
326
 
194
327
  ```typescript
195
- import {deleteKeysWithPattern, useRedisAuthState} from 'baileys-redis-auth'
196
- import makeWASocket, {DisconnectReason} from '@whiskeysockets/baileys'
197
- import type {Boom} from '@hapi/boom'
328
+ import { deleteKeysWithPattern, useRedisAuthState } from 'baileys-redis-auth'
329
+ import makeWASocket, { DisconnectReason } from 'baileys'
330
+ import type { Boom } from '@hapi/boom'
198
331
 
199
- const sessionPrefix = 'my-session'
200
- const {state, saveCreds, redis} = await useRedisAuthState(redisOptions, sessionPrefix, console.log)
332
+ const sessionId = 'my-session'
333
+ const { state, saveCreds, redis } = await useRedisAuthState(
334
+ redisOptions,
335
+ sessionId,
336
+ console.log
337
+ )
201
338
 
202
- const sock = makeWASocket({auth: state})
339
+ const sock = makeWASocket({ auth: state })
203
340
 
204
341
  // Handle connection updates
205
342
  sock.ev.on('connection.update', async (update) => {
206
- const {connection, lastDisconnect} = update
343
+ const { connection, lastDisconnect } = update
207
344
 
208
345
  if (connection === 'close') {
209
346
  const statusCode = (lastDisconnect?.error as Boom)?.output?.statusCode
@@ -212,8 +349,8 @@ sock.ev.on('connection.update', async (update) => {
212
349
  // Clear Redis session on logout
213
350
  await deleteKeysWithPattern({
214
351
  redis,
215
- pattern: `${sessionPrefix}:*`,
216
- logger: console.log // Optional: pass logger for debugging
352
+ sessionId: sessionId,
353
+ logger: console.log // Optional: pass logger for debugging
217
354
  })
218
355
  console.log('Session cleared')
219
356
  }
@@ -231,12 +368,14 @@ For detailed logout implementation guide, see [LOGOUT_GUIDE.md](./LOGOUT_GUIDE.m
231
368
  This project includes an example script to demonstrate the usage of `baileys-redis-auth`. To run it:
232
369
 
233
370
  1. **Clone the repository (if you haven't already):**
371
+
234
372
  ```bash
235
373
  git clone https://github.com/hbinduni/baileys-redis-auth.git
236
374
  cd baileys-redis-auth
237
375
  ```
238
376
 
239
377
  2. **Install dependencies:**
378
+
240
379
  ```bash
241
380
  npm install
242
381
  # or
@@ -248,12 +387,14 @@ This project includes an example script to demonstrate the usage of `baileys-red
248
387
  3. **Ensure you have a Redis server running** and accessible on `localhost:6379` (or update the example script with your Redis configuration).
249
388
 
250
389
  4. **Configure environment variables:**
390
+
251
391
  ```bash
252
392
  cp .env.example .env
253
393
  # Edit .env with your Redis configuration
254
394
  ```
255
395
 
256
396
  5. **Run the example script:**
397
+
257
398
  ```bash
258
399
  npm run example
259
400
  # or
@@ -261,10 +402,12 @@ This project includes an example script to demonstrate the usage of `baileys-red
261
402
  # or
262
403
  # bun run example
263
404
  ```
264
- This command executes `ts-node -r tsconfig-paths/register example/example.ts`.
405
+
406
+ This command executes `tsx example/example.ts`.
265
407
  The example will guide you through connecting to WhatsApp using Baileys with Redis for authentication storage. You'll see a QR code in your terminal to scan with WhatsApp.
266
408
 
267
409
  **Interactive Commands:**
410
+
268
411
  - `send <phone> <message>` - Send a WhatsApp message
269
412
  - `logout` - Logout and clear session
270
413
  - `help` - Show available commands
@@ -286,4 +429,7 @@ Please ensure your code adheres to the existing style and that any new functiona
286
429
  ## License
287
430
 
288
431
  This project is licensed under the MIT License. Refer to the license information in the `package.json` for details.
432
+
433
+ ```
434
+
289
435
  ```
package/lib/index.d.ts CHANGED
@@ -1,42 +1,221 @@
1
- import { type AuthenticationState } from '@whiskeysockets/baileys';
2
- import { type RedisOptions, type Redis as RedisClient } from 'ioredis';
1
+ import { type AuthenticationState } from 'baileys';
2
+ import { Redis, type RedisOptions } from 'ioredis';
3
+ type RedisClient = Redis;
4
+ /**
5
+ * Options for deleting Hash-based authentication state
6
+ */
3
7
  interface IDeleteHSetKeyOptions {
8
+ /** Active Redis client instance */
4
9
  redis: RedisClient;
5
- key: string;
10
+ /** The session identifier to delete */
11
+ sessionId: string;
12
+ /** Optional logging function for debugging */
6
13
  logger?: (message: string, ...args: unknown[]) => void;
7
14
  }
15
+ /**
16
+ * Options for deleting key-value based authentication state
17
+ */
8
18
  interface IDeleteKeysOptions {
19
+ /** Active Redis client instance */
9
20
  redis: RedisClient;
10
- pattern: string;
21
+ /** The session identifier to delete */
22
+ sessionId: string;
23
+ /** Optional logging function for debugging */
24
+ logger?: (message: string, ...args: unknown[]) => void;
25
+ }
26
+ /**
27
+ * Options for listing sessions
28
+ */
29
+ interface IListSessionsOptions {
30
+ /** Active Redis client instance */
31
+ redis: RedisClient;
32
+ /** Optional logging function for debugging */
11
33
  logger?: (message: string, ...args: unknown[]) => void;
12
34
  }
13
35
  /**
14
36
  * Redis-based authentication state storage using Hash (HSET) - Recommended
15
- * Stores all authentication data in a single Redis Hash per prefix
16
- * More efficient than key-value approach for Redis memory and operations
37
+ *
38
+ * Stores all authentication data in a single Redis Hash per session.
39
+ * This approach is more efficient than key-value storage for Redis memory and operations.
40
+ * All authentication state (credentials, keys, and signals) is stored under a single hash key.
41
+ *
42
+ * @param redisOptions - Configuration options for the Redis client connection
43
+ * @param sessionId - Session identifier for the Redis hash key (default: 'session'). The hash key will be `${sessionId}:auth`
44
+ * @param logger - Optional logging function for debugging and monitoring Redis operations
45
+ *
46
+ * @returns Promise that resolves to an object containing:
47
+ * - `state`: The Baileys AuthenticationState object with creds and keys methods
48
+ * - `saveCreds`: Function to manually save credentials to Redis
49
+ * - `redis`: The Redis client instance for manual operations
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const { state, saveCreds, redis } = await useRedisAuthStateWithHSet(
54
+ * { host: 'localhost', port: 6379 },
55
+ * 'my-whatsapp-session',
56
+ * console.log
57
+ * );
58
+ *
59
+ * const conn = makeWASocket({ auth: state });
60
+ * // Credentials are automatically saved on state changes
61
+ * ```
62
+ *
63
+ * @see {@link useRedisAuthState} for key-value based storage alternative
17
64
  */
18
- export declare const useRedisAuthStateWithHSet: (redisOptions: RedisOptions, prefix?: string, logger?: (message: string, ...args: unknown[]) => void) => Promise<{
65
+ export declare const useRedisAuthStateWithHSet: (redisOptions: RedisOptions, sessionId?: string, logger?: (message: string, ...args: unknown[]) => void) => Promise<{
19
66
  state: AuthenticationState;
20
67
  saveCreds: () => Promise<void>;
21
68
  redis: RedisClient;
22
69
  }>;
23
70
  /**
24
- * Deletes all authentication data for a specific prefix using Hash (HSET)
71
+ * Deletes all authentication data for a specific session using Hash (HSET)
72
+ *
73
+ * Removes the entire Redis hash containing all authentication state for the given session.
74
+ * This is the cleanup function for sessions created with `useRedisAuthStateWithHSet`.
75
+ *
76
+ * @param options - Configuration object
77
+ * @param options.redis - Active Redis client instance
78
+ * @param options.sessionId - The session identifier to delete (e.g., 'session', 'my-whatsapp-session')
79
+ * @param options.logger - Optional logging function for debugging
80
+ *
81
+ * @returns Promise that resolves when the deletion is complete
82
+ *
83
+ * @throws {Error} If Redis deletion operation fails
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * const { redis } = await useRedisAuthStateWithHSet({ host: 'localhost' }, 'session-123');
88
+ *
89
+ * // Later, to logout and clean up:
90
+ * await deleteHSetKeys({
91
+ * redis,
92
+ * sessionId: 'session-123',
93
+ * logger: console.log
94
+ * });
95
+ * ```
96
+ *
97
+ * @see {@link useRedisAuthStateWithHSet} for the corresponding storage function
25
98
  */
26
- export declare const deleteHSetKeys: ({ redis, key, logger }: IDeleteHSetKeyOptions) => Promise<void>;
99
+ export declare const deleteHSetKeys: ({ redis, sessionId, logger }: IDeleteHSetKeyOptions) => Promise<void>;
27
100
  /**
28
101
  * Redis-based authentication state storage using key-value pairs
29
- * Stores each piece of authentication data as a separate Redis key
30
- * Less efficient than Hash approach but more compatible with existing systems
102
+ *
103
+ * Stores each piece of authentication data as a separate Redis key with the pattern `${sessionId}:${key}`.
104
+ * This approach is less efficient than the Hash-based storage but offers more compatibility with
105
+ * existing systems and allows for more granular key management and expiration.
106
+ *
107
+ * @param redisOptions - Configuration options for the Redis client connection
108
+ * @param sessionId - Session identifier for Redis keys (default: 'session'). Each key will be `${sessionId}:${keyname}`
109
+ * @param logger - Optional logging function for debugging and monitoring Redis operations
110
+ *
111
+ * @returns Promise that resolves to an object containing:
112
+ * - `state`: The Baileys AuthenticationState object with creds and keys methods
113
+ * - `saveCreds`: Function to manually save credentials to Redis
114
+ * - `redis`: The Redis client instance for manual operations
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * const { state, saveCreds, redis } = await useRedisAuthState(
119
+ * { host: 'localhost', port: 6379 },
120
+ * 'my-whatsapp-session',
121
+ * console.log
122
+ * );
123
+ *
124
+ * const conn = makeWASocket({ auth: state });
125
+ * // Credentials are automatically saved on state changes
126
+ * ```
127
+ *
128
+ * @see {@link useRedisAuthStateWithHSet} for the recommended Hash-based storage alternative
31
129
  */
32
- export declare const useRedisAuthState: (redisOptions: RedisOptions, prefix?: string, logger?: (message: string, ...args: unknown[]) => void) => Promise<{
130
+ export declare const useRedisAuthState: (redisOptions: RedisOptions, sessionId?: string, logger?: (message: string, ...args: unknown[]) => void) => Promise<{
33
131
  state: AuthenticationState;
34
132
  saveCreds: () => Promise<void>;
35
133
  redis: RedisClient;
36
134
  }>;
37
135
  /**
38
- * Deletes all authentication keys matching a pattern using key-value approach
39
- * Uses SCAN to safely iterate through keys without blocking Redis
136
+ * Deletes all authentication keys for a specific session using key-value approach
137
+ *
138
+ * Uses Redis SCAN command to safely iterate through keys without blocking the Redis server.
139
+ * This is the cleanup function for sessions created with `useRedisAuthState`.
140
+ * The SCAN operation is cursor-based and processes keys in batches of 100.
141
+ *
142
+ * @param options - Configuration object
143
+ * @param options.redis - Active Redis client instance
144
+ * @param options.sessionId - The session identifier to delete (e.g., 'session', 'my-whatsapp-session')
145
+ * @param options.logger - Optional logging function for debugging and monitoring deletion progress
146
+ *
147
+ * @returns Promise that resolves when all matching keys have been deleted
148
+ *
149
+ * @throws {Error} If Redis SCAN or UNLINK operations fail
150
+ *
151
+ * @example
152
+ * ```typescript
153
+ * const { redis } = await useRedisAuthState({ host: 'localhost' }, 'session-123');
154
+ *
155
+ * // Later, to logout and clean up all keys for this session:
156
+ * await deleteKeysWithPattern({
157
+ * redis,
158
+ * sessionId: 'session-123',
159
+ * logger: console.log
160
+ * });
161
+ * ```
162
+ *
163
+ * @see {@link useRedisAuthState} for the corresponding storage function
164
+ * @see {@link deleteHSetKeys} for Hash-based storage cleanup
165
+ */
166
+ export declare const deleteKeysWithPattern: ({ redis, sessionId, logger }: IDeleteKeysOptions) => Promise<void>;
167
+ /**
168
+ * Lists all session identifiers stored using Hash (HSET) approach
169
+ *
170
+ * Scans Redis for all hash keys with the pattern `*:auth` and extracts the session identifiers.
171
+ * This is useful for discovering all active sessions created with `useRedisAuthStateWithHSet`.
172
+ *
173
+ * @param options - Configuration object
174
+ * @param options.redis - Active Redis client instance
175
+ * @param options.logger - Optional logging function for debugging
176
+ *
177
+ * @returns Promise that resolves to an array of session identifiers
178
+ *
179
+ * @throws {Error} If Redis SCAN operation fails
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * const redis = new Redis({ host: 'localhost' });
184
+ *
185
+ * const sessions = await listHSetSessions({ redis, logger: console.log });
186
+ * console.log('Active sessions:', sessions);
187
+ * // Output: ['session-123', 'user-456', 'bot-789']
188
+ * ```
189
+ *
190
+ * @see {@link useRedisAuthStateWithHSet} for the corresponding storage function
191
+ * @see {@link listSessions} for key-value based session listing
192
+ */
193
+ export declare const listHSetSessions: ({ redis, logger }: IListSessionsOptions) => Promise<string[]>;
194
+ /**
195
+ * Lists all session identifiers stored using key-value approach
196
+ *
197
+ * Scans Redis for all keys with the pattern `*:creds` and extracts unique session identifiers.
198
+ * This is useful for discovering all active sessions created with `useRedisAuthState`.
199
+ *
200
+ * @param options - Configuration object
201
+ * @param options.redis - Active Redis client instance
202
+ * @param options.logger - Optional logging function for debugging
203
+ *
204
+ * @returns Promise that resolves to an array of unique session identifiers
205
+ *
206
+ * @throws {Error} If Redis SCAN operation fails
207
+ *
208
+ * @example
209
+ * ```typescript
210
+ * const redis = new Redis({ host: 'localhost' });
211
+ *
212
+ * const sessions = await listSessions({ redis, logger: console.log });
213
+ * console.log('Active sessions:', sessions);
214
+ * // Output: ['session-123', 'user-456', 'bot-789']
215
+ * ```
216
+ *
217
+ * @see {@link useRedisAuthState} for the corresponding storage function
218
+ * @see {@link listHSetSessions} for Hash-based session listing
40
219
  */
41
- export declare const deleteKeysWithPattern: ({ redis, pattern, logger }: IDeleteKeysOptions) => Promise<void>;
220
+ export declare const listSessions: ({ redis, logger }: IListSessionsOptions) => Promise<string[]>;
42
221
  export {};
package/lib/index.js CHANGED
@@ -1,40 +1,76 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.deleteKeysWithPattern = exports.useRedisAuthState = exports.deleteHSetKeys = exports.useRedisAuthStateWithHSet = void 0;
7
- const baileys_1 = require("@whiskeysockets/baileys");
8
- const ioredis_1 = __importDefault(require("ioredis"));
1
+ import { BufferJSON, initAuthCreds, proto, } from 'baileys';
2
+ import { Redis } from 'ioredis';
9
3
  /**
10
4
  * Sanitizes a string to make it safe for use as a Redis key
11
- * Replaces "/" with "__" and ":" with "-"
5
+ *
6
+ * Replaces problematic characters that might cause issues in Redis keys:
7
+ * - Forward slashes (/) are replaced with double underscores (__)
8
+ * - Colons (:) are replaced with hyphens (-)
9
+ *
10
+ * @param file - The string to sanitize
11
+ * @returns The sanitized string safe for use as a Redis key component
12
+ *
13
+ * @internal
12
14
  */
13
15
  const fixFileName = (file) => file.replace(/\//g, '__').replace(/:/g, '-');
14
- const createKey = (key, prefix) => `${prefix}:${key}`;
16
+ /**
17
+ * Creates a namespaced Redis key by combining sessionId and key
18
+ *
19
+ * @param key - The key name
20
+ * @param sessionId - The session identifier
21
+ * @returns The combined key in the format `${sessionId}:${key}`
22
+ *
23
+ * @internal
24
+ */
25
+ const createKey = (key, sessionId) => `${sessionId}:${key}`;
15
26
  /**
16
27
  * Redis-based authentication state storage using Hash (HSET) - Recommended
17
- * Stores all authentication data in a single Redis Hash per prefix
18
- * More efficient than key-value approach for Redis memory and operations
28
+ *
29
+ * Stores all authentication data in a single Redis Hash per session.
30
+ * This approach is more efficient than key-value storage for Redis memory and operations.
31
+ * All authentication state (credentials, keys, and signals) is stored under a single hash key.
32
+ *
33
+ * @param redisOptions - Configuration options for the Redis client connection
34
+ * @param sessionId - Session identifier for the Redis hash key (default: 'session'). The hash key will be `${sessionId}:auth`
35
+ * @param logger - Optional logging function for debugging and monitoring Redis operations
36
+ *
37
+ * @returns Promise that resolves to an object containing:
38
+ * - `state`: The Baileys AuthenticationState object with creds and keys methods
39
+ * - `saveCreds`: Function to manually save credentials to Redis
40
+ * - `redis`: The Redis client instance for manual operations
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * const { state, saveCreds, redis } = await useRedisAuthStateWithHSet(
45
+ * { host: 'localhost', port: 6379 },
46
+ * 'my-whatsapp-session',
47
+ * console.log
48
+ * );
49
+ *
50
+ * const conn = makeWASocket({ auth: state });
51
+ * // Credentials are automatically saved on state changes
52
+ * ```
53
+ *
54
+ * @see {@link useRedisAuthState} for key-value based storage alternative
19
55
  */
20
- const useRedisAuthStateWithHSet = async (redisOptions, prefix = 'session', logger) => {
21
- const redis = new ioredis_1.default(redisOptions);
56
+ export const useRedisAuthStateWithHSet = async (redisOptions, sessionId = 'session', logger) => {
57
+ const redis = new Redis(redisOptions);
22
58
  redis.on('connect', async () => {
23
- const redisClientName = `baileys-auth-${prefix}`;
59
+ const redisClientName = `baileys-auth-${sessionId}`;
24
60
  await redis.client('SETNAME', redisClientName);
25
- logger === null || logger === void 0 ? void 0 : logger(`Redis client name set to ${redisClientName}`);
61
+ logger?.(`Redis client name set to ${redisClientName}`);
26
62
  });
27
63
  const writeData = async (key, data) => {
28
- await redis.hset(createKey('auth', prefix), key, JSON.stringify(data, baileys_1.BufferJSON.replacer));
64
+ await redis.hset(createKey('auth', sessionId), key, JSON.stringify(data, BufferJSON.replacer));
29
65
  };
30
66
  const readData = async (key) => {
31
- const data = await redis.hget(createKey('auth', prefix), key);
32
- return data ? JSON.parse(data, baileys_1.BufferJSON.reviver) : null;
67
+ const data = await redis.hget(createKey('auth', sessionId), key);
68
+ return data ? JSON.parse(data, BufferJSON.reviver) : null;
33
69
  };
34
70
  const removeData = async (key) => {
35
- await redis.hdel(createKey('auth', prefix), key);
71
+ await redis.hdel(createKey('auth', sessionId), key);
36
72
  };
37
- const creds = (await readData('creds')) || (0, baileys_1.initAuthCreds)();
73
+ const creds = (await readData('creds')) || initAuthCreds();
38
74
  return {
39
75
  state: {
40
76
  creds,
@@ -45,7 +81,7 @@ const useRedisAuthStateWithHSet = async (redisOptions, prefix = 'session', logge
45
81
  const key = `${type}-${fixFileName(id)}`;
46
82
  const value = await readData(key);
47
83
  if (value) {
48
- data[id] = (type === 'app-state-sync-key' ? baileys_1.proto.Message.AppStateSyncKeyData.fromObject(value) : value);
84
+ data[id] = (type === 'app-state-sync-key' ? proto.Message.AppStateSyncKeyData.fromObject(value) : value);
49
85
  }
50
86
  }));
51
87
  return data;
@@ -74,46 +110,94 @@ const useRedisAuthStateWithHSet = async (redisOptions, prefix = 'session', logge
74
110
  redis,
75
111
  };
76
112
  };
77
- exports.useRedisAuthStateWithHSet = useRedisAuthStateWithHSet;
78
113
  /**
79
- * Deletes all authentication data for a specific prefix using Hash (HSET)
114
+ * Deletes all authentication data for a specific session using Hash (HSET)
115
+ *
116
+ * Removes the entire Redis hash containing all authentication state for the given session.
117
+ * This is the cleanup function for sessions created with `useRedisAuthStateWithHSet`.
118
+ *
119
+ * @param options - Configuration object
120
+ * @param options.redis - Active Redis client instance
121
+ * @param options.sessionId - The session identifier to delete (e.g., 'session', 'my-whatsapp-session')
122
+ * @param options.logger - Optional logging function for debugging
123
+ *
124
+ * @returns Promise that resolves when the deletion is complete
125
+ *
126
+ * @throws {Error} If Redis deletion operation fails
127
+ *
128
+ * @example
129
+ * ```typescript
130
+ * const { redis } = await useRedisAuthStateWithHSet({ host: 'localhost' }, 'session-123');
131
+ *
132
+ * // Later, to logout and clean up:
133
+ * await deleteHSetKeys({
134
+ * redis,
135
+ * sessionId: 'session-123',
136
+ * logger: console.log
137
+ * });
138
+ * ```
139
+ *
140
+ * @see {@link useRedisAuthStateWithHSet} for the corresponding storage function
80
141
  */
81
- const deleteHSetKeys = async ({ redis, key, logger }) => {
142
+ export const deleteHSetKeys = async ({ redis, sessionId, logger }) => {
82
143
  try {
83
- logger === null || logger === void 0 ? void 0 : logger('Removing auth state keys for prefix:', key);
84
- await redis.del(createKey('auth', key));
144
+ logger?.('Removing auth state for session:', sessionId);
145
+ await redis.del(createKey('auth', sessionId));
85
146
  }
86
147
  catch (err) {
87
148
  const error = err;
88
- logger === null || logger === void 0 ? void 0 : logger('Error deleting keys:', error.message);
149
+ logger?.('Error deleting session:', error.message);
89
150
  throw error;
90
151
  }
91
152
  };
92
- exports.deleteHSetKeys = deleteHSetKeys;
93
153
  /**
94
154
  * Redis-based authentication state storage using key-value pairs
95
- * Stores each piece of authentication data as a separate Redis key
96
- * Less efficient than Hash approach but more compatible with existing systems
155
+ *
156
+ * Stores each piece of authentication data as a separate Redis key with the pattern `${sessionId}:${key}`.
157
+ * This approach is less efficient than the Hash-based storage but offers more compatibility with
158
+ * existing systems and allows for more granular key management and expiration.
159
+ *
160
+ * @param redisOptions - Configuration options for the Redis client connection
161
+ * @param sessionId - Session identifier for Redis keys (default: 'session'). Each key will be `${sessionId}:${keyname}`
162
+ * @param logger - Optional logging function for debugging and monitoring Redis operations
163
+ *
164
+ * @returns Promise that resolves to an object containing:
165
+ * - `state`: The Baileys AuthenticationState object with creds and keys methods
166
+ * - `saveCreds`: Function to manually save credentials to Redis
167
+ * - `redis`: The Redis client instance for manual operations
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * const { state, saveCreds, redis } = await useRedisAuthState(
172
+ * { host: 'localhost', port: 6379 },
173
+ * 'my-whatsapp-session',
174
+ * console.log
175
+ * );
176
+ *
177
+ * const conn = makeWASocket({ auth: state });
178
+ * // Credentials are automatically saved on state changes
179
+ * ```
180
+ *
181
+ * @see {@link useRedisAuthStateWithHSet} for the recommended Hash-based storage alternative
97
182
  */
98
- const useRedisAuthState = async (redisOptions, prefix = 'session', logger) => {
99
- var _a;
100
- const redis = new ioredis_1.default(redisOptions);
183
+ export const useRedisAuthState = async (redisOptions, sessionId = 'session', logger) => {
184
+ const redis = new Redis(redisOptions);
101
185
  redis.on('connect', async () => {
102
- const redisClientName = `baileys-auth-${prefix}`;
186
+ const redisClientName = `baileys-auth-${sessionId}`;
103
187
  await redis.client('SETNAME', redisClientName);
104
- logger === null || logger === void 0 ? void 0 : logger(`Redis client name set to ${redisClientName}`);
188
+ logger?.(`Redis client name set to ${redisClientName}`);
105
189
  });
106
190
  const writeData = async (key, data) => {
107
- await redis.set(createKey(key, prefix), JSON.stringify(data, baileys_1.BufferJSON.replacer));
191
+ await redis.set(createKey(key, sessionId), JSON.stringify(data, BufferJSON.replacer));
108
192
  };
109
193
  const readData = async (key) => {
110
- const data = await redis.get(createKey(key, prefix));
111
- return data ? JSON.parse(data, baileys_1.BufferJSON.reviver) : null;
194
+ const data = await redis.get(createKey(key, sessionId));
195
+ return data ? JSON.parse(data, BufferJSON.reviver) : null;
112
196
  };
113
197
  const removeData = async (key) => {
114
- await redis.del(createKey(key, prefix));
198
+ await redis.del(createKey(key, sessionId));
115
199
  };
116
- const creds = (_a = (await readData('creds'))) !== null && _a !== void 0 ? _a : (0, baileys_1.initAuthCreds)();
200
+ const creds = (await readData('creds')) ?? initAuthCreds();
117
201
  return {
118
202
  state: {
119
203
  creds,
@@ -124,7 +208,7 @@ const useRedisAuthState = async (redisOptions, prefix = 'session', logger) => {
124
208
  const key = `${type}-${fixFileName(id)}`;
125
209
  const value = await readData(key);
126
210
  if (value) {
127
- data[id] = (type === 'app-state-sync-key' ? baileys_1.proto.Message.AppStateSyncKeyData.fromObject(value) : value);
211
+ data[id] = (type === 'app-state-sync-key' ? proto.Message.AppStateSyncKeyData.fromObject(value) : value);
128
212
  }
129
213
  }));
130
214
  return data;
@@ -153,28 +237,157 @@ const useRedisAuthState = async (redisOptions, prefix = 'session', logger) => {
153
237
  redis,
154
238
  };
155
239
  };
156
- exports.useRedisAuthState = useRedisAuthState;
157
240
  /**
158
- * Deletes all authentication keys matching a pattern using key-value approach
159
- * Uses SCAN to safely iterate through keys without blocking Redis
241
+ * Deletes all authentication keys for a specific session using key-value approach
242
+ *
243
+ * Uses Redis SCAN command to safely iterate through keys without blocking the Redis server.
244
+ * This is the cleanup function for sessions created with `useRedisAuthState`.
245
+ * The SCAN operation is cursor-based and processes keys in batches of 100.
246
+ *
247
+ * @param options - Configuration object
248
+ * @param options.redis - Active Redis client instance
249
+ * @param options.sessionId - The session identifier to delete (e.g., 'session', 'my-whatsapp-session')
250
+ * @param options.logger - Optional logging function for debugging and monitoring deletion progress
251
+ *
252
+ * @returns Promise that resolves when all matching keys have been deleted
253
+ *
254
+ * @throws {Error} If Redis SCAN or UNLINK operations fail
255
+ *
256
+ * @example
257
+ * ```typescript
258
+ * const { redis } = await useRedisAuthState({ host: 'localhost' }, 'session-123');
259
+ *
260
+ * // Later, to logout and clean up all keys for this session:
261
+ * await deleteKeysWithPattern({
262
+ * redis,
263
+ * sessionId: 'session-123',
264
+ * logger: console.log
265
+ * });
266
+ * ```
267
+ *
268
+ * @see {@link useRedisAuthState} for the corresponding storage function
269
+ * @see {@link deleteHSetKeys} for Hash-based storage cleanup
160
270
  */
161
- const deleteKeysWithPattern = async ({ redis, pattern, logger }) => {
271
+ export const deleteKeysWithPattern = async ({ redis, sessionId, logger }) => {
162
272
  try {
163
- logger === null || logger === void 0 ? void 0 : logger('Removing auth state keys matching pattern:', pattern);
273
+ const pattern = `${sessionId}:*`;
274
+ logger?.('Removing auth state for session:', sessionId);
164
275
  let cursor = 0;
165
276
  do {
166
277
  const [nextCursor, keys] = await redis.scan(cursor, 'MATCH', pattern, 'COUNT', 100);
167
278
  cursor = Number.parseInt(nextCursor, 10);
168
279
  if (keys.length > 0) {
169
280
  await redis.unlink(...keys);
170
- logger === null || logger === void 0 ? void 0 : logger(`Deleted keys: ${keys.join(', ')}`);
281
+ logger?.(`Deleted ${keys.length} keys for session: ${sessionId}`);
282
+ }
283
+ } while (cursor !== 0);
284
+ }
285
+ catch (err) {
286
+ const error = err;
287
+ logger?.('Error deleting session:', error.message);
288
+ throw error;
289
+ }
290
+ };
291
+ /**
292
+ * Lists all session identifiers stored using Hash (HSET) approach
293
+ *
294
+ * Scans Redis for all hash keys with the pattern `*:auth` and extracts the session identifiers.
295
+ * This is useful for discovering all active sessions created with `useRedisAuthStateWithHSet`.
296
+ *
297
+ * @param options - Configuration object
298
+ * @param options.redis - Active Redis client instance
299
+ * @param options.logger - Optional logging function for debugging
300
+ *
301
+ * @returns Promise that resolves to an array of session identifiers
302
+ *
303
+ * @throws {Error} If Redis SCAN operation fails
304
+ *
305
+ * @example
306
+ * ```typescript
307
+ * const redis = new Redis({ host: 'localhost' });
308
+ *
309
+ * const sessions = await listHSetSessions({ redis, logger: console.log });
310
+ * console.log('Active sessions:', sessions);
311
+ * // Output: ['session-123', 'user-456', 'bot-789']
312
+ * ```
313
+ *
314
+ * @see {@link useRedisAuthStateWithHSet} for the corresponding storage function
315
+ * @see {@link listSessions} for key-value based session listing
316
+ */
317
+ export const listHSetSessions = async ({ redis, logger }) => {
318
+ try {
319
+ const sessions = [];
320
+ let cursor = 0;
321
+ logger?.('Scanning for Hash-based sessions...');
322
+ do {
323
+ const [nextCursor, keys] = await redis.scan(cursor, 'MATCH', '*:auth', 'COUNT', 100);
324
+ cursor = Number.parseInt(nextCursor, 10);
325
+ for (const key of keys) {
326
+ // Extract sessionId from "sessionId:auth" pattern
327
+ const sessionId = key.replace(':auth', '');
328
+ if (sessionId) {
329
+ sessions.push(sessionId);
330
+ }
331
+ }
332
+ } while (cursor !== 0);
333
+ logger?.(`Found ${sessions.length} Hash-based sessions`);
334
+ return sessions;
335
+ }
336
+ catch (err) {
337
+ const error = err;
338
+ logger?.('Error listing sessions:', error.message);
339
+ throw error;
340
+ }
341
+ };
342
+ /**
343
+ * Lists all session identifiers stored using key-value approach
344
+ *
345
+ * Scans Redis for all keys with the pattern `*:creds` and extracts unique session identifiers.
346
+ * This is useful for discovering all active sessions created with `useRedisAuthState`.
347
+ *
348
+ * @param options - Configuration object
349
+ * @param options.redis - Active Redis client instance
350
+ * @param options.logger - Optional logging function for debugging
351
+ *
352
+ * @returns Promise that resolves to an array of unique session identifiers
353
+ *
354
+ * @throws {Error} If Redis SCAN operation fails
355
+ *
356
+ * @example
357
+ * ```typescript
358
+ * const redis = new Redis({ host: 'localhost' });
359
+ *
360
+ * const sessions = await listSessions({ redis, logger: console.log });
361
+ * console.log('Active sessions:', sessions);
362
+ * // Output: ['session-123', 'user-456', 'bot-789']
363
+ * ```
364
+ *
365
+ * @see {@link useRedisAuthState} for the corresponding storage function
366
+ * @see {@link listHSetSessions} for Hash-based session listing
367
+ */
368
+ export const listSessions = async ({ redis, logger }) => {
369
+ try {
370
+ const sessionsSet = new Set();
371
+ let cursor = 0;
372
+ logger?.('Scanning for key-value based sessions...');
373
+ do {
374
+ const [nextCursor, keys] = await redis.scan(cursor, 'MATCH', '*:creds', 'COUNT', 100);
375
+ cursor = Number.parseInt(nextCursor, 10);
376
+ for (const key of keys) {
377
+ // Extract sessionId from "sessionId:creds" pattern
378
+ const sessionId = key.replace(':creds', '');
379
+ if (sessionId) {
380
+ sessionsSet.add(sessionId);
381
+ }
171
382
  }
172
383
  } while (cursor !== 0);
384
+ const sessions = Array.from(sessionsSet);
385
+ logger?.(`Found ${sessions.length} key-value based sessions`);
386
+ return sessions;
173
387
  }
174
388
  catch (err) {
175
389
  const error = err;
176
- logger === null || logger === void 0 ? void 0 : logger('Error deleting keys:', error.message);
390
+ logger?.('Error listing sessions:', error.message);
177
391
  throw error;
178
392
  }
179
393
  };
180
- exports.deleteKeysWithPattern = deleteKeysWithPattern;
package/package.json CHANGED
@@ -1,20 +1,28 @@
1
1
  {
2
2
  "name": "baileys-redis-auth",
3
- "version": "1.1.0",
3
+ "version": "2.0.1",
4
4
  "description": "Redis Auth for Baileys",
5
5
  "author": "heriyanto binduni <hbinduni@gmail.com>",
6
6
  "license": "MIT",
7
+ "type": "module",
7
8
  "main": "lib/index.js",
9
+ "module": "lib/index.js",
8
10
  "types": "lib/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "import": "./lib/index.js",
14
+ "types": "./lib/index.d.ts"
15
+ }
16
+ },
9
17
  "homepage": "https://github.com/hbinduni/baileys-redis-auth",
10
18
  "repository": {
11
- "url": "https://github.com/hbinduni/baileys-redis-auth.git"
19
+ "url": "git+https://github.com/hbinduni/baileys-redis-auth.git"
12
20
  },
13
21
  "scripts": {
14
22
  "clean": "rm -rf lib",
15
23
  "build": "bun run clean && tsc -p tsconfig.json",
16
24
  "prebuild": "bun run check:all",
17
- "example": "ts-node -r tsconfig-paths/register example/example.ts",
25
+ "example": "tsx example/example.ts",
18
26
  "example:no-all": "bun run example -- --no-store --no-reply",
19
27
  "typecheck": "bun x tsc --noEmit -p tsconfig.json",
20
28
  "format": "biome format --write .",
@@ -36,21 +44,27 @@
36
44
  "auth"
37
45
  ],
38
46
  "devDependencies": {
39
- "@adiwajshing/keyed-db": "^0.2.4",
40
47
  "@biomejs/biome": "^1.9.4",
41
48
  "@hapi/boom": "^10.0.1",
42
- "@types/node": "^24.7.0",
49
+ "@types/node": "^24.10.4",
50
+ "baileys": "^7.0.0-rc.9",
43
51
  "dotenv": "^17.2.3",
44
52
  "node-cache": "^5.1.2",
45
- "pino": "^9.13.1",
46
- "pino-pretty": "^13.1.1",
53
+ "pino": "^9.14.0",
54
+ "pino-pretty": "^13.1.3",
47
55
  "qrcode-terminal": "^0.12.0",
48
- "ts-node": "^10.9.2",
49
- "tsconfig-paths": "^4.2.0",
56
+ "tsx": "^4.19.0",
50
57
  "typescript": "^5.9.3"
51
58
  },
52
59
  "dependencies": {
53
- "@whiskeysockets/baileys": "^6.7.20",
54
- "ioredis": "^5.8.1"
60
+ "ioredis": "^5.8.2"
61
+ },
62
+ "peerDependencies": {
63
+ "baileys": ">=7.0.0-rc.9"
64
+ },
65
+ "peerDependenciesMeta": {
66
+ "baileys": {
67
+ "optional": false
68
+ }
55
69
  }
56
70
  }