jmcdo29 / nest-commander

A module for using NestJS to build up CLI applications
https://nest-commander.jaymcdoniel.dev/
MIT License
437 stars 53 forks source link

Problem with resolving dependencies #1050

Closed pro100coder closed 1 year ago

pro100coder commented 1 year ago

Is there an existing issue for this?

Current behavior

I have two applications API and CLI with shared logic in library. When I add module to API app everything is working but when I add this module to CLI application(nestjs-commander) I catch the error

$ ts-node -r tsconfig-paths/register src/main.ts import
[Nest] 141  - 09/11/2023, 6:28:20 PM     LOG [NestFactory] Starting Nest application...
[Nest] 141  - 09/11/2023, 6:28:20 PM     LOG [InstanceLoader] CommandRootModule dependencies initialized +99ms
[Nest] 141  - 09/11/2023, 6:28:20 PM     LOG [InstanceLoader] AppModule dependencies initialized +0ms
[Nest] 141  - 09/11/2023, 6:28:20 PM     LOG [InstanceLoader] TypeOrmModule dependencies initialized +0ms
[Nest] 141  - 09/11/2023, 6:28:20 PM   ERROR [ExceptionHandler] Nest can't resolve dependencies of the ProductRepository (?). Please make sure that the argument DataSource at index [0] is available in the TypeOrmModule context.

Potential solutions:
- Is TypeOrmModule a valid NestJS module?
- If DataSource is a provider, is it part of the current TypeOrmModule?
- If DataSource is exported from a separate @Module, is that module imported within TypeOrmModule?
  @Module({
    imports: [ /* the Module containing DataSource */ ]
  })

Minimum reproduction code

app.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ImportModule } from '@cli/import/import.module';
import { TestCommand } from '@cli/test.command';
import { EventEmitterModule } from '@nestjs/event-emitter';
import { CqrsModule } from '@nestjs/cqrs';

@Module({
    imports: [
        CqrsModule,
        TypeOrmModule.forRoot({
            type: 'postgres',
            host: `${process.env.DATABASE_HOST}`,
            port: 5432,
            username: `${process.env.DATABASE_USERNAME}`,
            password: `${process.env.DATABASE_PASSWORD}`,
            database: `${process.env.DATABASE_NAME}`,
            entities: [__dirname + '/../../../app/src/**/*.entity.{js,ts}'],
            migrations: [__dirname + '/../migrations/*.{js,ts}'],
            // autoLoadEntities: true,
            synchronize: false,
        }),
        ImportModule,
        EventEmitterModule.forRoot(),
    ],
    providers: [],
})
export class AppModule {}

import.module.ts

import { Module } from '@nestjs/common';
import { ImportCommand } from '@cli/import/import.command';
import { AppProductModule } from '@app/product/infra/product.module';

@Module({
    imports: [AppProductModule],
    providers: [ImportCommand],
    exports: [],
})
export class ImportModule {} 

product.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Product } from '@app/product/domain/entity/product.entity';
import { ProductAggregates } from '@app/product/application/product.aggregates';

@Module({
    imports: [TypeOrmModule.forFeature([Product])],
    providers: [ProductAggregates],
    exports: [ProductAggregates],
})
export class AppProductModule {}

product.entity.ts

import { Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity('products')
export class Product implements EntityAttributesEntityInterface
{
    @PrimaryGeneratedColumn('uuid')
    uuid: string;
}

Expected behavior

Application works

Package

Package version

3.12.0

Node.js version

20

In which operating systems have you tested?

Other

image

jmcdo29 commented 1 year ago

Can you get this for me in a git repo, so I can see what's going on? From what I'm seeing here things should be okay, but there may be an environmental factor I'm not aware of like a monorepo setting.

jmcdo29 commented 1 year ago

Re-reading the error, it seems like the entities are not being found by the glob you're using. Double check that path and possibly try using the autoLoadEntities option

pro100coder commented 1 year ago

Entities are defined normally as I am using migration generation and if there was a problem I would have seen it. I also tried to connect another module from the common library, in it I get an error related to CommandBus from the CQRS package, although all connections and configs are identical to those in the API project

jmcdo29 commented 1 year ago

Then can you please provide a minimum reproduction repository?

pro100coder commented 1 year ago

Yes, please https://github.com/pro100coder/nest-commander-issue1050

For running, you can use this instruction

cd app
yarn install
cd ../cli
yarn install
yarn command:dev import
jmcdo29 commented 1 year ago

More than likely, the error comes from having two installs of @nestjs/typeorm (and other nest packages). They need to be co-installed in the same location, no symlinks, no duplicates, and it should all just work in that case

pro100coder commented 1 year ago

Hmm, this problem is only in the CLI app, and if I remove the Typeorm package from the app directory, I catch an error

return new TSError(diagnosticText, diagnosticCodes, diagnostics);
           ^
TSError: ⨯ Unable to compile TypeScript:
../app/src/product/infra/product.module.ts:2:31 - error TS2307: Cannot find module '@nestjs/typeorm' or its corresponding type declarations.

2 import { TypeOrmModule } from '@nestjs/typeorm';
jmcdo29 commented 1 year ago

The problem is that this is a monorepo with two node_modules that both point to @nestjs/typeorm and likely other nest packages. If you have a monorepo, you have to take a single version package approach by having a coming node_modules, because of how JS Realms and the instanceof check works