faye-redis-ng 1.0.2 → 1.1.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 CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  ![NPM Version](https://img.shields.io/npm/v/faye-redis-ng)
4
4
  [![Node.js Version](https://img.shields.io/node/v/faye-redis-ng.svg)](https://nodejs.org)
5
- [![CI](https://github.com/7a6163/faye-redis-node/workflows/CI/badge.svg)](https://github.com/7a6163/faye-redis-node/actions)
5
+ [![CI](https://github.com/7a6163/faye-redis-node-ng/workflows/CI/badge.svg)](https://github.com/7a6163/faye-redis-node-ng/actions)
6
+ [![codecov](https://codecov.io/gh/7a6163/faye-redis-node-ng/branch/main/graph/badge.svg)](https://codecov.io/gh/7a6163/faye-redis-node-ng)
6
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
8
 
8
9
  **Next Generation** Redis backend engine for [Faye](http://faye.jcoglan.com) - A modern, maintained fork with Redis v4 support, ES6+ syntax, and automatic reconnection.
@@ -13,11 +14,13 @@ This is a modernized fork of the original [faye-redis](https://github.com/7a6163
13
14
 
14
15
  ### ✨ Key Improvements
15
16
 
17
+ - ✅ **TypeScript Support** - Full TypeScript rewrite with type definitions
16
18
  - ✅ **Redis v4 Support** - Uses modern Promise-based Redis client API
17
19
  - ✅ **ES6+ Syntax** - Modern JavaScript with classes, async/await, const/let
18
20
  - ✅ **Auto-Reconnection** - Automatic Redis reconnection with exponential backoff
19
21
  - ✅ **Better Error Handling** - Comprehensive error logging and event triggers
20
22
  - ✅ **Node.js 22 LTS** - Updated for latest LTS Node.js version
23
+ - ✅ **Modern Testing** - Vitest with 77%+ code coverage
21
24
  - ✅ **Zero Breaking Changes** - Drop-in replacement for original faye-redis
22
25
 
23
26
  ### 🔄 Why This Fork?
@@ -0,0 +1,38 @@
1
+ import type { EngineOptions, FayeMessage, FayeServer, CallbackContext, ClientCallback, ExistsCallback, EmptyCallback } from './types';
2
+ declare class Engine {
3
+ private readonly DEFAULT_HOST;
4
+ private readonly DEFAULT_PORT;
5
+ private readonly DEFAULT_DATABASE;
6
+ private readonly DEFAULT_GC;
7
+ private readonly LOCK_TIMEOUT;
8
+ private _server;
9
+ private _options;
10
+ private _ns;
11
+ private _messageChannel;
12
+ private _closeChannel;
13
+ private _redis;
14
+ private _subscriber;
15
+ private _initialized;
16
+ private _subscriptionsSetUp;
17
+ private _gc;
18
+ constructor(server: FayeServer, options?: EngineOptions);
19
+ private _initializeClients;
20
+ private _reconnectStrategy;
21
+ private _waitForInit;
22
+ static create(server: FayeServer, options?: EngineOptions): Engine;
23
+ disconnect(): Promise<void>;
24
+ createClient(callback: ClientCallback, context: CallbackContext): void;
25
+ clientExists(clientId: string, callback: ExistsCallback, context: CallbackContext): void;
26
+ destroyClient(clientId: string, callback?: EmptyCallback, context?: CallbackContext): void;
27
+ ping(clientId: string): void;
28
+ subscribe(clientId: string, channel: string, callback?: EmptyCallback, context?: CallbackContext): void;
29
+ unsubscribe(clientId: string, channel: string, callback?: EmptyCallback, context?: CallbackContext): void;
30
+ publish(message: FayeMessage, channels: string[]): void;
31
+ emptyQueue(clientId: string): void;
32
+ gc(): void;
33
+ private _withLock;
34
+ }
35
+ export default Engine;
36
+ export { Engine };
37
+ export type { EngineOptions, FayeMessage, FayeServer };
38
+ //# sourceMappingURL=faye-redis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"faye-redis.d.ts","sourceRoot":"","sources":["../src/faye-redis.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,UAAU,EAEV,eAAe,EACf,cAAc,EACd,cAAc,EACd,aAAa,EACd,MAAM,SAAS,CAAC;AAEjB,cAAM,MAAM;IACV,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAQ;IACrC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAK;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAM;IACjC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAO;IAEpC,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,GAAG,CAAiB;gBAEhB,MAAM,EAAE,UAAU,EAAE,OAAO,GAAE,aAAkB;YAiB7C,kBAAkB;IA0FhC,OAAO,CAAC,kBAAkB;YAYZ,YAAY;IAM1B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM;IAI5D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAWjC,YAAY,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;IAqBtE,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;IAWxF,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI;IAkC1F,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAc5B,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI;IAgBvG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI;IAgBzG,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI;IA+BvD,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAsBlC,EAAE,IAAI,IAAI;IA0BV,OAAO,CAAC,SAAS;CA+BlB;AAED,eAAe,MAAM,CAAC;AACtB,OAAO,EAAE,MAAM,EAAE,CAAC;AAClB,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,336 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Engine = void 0;
4
+ const redis_1 = require("redis");
5
+ class Engine {
6
+ DEFAULT_HOST = 'localhost';
7
+ DEFAULT_PORT = 6379;
8
+ DEFAULT_DATABASE = 0;
9
+ DEFAULT_GC = 60;
10
+ LOCK_TIMEOUT = 120;
11
+ _server;
12
+ _options;
13
+ _ns;
14
+ _messageChannel;
15
+ _closeChannel;
16
+ _redis = null;
17
+ _subscriber = null;
18
+ _initialized = false;
19
+ _subscriptionsSetUp = false;
20
+ _gc;
21
+ constructor(server, options = {}) {
22
+ this._server = server;
23
+ this._options = options;
24
+ this._ns = options.namespace || '';
25
+ this._messageChannel = this._ns + '/notifications/messages';
26
+ this._closeChannel = this._ns + '/notifications/close';
27
+ // Start initialization
28
+ this._initializeClients().catch(err => {
29
+ console.error('Failed to initialize Redis clients:', err);
30
+ });
31
+ const gc = options.gc || this.DEFAULT_GC;
32
+ this._gc = setInterval(() => this.gc(), gc * 1000);
33
+ }
34
+ async _initializeClients() {
35
+ const host = this._options.host || this.DEFAULT_HOST;
36
+ const port = this._options.port || this.DEFAULT_PORT;
37
+ const db = this._options.database || this.DEFAULT_DATABASE;
38
+ const auth = this._options.password;
39
+ const socket = this._options.socket;
40
+ const clientConfig = {
41
+ database: db,
42
+ ...(auth && { password: auth }),
43
+ ...(socket && {
44
+ socket: {
45
+ path: socket,
46
+ reconnectStrategy: this._reconnectStrategy.bind(this)
47
+ }
48
+ }),
49
+ ...(!socket && {
50
+ socket: {
51
+ host,
52
+ port,
53
+ reconnectStrategy: this._reconnectStrategy.bind(this)
54
+ }
55
+ })
56
+ };
57
+ this._redis = (0, redis_1.createClient)(clientConfig);
58
+ this._subscriber = (0, redis_1.createClient)(clientConfig);
59
+ // Set up error handlers
60
+ this._redis.on('error', (err) => {
61
+ console.error('Redis client error:', err);
62
+ this._server.trigger('error', err);
63
+ });
64
+ this._subscriber.on('error', (err) => {
65
+ console.error('Redis subscriber error:', err);
66
+ this._server.trigger('error', err);
67
+ });
68
+ // Handle reconnection events
69
+ this._redis.on('reconnecting', () => {
70
+ console.log('Redis client reconnecting...');
71
+ this._initialized = false;
72
+ });
73
+ this._subscriber.on('reconnecting', () => {
74
+ console.log('Redis subscriber reconnecting...');
75
+ this._initialized = false;
76
+ });
77
+ this._redis.on('ready', () => {
78
+ console.log('Redis client ready');
79
+ this._initialized = true;
80
+ });
81
+ this._subscriber.on('ready', async () => {
82
+ console.log('Redis subscriber ready');
83
+ // Only re-subscribe after reconnection (not on initial connection)
84
+ if (this._subscriptionsSetUp) {
85
+ console.log('Redis subscriber reconnected, re-subscribing...');
86
+ try {
87
+ await this._subscriber.subscribe(this._messageChannel, (message) => {
88
+ this.emptyQueue(message);
89
+ });
90
+ await this._subscriber.subscribe(this._closeChannel, (message) => {
91
+ this._server.trigger('close', message);
92
+ });
93
+ this._initialized = true;
94
+ }
95
+ catch (err) {
96
+ console.error('Error re-subscribing after reconnection:', err);
97
+ }
98
+ }
99
+ });
100
+ await this._redis.connect();
101
+ await this._subscriber.connect();
102
+ // Initial subscription (only once)
103
+ await this._subscriber.subscribe(this._messageChannel, (message) => {
104
+ this.emptyQueue(message);
105
+ });
106
+ await this._subscriber.subscribe(this._closeChannel, (message) => {
107
+ this._server.trigger('close', message);
108
+ });
109
+ this._subscriptionsSetUp = true;
110
+ this._initialized = true;
111
+ }
112
+ _reconnectStrategy(retries) {
113
+ // Exponential backoff with max delay of 10 seconds
114
+ if (retries > 20) {
115
+ // After 20 retries, give up (roughly 2 minutes)
116
+ console.error('Redis reconnection failed after 20 retries');
117
+ return new Error('Max reconnection attempts reached');
118
+ }
119
+ const delay = Math.min(retries * 100, 10000);
120
+ console.log(`Redis reconnecting in ${delay}ms (attempt ${retries})`);
121
+ return delay;
122
+ }
123
+ async _waitForInit() {
124
+ while (!this._initialized) {
125
+ await new Promise(resolve => setTimeout(resolve, 10));
126
+ }
127
+ }
128
+ static create(server, options) {
129
+ return new this(server, options);
130
+ }
131
+ async disconnect() {
132
+ if (this._subscriber) {
133
+ await this._subscriber.unsubscribe();
134
+ await this._subscriber.quit();
135
+ }
136
+ if (this._redis) {
137
+ await this._redis.quit();
138
+ }
139
+ clearInterval(this._gc);
140
+ }
141
+ createClient(callback, context) {
142
+ this._waitForInit().then(async () => {
143
+ const clientId = this._server.generateId();
144
+ const added = await this._redis.zAdd(this._ns + '/clients', {
145
+ score: 0,
146
+ value: clientId
147
+ }, { NX: true });
148
+ if (added === 0) {
149
+ return this.createClient(callback, context);
150
+ }
151
+ this._server.debug('Created new client ?', clientId);
152
+ this.ping(clientId);
153
+ this._server.trigger('handshake', clientId);
154
+ callback.call(context, clientId);
155
+ }).catch(err => {
156
+ console.error('Error creating client:', err);
157
+ });
158
+ }
159
+ clientExists(clientId, callback, context) {
160
+ this._waitForInit().then(async () => {
161
+ const cutoff = new Date().getTime() - (1000 * 1.6 * this._server.timeout);
162
+ const score = await this._redis.zScore(this._ns + '/clients', clientId);
163
+ callback.call(context, score ? parseInt(score.toString(), 10) > cutoff : false);
164
+ }).catch(err => {
165
+ console.error('Error checking client existence:', err);
166
+ callback.call(context, false);
167
+ });
168
+ }
169
+ destroyClient(clientId, callback, context) {
170
+ this._waitForInit().then(async () => {
171
+ const channels = await this._redis.sMembers(this._ns + '/clients/' + clientId + '/channels');
172
+ const multi = this._redis.multi();
173
+ multi.zAdd(this._ns + '/clients', { score: 0, value: clientId });
174
+ for (const channel of channels) {
175
+ multi.sRem(this._ns + '/clients/' + clientId + '/channels', channel);
176
+ multi.sRem(this._ns + '/channels' + channel, clientId);
177
+ }
178
+ multi.del(this._ns + '/clients/' + clientId + '/messages');
179
+ multi.zRem(this._ns + '/clients', clientId);
180
+ multi.publish(this._closeChannel, clientId);
181
+ const results = await multi.exec();
182
+ channels.forEach((channel, i) => {
183
+ if (results[2 * i + 1] !== 1)
184
+ return;
185
+ this._server.trigger('unsubscribe', clientId, channel);
186
+ this._server.debug('Unsubscribed client ? from channel ?', clientId, channel);
187
+ });
188
+ this._server.debug('Destroyed client ?', clientId);
189
+ this._server.trigger('disconnect', clientId);
190
+ if (callback)
191
+ callback.call(context);
192
+ }).catch(err => {
193
+ console.error('Error destroying client:', err);
194
+ if (callback)
195
+ callback.call(context);
196
+ });
197
+ }
198
+ ping(clientId) {
199
+ const timeout = this._server.timeout;
200
+ if (typeof timeout !== 'number')
201
+ return;
202
+ const time = new Date().getTime();
203
+ this._server.debug('Ping ?, ?', clientId, time);
204
+ this._waitForInit().then(async () => {
205
+ await this._redis.zAdd(this._ns + '/clients', { score: time, value: clientId });
206
+ }).catch(err => {
207
+ console.error('Error pinging client:', err);
208
+ });
209
+ }
210
+ subscribe(clientId, channel, callback, context) {
211
+ this._waitForInit().then(async () => {
212
+ const added = await this._redis.sAdd(this._ns + '/clients/' + clientId + '/channels', channel);
213
+ if (added === 1) {
214
+ this._server.trigger('subscribe', clientId, channel);
215
+ }
216
+ await this._redis.sAdd(this._ns + '/channels' + channel, clientId);
217
+ this._server.debug('Subscribed client ? to channel ?', clientId, channel);
218
+ if (callback)
219
+ callback.call(context);
220
+ }).catch(err => {
221
+ console.error('Error subscribing:', err);
222
+ if (callback)
223
+ callback.call(context);
224
+ });
225
+ }
226
+ unsubscribe(clientId, channel, callback, context) {
227
+ this._waitForInit().then(async () => {
228
+ const removed = await this._redis.sRem(this._ns + '/clients/' + clientId + '/channels', channel);
229
+ if (removed === 1) {
230
+ this._server.trigger('unsubscribe', clientId, channel);
231
+ }
232
+ await this._redis.sRem(this._ns + '/channels' + channel, clientId);
233
+ this._server.debug('Unsubscribed client ? from channel ?', clientId, channel);
234
+ if (callback)
235
+ callback.call(context);
236
+ }).catch(err => {
237
+ console.error('Error unsubscribing:', err);
238
+ if (callback)
239
+ callback.call(context);
240
+ });
241
+ }
242
+ publish(message, channels) {
243
+ this._server.debug('Publishing message ?', message);
244
+ this._waitForInit().then(async () => {
245
+ const jsonMessage = JSON.stringify(message);
246
+ const keys = channels.map(c => this._ns + '/channels' + c);
247
+ const clients = await this._redis.sUnion(keys);
248
+ for (const clientId of clients) {
249
+ const queue = this._ns + '/clients/' + clientId + '/messages';
250
+ this._server.debug('Queueing for client ?: ?', clientId, message);
251
+ await this._redis.rPush(queue, jsonMessage);
252
+ await this._redis.publish(this._messageChannel, clientId);
253
+ const exists = await new Promise((resolve) => {
254
+ this.clientExists(clientId, resolve, null);
255
+ });
256
+ if (!exists) {
257
+ await this._redis.del(queue);
258
+ }
259
+ }
260
+ this._server.trigger('publish', message.clientId, message.channel, message.data);
261
+ }).catch(err => {
262
+ console.error('Error publishing:', err);
263
+ });
264
+ }
265
+ emptyQueue(clientId) {
266
+ if (!this._server.hasConnection(clientId))
267
+ return;
268
+ this._waitForInit().then(async () => {
269
+ const key = this._ns + '/clients/' + clientId + '/messages';
270
+ const multi = this._redis.multi();
271
+ multi.lRange(key, 0, -1);
272
+ multi.del(key);
273
+ const results = await multi.exec();
274
+ const jsonMessages = results[0];
275
+ if (jsonMessages && jsonMessages.length > 0) {
276
+ const messages = jsonMessages.map(json => JSON.parse(json));
277
+ this._server.deliver(clientId, messages);
278
+ }
279
+ }).catch(err => {
280
+ console.error('Error emptying queue:', err);
281
+ });
282
+ }
283
+ gc() {
284
+ const timeout = this._server.timeout;
285
+ if (typeof timeout !== 'number')
286
+ return;
287
+ this._withLock('gc', async (releaseLock) => {
288
+ const cutoff = new Date().getTime() - 1000 * 2 * timeout;
289
+ const clients = await this._redis.zRangeByScore(this._ns + '/clients', 0, cutoff);
290
+ if (clients.length === 0) {
291
+ releaseLock();
292
+ return;
293
+ }
294
+ let completed = 0;
295
+ for (const clientId of clients) {
296
+ this.destroyClient(clientId, () => {
297
+ completed++;
298
+ if (completed === clients.length) {
299
+ releaseLock();
300
+ }
301
+ }, this);
302
+ }
303
+ });
304
+ }
305
+ _withLock(lockName, callback) {
306
+ this._waitForInit().then(async () => {
307
+ const lockKey = this._ns + '/locks/' + lockName;
308
+ const currentTime = new Date().getTime();
309
+ const expiry = currentTime + this.LOCK_TIMEOUT * 1000 + 1;
310
+ const releaseLock = async () => {
311
+ if (new Date().getTime() < expiry) {
312
+ await this._redis.del(lockKey);
313
+ }
314
+ };
315
+ const set = await this._redis.setNX(lockKey, expiry.toString());
316
+ if (set) {
317
+ return callback.call(this, releaseLock);
318
+ }
319
+ const timeout = await this._redis.get(lockKey);
320
+ if (!timeout)
321
+ return;
322
+ const lockTimeout = parseInt(timeout, 10);
323
+ if (currentTime < lockTimeout)
324
+ return;
325
+ const oldValue = await this._redis.set(lockKey, expiry.toString(), { GET: true });
326
+ if (oldValue === timeout) {
327
+ callback.call(this, releaseLock);
328
+ }
329
+ }).catch(err => {
330
+ console.error('Error with lock:', err);
331
+ });
332
+ }
333
+ }
334
+ exports.Engine = Engine;
335
+ exports.default = Engine;
336
+ //# sourceMappingURL=faye-redis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"faye-redis.js","sourceRoot":"","sources":["../src/faye-redis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import Engine from './faye-redis';
2
+ export = Engine;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,MAAM,MAAM,cAAc,CAAC;AAGlC,SAAS,MAAM,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ // Backward compatibility entry point
3
+ // This file provides CommonJS compatibility while maintaining TypeScript benefits
4
+ //
5
+ // Usage patterns supported:
6
+ // - const Engine = require('faye-redis-ng'); (CommonJS direct)
7
+ // - const { Engine } = require('faye-redis-ng'); (CommonJS destructured)
8
+ // - import Engine from 'faye-redis-ng'; (ES6 default)
9
+ // - import { Engine } from 'faye-redis-ng'; (ES6 named)
10
+ var __importDefault = (this && this.__importDefault) || function (mod) {
11
+ return (mod && mod.__esModule) ? mod : { "default": mod };
12
+ };
13
+ const faye_redis_1 = __importDefault(require("./faye-redis"));
14
+ module.exports = faye_redis_1.default;
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,qCAAqC;AACrC,kFAAkF;AAClF,EAAE;AACF,4BAA4B;AAC5B,yEAAyE;AACzE,+EAA+E;AAC/E,qEAAqE;AACrE,mEAAmE;;;;AAEnE,8DAAkC;AAGlC,iBAAS,oBAAM,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { RedisClientType } from 'redis';
2
+ export interface EngineOptions {
3
+ host?: string;
4
+ port?: number;
5
+ password?: string;
6
+ database?: number;
7
+ namespace?: string;
8
+ socket?: string;
9
+ gc?: number;
10
+ }
11
+ export interface FayeMessage {
12
+ clientId?: string;
13
+ channel: string;
14
+ data: any;
15
+ id?: string;
16
+ }
17
+ export interface FayeServer {
18
+ timeout: number;
19
+ generateId(): string;
20
+ debug(...args: any[]): void;
21
+ trigger(event: string, ...args: any[]): void;
22
+ hasConnection(clientId: string): boolean;
23
+ deliver(clientId: string, messages: FayeMessage[]): void;
24
+ }
25
+ export type RedisClient = RedisClientType;
26
+ export type CallbackContext = any;
27
+ export type EmptyCallback = () => void;
28
+ export type ClientCallback = (clientId: string) => void;
29
+ export type ExistsCallback = (exists: boolean) => void;
30
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAExC,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,GAAG,CAAC;IACV,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,IAAI,MAAM,CAAC;IACrB,KAAK,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC7C,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACzC,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;CAC1D;AAED,MAAM,MAAM,WAAW,GAAG,eAAe,CAAC;AAE1C,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC;AAElC,MAAM,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC;AACvC,MAAM,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;AACxD,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "faye-redis-ng",
3
3
  "description": "Modern Redis backend engine for Faye (Next Generation fork with Redis v4, ES6+, auto-reconnection)",
4
- "homepage": "http://github.com/7a6163/faye-redis-node",
4
+ "homepage": "https://github.com/7a6163/faye-redis-node-ng",
5
5
  "contributors": [
6
6
  "Modernized and maintained by the community"
7
7
  ],
@@ -15,23 +15,40 @@
15
15
  "realtime"
16
16
  ],
17
17
  "license": "MIT",
18
- "version": "1.0.2",
18
+ "version": "1.1.1",
19
19
  "engines": {
20
20
  "node": ">=22.0.0"
21
21
  },
22
- "main": "./faye-redis",
22
+ "main": "./dist/index.js",
23
+ "types": "./dist/index.d.ts",
24
+ "files": [
25
+ "dist",
26
+ "src",
27
+ "LICENSE",
28
+ "README.md"
29
+ ],
23
30
  "dependencies": {
24
31
  "redis": "^4.7.0"
25
32
  },
26
33
  "devDependencies": {
27
- "jstest": "^1.0.5"
34
+ "@types/node": "^22.10.5",
35
+ "@vitest/coverage-v8": "^4.0.16",
36
+ "@vitest/ui": "^4.0.16",
37
+ "typescript": "^5.7.2",
38
+ "vitest": "^4.0.16"
28
39
  },
29
40
  "scripts": {
30
- "test": "node spec/runner.js"
41
+ "build": "tsc",
42
+ "build:watch": "tsc --watch",
43
+ "prepublishOnly": "npm run build",
44
+ "test": "vitest run",
45
+ "test:watch": "vitest",
46
+ "test:ui": "vitest --ui",
47
+ "test:coverage": "vitest run --coverage"
31
48
  },
32
- "bugs": "http://github.com/7a6163/faye-redis-node/issues",
49
+ "bugs": "https://github.com/7a6163/faye-redis-node-ng/issues",
33
50
  "repository": {
34
51
  "type": "git",
35
- "url": "git://github.com/7a6163/faye-redis-node.git"
52
+ "url": "git+https://github.com/7a6163/faye-redis-node-ng.git"
36
53
  }
37
54
  }