The NestJs provider fails to inject and throws an error stating that this.iGalleryRepository.addImage is not a recognized function

I'm currently working on developing a NestJS TypeScript backend application that interacts with MySQL as its database, following the principles of clean architecture. My implementation includes JWT and Authorization features. However, I seem to be encountering issues with my function due to problems related to dependency injection. To resolve this, I'll share relevant files here, but please let me know if you require access to any additional files for debugging purposes. I've been troubleshooting this problem for the past 3-4 days. :/

Full Error :

ERROR Method: POST; Path: /images/add; Error: this.iGalleryRepository.addImage is not a function


The module "AppModule" is named as .RootModule where I package my app:

    @Module({
      imports: [
          InfraModule,
          AuthModule,
          UserModule,
          ImageModule
      ]
    })
    export class RootModule { }

Here's the structure of the Image Module:


const persistenceProviders: Provider[] = [
    {
        provide: DITokens.ImageDITokens.ImageRepository,
        useFactory: (dataSource: DataSource) => dataSource.getRepository(TypeOrmImage).extend(TypeOrmImageRepositoryAdapter),
        inject: [DITokens.CoreDITokens.DataSource]
    }
];

@Module({
    controllers: [
        ImageController
    ],
    providers: [
        ...persistenceProviders,
        ImageService,
        ImageHandler
    ]
})
export class ImageModule { }

You might wonder about the definition of the database:

export const databaseProviders = [
    {
        provide: DITokens.CoreDITokens.DataSource,
        useFactory: async () => {
            return AppDataSource.initialize();
        }
    }
];

.
.
.
@Global()
@Module({
    imports: [
        CqrsModule,
    ],
    providers: [
        ...providers,
        ...databaseProviders
    ],
    exports: [
        DITokens.CoreDITokens.CommandBus,
        DITokens.CoreDITokens.QueryBus,
        DITokens.CoreDITokens.EventBus,
        ...databaseProviders
    ]
})
export class InfraModule implements OnApplicationBootstrap {
    onApplicationBootstrap(): void {
        initializeTransactionalContext();
    }
}

Details about the Image Controller:

It's worth noting that the line Logger.log(adapter, "CreateImageDTO") works fine and outputs correctly, but the subsequent line Logger.log(createdImage, "createdImage") seems to have an issue.

@Controller('images')
@ApiTags('images')
export class ImageController {

    constructor(
        private readonly imageService: ImageService,
        private readonly imageHandler: ImageHandler,
    ) { }

@Post("add")
    @HttpCode(HttpStatus.OK)
    @ApiBody({ type: HttpRestApiModelCreateImageBody })
    @ApiResponse({ status: HttpStatus.OK, type: HttpRestApiResponseImage })
    public async createImage(
        @Body() body: HttpRestApiModelCreateImageBody

    ): Promise<CoreApiResponse<ImageUseCaseDTO>> {

        const adapter: ICreateImageDTO = await CreateImageDTO.new({
            parentId: body.parentId,
            title: body.title,
            imageUrl: body.imageUrl,
            type: body.type
        });

        Logger.log(adapter, "CreateImageDTO")

        const createdImage: ImageUseCaseDTO = await this.imageService.createImage(adapter);

        Logger.log(createdImage, "createdImage")

        return CoreApiResponse.success(createdImage);
    }
 }

Information regarding the Image Service:

@Injectable()
export class ImageService {

    /**
     * @param {IGalleryRepository} iGalleryRepository
     */
    constructor(
        @Inject(DITokens.ImageDITokens.ImageRepository)
        private readonly iGalleryRepository: IGalleryRepository
    ) { }
   
    public async createImage(payload: ICreateImageDTO): Promise<ImageUseCaseDTO> {
        const image: Image = await Image.new({
            title: payload.title,
            type: payload.type,
            parentId: payload.parentId,
            imageUrl: payload.imageUrl
        })

        await this.iGalleryRepository.addImage(image);

        return ImageUseCaseDTO.newFromImage(image);
    }

}

Error description from the above code snippet mentioned earlier

When attempting to log this.iGalleryRepository using console.log(), the output is as follows:

Repository {
  target: [class TypeOrmImage],
  manager: <ref *1> EntityManager {
    '@instanceof': Symbol(EntityManager),
    repositories: [ [Repository], [Repository] ],
    treeRepositories: [],
    plainObjectToEntityTransformer: PlainObjectToNewEntityTransformer {},
    connection: DataSource {
      '@instanceof': Symbol(DataSource),
      migrations: [],
      subscribers: [],
      entityMetadatas: [Array],
      name: 'default',
      options: [Object],
      logger: [AdvancedConsoleLogger],
      driver: [MysqlDriver],
      manager: [Circular *1],
      namingStrategy: [DefaultNamingStrategy],
      metadataTableName: 'typeorm_metadata',
      queryResultCache: undefined,
      relationLoader: [RelationLoader],
      relationIdLoader: [RelationIdLoader],
      isInitialized: true
    }
  },
  queryRunner: undefined
}

Your assistance is greatly appreciated in advance.

Answer №1

Finally, I managed to solve the issue.

dataSource.getRepository(TypeOrmImage).extend(TypeOrmImageRepositoryAdapter)

Although it was supposed to work, for some mysterious reason, it didn't. The .extend function wasn't behaving as expected, leading me to believe that either the extend method had a bug or my implementation was incorrect. So if you encounter this error, double-check your implementation first before trying something else.

To resolve it, all I did was

provide: DITokens.ImageDITokens.ImageRepository,
        useFactory: (dataSource: DataSource) => dataSource.getRepository(TypeOrmImage).extend(TypeOrmImageRepositoryAdapter),
        inject: [DITokens.CoreDITokens.DataSource]


