TypeError: Cannot read property 'debug' of undefined in nestJs

Viewed 32

error 1. "TypeError: Cannot read property 'debug' of undefined".

  68 |     }
  69 |
> 70 |     this._logger.debug(
     |                  ^
  71 |       `Creating a ${
  72 |         createCacheControlDto.type
  73 |       } for site - ${siteId} with body - ${JSON.stringify(

error 2. TypeError: this._cacheControlModel is not a constructor

  87 |     };
  88 |
> 89 |     const cacheControlToCreate = new this._cacheControlModel({
     |                                  ^
  90 |       ...createCacheControlPayload
  91 |     });
  92 |

I try to call the create method of service file. But getting error

Please Help to find the solution. Here I am placing the code. Please find it.

file 1. cache-control.service.spec.ts

import { getModelToken } from '@nestjs/mongoose';
import { Test, TestingModule } from '@nestjs/testing';
import { MongoMemoryServer } from 'mongodb-memory-server';
import { Connection, Model, connect } from 'mongoose';
import { CacheControlController } from './cache-control.controller';
import { CacheControlService } from './cache-control.service';
import { mockCacheControlService } from './mock/mock-cache-control.service';
import {
  SearchAndProjectDto,
  SearchDTO
} from '@classes/search-and-project-dto';
import { LABELS } from '@constants/labels.constant';
import { CacheControlStatus } from '@enums/cache-control-status.enum';
import { CacheControlType } from '@enums/cache-control-type.enum';
import { JmsCommandResponse } from '@interfaces/jms-command-response.interface';
import { JmsResponse } from '@interfaces/jms-response.interface';
import { PaginatedData } from '@interfaces/paginated-data.interface';
import { Injectable, Logger } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { DbUtilService } from '@services/db-util.service';
import { ExceptionService } from '@services/exception.service';
import { JMSService } from '@services/jms.service';
import { LabelService } from '@services/label.service';
import { QueryService } from '@services/query.service';
import { SiteCommonService } from '@services/site-common.service';
import { SoftDeleteModel } from 'mongoose-delete';
import { JournalService } from '../journal/journal.service';
import { Site, SiteDocument, SiteSchema } from '../site/schemas/site.schema';
import {
  CacheControl,
  CacheControlSchema
} from './schemas/cache-control.schema';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { FileUploadService } from '../file-upload/file-upload.service';
import {
  Journal,
  JournalDocument,
  JournalSchema
} from '../journal/schemas/journal.schema';
import { ConfigService } from '@nestjs/config';
import { RetryService } from '@services/retry.service';
import {
  FileUpload,
  FileUploadSchema,
  FileUploadDocument
} from '../file-upload/schema/file-upload.schema';
import { CreateCacheControlDTOStub } from './mock/create-cache-control.dto.stub';

describe('CacheControlService', () => {
  let service: CacheControlService;

  let mongod: MongoMemoryServer;
  let mongoConnection: Connection;
  let cacheControlModel: Model<CacheControl>;
  let siteModel: Model<Site>;
  let journalModel: Model<Journal>;
  let fileUploadModel: Model<FileUpload>;
  const mockRequest = <Request>{};
  const mockCacheControlService = {};

  const siteId = '62f134d689922f41a50095f7';
  const cacheControlId = '63084113d836f908a66b0db4';
  const accountId = '63084113d836f908a66b0db4';

  // beforeEach(async () => {
  beforeAll(async () => {
    mongod = await MongoMemoryServer.create();
    const uri = mongod.getUri();
    mongoConnection = (await connect(uri)).connection;
    cacheControlModel = mongoConnection.model(
      'CacheControl',
      CacheControlSchema
    );
    siteModel = mongoConnection.model('Site', SiteSchema);
    // journalModel = mongoConnection.model('Journal', JournalSchema);

    fileUploadModel = mongoConnection.model('FileUpload', FileUploadSchema);
    // accountModel = mongoConnection.model('Account', AccountSchema);

    const module: TestingModule = await Test.createTestingModule({
      imports: [HttpModule],
      controllers: [CacheControlController],
      providers: [
        CacheControlService,
        SiteCommonService,
        JournalService,
        JMSService,
        FileUploadService,
        ConfigService,
        EventEmitter2,
        Logger,
        // HttpService,
        RetryService,
        {
          provide: getModelToken(CacheControl.name),
          useValue: cacheControlModel
        },
        { provide: getModelToken(Journal.name), useValue: journalModel },
        { provide: getModelToken(Site.name), useValue: siteModel },
        { provide: getModelToken(FileUpload.name), useValue: fileUploadModel },
        {
          provide: getModelToken(Journal.name),
          useValue: jest.fn()
        },
        {
          provide: getModelToken(CacheControl.name),
          useValue: jest.fn()
        }
      ]
    })
      // .useValue(mockCacheControlService)
      .setLogger(new Logger(CacheControlService.name))
      .compile();

    service = module.get<CacheControlService>(CacheControlService);
  });

  afterAll(async () => {
    await mongoConnection.dropDatabase();
    await mongoConnection.close();
    await mongod.stop();
  });

  afterEach(async () => {
    const collections = mongoConnection.collections;
    for (const key in collections) {
      const collection = collections[key];
      await collection.deleteMany({});
    }
  });

    describe('CreateCacheControl', () => {
    it('should create a Cache Control', async () => {
      const createdCacheControl = await service.create(
        accountId,
        siteId,
        CreateCacheControlDTOStub()
      );
     
    });
  });
});

file 2. cache-control.service.ts

  SearchAndProjectDto,
  SearchDTO
} from '@classes/search-and-project-dto';
import { LABELS } from '@constants/labels.constant';
import { CacheControlStatus } from '@enums/cache-control-status.enum';
import { CacheControlType } from '@enums/cache-control-type.enum';
import { JmsCommandResponse } from '@interfaces/jms-command-response.interface';
import { JmsResponse } from '@interfaces/jms-response.interface';
import { PaginatedData } from '@interfaces/paginated-data.interface';
import { Injectable, Logger } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { DbUtilService } from '@services/db-util.service';
import { ExceptionService } from '@services/exception.service';
import { JMSService } from '@services/jms.service';
import { LabelService } from '@services/label.service';
import { QueryService } from '@services/query.service';
import { SiteCommonService } from '@services/site-common.service';
import { SoftDeleteModel } from 'mongoose-delete';
import { JournalService } from '../journal/journal.service';
import { Site } from '../site/schemas/site.schema';
import {
  CACHE_CONTROL_JOB_TYPE,
  CACHE_CONTROL_JOURNAL_TYPE,
  INVALIDATION_PATH_PATTERN_REGEX,
  PURGE_PATH_PATTERN
} from './cache-control.constant';
import { CreateCacheControlDto } from './dto/create-cache-control.dto';
import {
  CacheControl,
  CacheControlDocument
} from './schemas/cache-control.schema';
import * as mongoose from 'mongoose';
import { CdnS3Bucket } from '../file-upload/file-upload.constant';
import { FileUploadService } from '../file-upload/file-upload.service';
import { CacheControlBulkUpload } from '@constants/event.constant';
import { PopulateService } from '@services/populate.service';
import * as crypto from 'crypto';
import { SegmentConfiguration } from '../segment-configuration/schemas/segment-configuration.schema';

@Injectable()
export class CacheControlService {
  private readonly _logger = new Logger(CacheControlService.name);

  constructor(
    @InjectModel(CacheControl.name)
    private readonly _cacheControlModel: SoftDeleteModel<CacheControlDocument>,
    private readonly _siteCommonService: SiteCommonService,
    private readonly _journalService: JournalService,
    private readonly _jmsService: JMSService,
    private readonly _fileUploadService: FileUploadService
  ) {}

  async create(
    accountId: string,
    siteId: string,
    createCacheControlDto: CreateCacheControlDto
  ): Promise<any> {
    if (!createCacheControlDto.isBulkUpload) {
      // Validating path pattern array
      const isValidPathPattern = this._isValidPathPattern(
        createCacheControlDto.pathPatterns,
        createCacheControlDto.type
      );
      if (!isValidPathPattern) {
        ExceptionService.badRequest('Invalid path pattern');
      }
    }

    this._logger.debug(
      `Creating a ${
        createCacheControlDto.type
      } for site - ${siteId} with body - ${JSON.stringify(
        createCacheControlDto
      )}`
    );

    const createCacheControlPayload = {
      ...createCacheControlDto,
      siteId,
      accountId,
      status:
        createCacheControlDto.type === CacheControlType.INVALIDATION &&
        !createCacheControlDto?.isBulkUpload
          ? CacheControlStatus.COMPLETED
          : CacheControlStatus.IN_PROGRESS
    };

    const cacheControlToCreate = new this._cacheControlModel({
      ...createCacheControlPayload
    });

    const createdCacheControl: CacheControl = await cacheControlToCreate.save();

    switch (createCacheControlDto.type) {
      case CacheControlType.INVALIDATION: {
        // Journal the invalidation config change
        this._journalService.createContext(
          CACHE_CONTROL_JOURNAL_TYPE.invalidation
        );
        this._journalService.logCreateAction({
          newValue: createdCacheControl
        });
        break;
      }

      case CacheControlType.PURGE: {
        // Send command to JMS

        // If bulk upload CSV, event will be fired to validate, process CSV and create Job in JMS
        if (createdCacheControl.isBulkUpload) {
          break;
        }

        // Getting site with segment configuration for token authentication
        const site: Site = await this._getSiteWithSegmentConfigurations(siteId);
        // Sign URL based on segment configuration's token auth
        if (site.segmentConfigurations.length > 0) {
          createCacheControlDto.pathPatterns = this._getSignedUrls(
            createCacheControlDto.pathPatterns,
            site.domainName,
            site.segmentConfigurations
          );
        }

        try {
          const jmsJobId = await this._createAnCachePurgeJob(
            createdCacheControl.id,
            createCacheControlDto.pathPatterns,
            site
          );

          // Updating Cache control with jmsJobId
          await this.updateById(createdCacheControl._id, { jmsJobId });
        } catch (exception) {
          console.log(exception?.response?.statusText);
          // Updating Cache control with FAILED status if we get error while creating job
          await this.updateById(createdCacheControl._id, {
            status: CacheControlStatus.FAILED,
            message: 'Failed to create job, please try again'
          });
        }
        break;
      }
    }

    return createdCacheControl;
  }
}

file 3. cache-control.controller.ts

import { CONTROLLER_VERSION_1 } from '@constants/api-version.constant';
import { CacheControlBulkUpload, EVENTS } from '@constants/event.constant';
import { CacheControlType } from '@enums/cache-control-type.enum';
import { JwtAuthGuard } from '@guards/jwt-auth.guard';
import { PaginatedData } from '@interfaces/paginated-data.interface';
import {
  Body,
  Controller,
  Get,
  HttpCode,
  HttpStatus,
  Param,
  Post,
  Query,
  Req,
  Request,
  UploadedFile,
  UseGuards,
  UseInterceptors,
  ValidationPipe
} from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { FileInterceptor } from '@nestjs/platform-express';
import { IdentifierPipe } from '@pipes/identifier.pipe';
import { ExceptionService } from '@services/exception.service';
import { SbJwtService } from '@services/sb-jwt.service';
import { isCSVFileformat } from '../bulk-upload-job/utils/csv-file-filter';
import {
  CdnS3Bucket,
  CdnS3FolderName,
  FileUploadModuleType
} from '../file-upload/file-upload.constant';
import { FileUploadService } from '../file-upload/file-upload.service';
import { SITE_PARAMS } from '../site/site.constant';
import {
  CACHE_CONTROL_PARAMS,
  CACHE_CONTROL_ROUTES
} from './cache-control.constant';
import { CacheControlService } from './cache-control.service';
import { CreateCacheControlDto } from './dto/create-cache-control.dto';
import { CacheControl } from './schemas/cache-control.schema';

@UseGuards(JwtAuthGuard)
@Controller({
  ...CONTROLLER_VERSION_1,
  path: `${CACHE_CONTROL_ROUTES.cacheControl_home}/${CACHE_CONTROL_ROUTES.cacheControl}/`
})
export class CacheControlController {
  constructor(
    private readonly _cacheControlService: CacheControlService,
    private readonly _fileUploadService: FileUploadService,
    private readonly eventEmitter: EventEmitter2
  ) {}

  @Post()
  @HttpCode(HttpStatus.CREATED)
  async create(
    @Request() request: Request,
    @Param(SITE_PARAMS.siteId, new IdentifierPipe())
    siteId: string,
    @Body() body: CreateCacheControlDto
  ) {
    const accountId = SbJwtService.getLoggedInAccountId(request);
    return await this._cacheControlService.create(accountId, siteId, body);
  }
}

file 4. cache-control.schema.ts

import { CacheControlType } from '@enums/cache-control-type.enum';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import * as mongoose from 'mongoose';
import { Document } from 'mongoose';
import { SoftDeleteDocument } from 'mongoose-delete';
import { Site } from 'src/modules/site/schemas/site.schema';

export type CacheControlDocument = CacheControl & Document & SoftDeleteDocument;

@Schema({
  collection: 'cacheControls',
  timestamps: true
})
export class CacheControl extends Document {
  @Prop({
    type: mongoose.Schema.Types.String,
    required: false
  })
  title: string;

  @Prop({
    type: mongoose.Schema.Types.ObjectId,
    required: true,
    ref: 'accounts'
  })
  accountId: string;

  @Prop({
    type: mongoose.Schema.Types.ObjectId,
    required: true,
    ref: 'sites'
  })
  siteId: string;

  @Prop({
    type: mongoose.Schema.Types.ObjectId
  })
  jmsJobId?: string;

  @Prop({
    type: mongoose.Schema.Types.Array,
    required: true,
    minlength: 1
  })
  pathPatterns: string[];

  @Prop({
    type: mongoose.Schema.Types.String,
    enum: Object.values(CacheControlStatus),
    required: true
  })
  status: CacheControlStatus;

  @Prop({
    type: mongoose.Schema.Types.String,
    required: false
  })
  message?: string;

  @Prop({
    type: mongoose.Schema.Types.String,
    enum: Object.values(CacheControlType),
    required: true
  })
  type: CacheControlType;

  @Prop({
    type: mongoose.Schema.Types.Boolean,
    required: true,
    default: false
  })
  isBulkUpload: boolean;

  @Prop({
    type: mongoose.Schema.Types.String,
    required: false
  })
  fileName: string;

  @Prop({
    type: mongoose.Schema.Types.String,
    required: false
  })
  fileLink: string;

  @Prop({
    type: mongoose.Schema.Types.String,
    required: false
  })
  fileKey: string;

  @Prop({
    type: mongoose.Schema.Types.String,
    required: false
  })
  commandId: string;

  site: Site;
}

export const CacheControlSchema = SchemaFactory.createForClass(CacheControl);

CacheControlSchema.virtual('site', {
  ref: 'Site',
  localField: 'siteId',
  foreignField: '_id',
  justOne: true
});
0 Answers
Related