diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index a15431a..28a6053 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -13,6 +13,7 @@ body:
- '@nestjs-redis/kit'
- '@nestjs-redis/client'
- '@nestjs-redis/lock'
+ - '@nestjs-redis/socket.io-adapter'
- '@nestjs-redis/throttler-storage'
- '@nestjs-redis/health-indicator'
validations:
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index bc60fa5..e3c5250 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -12,6 +12,7 @@ body:
- '@nestjs-redis/kit'
- '@nestjs-redis/client'
- '@nestjs-redis/lock'
+ - '@nestjs-redis/socket.io-adapter'
- '@nestjs-redis/throttler-storage'
- '@nestjs-redis/health-indicator'
- 'New package'
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b74b458..2072abc 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -61,7 +61,7 @@ jobs:
with:
token: ${{ secrets.CODECOV_TOKEN }}
directory: ./test-output
- files: ./client/lcov.info,./health-indicator/lcov.info,./lock/lcov.info,./throttler-storage/lcov.info
+ files: ./client/lcov.info,./health-indicator/lcov.info,./lock/lcov.info,./throttler-storage/lcov.info,./socket.io-adapter/lcov.info
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
diff --git a/.github/workflows/compatibility-test.yml b/.github/workflows/compatibility-test.yml
index fa008f8..5e99ffe 100644
--- a/.github/workflows/compatibility-test.yml
+++ b/.github/workflows/compatibility-test.yml
@@ -23,7 +23,14 @@ jobs:
fail-fast: false
matrix:
node-version: ['18', '20', '22']
- package: ['client', 'health-indicator', 'throttler-storage', 'lock']
+ package:
+ [
+ 'client',
+ 'health-indicator',
+ 'throttler-storage',
+ 'lock',
+ 'socket.io-adapter',
+ ]
nestjs-version: ['9', '10', '11']
include:
- nestjs-version: '9'
diff --git a/README.md b/README.md
index 2801b29..93e81a5 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,7 @@ NestJS Redis Toolkit is a cohesive set of utilities for Redis in NestJS applicat
- [@nestjs-redis/lock](packages/lock/README.md) — Distributed locking via Redlock
- [@nestjs-redis/throttler-storage](packages/throttler-storage/README.md) — Redis storage for NestJS Throttler
- [@nestjs-redis/health-indicator](packages/health-indicator/README.md) — Redis health checks for Terminus
+- [@nestjs-redis/socket.io-adapter](packages/socket.io-adapter/README.md) — Redis-powered Socket.IO adapter for scalable WebSocket connections
## Quick Start
@@ -94,9 +95,10 @@ import { RedisModule } from '@nestjs-redis/client';
| -------------------------------------------------------------------------------------------------- | ------- | ------ | ----- |
| [`@nestjs-redis/kit`](https://www.npmjs.com/package/@nestjs-redis/kit) | 18+ | 9+ | 5+ |
| [`@nestjs-redis/client`](https://www.npmjs.com/package/@nestjs-redis/client) | 18+ | 9+ | 5+ |
+| [`@nestjs-redis/lock`](https://www.npmjs.com/package/@nestjs-redis/lock) | 18+ | 9+ | 5+ |
| [`@nestjs-redis/throttler-storage`](https://www.npmjs.com/package/@nestjs-redis/throttler-storage) | 18+ | 9+ | 5+ |
| [`@nestjs-redis/health-indicator`](https://www.npmjs.com/package/@nestjs-redis/health-indicator) | 18+ | 9+ | 5+ |
-| [`@nestjs-redis/lock`](https://www.npmjs.com/package/@nestjs-redis/lock) | 18+ | 9+ | 5+ |
+| [`@nestjs-redis/socket.io-adapter`](https://www.npmjs.com/package/@nestjs-redis/socket.io-adapter) | 18+ | 9+ | 5+ |
All packages support NestJS 9.x, 10.x, and 11.x.
diff --git a/packages/kit/package.json b/packages/kit/package.json
index 378413a..ef7bb92 100644
--- a/packages/kit/package.json
+++ b/packages/kit/package.json
@@ -67,7 +67,8 @@
"@nestjs-redis/client": "workspace:*",
"@nestjs-redis/health-indicator": "workspace:*",
"@nestjs-redis/throttler-storage": "workspace:*",
- "@nestjs-redis/lock": "workspace:*"
+ "@nestjs-redis/lock": "workspace:*",
+ "@nestjs-redis/socket.io-adapter": "workspace:*"
},
"engines": {
"node": ">=18.0.0",
diff --git a/packages/kit/src/index.ts b/packages/kit/src/index.ts
index 3128054..6884b1f 100644
--- a/packages/kit/src/index.ts
+++ b/packages/kit/src/index.ts
@@ -2,3 +2,4 @@ export * from '@nestjs-redis/client';
export { RedisHealthIndicator } from '@nestjs-redis/health-indicator';
export * from '@nestjs-redis/throttler-storage';
export * from '@nestjs-redis/lock';
+export * from '@nestjs-redis/socket.io-adapter';
diff --git a/packages/socket.io-adapter/.spec.swcrc b/packages/socket.io-adapter/.spec.swcrc
new file mode 100644
index 0000000..3b52a53
--- /dev/null
+++ b/packages/socket.io-adapter/.spec.swcrc
@@ -0,0 +1,22 @@
+{
+ "jsc": {
+ "target": "es2017",
+ "parser": {
+ "syntax": "typescript",
+ "decorators": true,
+ "dynamicImport": true
+ },
+ "transform": {
+ "decoratorMetadata": true,
+ "legacyDecorator": true
+ },
+ "keepClassNames": true,
+ "externalHelpers": true,
+ "loose": true
+ },
+ "module": {
+ "type": "es6"
+ },
+ "sourceMaps": true,
+ "exclude": []
+}
diff --git a/packages/socket.io-adapter/README.md b/packages/socket.io-adapter/README.md
new file mode 100644
index 0000000..2401287
--- /dev/null
+++ b/packages/socket.io-adapter/README.md
@@ -0,0 +1,174 @@
+
+
+

+
+# @nestjs-redis/socket.io-adapter
+
+Redis-powered Socket.IO adapter for NestJS enabling scalable WebSocket connections across multiple instances.
+
+[](https://www.npmjs.com/package/@nestjs-redis/socket.io-adapter)
+[](https://www.npmjs.com/package/@nestjs-redis/socket.io-adapter)
+[](https://opensource.org/licenses/MIT)
+[](https://www.typescriptlang.org/)
+[](https://nestjs.com/) [](https://redis.io/)
+
+
+
+---
+
+## Features
+
+- **Horizontal scaling**: Connect clients to any server instance
+- **Redis pub/sub**: Automatic event distribution across instances
+- **Lifecycle management**: Redis connections are managed automatically
+- **Works with existing connections**: Integrates seamlessly with `@nestjs-redis/client`
+- **Type-safe**: Full TypeScript support
+- **Production-ready**: Built on the official Socket.IO Redis adapter
+
+## Installation
+
+```bash
+npm install @nestjs-redis/socket.io-adapter
+# or
+yarn add @nestjs-redis/socket.io-adapter
+# or
+pnpm add @nestjs-redis/socket.io-adapter
+```
+
+## Quick Start
+
+### Setup with existing Redis connection (Recommended)
+
+```typescript
+// app.module.ts
+import { Module } from '@nestjs/common';
+import { RedisModule } from '@nestjs-redis/client';
+
+@Module({
+ imports: [
+ RedisModule.forRoot({
+ options: { url: 'redis://localhost:6379' },
+ }),
+ ],
+})
+export class AppModule {}
+```
+
+```typescript
+// main.ts
+import { NestFactory } from '@nestjs/core';
+import { setupRedisAdapter } from '@nestjs-redis/socket.io-adapter';
+import { AppModule } from './app.module';
+
+async function bootstrap() {
+ const app = await NestFactory.create(AppModule);
+
+ // Setup Redis adapter for Socket.IO
+ await setupRedisAdapter(app);
+
+ await app.listen(3000);
+}
+bootstrap();
+```
+
+### Multiple Redis connections
+
+If you have multiple Redis connections, specify which one to use:
+
+```typescript
+// app.module.ts
+@Module({
+ imports: [
+ RedisModule.forRoot({
+ options: { url: 'redis://localhost:6379' },
+ }),
+ RedisModule.forRoot({
+ connectionName: 'websockets',
+ options: { url: 'redis://websockets:6379' },
+ }),
+ ],
+})
+export class AppModule {}
+```
+
+```typescript
+// main.ts
+async function bootstrap() {
+ const app = await NestFactory.create(AppModule);
+
+ // Use the 'websockets' Redis connection
+ await setupRedisAdapter(app, 'websockets');
+
+ await app.listen(3000);
+}
+```
+
+## The Problem
+
+When scaling your NestJS application horizontally with multiple instances, WebSocket connections become a challenge. By default, Socket.IO connections are tied to a single server instance, which means:
+
+- Events sent from one server instance won't reach clients connected to other instances
+- Real-time features break when users connect to different servers
+- Load balancing becomes complex as you need sticky sessions
+
+## The Solution
+
+This package provides a Redis-backed Socket.IO adapter that uses Redis pub/sub to synchronize events across all server instances. When a server emits an event, it's published to Redis and distributed to all other server instances, ensuring all clients receive the event regardless of which server they're connected to.
+
+## How It Works
+
+1. **Redis Pub/Sub**: The adapter creates two Redis connections - one for publishing and one for subscribing
+2. **Event Distribution**: When a server emits an event, it's published to a Redis channel
+3. **Cross-Instance Delivery**: All server instances subscribe to the same channels and forward events to their connected clients
+4. **Automatic Management**: Connection lifecycle is handled automatically by the adapter
+
+## API
+
+### `setupRedisAdapter(app, redisToken?)`
+
+Sets up the Redis adapter for the NestJS application.
+
+- `app`: NestJS application instance
+- `redisToken` (optional): Redis connection name (defaults to the default connection)
+
+### `RedisIoAdapter`
+
+The underlying Socket.IO adapter class that handles Redis connections.
+
+## Architecture
+
+```
+┌─────────────┐ ┌─────────────┐ ┌─────────────┐
+│ Server 1 │ │ Server 2 │ │ Server 3 │
+│ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │
+│ │Client │ │ │ │Client │ │ │ │Client │ │
+│ └───────┘ │ │ └───────┘ │ │ └───────┘ │
+└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
+ │ │ │
+ └──────────────────┼──────────────────┘
+ │
+ ┌─────▼─────┐
+ │ Redis │
+ │ Pub/Sub │
+ └───────────┘
+```
+
+## Learn More
+
+- [NestJS WebSocket Adapter Documentation](https://docs.nestjs.com/websockets/adapter)
+- [Socket.IO Redis Adapter](https://socket.io/docs/v4/redis-adapter/)
+- [Redis Pub/Sub](https://redis.io/docs/manual/pubsub/)
+
+## Links
+
+- Root repo: [CSenshi/nestjs-redis](https://github.com/CSenshi/nestjs-redis)
+- Issues: [GitHub Issues](https://github.com/CSenshi/nestjs-redis/issues)
+- Discussions: [GitHub Discussions](https://github.com/CSenshi/nestjs-redis/discussions)
+
+## Contributing
+
+Please see the [root contributing guidelines](https://github.com/CSenshi/nestjs-redis#contributing).
+
+## License
+
+MIT © [CSenshi](https://github.com/CSenshi)
diff --git a/packages/socket.io-adapter/eslint.config.mjs b/packages/socket.io-adapter/eslint.config.mjs
new file mode 100644
index 0000000..b775541
--- /dev/null
+++ b/packages/socket.io-adapter/eslint.config.mjs
@@ -0,0 +1,22 @@
+import baseConfig from '../../eslint.config.mjs';
+
+export default [
+ ...baseConfig,
+ {
+ files: ['**/*.json'],
+ rules: {
+ '@nx/dependency-checks': [
+ 'error',
+ {
+ ignoredFiles: ['{projectRoot}/eslint.config.{js,cjs,mjs,ts,cts,mts}'],
+ ignoredDependencies: [
+ 'redis', // redis is imported only for typing via import type statement
+ ],
+ },
+ ],
+ },
+ languageOptions: {
+ parser: await import('jsonc-eslint-parser'),
+ },
+ },
+];
diff --git a/packages/socket.io-adapter/jest.config.ts b/packages/socket.io-adapter/jest.config.ts
new file mode 100644
index 0000000..60c8b8d
--- /dev/null
+++ b/packages/socket.io-adapter/jest.config.ts
@@ -0,0 +1,21 @@
+/* eslint-disable */
+import { readFileSync } from 'fs';
+
+// Reading the SWC compilation config for the spec files
+const swcJestConfig = JSON.parse(
+ readFileSync(`${__dirname}/.spec.swcrc`, 'utf-8'),
+);
+
+// Disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves
+swcJestConfig.swcrc = false;
+
+export default {
+ displayName: 'socket.io-adapter',
+ preset: '../../jest.preset.js',
+ testEnvironment: 'node',
+ transform: {
+ '^.+\\.[tj]s$': ['@swc/jest', swcJestConfig],
+ },
+ moduleFileExtensions: ['ts', 'js', 'html'],
+ coverageDirectory: 'test-output/jest/coverage',
+};
diff --git a/packages/socket.io-adapter/package.json b/packages/socket.io-adapter/package.json
new file mode 100644
index 0000000..a78d55a
--- /dev/null
+++ b/packages/socket.io-adapter/package.json
@@ -0,0 +1,80 @@
+{
+ "name": "@nestjs-redis/socket.io-adapter",
+ "version": "0.0.1",
+ "license": "MIT",
+ "author": "Saba Pochkhua (https://github.com/CSenshi)",
+ "description": "Redis-powered Socket.IO adapter for NestJS enabling scalable WebSocket connections",
+ "keywords": [
+ "nestjs",
+ "redis",
+ "socket.io",
+ "websockets",
+ "adapter",
+ "scalable",
+ "typescript",
+ "node-redis"
+ ],
+ "homepage": "https://github.com/CSenshi/nestjs-redis/tree/main/packages/socket.io-adapter",
+ "main": "./src/index.js",
+ "module": "./src/index.js",
+ "types": "./src/index.d.ts",
+ "exports": {
+ "./package.json": "./package.json",
+ ".": {
+ "development": "./src/index.ts",
+ "types": "./src/index.d.ts",
+ "import": "./src/index.js",
+ "default": "./src/index.js"
+ }
+ },
+ "files": [
+ "src",
+ "!**/*.tsbuildinfo"
+ ],
+ "nx": {
+ "name": "socket.io-adapter",
+ "targets": {
+ "build": {
+ "executor": "@nx/js:tsc",
+ "outputs": [
+ "{options.outputPath}"
+ ],
+ "options": {
+ "outputPath": "dist/packages/socket.io-adapter",
+ "tsConfig": "packages/socket.io-adapter/tsconfig.lib.json",
+ "packageJson": "packages/socket.io-adapter/package.json",
+ "main": "packages/socket.io-adapter/src/index.ts",
+ "assets": [
+ "packages/socket.io-adapter/*.md",
+ "LICENSE"
+ ]
+ }
+ }
+ }
+ },
+ "dependencies": {
+ "@nestjs/platform-socket.io": "^11.1.6",
+ "@socket.io/redis-adapter": "^8.3.0",
+ "tslib": "^2.8.0"
+ },
+ "devDependencies": {
+ "@nestjs-redis/client": "0.10.1",
+ "@nestjs/testing": "^11.0.0",
+ "@nestjs/websockets": "^11.1.6",
+ "redis": "^5.0.0",
+ "socket.io-client": "^4.0.0"
+ },
+ "peerDependencies": {
+ "@nestjs/common": "^9.0.0 || ^10.0.0 || ^11.0.0",
+ "@nestjs/core": "^9.0.0 || ^10.0.0 || ^11.0.0"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/CSenshi/nestjs-redis",
+ "directory": "packages/socket.io-adapter"
+ }
+}
diff --git a/packages/socket.io-adapter/src/index.ts b/packages/socket.io-adapter/src/index.ts
new file mode 100644
index 0000000..76eeea5
--- /dev/null
+++ b/packages/socket.io-adapter/src/index.ts
@@ -0,0 +1,3 @@
+export * from './lib/exceptions';
+export * from './lib/redis-io.adapter';
+export * from './lib/setup-redis-adapter';
diff --git a/packages/socket.io-adapter/src/lib/exceptions.ts b/packages/socket.io-adapter/src/lib/exceptions.ts
new file mode 100644
index 0000000..e48c339
--- /dev/null
+++ b/packages/socket.io-adapter/src/lib/exceptions.ts
@@ -0,0 +1,38 @@
+export class RedisClientNotFoundException extends Error {
+ constructor(redisToken?: string) {
+ const baseMessage = `Redis client not found. Please ensure that the Redis client is properly configured and provided in the application context.
+
+Most common solution:
+Import and configure RedisModule in your app.module.ts:`;
+
+ const configExample = redisToken
+ ? ` RedisModule.forRoot({
+ connectionName: '${redisToken}', // <-- connection name
+ options: { url: process.env['REDIS_URL'] },
+ }),`
+ : ` RedisModule.forRoot({
+ options: { url: process.env['REDIS_URL'] },
+ }),`;
+
+ const troubleshooting = `
+
+Make sure you have:
+1. RedisModule imported in your module`;
+
+ super(baseMessage + '\n\n' + configExample + troubleshooting);
+ this.name = 'RedisClientNotFoundException';
+
+ if (redisToken) {
+ this.message += `\n\nRequired connection name: ${redisToken}`;
+ }
+
+ this.message += `\n`;
+ }
+}
+
+export class RedisAdapterAlreadySetUpException extends Error {
+ constructor() {
+ super('Redis adapter is already set up for this application instance.');
+ this.name = 'RedisAdapterAlreadySetUpException';
+ }
+}
diff --git a/packages/socket.io-adapter/src/lib/redis-io.adapter.int.spec.ts b/packages/socket.io-adapter/src/lib/redis-io.adapter.int.spec.ts
new file mode 100644
index 0000000..59f9043
--- /dev/null
+++ b/packages/socket.io-adapter/src/lib/redis-io.adapter.int.spec.ts
@@ -0,0 +1,110 @@
+import { Injectable } from '@nestjs/common';
+import { Test, TestingModule } from '@nestjs/testing';
+import { WebSocketGateway } from '@nestjs/websockets';
+import { RedisModule } from '@nestjs-redis/client';
+import {
+ RedisAdapterAlreadySetUpException,
+ RedisClientNotFoundException,
+} from './exceptions';
+import { setupRedisAdapter } from './setup-redis-adapter';
+
+// Integration tests require a running Redis instance
+const REDIS_URL = process.env.REDIS_URL || 'redis://localhost:6379';
+
+@WebSocketGateway({})
+@Injectable()
+export class EventsGateway {}
+
+describe('setupRedisAdapter Integration Tests', () => {
+ const moduleConfig = {
+ imports: [
+ RedisModule.forRoot({
+ type: 'client',
+ options: { url: REDIS_URL },
+ }),
+ RedisModule.forRoot({
+ connectionName: 'cache',
+ type: 'client',
+ options: { url: REDIS_URL },
+ }),
+ ],
+ providers: [EventsGateway],
+ };
+ let module: TestingModule;
+
+ beforeEach(async () => {
+ module = await Test.createTestingModule(moduleConfig).compile();
+ });
+
+ it('should setup Redis adapter successfully with default and named connections', async () => {
+ // Test 1: Default connection using RedisModule
+ const app = module.createNestApplication();
+ await app.init();
+
+ // Should work with default connection
+ await expect(setupRedisAdapter(app)).resolves.not.toThrow();
+
+ await app.close();
+
+ // Test 2: Named connection using RedisModule
+ const appWithNamedConnection = (
+ await Test.createTestingModule(moduleConfig).compile()
+ ).createNestApplication();
+ await appWithNamedConnection.init();
+
+ // Should work with named connection
+ await expect(
+ setupRedisAdapter(appWithNamedConnection, 'cache'),
+ ).resolves.not.toThrow();
+
+ await appWithNamedConnection.close();
+ });
+
+ it('should throw RedisClientNotFoundException when Redis client is not configured', async () => {
+ // Test 2: Named connection not configured
+ const app = module.createNestApplication();
+ await app.init();
+
+ // Should throw an error when trying to setup with a non-existent named connection
+ await expect(
+ setupRedisAdapter(app, 'nonExistentConnection'),
+ ).rejects.toThrow(RedisClientNotFoundException);
+
+ await app.close();
+ });
+
+ it('should fail when trying to set adapter multiple times', async () => {
+ const app = module.createNestApplication();
+ await app.init();
+
+ // First setup should succeed
+ await expect(setupRedisAdapter(app)).resolves.not.toThrow();
+
+ // Second setup should throw an error
+ await expect(setupRedisAdapter(app, 'cache')).rejects.toThrow(
+ RedisAdapterAlreadySetUpException,
+ );
+
+ await app.close();
+ });
+
+ it('should handle multiple applications independently', async () => {
+ const app1 = module.createNestApplication();
+ const app2 = (
+ await Test.createTestingModule(moduleConfig).compile()
+ ).createNestApplication();
+
+ await app1.init();
+ await app2.init();
+
+ // Setup Redis adapter for first app
+ await expect(setupRedisAdapter(app1)).resolves.not.toThrow();
+
+ // Setup Redis adapter for second app
+ await expect(setupRedisAdapter(app2, 'cache')).resolves.not.toThrow();
+
+ // Ensure both apps can close without issues
+ await app1.close();
+ await app2.close();
+ });
+});
diff --git a/packages/socket.io-adapter/src/lib/redis-io.adapter.ts b/packages/socket.io-adapter/src/lib/redis-io.adapter.ts
new file mode 100644
index 0000000..99d9d26
--- /dev/null
+++ b/packages/socket.io-adapter/src/lib/redis-io.adapter.ts
@@ -0,0 +1,38 @@
+import { IoAdapter } from '@nestjs/platform-socket.io';
+import { createAdapter } from '@socket.io/redis-adapter';
+import type { RedisClientType } from 'redis';
+
+export class RedisIoAdapter extends IoAdapter {
+ private pubClient: RedisClientType | undefined;
+ private subClient: RedisClientType | undefined;
+
+ private adapterConstructor: ReturnType | undefined;
+
+ async connectToRedis(redisClient: RedisClientType): Promise {
+ this.pubClient = redisClient;
+ this.subClient = this.pubClient.duplicate();
+
+ await this.subClient.connect();
+
+ this.adapterConstructor = createAdapter(this.pubClient, this.subClient);
+ }
+
+ override createIOServer(
+ port: number,
+ options?: Parameters[1],
+ ): ReturnType {
+ const server = super.createIOServer(port, options);
+ server.adapter(this.adapterConstructor);
+ return server;
+ }
+
+ override async close(
+ server: Parameters[0],
+ ): Promise {
+ super.close(server);
+
+ if (this.subClient) {
+ await this.subClient.quit();
+ }
+ }
+}
diff --git a/packages/socket.io-adapter/src/lib/setup-redis-adapter.ts b/packages/socket.io-adapter/src/lib/setup-redis-adapter.ts
new file mode 100644
index 0000000..6de9ad7
--- /dev/null
+++ b/packages/socket.io-adapter/src/lib/setup-redis-adapter.ts
@@ -0,0 +1,60 @@
+import type { INestApplication } from '@nestjs/common';
+import { ModuleRef } from '@nestjs/core';
+import { UnknownElementException } from '@nestjs/core/errors/exceptions';
+import {
+ RedisAdapterAlreadySetUpException,
+ RedisClientNotFoundException,
+} from './exceptions';
+import { RedisIoAdapter } from './redis-io.adapter';
+
+const appSet = new Set();
+
+/**
+ * Sets up the Redis adapter for a NestJS application.
+ *
+ * @param app - The NestJS application instance
+ * @param redisToken - Optional Redis client token for named connections
+ * @returns A promise that resolves when the adapter is set up
+ * @throws RedisClientNotFoundException if the Redis client is not found
+ */
+export async function setupRedisAdapter(
+ app: INestApplication,
+ redisToken?: string,
+): Promise {
+ if (appSet.has(app)) {
+ throw new RedisAdapterAlreadySetUpException();
+ }
+
+ appSet.add(app);
+ const redisIoAdapter = new RedisIoAdapter(app);
+
+ try {
+ const moduleRef = app.get(ModuleRef);
+ const redisClient = moduleRef.get(RedisToken(redisToken), {
+ strict: false,
+ });
+ await redisIoAdapter.connectToRedis(redisClient);
+ app.useWebSocketAdapter(redisIoAdapter);
+ } catch (error) {
+ if (error instanceof UnknownElementException) {
+ throw new RedisClientNotFoundException(redisToken);
+ }
+
+ throw error;
+ }
+}
+
+/**
+ * Creates a Redis client injection token.
+ *
+ * @param connectionName - Optional connection name
+ * @returns Injection token for the Redis client
+ * @publicApi
+ */
+function RedisToken(connectionName?: string): string {
+ if (connectionName) {
+ return `REDIS_CLIENT_${connectionName.toUpperCase()}`;
+ }
+
+ return 'REDIS_CLIENT';
+}
diff --git a/packages/socket.io-adapter/tsconfig.json b/packages/socket.io-adapter/tsconfig.json
new file mode 100644
index 0000000..62ebbd9
--- /dev/null
+++ b/packages/socket.io-adapter/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.lib.json"
+ },
+ {
+ "path": "./tsconfig.spec.json"
+ }
+ ]
+}
diff --git a/packages/socket.io-adapter/tsconfig.lib.json b/packages/socket.io-adapter/tsconfig.lib.json
new file mode 100644
index 0000000..c918def
--- /dev/null
+++ b/packages/socket.io-adapter/tsconfig.lib.json
@@ -0,0 +1,20 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "rootDir": "src",
+ "outDir": "dist",
+ "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
+ "emitDeclarationOnly": false,
+ "forceConsistentCasingInFileNames": true,
+ "types": ["node"],
+ "target": "es2021",
+ "strictNullChecks": true,
+ "noImplicitAny": true,
+ "strictBindCallApply": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src/**/*.ts"],
+ "references": [],
+ "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
+}
diff --git a/packages/socket.io-adapter/tsconfig.spec.json b/packages/socket.io-adapter/tsconfig.spec.json
new file mode 100644
index 0000000..59d4010
--- /dev/null
+++ b/packages/socket.io-adapter/tsconfig.spec.json
@@ -0,0 +1,19 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "./out-tsc/jest",
+ "types": ["jest", "node"],
+ "forceConsistentCasingInFileNames": true
+ },
+ "include": [
+ "jest.config.ts",
+ "src/**/*.test.ts",
+ "src/**/*.spec.ts",
+ "src/**/*.d.ts"
+ ],
+ "references": [
+ {
+ "path": "./tsconfig.lib.json"
+ }
+ ]
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 326d75a..0b8c409 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -13,7 +13,7 @@ importers:
version: 11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2)
'@nestjs/core':
specifier: ^11.0.0
- version: 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(reflect-metadata@0.1.14)(rxjs@7.8.2)
+ version: 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(@nestjs/websockets@11.1.6)(reflect-metadata@0.1.14)(rxjs@7.8.2)
'@nestjs/platform-express':
specifier: ^11.0.0
version: 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.5)
@@ -131,7 +131,7 @@ importers:
version: 11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2)
'@nestjs/core':
specifier: ^9.0.0 || ^10.0.0 || ^11.0.0
- version: 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(reflect-metadata@0.1.14)(rxjs@7.8.2)
+ version: 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(@nestjs/websockets@11.1.6)(reflect-metadata@0.1.14)(rxjs@7.8.2)
redis:
specifier: ^5.0.0
version: 5.6.0
@@ -173,6 +173,9 @@ importers:
'@nestjs-redis/lock':
specifier: workspace:*
version: link:../lock
+ '@nestjs-redis/socket.io-adapter':
+ specifier: workspace:*
+ version: link:../socket.io-adapter
'@nestjs-redis/throttler-storage':
specifier: workspace:*
version: link:../throttler-storage
@@ -196,6 +199,40 @@ importers:
specifier: ^11.0.0
version: 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.5)(@nestjs/platform-express@11.1.5)
+ packages/socket.io-adapter:
+ dependencies:
+ '@nestjs/common':
+ specifier: ^9.0.0 || ^10.0.0 || ^11.0.0
+ version: 11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2)
+ '@nestjs/core':
+ specifier: ^9.0.0 || ^10.0.0 || ^11.0.0
+ version: 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(@nestjs/websockets@11.1.6)(reflect-metadata@0.1.14)(rxjs@7.8.2)
+ '@nestjs/platform-socket.io':
+ specifier: ^11.1.6
+ version: 11.1.6(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/websockets@11.1.6)(rxjs@7.8.2)
+ '@socket.io/redis-adapter':
+ specifier: ^8.3.0
+ version: 8.3.0(socket.io-adapter@2.5.5)
+ tslib:
+ specifier: ^2.8.0
+ version: 2.8.1
+ devDependencies:
+ '@nestjs-redis/client':
+ specifier: 0.10.1
+ version: 0.10.1(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.5)(redis@5.6.0)
+ '@nestjs/testing':
+ specifier: ^11.0.0
+ version: 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.5)(@nestjs/platform-express@11.1.5)
+ '@nestjs/websockets':
+ specifier: ^11.1.6
+ version: 11.1.6(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.5)(@nestjs/platform-socket.io@11.1.6)(reflect-metadata@0.1.14)(rxjs@7.8.2)
+ redis:
+ specifier: ^5.0.0
+ version: 5.6.0
+ socket.io-client:
+ specifier: ^4.0.0
+ version: 4.8.1
+
packages/throttler-storage:
dependencies:
'@nestjs/common':
@@ -1103,6 +1140,14 @@ packages:
'@napi-rs/wasm-runtime@0.2.4':
resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==}
+ '@nestjs-redis/client@0.10.1':
+ resolution: {integrity: sha512-Tn5KGVvA7SJOqHcvOAj+xPSFhnO2mOWuFCMZDaADeYhXGBmsVPEmMW6f/jujH4AJTBJDDgfMx3oajrpVOR1Gyg==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ peerDependencies:
+ '@nestjs/common': ^9.0.0 || ^10.0.0 || ^11.0.0
+ '@nestjs/core': ^9.0.0 || ^10.0.0 || ^11.0.0
+ redis: ^5.0.0
+
'@nestjs/common@11.1.5':
resolution: {integrity: sha512-DQpWdr3ShO0BHWkHl3I4W/jR6R3pDtxyBlmrpTuZF+PXxQyBXNvsUne0Wyo6QHPEDi+pAz9XchBFoKbqOhcdTg==}
peerDependencies:
@@ -1146,6 +1191,13 @@ packages:
'@nestjs/common': ^11.0.0
'@nestjs/core': ^11.0.0
+ '@nestjs/platform-socket.io@11.1.6':
+ resolution: {integrity: sha512-ozm+OKiRiFLNQdFLA3ULDuazgdVaPrdRdgtG/+404T7tcROXpbUuFL0eEmWJpG64CxMkBNwamclUSH6J0AeU7A==}
+ peerDependencies:
+ '@nestjs/common': ^11.0.0
+ '@nestjs/websockets': ^11.0.0
+ rxjs: ^7.1.0
+
'@nestjs/schematics@11.0.5':
resolution: {integrity: sha512-T50SCNyqCZ/fDssaOD7meBKLZ87ebRLaJqZTJPvJKjlib1VYhMOCwXYsr7bjMPmuPgiQHOwvppz77xN/m6GM7A==}
peerDependencies:
@@ -1219,6 +1271,18 @@ packages:
'@nestjs/core': ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0
reflect-metadata: ^0.1.13 || ^0.2.0
+ '@nestjs/websockets@11.1.6':
+ resolution: {integrity: sha512-jlBX5QpqhfEVfxkwxTesIjgl0bdhgFMoORQYzjRg1i+Z+Qouf4KmjNPv5DZE3DZRDg91E+3Bpn0VgW0Yfl94ng==}
+ peerDependencies:
+ '@nestjs/common': ^11.0.0
+ '@nestjs/core': ^11.0.0
+ '@nestjs/platform-socket.io': ^11.0.0
+ reflect-metadata: ^0.1.12 || ^0.2.0
+ rxjs: ^7.1.0
+ peerDependenciesMeta:
+ '@nestjs/platform-socket.io':
+ optional: true
+
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@@ -1391,6 +1455,15 @@ packages:
'@sinonjs/fake-timers@13.0.5':
resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==}
+ '@socket.io/component-emitter@3.1.2':
+ resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
+
+ '@socket.io/redis-adapter@8.3.0':
+ resolution: {integrity: sha512-ly0cra+48hDmChxmIpnESKrc94LjRL80TEmZVscuQ/WWkRP81nNj8W8cCGMqbI4L6NCuAaPRSzZF1a9GlAxxnA==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ socket.io-adapter: ^2.5.4
+
'@swc-node/core@1.13.3':
resolution: {integrity: sha512-OGsvXIid2Go21kiNqeTIn79jcaX4l0G93X2rAnas4LFoDyA9wAwVK7xZdm+QsKoMn5Mus2yFLCc4OtX2dD/PWA==}
engines: {node: '>= 10'}
@@ -1544,6 +1617,9 @@ packages:
'@types/babel__traverse@7.20.7':
resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==}
+ '@types/cors@2.8.19':
+ resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==}
+
'@types/estree@1.0.8':
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
@@ -2051,6 +2127,10 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+ base64id@2.0.0:
+ resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==}
+ engines: {node: ^4.5.0 || >= 5.9}
+
bcrypt-pbkdf@1.0.2:
resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==}
@@ -2465,6 +2545,17 @@ packages:
end-of-stream@1.4.5:
resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
+ engine.io-client@6.6.3:
+ resolution: {integrity: sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==}
+
+ engine.io-parser@5.2.3:
+ resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==}
+ engines: {node: '>=10.0.0'}
+
+ engine.io@6.6.4:
+ resolution: {integrity: sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==}
+ engines: {node: '>=10.2.0'}
+
enquirer@2.3.6:
resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==}
engines: {node: '>=8.6'}
@@ -3625,6 +3716,9 @@ packages:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
+ notepack.io@3.0.1:
+ resolution: {integrity: sha512-TKC/8zH5pXIAMVQio2TvVDTtPRX+DJPHDqjRbxogtFiByHyzKmy96RA0JtCQJ+WouyyL4A10xomQzgbUT+1jCg==}
+
npm-package-arg@11.0.1:
resolution: {integrity: sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==}
engines: {node: ^16.14.0 || >=18.0.0}
@@ -3649,6 +3743,10 @@ packages:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
+ object-hash@3.0.0:
+ resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
+ engines: {node: '>= 6'}
+
object-inspect@1.13.4:
resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
engines: {node: '>= 0.4'}
@@ -4076,6 +4174,21 @@ packages:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
+ socket.io-adapter@2.5.5:
+ resolution: {integrity: sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==}
+
+ socket.io-client@4.8.1:
+ resolution: {integrity: sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==}
+ engines: {node: '>=10.0.0'}
+
+ socket.io-parser@4.2.4:
+ resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==}
+ engines: {node: '>=10.0.0'}
+
+ socket.io@4.8.1:
+ resolution: {integrity: sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==}
+ engines: {node: '>=10.2.0'}
+
sonic-boom@3.8.1:
resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==}
@@ -4376,6 +4489,10 @@ packages:
engines: {node: '>=0.8.0'}
hasBin: true
+ uid2@1.0.0:
+ resolution: {integrity: sha512-+I6aJUv63YAcY9n4mQreLUt0d4lvwkkopDNmpomkAUz0fAkEMV9pRWxN0EjhW1YfRhcuyHg2v3mwddCDW1+LFQ==}
+ engines: {node: '>= 4.0.0'}
+
uid@2.0.2:
resolution: {integrity: sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==}
engines: {node: '>=8'}
@@ -4513,6 +4630,22 @@ packages:
resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+ ws@8.17.1:
+ resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
+ xmlhttprequest-ssl@2.1.2:
+ resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==}
+ engines: {node: '>=0.4.0'}
+
xtend@4.0.2:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'}
@@ -5816,6 +5949,13 @@ snapshots:
'@emnapi/runtime': 1.4.5
'@tybys/wasm-util': 0.9.0
+ '@nestjs-redis/client@0.10.1(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.5)(redis@5.6.0)':
+ dependencies:
+ '@nestjs/common': 11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2)
+ '@nestjs/core': 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(@nestjs/websockets@11.1.6)(reflect-metadata@0.1.14)(rxjs@7.8.2)
+ redis: 5.6.0
+ tslib: 2.8.1
+
'@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2)':
dependencies:
file-type: 21.0.0
@@ -5836,7 +5976,7 @@ snapshots:
lodash: 4.17.21
rxjs: 7.8.2
- '@nestjs/core@11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(reflect-metadata@0.1.14)(rxjs@7.8.2)':
+ '@nestjs/core@11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(@nestjs/websockets@11.1.6)(reflect-metadata@0.1.14)(rxjs@7.8.2)':
dependencies:
'@nestjs/common': 11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2)
'@nuxt/opencollective': 0.4.1
@@ -5849,11 +5989,12 @@ snapshots:
uid: 2.0.2
optionalDependencies:
'@nestjs/platform-express': 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.5)
+ '@nestjs/websockets': 11.1.6(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.5)(@nestjs/platform-socket.io@11.1.6)(reflect-metadata@0.1.14)(rxjs@7.8.2)
'@nestjs/platform-express@11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.5)':
dependencies:
'@nestjs/common': 11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2)
- '@nestjs/core': 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(reflect-metadata@0.1.14)(rxjs@7.8.2)
+ '@nestjs/core': 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(@nestjs/websockets@11.1.6)(reflect-metadata@0.1.14)(rxjs@7.8.2)
cors: 2.8.5
express: 5.1.0
multer: 2.0.2
@@ -5862,6 +6003,18 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@nestjs/platform-socket.io@11.1.6(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/websockets@11.1.6)(rxjs@7.8.2)':
+ dependencies:
+ '@nestjs/common': 11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2)
+ '@nestjs/websockets': 11.1.6(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.5)(@nestjs/platform-socket.io@11.1.6)(reflect-metadata@0.1.14)(rxjs@7.8.2)
+ rxjs: 7.8.2
+ socket.io: 4.8.1
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
'@nestjs/schematics@11.0.5(typescript@5.8.3)':
dependencies:
'@angular-devkit/core': 19.2.6
@@ -5876,7 +6029,7 @@ snapshots:
'@nestjs/terminus@11.0.0(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.5)(reflect-metadata@0.1.14)(rxjs@7.8.2)':
dependencies:
'@nestjs/common': 11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2)
- '@nestjs/core': 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(reflect-metadata@0.1.14)(rxjs@7.8.2)
+ '@nestjs/core': 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(@nestjs/websockets@11.1.6)(reflect-metadata@0.1.14)(rxjs@7.8.2)
boxen: 5.1.2
check-disk-space: 3.4.0
reflect-metadata: 0.1.14
@@ -5885,7 +6038,7 @@ snapshots:
'@nestjs/testing@11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.5)(@nestjs/platform-express@11.1.5)':
dependencies:
'@nestjs/common': 11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2)
- '@nestjs/core': 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(reflect-metadata@0.1.14)(rxjs@7.8.2)
+ '@nestjs/core': 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(@nestjs/websockets@11.1.6)(reflect-metadata@0.1.14)(rxjs@7.8.2)
tslib: 2.8.1
optionalDependencies:
'@nestjs/platform-express': 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.5)
@@ -5893,9 +6046,21 @@ snapshots:
'@nestjs/throttler@6.4.0(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.5)(reflect-metadata@0.1.14)':
dependencies:
'@nestjs/common': 11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2)
- '@nestjs/core': 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(reflect-metadata@0.1.14)(rxjs@7.8.2)
+ '@nestjs/core': 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(@nestjs/websockets@11.1.6)(reflect-metadata@0.1.14)(rxjs@7.8.2)
reflect-metadata: 0.1.14
+ '@nestjs/websockets@11.1.6(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.5)(@nestjs/platform-socket.io@11.1.6)(reflect-metadata@0.1.14)(rxjs@7.8.2)':
+ dependencies:
+ '@nestjs/common': 11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2)
+ '@nestjs/core': 11.1.5(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.5)(@nestjs/websockets@11.1.6)(reflect-metadata@0.1.14)(rxjs@7.8.2)
+ iterare: 1.2.1
+ object-hash: 3.0.0
+ reflect-metadata: 0.1.14
+ rxjs: 7.8.2
+ tslib: 2.8.1
+ optionalDependencies:
+ '@nestjs/platform-socket.io': 11.1.6(@nestjs/common@11.1.5(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/websockets@11.1.6)(rxjs@7.8.2)
+
'@nodelib/fs.scandir@2.1.5':
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -6191,6 +6356,17 @@ snapshots:
dependencies:
'@sinonjs/commons': 3.0.1
+ '@socket.io/component-emitter@3.1.2': {}
+
+ '@socket.io/redis-adapter@8.3.0(socket.io-adapter@2.5.5)':
+ dependencies:
+ debug: 4.3.4
+ notepack.io: 3.0.1
+ socket.io-adapter: 2.5.5
+ uid2: 1.0.0
+ transitivePeerDependencies:
+ - supports-color
+
'@swc-node/core@1.13.3(@swc/core@1.5.29(@swc/helpers@0.5.17))(@swc/types@0.1.23)':
dependencies:
'@swc/core': 1.5.29(@swc/helpers@0.5.17)
@@ -6339,6 +6515,10 @@ snapshots:
dependencies:
'@babel/types': 7.28.1
+ '@types/cors@2.8.19':
+ dependencies:
+ '@types/node': 18.16.9
+
'@types/estree@1.0.8': {}
'@types/graceful-fs@4.1.9':
@@ -6952,6 +7132,8 @@ snapshots:
base64-js@1.5.1: {}
+ base64id@2.0.0: {}
+
bcrypt-pbkdf@1.0.2:
dependencies:
tweetnacl: 0.14.5
@@ -7352,6 +7534,36 @@ snapshots:
dependencies:
once: 1.4.0
+ engine.io-client@6.6.3:
+ dependencies:
+ '@socket.io/component-emitter': 3.1.2
+ debug: 4.3.4
+ engine.io-parser: 5.2.3
+ ws: 8.17.1
+ xmlhttprequest-ssl: 2.1.2
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ engine.io-parser@5.2.3: {}
+
+ engine.io@6.6.4:
+ dependencies:
+ '@types/cors': 2.8.19
+ '@types/node': 18.16.9
+ accepts: 1.3.8
+ base64id: 2.0.0
+ cookie: 0.7.2
+ cors: 2.8.5
+ debug: 4.3.4
+ engine.io-parser: 5.2.3
+ ws: 8.17.1
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
enquirer@2.3.6:
dependencies:
ansi-colors: 4.1.3
@@ -8875,6 +9087,8 @@ snapshots:
normalize-path@3.0.0: {}
+ notepack.io@3.0.1: {}
+
npm-package-arg@11.0.1:
dependencies:
hosted-git-info: 7.0.2
@@ -8941,6 +9155,8 @@ snapshots:
object-assign@4.1.1: {}
+ object-hash@3.0.0: {}
+
object-inspect@1.13.4: {}
on-exit-leak-free@2.1.2: {}
@@ -9407,6 +9623,47 @@ snapshots:
slash@3.0.0: {}
+ socket.io-adapter@2.5.5:
+ dependencies:
+ debug: 4.3.4
+ ws: 8.17.1
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ socket.io-client@4.8.1:
+ dependencies:
+ '@socket.io/component-emitter': 3.1.2
+ debug: 4.3.4
+ engine.io-client: 6.6.3
+ socket.io-parser: 4.2.4
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ socket.io-parser@4.2.4:
+ dependencies:
+ '@socket.io/component-emitter': 3.1.2
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+
+ socket.io@4.8.1:
+ dependencies:
+ accepts: 1.3.8
+ base64id: 2.0.0
+ cors: 2.8.5
+ debug: 4.3.4
+ engine.io: 6.6.4
+ socket.io-adapter: 2.5.5
+ socket.io-parser: 4.2.4
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
sonic-boom@3.8.1:
dependencies:
atomic-sleep: 1.0.0
@@ -9709,6 +9966,8 @@ snapshots:
uglify-js@3.19.3:
optional: true
+ uid2@1.0.0: {}
+
uid@2.0.2:
dependencies:
'@lukeed/csprng': 1.1.0
@@ -9903,6 +10162,10 @@ snapshots:
imurmurhash: 0.1.4
signal-exit: 4.1.0
+ ws@8.17.1: {}
+
+ xmlhttprequest-ssl@2.1.2: {}
+
xtend@4.0.2: {}
y18n@5.0.8: {}
diff --git a/tsconfig.json b/tsconfig.json
index 7aaf938..75aa801 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -17,6 +17,9 @@
},
{
"path": "./packages/kit"
+ },
+ {
+ "path": "./packages/socket.io-adapter"
}
]
}