changed it to

 provide: DITokens.ImageDITokens.ImageRepository,
        useClass: TypeOrmImageRepositoryAdapter

and surprisingly, it worked perfectly. It seems that referencing the repository in the class signature generates the TypeORM repository automatically.

I hope this solution works for you as well!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can this method determine the number of rows in a table? What is the correct way to call this method from PHP?

test1 is a function that calculates the number of rows in a table created after passing two variables v_col1 and v_col2. Despite successful execution on MySQL, it returns an empty result set (zero rows) stating "MySQL returned an empty result set (i.e. zer ...

Leverage the power of Angular's library dependency injection with the @inject

I am currently working on a project that involves a library. Within one of the classes in this library, I am attempting to provide a service using @optional, @host, and @inject decorators with an injection token. In the parent component, I have the optio ...

Ways to specify an unused parameter within a function

As I work on my code, I encounter the need to separate the key and value from a request params object in order to validate the value using ObjectID. To achieve this, I decided to iterate over an array of entries and destructure the key and value for testin ...

Monitor changes in a dynamic child component using Angular fire and TypeScript only (no HTML)

Currently, I am developing a component using TypeScript and passing inputs to my child component from there. In the parent TypeScript file: this.childComponent = this.viewContainerRef.createComponent(this.data.body).instance; this.childComponent['chi ...

The traditional function does not have access to a reference to this

For my web development project with Angular 9, I needed to add a typeahead feature using ng bootstrap typeahead. The code provided below worked perfectly: search = (text$: Observable<string>) => text$.pipe( debounceTime(150), disti ...

What are some ways to make autorun compatible with runInAction in mobx?

Currently delving into the world of mobx and runInAction, facing a challenge in comprehending why autorun fails to trigger my callback in this particular scenario: class ExampleClass { // constructor() { // this.exampleMethod(); // } ...

Show video when there is no image in the database row using PHP

My goal is to either display a video or an image based on the content of the database row. In my tbl_library database, I have columns for image and video with library_id as the primary key. Using a while loop, I am able to view table information and provi ...

Is it possible to use v-if in conjunction with a style tag to specify a different source file? Alternatively, is there a more efficient method I

I attempted the example provided below, but unfortunately, it did not function as expected. The reason behind my endeavor is that adding numerous modifiers (--tuned) to achieve the desired outcome seemed impractical. Therefore, I decided to try and link ...

The attribute 'value' is not present in the object of type 'Readonly<{}>'

My current project involves creating a form that will dynamically display content based on the response from an API. The code I am working with is structured as follows: class Application extends React.Component { constructor(props) { super(props); ...

How can we achieve a seamless fade transition effect between images in Ionic 2?

My search for Ionic 2 animations led me to some options, but none of them quite fit what I was looking for. I have a specific animation in mind - a "fade" effect between images. For example, I have a set of 5 images and I want each image to fade into the ...

Typescript enables bidirectional control of Swiper

I attempted to use the two-way control slider example from Swiper documentation, but I encountered TypeScript errors that prevented it from working correctly. Is there a way to make it compatible with TypeScript? The specific errors I received were: TS23 ...

Create the HTTP POST request body using an object in readiness for submission

When sending the body of an http post request in Angular, I typically use the following approach: let requestBody: String = ""; //dataObject is the object containing form values to send for (let key in dataObject) { if (dataObject[key]) { ...

Retrieving a single column entry using MySQL and PHP with the Insert row query

Let me set the scene for you: I have a small project where users can register through a table called users, which has various fields: userid int unsigned auto_increment, name varchar(50), gender enum('m','f'), time datetime, joiningyea ...

Having Trouble Connecting to AWS RDS MySQL + PHP on Heroku

I've encountered an issue while moving my application to Heroku. I am facing difficulties accessing the database via PHP on Heroku, even though I can access the AWS database locally from my machine. When I deploy to Heroku, the connection fails. I ha ...

Execute an Asynchronous Operation in NgRx After Triggering an Action

Please note that this is a question seeking clarification Instructions Needed I am currently working on dispatching an action to NgRx in order to add a task to a list of tasks. Additionally, I need to perform a put request to an API to save the changes ma ...

What causes Enum[Enum.member] to be undefined in the TypeScript playground on codepen.io?

My intention was to test out some type settings on TypeScript playground at codepen.io, but I encountered an unexpected issue: enum Order { Asc = 'asc', Desc = 'desc' } console.log(Order[Order.Asc]); // undefined in codepen.io ...

Ways to display or conceal information depending on the dropdown choice

In my Angular project, I am dealing with a dropdown menu that is followed by some data displayed in a div element. component.html <select class="form-control" id="power" required> <option value="" disabled selected ...

Steps to filter types by a singular property assessment

export type HalfSpin = { halfspin: string } export type FullSpin = { fullspin: string } export type SpinType = | HalfSpin | FullSpin export function isHalfSpin(_: SpinType) ...

Issue: Unable to locate a differ that supports the object '[object Object]' of type 'object'. NgFor can only bind to Iterables like Arrays

I have successfully pulled data from the jsonplaceholder fake API and now I am attempting to bind it using Angular 2 {{}} syntax. However, I encountered an error that states: "Error: Cannot find a differ supporting object '[object Object]' of typ ...

TypeScript enables the use of optional arguments through method overloading

Within my class, I have defined a method like so: lock(key: string, opts: any, cb?: LMClientLockCallBack): void; When a user calls it with all arguments: lock('foo', null, (err,val) => { }); The typings are correct. However, if they skip ...