Why Nest.js throw a error when run main.js? - nestjs

I am using Nest.js to develop a web backend.
When I use npm run build, the cmd shows success.
But when I use node dist/main.js, the cmd shows error. But I'm sure this file exist and in develop mode (npm run start), everything's ok.
This is github address.
https://github.com/Eve-1995/Oreo/tree/master/oreo-back-end
What should I do next?

entities: [__dirname + '/../**/**/!(*.d).entity.{ts,js}'], is doing the trick for me both in production and dev envs.

I think the reason is in TypeOrm config.
#Module({
imports: [
AuthModule,
ClassificationModule,
ArticleModule,
UserModule,
CommentModule,
FragmentModule,
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
// logging: ["query"],
port: 3306,
username: 'root',
password: '123456',
database: 'myblog',
entities: ['src/**/**.entity{.ts,.js}'], // <-- replace it to 'dist/**/**.entity.js' in prod mode or use relative path
synchronize: true,
}),
],
})
export class AppModule { }

You probably just need to add this in your tsconfig.json:
"paths": {
"src/*": ["./src/*"]
}
TS can now correctly transform the src/ alias import when building the project.

Related

NestJs: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string

i have a problem with connecting to database in nest.js with typeorm and postgres.
I created a .env file in the root project directory with the following content
POSTGRES_HOST=127.0.0.1
POSTGRES_PORT=5432
POSTGRES_USER=postgres
POSTGRES_PASSWORD=password
POSTGRES_DATABASE=db-name
In the app.module.ts I writed the code below:
import { Module } from '#nestjs/common';
import { ConfigModule } from '#nestjs/config';
import { TypeOrmModule } from '#nestjs/typeorm';
import { FeedModule } from './feed/feed.module';
#Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
TypeOrmModule.forRoot({
type: 'postgres',
host: process.env.POSTGRES_HOST,
port: parseInt(<string>process.env.POSTGRES_PORT),
username: process.env.POSTGRES_USER,
password: process.env.POSTGRES_PASSWORD,
database: process.env.POSTGRES_DATABASE,
autoLoadEntities: true,
synchronize: true,
}),
FeedModule,
],
})
export class AppModule {}
But when im running the app by npm start it throws this error: new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string')
What am I missing or doing wrong?
In NestJs you should use ConfigService to get environment variables inside your typeorm module, read the docs for more information.
You can use it like that:
import { ConfigModule, ConfigService } from '#nestjs/config';
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
#Module({
imports: [
ConfigModule.forRoot(
envFilePath: `.${process.env.NODE_ENV}.env`
),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
injects: [ConfigService],
useFactory: (configService: ConfigService) => ({
type: 'postgres',
host: configService.get("POSTGRES_HOST"),
port: configService.get("POSTGRES_PORT"),
username: configService.get("POSTGRES_USER"),
password: configService.get("POSTGRES_PASSWORD"),
database: configService.get("POSTGRES_DB"),
entities: [],
synchronize: true,
}),
}),
],
controllers: [],
providers: [],
})
export class AppModule {}
As explained in the docs, you can define a factory function where you inject the config-service allowing you to resolve the corresponding values:
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
type: 'postgres',
host: configService.get('POSTGRES_HOST'),
port: +configService.get<number>('POSTGRES_PORT'),
username: configService.get('POSTGRES_USER'),
password: configService.get('POSTGRES_PASSWORD'),
database: configService.get('POSTGRES_DATABASE'),
synchronize: true,
autoLoadEntities: true,
}),
inject: [ConfigService],
});
I was able to fix the problem by using the config module.
Just do npm i #nestjs/config. Then in the imports array just above the TypeOrmModule put ConfigModule.forRoot({ isGlobal: true }),. This allows your module to get the environment variables from the .env file
I got this error because I put the .env file inside the src by mistake. If you put it outside of the src it will fix it
I was facing the same issue and it was weird because I modified several times that configuration just to check if "something new happens" but have no success.
Long story short, I deleted the "dist" folder of the project and build the app again (npm run build) and it worked! It appeared that I had a "bad build" running over and over again so this workaround kind of "refreshed" the build and let things running well again.
Hope this help!

TypeOrm migration - Error: Cannot find module

I'm trying npm run typeorm migration:run in my project and it is showing the error below.
Error during migration run:
Error: Cannot find module 'src/permission/permission.entity'
ormconfig.js
module.exports = {
type: 'mysql',
host: 'localhost',
port: 33066,
username: 'root',
password: '123456',
database: 'admin',
synchronize: false,
entities: ['./src/**/*.entity.ts'],
migrations: ['./src/migrations/*.ts'],
cli: {
entitiesDir: './ts/',
migrationsDir: './src/migrations',
},
};
What am I doing wrong?
This is my git repo: https://github.com/wesoz/udemy-nest-admin/tree/td/seed
You need to use a relative import path.
import { Permission } from '../permission/permission.entity';
You must add decorator #entity()
to entity class

