skip to Main Content

I’m trying to implement express-session package along with connect-redis for session storage in my NestJS backend, but i got such an error as follows. I even changed the client inside the store to RedisClient, which is injection token declared in provider file, but still no luck, where im mistaken exactly? whats the best practises to implement such feature so that I can use redis as session storage, either using connect-redis or something else…thanks a lot in advance, any help appreciated

error message:

store: new ((0, connect_redis_1.default)(session))({
                                                        ^
TypeError: Class constructor RedisStore cannot be invoked without 'new'
ERROR in ./src/app.module.ts:34:5
TS2322: Type 'RequestHandler<ParamsDictionary, any, any, ParsedQs, Record<string, any>>' is not assignable to type 'Type<any> | DynamicModule | Promise<DynamicModule> | ForwardReference<any>'.
    32 |     CartModule,
    33 |     RedisModule,
  > 34 |     session({
       |     ^^^^^^^^^
  > 35 |       store: new (RedisStore(session))({
       | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  > 36 |         client: redisClientFactory,
       | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  > 37 |       }),
       | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  > 38 |       secret: 'my-secret',
       | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  > 39 |       resave: false,
       | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  > 40 |       saveUninitialized: false,
       | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  > 41 |     }),
       | ^^^^^^^
    42 |   ],
    43 |   controllers: [AppController],
    44 |   providers: [AppService, AccessControlService, ReviewService],

ERROR in ./src/app.module.ts:35:19
TS2348: Value of type 'typeof RedisStore' is not callable. Did you mean to include 'new'?
    33 |     RedisModule,
    34 |     session({
  > 35 |       store: new (RedisStore(session))({
       |                   ^^^^^^^^^^^^^^^^^^^
    36 |         client: redisClientFactory,
    37 |       }),
    38 |       secret: 'my-secret',

app.module.ts

import { Module, Inject, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { LoggerModule } from '@app/common';
import { ConfigModule } from '@app/common';
import { DatabaseModule } from './database/database.module';
import { AuthModule } from './auth/auth.module';
import { UserModule } from './user/user.module';
import { ProductModule } from './product/product.module';
import { CategoryModule } from './category/category.module';
import { Role } from '@prisma/client';
import { AccessControlService } from '@app/common/access-control/access-control.service';
import { SearchModule } from '@app/common/elastic-search/elasticsearch.module';
import { ReviewService } from './review/review.service';
import { ReviewModule } from './review/review.module';
import { CartModule } from './cart/cart.module';
import RedisStore from 'connect-redis';
import * as session from 'express-session';
import { RedisModule } from '@app/common/redis/redis.module';
import { redisClientFactory } from '@app/common/redis/redis.provider';

@Module({
  imports: [
    LoggerModule,
    ConfigModule,
    DatabaseModule,
    AuthModule,
    UserModule,
    ProductModule,
    CategoryModule,
    ReviewModule,
    CartModule,
    RedisModule,
    session({
      store: new (RedisStore(session))({
        client: redisClientFactory,
      }),
      secret: 'my-secret',
      resave: false,
      saveUninitialized: false,
    }),
  ],
  controllers: [AppController],
  providers: [AppService, AccessControlService, ReviewService],
})
export class AppModule {}

redis.module.ts

import { Module } from '@nestjs/common';
import { RedisRepository } from './redis.repository';
import { RedisService } from './redis.service';
import { redisClientFactory } from './redis.provider';

@Module({
  providers: [RedisService, RedisRepository, redisClientFactory],
  exports: [RedisService, RedisRepository, redisClientFactory],
})
export class RedisModule {}

redis.provider.ts

import { FactoryProvider } from '@nestjs/common';
import { Redis } from 'ioredis';
import { ConfigService } from '@nestjs/config';

export const redisClientFactory: FactoryProvider<Redis> = {
  provide: 'RedisClient',
  inject: [ConfigService],
  useFactory: (configService: ConfigService) => {
    const redisInstance = new Redis({
      host: configService.get('REDIS_HOST'),
      port: configService.get('REDIS_PORT'),
      password: configService.get('REDIS_PASSWORD'),
    });

    redisInstance.on('error', (error) => {
      console.error('Redis error', error);
    });

    return redisInstance;
  },
};

even changed the client inside the store to RedisClient, which is injection token declared in provider file

2

Answers


  1. Chosen as BEST ANSWER
    ERROR in ./src/app.module.ts:34:5
    TS2322: Type 'RequestHandler<ParamsDictionary, any, any, ParsedQs, Record<string, any>>' is not assignable to type 'Type<any> | DynamicModule | Promise<DynamicModule> | ForwardReference<any>'.
        32 |     CartModule,
        33 |     RedisModule,
      > 34 |     session({
           |     ^^^^^^^^^
      > 35 |       store: (new RedisStore(session))({
           | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      > 36 |         client: redisClientFactory,
           | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      > 37 |       }),
           | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      > 38 |       secret: 'my-secret',
           | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      > 39 |       resave: false,
           | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      > 40 |       saveUninitialized: false,
           | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      > 41 |     }),
           | ^^^^^^^
        42 |   ],
        43 |   controllers: [AppController],
        44 |   providers: [AppService, AccessControlService, ReviewService],
    
    ERROR in ./src/app.module.ts:35:14
    TS2349: This expression is not callable.
      Type 'RedisStore' has no call signatures.
        33 |     RedisModule,
        34 |     session({
      > 35 |       store: (new RedisStore(session))({
           |              ^^^^^^^^^^^^^^^^^^^^^^^^^
        36 |         client: redisClientFactory,
        37 |       }),
        38 |       secret: 'my-secret',
    
    ERROR in ./src/app.module.ts:35:30
    TS2345: Argument of type 'typeof session' is not assignable to parameter of type 'RedisStoreOptions'.
      Property 'client' is missing in type 'typeof session' but required in type 'RedisStoreOptions'.
        33 |     RedisModule,
        34 |     session({
      > 35 |       store: (new RedisStore(session))({
           |                              ^^^^^^^
        36 |         client: redisClientFactory,
        37 |       }),
        38 |       secret: 'my-secret',
    
    
            let isRedis = "scanIterator" in client;
                                         ^
    TypeError: Cannot use 'in' operator to search for 'scanIterator' in undefined
        at RedisStore.normalizeClient 
    

  2. Not familiar with the library, but this looks like a garden-variety TypeScript error to me. The RedisStore class is a class and requires the new operator to instantiate it. However, it’s being invoked like a function inside of the parentheses.

    new (RedisStore(session))
    
    

    I’d try moving the new and see if the error changes:

    (new RedisStore(session))
    

    Hope this helps.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search