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 Toolkit Logo + +# @nestjs-redis/socket.io-adapter + +Redis-powered Socket.IO adapter for NestJS enabling scalable WebSocket connections across multiple instances. + +[![npm version](https://badge.fury.io/js/%40nestjs-redis%2Fsocket.io-adapter.svg)](https://www.npmjs.com/package/@nestjs-redis/socket.io-adapter) +[![npm downloads](https://img.shields.io/npm/dm/@nestjs-redis/socket.io-adapter.svg)](https://www.npmjs.com/package/@nestjs-redis/socket.io-adapter) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/) +[![NestJS](https://img.shields.io/badge/NestJS-9%2B-red.svg)](https://nestjs.com/) [![Redis](https://img.shields.io/badge/Redis-5+-red.svg)](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" } ] }