Reading .env for nestjs app with typeorm having custom provider

I am new to nestJS and I want to setup .env for existing application & facing issue.
I have custom provider for appModule as below,
#Module({
providers: [
AbcService,
XyzService,
],
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'xxxxxxxx',
port: 3230,
username: 'xyz',
password: 'password',
database: 'xyz-db',
entities: [__dirname + '/entities/**/*.entity{.ts,.js}'],
synchronize: true,
migrationsRun: true,
logging: true,
}),
TypeOrmModule.forFeature([
Transaction,
Payment,
]),
KafkaModule.forRoot(serviceConfig),
],
exports: [],
controllers: [ServiceSubscriptionController],
})
export class TopicModule { }
I have imported it inside AppModule as below,
#Module({
imports: [TopicModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
I want to keep these stuff inside .env and I tried it as per documentation as below,
TypeOrmModule.forRootAsync({
imports: [ConfigModule.forRoot({
envFilePath: '.env',
})],
useFactory: async (configService: ConfigService) => {
return {
host: configService.get('HOST'),
type: 'mysql',
port: 3230,
username: 'xyz',
password: 'password',
database: 'xyz-db',
entities: [__dirname + '/entities/**/*.entity{.ts,.js}'],
synchronize: true,
migrationsRun: true,
logging: true,
}
},
inject: [ConfigService]
}),
I have .env at root path with HOST key-value pair as below but it read undefined from it.
In package.json,
"start": "nest start",
"start:dev": "nest start --watch",
It seems that Nest's ConfigModule will run fs.readFileSync(envFilePath) if you pass a file path to the forRoot() method. If you want it to read from the root directory, either remove the envFilePath option, or set the full file path, from your user's home directory.
I have loaded config in main.ts manually as below.
import { config } from 'dotenv';
async function bootstrap() {
//factory method for normal TS app
await config();
const app = await NestFactory.create(AppModule);
Now I can access it as,
configService.get('HOST') // as provided in question
or as process.env.HOST
Note: I have to use forRootAsync instead of forRoot to access process.env

NestJS - [TypeOrmModule] Unable to connect to the database. Retrying ER_PARSE_ERROR

Cannot able to connect database with correct connection info, followed documentation to connect database from https://docs.nestjs.com/techniques/database
Database connected on SQLYog
Following same database information in app.module.ts
#Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: null,
database: 'the_local_db',
entities: [
Table_one,
],
// entities: ['../typeorm/entities/*.ts'],
synchronize: true,
}),
StaffModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Error Details
`[Nest] 5528 - 06/30/2020, 1:39:51 AM [ExceptionHandler] ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''"'' at line 1 +18m
QueryFailedError: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''"'' at line 1
at new QueryFailedError (C:\Users\UserName\ProjectName\nrwl\src\error\QueryFailedError.ts:9:9)
at Query. (C:\Users\UserName\ProjectName\nrwl\src\driver\mysql\MysqlQueryRunner.ts:167:37)
at Query. (C:\Users\UserName\ProjectName\nrwl\node_modules\mysql\lib\Connection.js:526:10)
at Query._callback (C:\Users\UserName\ProjectName\nrwl\node_modules\mysql\lib\Connection.js:488:16)
at Query.Sequence.end (C:\Users\UserName\ProjectName\nrwl\node_modules\mysql\lib\protocol\sequences\Sequence.js:83:24)
at Query.ErrorPacket (C:\Users\UserName\ProjectName\nrwl\node_modules\mysql\lib\protocol\sequences\Query.js:92:8)
at Protocol._parsePacket (C:\Users\UserName\ProjectName\nrwl\node_modules\mysql\lib\protocol\Protocol.js:291:23)
at Parser._parsePacket (C:\Users\UserName\ProjectName\nrwl\node_modules\mysql\lib\protocol\Parser.js:433:10)
at Parser.write (C:\Users\UserName\ProjectName\nrwl\node_modules\mysql\lib\protocol\Parser.js:43:10)
at Protocol.write (C:\Users\UserName\ProjectName\nrwl\node_modules\mysql\lib\protocol\Protocol.js:38:16)`
Check if you have synchronize connection option set to true in database configuration. Make it to false.
It worked for me.
I was faced with a similar issue and the verified response did not help me. I was able to solve my issue using the mysql2 module instead of mysql.
$ npm install mysql2 --save
I also had to uninstall mysql module to connect to my database
$ npm uninstall mysql --save
Hope this response helped others with stuck in the same issue.
I have just removed the port:3306, now it's working.
#Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
username: 'root',
password: null,
database: 'the_local_db',
entities: [
Table_one,
],
// entities: ['../typeorm/entities/*.ts'],
synchronize: true,
}),
StaffModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
In my case the solution was some different because my localhost had a different name,it happened in OSX sometimes,so I changed the "localhost" by the ip adress 127.0.0.1
TypeOrmModule.forRoot({
type: 'mysql',
host: '127.0.0.1',
port: 3306,
username: 'test',
password: '123456',
database: 'nest',
entities: ["dist/**/*.entity{.ts,.js}"],
synchronize: true,
dropSchema:true })
First, i solved my problem by using as following:
1/ synchronize :false in the app.module
2/nmp uninstall mysql
3/npm install mysql2
--> when i run >>npm run start:dev everything is ok
I solved this issue by using a connection URL instead of splitting the MongoDB URI.
dbConfig: {
type: 'mongodb',
url: process.env.MONGO_CONNECTION_STRING,
ssl: true,
useUnifiedTopology: true,
autoLoadEntities: true,
synchronize: false,
logging: true,
}
Where MONGO_CONNECTION_STRING: mongodb://ussername:password#host_name:port/?authSource=admin
. This way one can avoid getting this error in TypeORM. Also, there is a flag useNewUrlParser: true which could be used to configure DB in a way using the host username and password separately.
did you start your XAMP mysql server on locally? because i was not (:
just reminder

How use external entities in nestjs project with typeorm?

I'm trying to use type orm entities defined outside of the project. That is, I have two projects: models and core-api. Models is an npm package that exports the entities definition. So, from core-api(nestjs project) i'm trying to define the connection using those entities. Something like this:
#Module({
imports: [ TypeOrmModule.forRoot({
type: 'postgres',
host: 'postgres',
port: 5432,
username: 'myuser',
password: 'mypass',
database: 'mydb',
entities: [
__dirname + '../node_modules/something/models/src/*.entity.ts'
],
synchronize: true,
}), AModule ],
controllers: [],
providers: [],
})
export class AppModule {}
Then, in A module, I'm importing the A entity from the npm package:
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
import { AsController } from './As.controller';
import { AsService } from './As.service';
import { A } from 'something/models';
#Module({
imports: [TypeOrmModule.forFeature([ A ])],
controllers: [AController],
providers: [AService],
})
export class AModule {}
This ends up with the next error:
RepositoryNotFoundError: No repository for "A" was found. Looks like this entity is not registered in current "https://stackoverflow.com/a/54191513/3943197https://stackoverflow.com/a/54191513/3943197default" connection?
I'm quite lost in how to follow since i don't understand how it works under the hood. I saw the code of typeorm and #nestjs/typeorm but I couldn't figure out how to solve it.
Thanks!
UPDATE:
I could make it work adding the entity class instead of a path like #serianox said. Also, the something/models npm package exports a standalone nest module. This module import/export the entities defined on the package. Thus, I could inject the entities on the main application.
You can pass the references to the classes to "entities" instead of the path,
for example:
import {Entity1, Entity2} from '#models'
#Module({
imports: [ TypeOrmModule.forRoot({
type: 'postgres',
host: 'postgres',
port: 5432,
username: 'myuser',
password: 'mypass',
database: 'mydb',
entities: [
Entity1, Entity2
],
synchronize: true,
}), AModule ],
controllers: [],
providers: [],
})
export class AppModule {}
I think found a workaround for this problem;
we can import modules from npm module like this
import * as Models from "your-models-package";
then iterate them and store in an array
const models = [];
for (const key in Models) {
if (Models.hasOwnProperty(key)) {
const model = Models[key];
models.push(model);
}
}
finaly use in module definition
const dbConfig = TypeOrmModule.forRoot({
type: "postgres",
database: config.postgres.db,
host: config.postgres.host,
port: Number(config.postgres.port),
username: config.postgres.user,
password: config.postgres.pass,
entities: models,
synchronize: true,
});
I hope it helps
cheers
It seems you are importing .ts files from node_modules. I believe once you have built your npm package that these entities are now .js files. You should try modifying your expression so it can parse .js files.
Personally I never use ts-node as it brings this kind of troubles and debugging is not really available with it. I feel you should always use the node runtime and parsing only .js files (also, it is closer to production runtime).

Resources