typeORM No changes in database schema were found - cannot generate a migration. To create a new empty migration use "typeorm migration:create" command - node.js

I'm doing a course where we are using express-node postgres and react (with typescript) and typeORM. Everything has worked well so far, but I'm facing an issue with typeORM and I don't know what is going and why is this error happening
The Big Problem : So, the problem is that, I was doing the auth, and at some point we changed users schema in the DB so we had to make a migration, but, before migration, we did npm run typeorm schema:drop ,but when I tried, this happened with migration
This is the first command I used
npm run typeorm migration:generate -- --n create-users-table
This was the error
> new-typeorm-project#0.0.1 typeorm C:\Users\diego cifuentes\Desktop\Studying Backend\redit> ts-node ./node_modules/typeorm/cli.js "migration:generate" "create-users-table"
bin.js migration:generate
Generates a new migration file with sql needs to be executed to update
schema.
Opciones:
-h, --help Muestra ayuda [booleano] -c, --connection Name of the connection on which run a query.
[defecto: "default"] -n, --name Name of the migration class.
[cadena de caracteres] [requerido] -d, --dir Directory where migration should be created.
-p, --pretty Pretty-print generated SQL
[booleano] [defecto: false] -f, --config Name of the file with connection configuration.
[defecto: "ormconfig"] -o, --outputJs Generate a migration file on Javascript instead of
Typescript [booleano] [defecto: false] --dr, --dryrun Prints out the contents of the migration instead of
writing it to a file [booleano] [defecto: false] --ch, --check Verifies that the current database is up to date and that no migrations are needed. Otherwise exits with
code 1. [booleano] [defecto: false] -v, --version Muestra número de versión [booleano]
Falta argumento requerido: n
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! new-typeorm-project#0.0.1 typeorm: `ts-node ./node_modules/typeorm/cli.js "migration:generate" "create-users-table"`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the new-typeorm-project#0.0.1 typeorm script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\diego cifuentes\AppData\Roaming\npm-cache\_logs\2021-05-11T15_29_02_081Z-debug.log
After hours trying to search for solution everywhere, I change the last command to this one
npx typeorm migration:generate -- --n create-users-table
And the error was different this time, looks like this
No changes in database schema were found - cannot generate a migration. To create a new empty migration use "typeorm migration:create" command
So, I said, ok, I'm getting closer to fixing this, but... After hours ( again ) looking for a new answer, I couldn't find anything, so, I'm getting to a point where I need to write this post in order to fix my problem. So now, let me show you my ormconfig, my package.json and the entity I want to migrate in my postgres DB.
package.json (the script typeorm is at the end)
{
"name": "new-typeorm-project",
"version": "0.0.1",
"description": "Awesome project developed with TypeORM.",
"devDependencies": {
"#types/bcrypt": "^5.0.0",
"#types/cookie": "^0.4.0",
"#types/cookie-parser": "^1.4.2",
"#types/express": "^4.17.11",
"#types/jsonwebtoken": "^8.5.1",
"#types/morgan": "^1.9.2",
"#types/node": "^15.0.2",
"morgan": "^1.10.0",
"nodemon": "^2.0.7",
"ts-node": "^9.1.1",
"typescript": "^4.2.4"
},
"dependencies": {
"bcrypt": "^5.0.1",
"class-transformer": "^0.4.0",
"class-validator": "^0.13.1",
"cookie": "^0.4.1",
"cookie-parser": "^1.4.5",
"dotenv": "^9.0.1",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"pg": "^8.4.0",
"reflect-metadata": "^0.1.10",
"typeorm": "0.2.32"
},
"scripts": {
"start": "ts-node src/server.ts",
"dev": "nodemon --exec ts-node src/server.ts",
"typeorm": "ts-node ./node_modules/typeorm/cli.js"
}
}
ormconfing.json Quick note : I changed entities, migrations and subscribers to .js, because with .ts was always giving me error.
{
"type": "postgres",
"host": "localhost",
"port": 5432,
"username": "**",
"password": "**",
"database": "**",
"synchronize": true,
"logging": true,
"entities": ["src/entities/**/*.js"],
"migrations": ["src/migrations/**/*.js"],
"subscribers": ["src/subscribers/**/*.js"],
"cli": {
"entitiesDir": "src/entities",
"migrationsDir": "src/migrations",
"subscribersDir": "src/subscribers"
}
}
And last thing I want to show you, even though it might not be that important, this is the users schema
import {
Entity as TOEntity,
Column,
Index,
BeforeInsert,
OneToMany
} from "typeorm";
import bcrypt from "bcrypt";
import { IsEmail, Length } from "class-validator";
import { Exclude } from "class-transformer";
import Entity from "./Entity";
// import Post from "./Post";
#TOEntity("users")
export default class User extends Entity {
constructor(user: Partial<User>) {
super();
Object.assign(this, user);
}
#Index()
#IsEmail()
#Column({ unique: true })
email: string;
#Index()
#Length(3, 200)
#Column({ unique: true })
username: string;
#Exclude()
#Length(6, 200)
#Column()
password: string;
// #OneToMany(() => Post, post => post.user)
// posts: Post[];
#BeforeInsert()
async hashedPassword() {
this.password = await bcrypt.hash(this.password, 6);
}
}
End Goal: So, if you can help me with this, you will save my life. One last thing is that I tried to post my problems first in the Spanish website of stack overflow, but nobody could help me, so maybe here someone will, thanks for your time and take care!

Change your entities, migrations and subscribers into your dist directory.
e.g.:
entities: ["dist/entities/**/*{.js,.ts}"],
migrations: ["dist/migrations/**/*{.js,.ts}"],
subscribers: ["dist/subscribers/**/*{.js,.ts}"],
dist directory is the directory which gets created when you build the app. You can find your dist directory using tsconfig.json -> compilerOptions -> outDir.
Then build your app again using npm run build and try to generate the migrations.

For me the ormconfig.json's was like this,
"entities": [
"dist/entity/**/*.ts"
],
"migrations": [
"src/migration/**/*.ts"
],
"subscribers": [
"src/subscriber/**/*.ts"
],
Changing it to
"entities": [
"src/entity/**/*{.js,.ts}"
],
"migrations": [
"src/migration/**/*{.js,.ts}"
],
"subscribers": [
"src/subscriber/**/*{.js,.ts}"
],
generated the migration correctly.
And the package.json script is like this
"typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js"
And the command used is
npm run typeorm migration:generate -- -n FileAddTemporaryDeletedFields -p --dr --ch

I've seen this error, and if I'm not mistaken it's because I was trying to create a bank that had already been created.
This command below deletes all tables:
yarn typeorm query "DROP SCHEMA public CASCADE; CREATE SCHEMA public; GRANT USAGE ON SCHEMA public to PUBLIC; GRANT CREATE ON SCHEMA public to PUBLIC; COMMENT ON SCHEMA public IS 'standard public schema';"
then:
yarn typeorm --migration:generate -n migration_name -d path/to/your/migrations/

ormconfig.json is deprecated in latest version as i know.
but anyway I'm gonna share my solution when i used old version.
when generate, typeorm first reads ormconfig.json and login into rdbms.
and compares between 'the actual schema of db' and
'schema file as ormconfig.json[entities]'
so, if the file (writen at 'entities' in ormconfig.json) is in dist folder.
you have to edit that .js file.(not .ts file in src folder)
but, if the 'entities' file is in src folder as ormconfig.json,
check if 'autosave' feature of vscode is on.
if you 'npm run start:dev'
It could be the case that the actual schema of db has been already modified
before you edit entities file.

Related

TypeError: trying to use aws-elasticsearch-connector

I'm attempting to update a legacy elastic-search node app, using the the package aws-elasticsearch-connector
and for some reason I'm unable to get it to work at all, even the simplest provided example...
I installed the packages, exactly as shown...
> npm install --save aws-elasticsearch-connector #elastic/elasticsearch aws-sdk
This is the sample code...
const { Client } = require('#elastic/elasticsearch')
const AWS = require('aws-sdk')
const createAwsElasticsearchConnector = require('aws-elasticsearch-connector')
// (Optional) load profile credentials from file
AWS.config.update({
profile: 'myawsprofile'
})
const client = new Client({
...createAwsElasticsearchConnector(AWS.config),
node: 'https://my-elasticsearch-cluster.us-east-1.es.amazonaws.com'
})
When I attempt to run it with this...
> node .\index.js
I get this error...
class AmazonConnection extends Connection {
TypeError: Class extends value undefined is not a constructor or null
I have no idea how I'm supposed to fix this, since the error seems to be in the module itself, not my sample code.
Most of the examples of this error that I've seen, suggest that it's related to circular references, but that doesn't seem to be of any help to me.
I'm using node v16.14.0
This is my package.json...
{
"name": "test_es",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"#elastic/elasticsearch": "^8.0.0",
"aws-elasticsearch-connector": "^9.0.3",
"aws-sdk": "^2.1087.0"
}
}
I'm probably doing something wrong, or the package author may be assuming some additional knowledge that I just don't have.
Any suggestions would be greatly appreciated.
It seems version 8 of #elastic/elasticsearch is not compatible with aws-elasticsearch-connector.
Changing to version 7.17.0 seems to resolve this particular error.

Babel and Node - No stack trace on syntax errors

I am converting a project over from using gulp to using nodemon so that I can use ES6 with babel. I'm following a pretty simple procedure to do so, which is well described here. A quick look at my package.json:
{
"main": "index.js",
"scripts": {
"start": "FORCE_COLOR=3 nodemon --exec babel-node index.js"
},
"dependencies": {
"deps": "1.1.1"
},
"devDependencies": {
"#babel/cli": "^7.16.0",
"#babel/core": "^7.16.5",
"#babel/node": "^7.16.5",
"#babel/polyfill": "^7.12.1",
"#babel/preset-env": "^7.16.5",
"nodemon": "^2.0.15"
},
"babel": {
"presets": [
[
"#babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
]
}
}
When I run npm start, nodemon runs the app, and reruns on save, but it crashes with a syntax error:
[nodemon] starting `babel-node index.js`
[HPM] Proxy created: /auth -> http://localhost:8081/
/myproject/node_modules/#babel/core/lib/parser/index.js:93
throw err;
^
SyntaxError: Legacy octal literals are not allowed in strict mode. (38:46)
at Parser._raise (/myproject/node_modules/#babel/parser/src/parser/error.js:147:45)
at Parser.raiseWithData (/myproject/node_modules/#babel/parser/src/parser/error.js:142:17)
at Parser.raise (/myproject/node_modules/#babel/parser/src/parser/error.js:91:17)
at Parser.recordStrictModeErrors (/myproject/node_modules/#babel/parser/src/tokenizer/index.js:1444:12)
at Parser.readNumber (/myproject/node_modules/#babel/parser/src/tokenizer/index.js:1239:12)
at Parser.getTokenFromCode (/myproject/node_modules/#babel/parser/src/tokenizer/index.js:951:14)
at Parser.nextToken (/myproject/node_modules/#babel/parser/src/tokenizer/index.js:307:10)
at Parser.next (/myproject/node_modules/#babel/parser/src/tokenizer/index.js:169:10) {
loc: Position { line: 38, column: 46 },
pos: 933,
code: 'BABEL_PARSE_ERROR',
reasonCode: 'StrictOctalLiteral'
}
[nodemon] app crashed - waiting for file changes before starting...
There doesn't seem to be a stack trace to the place in my code where this error is happening. I managed to track it down with some careful understanding of the no octal error, but other errors that come up look very similar, with no stack trace to the place in my own code where the error occurs. How can I debug like that? Is there a way to configure babel to include the origin of the error from my code?
Running babel-node with Node 16.9 seems to fix this.
With Node 12 to 16.8:
SyntaxError: Legacy octal literals are not allowed in strict mode. (1:4)
at Parser._raise (/tmp/babel-test-3/node_modules/#babel/parser/lib/index.js:569:17)
With Node 16.9+:
SyntaxError: /tmp/babel-test-3/index2.js: Legacy octal literals are not allowed in strict mode. (1:4)
> 1 | a = 01;
| ^
2 |
at Parser._raise (/tmp/babel-test-3/node_modules/#babel/parser/lib/index.js:569:17)
No other changes were required.
A bug report has been filed.
It could potentially be that there is something wrong with the package itself. But babel is a properly and well maintained project so it could be something on your end
The error here is that leading zeros aren't allowed. Try and remove any instance of hard-coded leading zeros and then use +number or parseInt on any numbers which the values you won't know, such as from an API, reading from a database, or receiving user input.

TypeORM Entity in NESTJS - Cannot use import statement outside a module

Started new project with 'nest new' command. Works fine until I add entity file to it.
Got following error:
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
^^^^^^
SyntaxError: Cannot use import statement outside a module
What do I miss?
Adding Entity to Module:
import { Module } from '#nestjs/common';
import { BooksController } from './books.controller';
import { BooksService } from './books.service';
import { BookEntity } from './book.entity';
import { TypeOrmModule } from '#nestjs/typeorm';
#Module({
imports: [TypeOrmModule.forFeature([BookEntity])],
controllers: [BooksController],
providers: [BooksService],
})
export class BooksModule {}
app.module.ts:
import { Module } from '#nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '#nestjs/typeorm';
import { Connection } from 'typeorm';
import { BooksModule } from './books/books.module';
#Module({
imports: [TypeOrmModule.forRoot()],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
My assumption is that you have a TypeormModule configuration with an entities property that looks like this:
entities: ['src/**/*.entity.{ts,js}']
or like
entities: ['../**/*.entity.{ts,js}']
The error you are getting is because you are attempting to import a ts file in a js context. So long as you aren't using webpack you can use this instead so that you get the correct files
entities: [join(__dirname, '**', '*.entity.{ts,js}')]
where join is imported from the path module. Now __dirname will resolve to src or dist and then find the expected ts or js file respectively. let me know if there is still an issue going on.
EDIT 1/10/2020
The above assumes the configuration is done is a javascript compatible file (.js or in the TypeormModule.forRoot() passed parameters). If you are using an ormconfig.json instead, you should use
entities: ["dist/**/*.entity.js"]
so that you are using the compiled js files and have no chance to use the ts files in your code.
In the TypeORM documentation, i found a specific section for Typescript.
This section says:
Install ts-node globally:
npm install -g ts-node
Add typeorm command under scripts section in package.json
"scripts" {
...
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js"
}
Then you may run the command like this:
npm run typeorm migration:run
If you need to pass parameter with dash to npm script, you will need
to add them after --. For example, if you need to generate, the
command is like this:
npm run typeorm migration:generate -- -n migrationNameHere
This works with my file config:
{
"type": "postgres",
"host": "yourhost",
"port": 5423,
"username": "username",
"password": "password",
"database": "your_db",
"synchronize": true,
"entities": [
"src/modules/**/*.entity.{ts,js}"
],
"migrations": [
"src/migrations/**/*.{ts,js}"
],
"cli": {
"entitiesDir": "src/modules",
"migrationsDir": "src/migrations"
}
}
Then you can run the generate command.
As Jay McDoniel explained in his answer, the problem seems to be the pattern matching of entity files in ormconfig.json file: Probably a typescript file (module) is imported from a javascript file (presumably a previously transpiled typescript file).
It should be sufficient to remove an existing ts glob pattern in the ormconfig.json, so that TypeORM will only load javascript files. The path to the entity files should be relative to the working directory where node is executed.
"entities" : [
"dist/entity/**/*.js"
],
"migrations" : [
"dist/migration/**/*.js"
],
"subscribers": [
"dist/subscriber/**/*.js"
],
I changed in tsconfig.json file next:
"module": "es6"
To:
"module": "commonjs",
It helps me
Defining the entities property in ormconfig.json as mentioned in the official documentation resolved this issue for me.
// This is your ormconfig.json file
...
"entities": ["dist/**/*.entity{.ts,.js}"]
...
This is how I've manage to fix it. With a single configuration file I can run the migrations on application boostrap or using TypeOrm's CLI.
src/config/ormconfig.ts
import parseBoolean from '#eturino/ts-parse-boolean';
import { TypeOrmModuleOptions } from '#nestjs/typeorm';
import * as dotenv from 'dotenv';
import { join } from 'path';
dotenv.config();
export = [
{
//name: 'default',
type: 'mssql',
host: process.env.DEFAULT_DB_HOST,
username: process.env.DEFAULT_DB_USERNAME,
password: process.env.DEFAULT_DB_PASSWORD,
database: process.env.DEFAULT_DB_NAME,
options: {
instanceName: process.env.DEFAULT_DB_INSTANCE,
enableArithAbort: false,
},
logging: parseBoolean(process.env.DEFAULT_DB_LOGGING),
dropSchema: false,
synchronize: false,
migrationsRun: parseBoolean(process.env.DEFAULT_DB_RUN_MIGRATIONS),
migrations: [join(__dirname, '..', 'model/migration/*.{ts,js}')],
cli: {
migrationsDir: 'src/model/migration',
},
entities: [
join(__dirname, '..', 'model/entity/default/**/*.entity.{ts,js}'),
],
} as TypeOrmModuleOptions,
{
name: 'other',
type: 'mssql',
host: process.env.OTHER_DB_HOST,
username: process.env.OTHER_DB_USERNAME,
password: process.env.OTHER_DB_PASSWORD,
database: process.env.OTHER_DB_NAME,
options: {
instanceName: process.env.OTHER_DB_INSTANCE,
enableArithAbort: false,
},
logging: parseBoolean(process.env.OTHER_DB_LOGGING),
dropSchema: false,
synchronize: false,
migrationsRun: false,
entities: [],
} as TypeOrmModuleOptions,
];
src/app.module.ts
import configuration from '#config/configuration';
import validationSchema from '#config/validation';
import { Module } from '#nestjs/common';
import { ConfigModule } from '#nestjs/config';
import { TypeOrmModule } from '#nestjs/typeorm';
import { LoggerService } from '#shared/logger/logger.service';
import { UsersModule } from '#user/user.module';
import { AppController } from './app.controller';
import ormconfig = require('./config/ormconfig'); //path mapping doesn't work here
#Module({
imports: [
ConfigModule.forRoot({
cache: true,
isGlobal: true,
validationSchema: validationSchema,
load: [configuration],
}),
TypeOrmModule.forRoot(ormconfig[0]), //default
TypeOrmModule.forRoot(ormconfig[1]), //other db
LoggerService,
UsersModule,
],
controllers: [AppController],
})
export class AppModule {}
package.json
"scripts": {
...
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js --config ./src/config/ormconfig.ts",
"typeorm:migration:generate": "npm run typeorm -- migration:generate -n",
"typeorm:migration:run": "npm run typeorm -- migration:run"
},
Project structure
src/
├── app.controller.ts
├── app.module.ts
├── config
│ ├── configuration.ts
│ ├── ormconfig.ts
│ └── validation.ts
├── main.ts
├── model
│ ├── entity
│ ├── migration
│ └── repository
├── route
│ └── user
└── shared
└── logger
I was using Node.js with Typescript and TypeORM when I faced this issue. Configuring in ormconfig.json file worked for me.
entities: ['dist/**/*.entity.js']
My full code of ormconfig.json file:
{
"type": "mysql",
"host": "localhost",
"port": 3306,
"username": "xxxxxxxx",
"password": "xxxxxxxx",
"database": "typescript_orm",
"synchronize": true,
"logging": false,
"migrationTableName": "migrations",
"entities": [
"dist/**/*.entity.js"
],
"migrations": [
"src/migration/**/*.{ts, js}"
],
"suscribers": [
"src/suscriber/**/*.{ts, js}"
],
"cli": {
"entitiesDir": "src/model",
"migrationDir": "src/migration",
"suscribersDir": "src/suscriber"
}
}
Also check out your imports in the entities. Don't import { SomeClassFromTypeorm } from 'typeorm/browser'; since this can lead to the same error.
It happened to me after my IDE automatically imported the wrong package. Delete '/browser' from the import.
In line with other people's comments - it does in fact seem silly to have to depend on generated code for this to work. I do not take credit for this solution as it's someone else's repository, but it does in fact allow full Typescript only migrations. It relies on the .env file Typeorm values instead of ormconfig.json although I'm sure it could be translated. I found it instrumental in helping me remove the dependency on .js files.
Here is the repo:
https://github.com/mthomps4/next-now-test/tree/next-typeorm-example
Explanation as to how it's working:
Aside from your usual .env or ormconfig.json file with the proper localhost db connection in it, you also need to specify the following properly in ormconfig.json or .env file
TYPEORM_ENTITIES="entities/*.ts"
TYPEORM_MIGRATIONS="migrations/*.ts"
TYPEORM_ENTITIES_DIR="entities"
TYPEORM_MIGRATIONS_DIR="migrations"
Notice the entities and migrations globs only have *.ts. The other very important piece is how your npm scripts are setup to run with ts-node.
You need an extended tsconfig that has the following in it somewhere:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs"
}
}
This is what allows ts-node to "pick up" the .ts files properly while generating a migration.
This npm script (the DOTENV part is only if using .env files instead of ormconfig.json) specifies to use that tsconfig.json
"local": "DOTENV_CONFIG_PATH=./.env ts-node -P ./tsconfig.yarn.json -r dotenv/config"
Which is leveraged as a "pre-cursor" script to this:
"typeorm:local": "yarn local ./node_modules/typeorm/cli.js"
I'm not 100% sure all of that is necessary (you may could do it all inline) but it works for me. Basically this says "invoke the typrorm cli in the context of ts-node with a specific .env file and a specific tsconfig." You may be able to skip those configurations in some cases.
Lastly, this script now works:
"g:migration": "yarn typeorm:local migration:generate -n"
So by running:
npm run g:migration -- User
You will get your automatically generated migration file based on your current changed entities!
So 3 nested npm scripts later, we have a very specific way to run the "generate" migration conmmand with all the proper configuration to use only TS files. Yay - no wonder some people still rail against typescript but thankfully this does work and the example repo above has it all preconfigured if you want to try it out to see how it "just works".
Actually, typeorm was designed to work with javascript by default.
To run the migrations with typescript, you must tell typeorm to do it.
Just put in your package.json, in the scripts part this line below:
"typeorm": "ts-node-dev ./node_modules/typeorm/cli.js"
and then, try to migrate again:
yarn typeorm migration:run
I ran into this error trying to run typeorm migration:generate from a project created with the TypeORM starter kit (npx typeorm init). The issue came down to this bit that it inserted into package.json:
"scripts": {
"typeorm": "typeorm-ts-node-commonjs"
}
Change that to:
"scripts": {
"typeorm": "typeorm-ts-node-esm"
}
And you should be good to go:
npm run -- typeorm migration:generate --dataSource path/to/data-source.ts NameOfMigration
Surprised about these almost kinda hacky solutions, particularely at the accepted one...
You should never import anything from a dist folder inside your ts source code!
If the answered assumption is true, and you do this:
entities: ['src/**/*.entity.{ts,js}']
then, why don't you rather DO THIS:
import { Answer } from './entities/answer/answer.entity';
entities: [Answer]
This way you would you use your ts code (correctly) and the builded js code would get provided to the TypeOrmModule in runtime.
check your TypeOrmModule's entities
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: '#GoHomeGota',
database: 'quiz',
**entities: ["dist/**/*.entity{.ts,.js}"],**
synchronize: true,
}),
The alternative I found for this is having two orm config files
namely orm-config.ts and cli-orm-config.ts (You can name them whatever)
//content of cli-orm-config.ts
import { DataSource, DataSourceOptions } from "typeorm"
import 'dotenv/config'
export const cliOrmConfig: DataSourceOptions = {
type: 'postgres',
host: process.env.DATABASE_HOST,
port: (process.env.PG_DATABASE_PORT as any) as number,
username: process.env.PG_DATABASE_USER,
password: process.env.PG_DATABASE_PASSWORD,
database: process.env.DATABASE_NAME,
entities: ["src/**/*/*.entity{.ts,.js}"],
migrations: ["src/**/*/*-Migration{.ts,.js}"]
}
const datasource = new DataSource(cliOrmConfig)
export default datasource
//content of orm-config.ts, this is the one I use in nest TypeOrmModule.forRoot(ormConfig)
import { DataSource, DataSourceOptions } from 'typeorm';
import 'dotenv/config'
export const ormConfig: DataSourceOptions = {
type: 'postgres',
host: process.env.DATABASE_HOST,
port: (process.env.PG_DATABASE_PORT as any) as number,
username: process.env.PG_DATABASE_USER,
password: process.env.PG_DATABASE_PASSWORD,
database: process.env.DATABASE_NAME,
entities: ["dist/src/**/*/*.entity{.ts,.js}"]
}
const datasource = new DataSource(ormConfig)
export default datasource
// My package.json relevant scripts section
"typeorm": "ts-node ./node_modules/typeorm/cli -d ./src/db/cli-orm-config.ts",
"nest:migration:generate": "npm run typeorm migration:generate ./src/db/migrations/Migration",
"nest:migration:run": "npm run typeorm migration:run"
I think as far as TypeOrm is concerned, the migration, cli parts should be teared apart from models loading and other stuffs; hence the seperation of the orm configs file for both.
Hope it helps somebody
You need to have a something.module.ts for every section of your app. It works like Angular. This is setup with GraphQL resolvers and service. REST is a bit different with a controller. Each module will probably have an entity and if GraphQL, projects.schema.graphql.
projects.module.ts
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
import { ProjectsService } from './projects.service';
import { Projects } from './projects.entity';
import { ProjectsResolvers } from './projects.resolvers';
#Module({
imports: [
TypeOrmModule.forFeature([Projects])],
providers: [
ProjectsService,
ProjectsResolvers
],
})
export class ProjectsModule {}
This worked for me - no changes needed to your ormconfig.js. Run from your root directory where the node_modules are:
ts-node ./node_modules/typeorm/cli.js migration:generate -n <MirgrationName> -c <ConnectionType>
Example:
ts-node ./node_modules/typeorm/cli.js migration:create -n AuthorHasMultipleBooks -c development
Configuration to support migrations:
// FILE: src/config/ormconfig.ts
const connectionOptions: ConnectionOptions = {
// Other configs here
// My ormconfig isn't in root folder
entities: [`${__dirname}/../**/*.entity.{ts,js}`],
synchronize: false,
dropSchema: false,
migrationsRun: false,
migrations: [getMigrationDirectory()],
cli: {
migrationsDir: 'src/migrations',
}
}
function getMigrationDirectory() {
const directory = process.env.NODE_ENV === 'migration' ? 'src' : `${__dirname}`;
return `${directory}/migrations/**/*{.ts,.js}`;
}
export = connectionOptions;
// FILE package.json
{
// Other configs here
"scripts": {
"typeorm": "NODE_ENV=migration ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js --config src/config/database.ts",
"typeorm:migrate": "npm run typeorm migration:generate -- -n",
"typeorm:run": "npm run typeorm migration:run",
"typeorm:revert": "npm run typeorm migration:revert"
}
}
I think a better solution, than the accepted one, is to create a alias in your shell of choice, that uses ts-node inside node_modules.
Note: I'm doing this in bash, with OhMyZsh, so your configuration might be totally different.
1: Open shell configuration
Open shell configuration1
nano ~/.zshrc
2: Find the place where other aliases are defined and add a new alias
alias typeorm="ts-node ./node_modules/typeorm/cli.js"
3: Close and save
Press CTRL + X to request nano to exit and press Y to confirm to save the configuration.
4: Apply the new configuration
. ~/.zshrc
5: Close terminal and open it again
You can now go to your project root and type "typeorm" which will use ts-node in conjunction with the typeorm-cli from your node_modules.
I used this solution only for production.
for development I change "../src/entity/**/*.ts" to "src/entity/**/*.ts" and then run this command: "nodemon --exec ts-node ./src/index.ts" and it works –
I solved the problem!
Create pm2.config.js file in root with below codes:
module.exports = {
apps: [
{
name: "app",
script: "./build/index.js",
},
],
};
Change entity path in ormconfig.js
{
"type": "postgres",
"host": "localhost",
"port": 5432,
"username": "postgres",
"password": "password",
"database": "db_name",
"synchronize": false,
"logging": true,
"entities": [
"../src/entity/**/*.ts", ===>>> this line is important
"./build/entity/**/*.js"
],
"migrations": [
"../src/migration/**/*.ts",===>>> this line is important
"./build/migration/**/*.js"
],
"subscribers": [
"../src/subscriber/**/*.ts",===>>> this line is important
"./build/subscriber/**/*.js"
],
"cli": {
"entitiesDir": "src/entity",
"migrationsDir": "src/migration",
"subscribersDir": "src/subscriber"
}
}
tsconfig.json with below code:
{
"compilerOptions": {
"lib": [
"es5",
"es6"
],
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"outDir": "./build",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true,
"esModuleInterop": true
}
}
Run below command for production:
tsc =>> This command generate "build" folder
Run below command for run node app in pm2:
tsc && pm2 start pm2.config.js
Now after 2 days with this solution my app with node express & typeorm is worked!
Also my app are working on linux & nginx with pm2.
For me, changing module in my tsconfig.ts
from
"module": "esnext"
To:
"module": "commonjs",
Did the job.
If you are writing in typescript and use tsc to create a dist folder with translated js files in it, then you probably have my issue and it will get fixed here.
As it is mentioned here in the docs if you use nodemon server.js, then you will hit the entities from js perspective and it will not recognize import as it is ts and es6 related. However if you want to import entities from ts files, you should run ts-node server.ts!
Personally I believe the former node server.js is a safer one to do as it is closer to the real case application.
!!! HOWEVER !!! Be very careful as you have to delete the dist folder and rebuild it if you change an entity's name, otherwise it will throw an error or work unexpectedly.
The error happens because the tsc will try to translate the changed and created ts files and leave the deleted files so it can run faster!
I hope it helped as it will definitely help me in the future as I am almost certain I will forget about it again!
I have encountered the same problem. The only difference is that my project uses .env file instead of ormconfig.json
This is what my .env file configuration looks like.
TYPEORM_ENTITIES = src/modules/*.entity.ts
TYPEORM_MIGRATIONS = src/migrations/*.entity.ts
TYPEORM_MIGRATIONS_RUN = src/migrations
TYPEORM_ENTITIES_DIR = src/modules
TYPEORM_MIGRATIONS_DIR = src/migrations
And run by using command
nest start
The problem appears to be that TypeORM does not accept entities in the form of typescript files.
There are two approaches that can be used to solve this problem.
Use node-ts instead of nest start solved the problem without modifying the path of the entities file. From my understanding, node-ts will process the typescript file in the src folder without issue.
Change the entity and migration file paths to point to the compiled js file in the dist folder instead.
TYPEORM_ENTITIES = dist/modules/*.entity.js
TYPEORM_MIGRATIONS = dist/migrations/*.entity.js
TYPEORM_MIGRATIONS_RUN = dist/migrations
TYPEORM_ENTITIES_DIR = dist/modules
TYPEORM_MIGRATIONS_DIR = dist/migrations
with this approach, I can use nest start without any problem.
The accepted answer here (https://stackoverflow.com/a/59607836/2040160) was help me generate and run the migrations, but not to run the NestJS project. I got the same error as the author when I npm run start:dev.
What worked for me, is to just generate the migrations file in vanilla JavaScript.
My ormconfig,json file:
{
"type": "cockroachdb",
"host": "localhost",
"port": 26257,
"username": "root",
"password": "",
"database": "test",
"entities": ["dist/**/*.entity{.ts,.js}"],
"migrations": ["migration/*.js"],
"synchronize": false,
"cli": {
"migrationsDir": "migration"
}
}
The script in package.json:
"typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js"
And the command I use to generate the migrations:
npm run typeorm migration:generate -- -o -n init
The -o flag will output the migrations in vanilla JavaScript.
The error is on your ormconfig.json file. check where is your code searching for the entities, migrations, subscribers. In a dev, test environment it will search for them in your src/entities src/migrations src/subscribers. But in a production environment, if you leave it as it is, it will still search in the same path instead of your build path dist/src/entities etc.... ;)
I spent so much time in this mini compilation hell :)
Just use the autoLoadEntities option in https://docs.nestjs.com/techniques/database
v useful!!
npm run typeorm migration:generate -- -n translationLength

Jest passing tests but --covering option not picking up files

Problem description:
I have written two tests for a typescript class. Those two tests pass so jest successfully retrieves the test files. I then use the --coverage option but it appears jest is not picking the covered files here.
Here is the output I am getting:
api_jester | PASS src/tests/repositories/user.test.ts
api_jester | User Repository
api_jester | ✓ it should return an empty array (18ms)
api_jester | ✓ should successfully create a user and return its data (7ms)
api_jester |
api_jester | ----------|----------|----------|----------|----------|-------------------|
api_jester | File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
api_jester | ----------|----------|----------|----------|----------|-------------------|
api_jester | All files | 0 | 0 | 0 | 0 | |
api_jester | ----------|----------|----------|----------|----------|-------------------|
api_jester | Test Suites: 1 passed, 1 total
api_jester | Tests: 2 passed, 2 total
api_jester | Snapshots: 0 total
api_jester | Time: 3.208s
api_jester | Ran all test suites.
I have tried playing with the collectCoverageFrom option but without any success. I have tested covering with some simple examples found on github and those were working so the problem is not from my environment. I am guessing I somehow missed something in my configuration but I have spend so much time on this I am getting kind of frustrated so maybe some fresh looks could help..
Project architecture :
config
|__ jest.config.js
|__ tsconfig.json
src
|__tests
| |__repositories
| |__user.test.ts
|__repositories
|___ userRepository
|__User.ts
Jest.config.js :
module.exports = {
preset: "ts-jest",
testEnvironment: "node",
roots: ["../src/tests/"],
transform: {
"^.+\\.tsx?$": "ts-jest"
},
collectCoverageFrom: ["../src/"],
moduleFileExtensions: ["ts", "js", "json"],
coverageDirectory: "../coverage"
};
package.json
{
"name": "theralog_api",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"build": "tsc",
"prettier": "npx prettier --write src/**/*.ts --config ./config/.prettierrc",
"eslint": "npx eslint --config ./config/.eslintrc ./src/**/**/*",
"start:dev": "npx nodemon -L --config ./config/api.nodemon.json",
"test:watch": "npx nodemon -L --config ./config/jester.nodemon.json",
"test:coverage": "npx jest --config ./config/jest.config.js --coverage --colors --watch"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"#types/compression": "^1.0.1",
"#types/express": "^4.17.1",
"#types/graphql-depth-limit": "^1.1.2",
"#types/jest": "^24.0.23",
"#types/node": "^12.7.12",
"#typescript-eslint/eslint-plugin": "^2.5.0",
"#typescript-eslint/parser": "^2.5.0",
"apollo-server-testing": "2.9.7",
"babel-jest": "^24.9.0",
"eslint": "^6.5.1",
"eslint-config-prettier": "^6.4.0",
"graphql-depth-limit": "^1.1.0",
"graphql-import": "^0.7.1",
"graphql-import-node": "0.0.4",
"jest": "^24.9.0",
"nodemon": "^1.19.3",
"prettier": "^1.18.2",
"ts-jest": "^24.1.0",
"ts-node": "^8.4.1",
"tsconfig-paths": "^3.9.0",
"typescript": "^3.7.2"
},
"dependencies": {
"apollo-server-express": "^2.9.6",
"compression": "^1.7.4",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"graphql": "^14.5.8",
"http": "0.0.0",
"lodash": "^4.17.15",
"ncp": "^2.0.0",
"pg": "^7.12.1",
"winston": "3.2.1"
}
}
jester.nodemon.json
{
"watch": ["../src"],
"ext": "ts",
"exec": "npx jest --config ./config/jest.config.js --watchAll"
}
You are missing a setting in the jest.config.js, collectCoverage: true
module.exports = {
preset: "ts-jest",
testEnvironment: "node",
roots: ["../src/tests/"],
transform: {
"^.+\\.tsx?$": "ts-jest"
},
collectCoverage: true,
collectCoverageFrom: ["../src/"],
moduleFileExtensions: ["ts", "js", "json"],
coverageDirectory: "../coverage"
};
I also use a more descriptive collectCoverageFrom:
collectCoverageFrom: [
'<rootDir>/src/**/*.ts',
'!<rootDir>/src/**/*.interface.ts',
'!<rootDir>/src/**/*.mock.ts',
'!<rootDir>/src/**/*.module.ts',
'!<rootDir>/src/**/*.spec.ts',
'!<rootDir>/src/**/*.test.ts',
'!<rootDir>/src/**/*.d.ts'
],
This way I exclude a number of files I do not want to count coverage from, such as my modules, mocks, and tests.
My full file with the original Jest init process and the comments from that.
For a detailed explanation regarding each configuration property, visit: the Jest documentation
module.exports = {
// All imported modules in your tests should be mocked automatically
// automock: false,
// Stop running tests after the first failure
// bail: false,
// Respect "browser" field in package.json when resolving modules
// browser: false,
// The directory where Jest should store its cached dependency information
// cacheDirectory: "C:\\Users\\sscott\\AppData\\Local\\Temp\\jest",
// Automatically clear mock calls and instances between every test
// clearMocks: false,
// Indicates whether the coverage information should be collected while executing the test
collectCoverage: true,
// An array of glob patterns indicating a set of files for which coverage information should be collected
collectCoverageFrom: [
'<rootDir>/src/**/*.ts',
'!<rootDir>/src/**/*.mock.ts',
'!<rootDir>/src/**/*.module.ts',
'!<rootDir>/src/**/*.spec.ts',
'!<rootDir>/src/**/*.test.ts',
'!<rootDir>/src/**/*.d.ts'
],
// The directory where Jest should output its coverage files
coverageDirectory: "<rootDir>/docs",
// An array of regexp pattern strings used to skip coverage collection
coveragePathIgnorePatterns: [
"\\\\node_modules\\\\"
],
// A list of reporter names that Jest uses when writing coverage reports
coverageReporters: [
"lcov",
"clover",
"text-summary"
],
// An object that configures minimum threshold enforcement for coverage results
// coverageThreshold: null,
// Make calling deprecated APIs throw helpful error messages
errorOnDeprecated: true,
// Force coverage collection from ignored files usin a array of glob patterns
// forceCoverageMatch: [],
// A path to a module which exports an async function that is triggered once before all test suites
// globalSetup: null,
// A path to a module which exports an async function that is triggered once after all test suites
// globalTeardown: null,
// A set of global variables that need to be available in all test environments
globals: {
"ts-jest": {
"diagnostics": false,
"tsConfig": "tsconfig.json"
}
},
// An array of directory names to be searched recursively up from the requiring module's location
// moduleDirectories: [
// "node_modules"
// ],
// An array of file extensions your modules use
moduleFileExtensions: [
"ts",
"tsx",
"js"
],
// A map from regular expressions to module names that allow to stub out resources with a single module
// moduleNameMapper: {},
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
// modulePathIgnorePatterns: [],
// Activates notifications for test results
// notify: false,
// An enum that specifies notification mode. Requires { notify: true }
// notifyMode: "always",
// A preset that is used as a base for Jest's configuration
// preset: null,
// Run tests from one or more projects
// projects: null,
// Use this configuration option to add custom reporters to Jest
// reporters: undefined,
// Automatically reset mock state between every test
// resetMocks: false,
// Reset the module registry before running each individual test
// resetModules: false,
// A path to a custom resolver
// resolver: null,
// Automatically restore mock state between every test
// restoreMocks: false,
// The root directory that Jest should scan for tests and modules within
// rootDir: null,
// A list of paths to directories that Jest should use to search for files in
roots: [
"<rootDir>/src"
],
// Allows you to use a custom runner instead of Jest's default test runner
// runner: "jest-runner",
// The paths to modules that run some code to configure or set up the testing environment before each test
// setupFiles: [],
// The path to a module that runs some code to configure or set up the testing framework before each test
// setupTestFrameworkScriptFile: null,
// A list of paths to snapshot serializer modules Jest should use for snapshot testing
// snapshotSerializers: [],
// The test environment that will be used for testing
testEnvironment: "node",
// Options that will be passed to the testEnvironment
// testEnvironmentOptions: {},
// Adds a location field to test results
// testLocationInResults: false,
// The glob patterns Jest uses to detect test files
testMatch: [
"**/*.spec.ts"
],
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
// testPathIgnorePatterns: [
// "\\\\node_modules\\\\"
// ],
// The regexp pattern Jest uses to detect test files
// testRegex: "",
// This option allows the use of a custom results processor
// testResultsProcessor: null,
// "testResultsProcessor": "jest-jenkins-reporter",
// This option allows use of a custom test runner
// testRunner: "jasmine2",
// This option sets the URL for the jsdom environment. It is reflected in properties such as location.href
// testURL: "http://localhost",
// Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout"
// timers: "real",
// A map from regular expressions to paths to transformers
transform: {
"^.+\\.(ts|tsx)$": "ts-jest"
},
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
// transformIgnorePatterns: [
// "\\\\node_modules\\\\"
// ],
// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
// unmockedModulePathPatterns: undefined,
// Indicates whether each individual test should be reported during the run
verbose: false
// An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
// watchPathIgnorePatterns: [],
// Whether to use watchman for file crawling
// watchman: true,
};
After a lot of research at several pages, this worked for me to get the coverage report:
put below line under scripts:
"test:coverage": "set CI=true && react-scripts test --coverage",
And, add below code for jest configuration in package.json file as below:
"jest": {
"collectCoverageFrom": [
"**/*.{js,jsx}",
"!**/node_modules/**",
"!**/coverage/**",
"!**/serviceWorker.js",
"!**/index.js"
],
"coveragePathIgnorePatterns": [
"/node_modules/",
"package.json",
"package-lock.json"
]
}
And, then run
npm run test:coverage
Apparently you have to add your source files to roots to make it work. See this PR comment.
Instead of this:
roots: ["../src/tests/"]
Also include your source files:
roots: ["../src/tests/", "../src/repositories/"]
After that and having the correct collectCoverageFrom, all files with 0% coverage were detected as expected.

Cucumber testing example is not running

I have setup a working nightwatch environment and now want to use cucumber for testing. I have followed this guide: https://www.youtube.com/watch?v=Jdlsv0CQ2CY&t=22s. No matter what I try I cannot get the test to work, I get this as output:
> cucumberpractice#1.0.0 test /Users/kieran/Documents/cucumberPractice
> cucumber-js --require cucumber.conf.js --require step-definitions --format node_modules/cucumber-pretty
Feature: Hacker News Search
Scenario: Searching Hacker News
Given I open Hacker News's home page
? undefined
Then the title is "Hacker News"
? undefined
And the Hacker News search form exists
? undefined
Warnings:
1) Scenario: Searching Hacker News # features/hackernews.feature:3
? Given I open Hacker News's home page
Undefined. Implement with the following snippet:
Given('I open Hacker News\'s home page', function () {
// Write code here that turns the phrase above into concrete actions
return 'pending';
});
? Then the title is "Hacker News"
Undefined. Implement with the following snippet:
Then('the title is {string}', function (string) {
// Write code here that turns the phrase above into concrete actions
return 'pending';
});
? And the Hacker News search form exists
Undefined. Implement with the following snippet:
Then('the Hacker News search form exists', function () {
// Write code here that turns the phrase above into concrete actions
return 'pending';
});
1 scenario (1 undefined)
3 steps (3 undefined)
0m00.000s
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! cucumberpractice#1.0.0 test: `cucumber-js --require cucumber.conf.js --require step-definitions --format node_modules/cucumber-pretty`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the cucumberpractice#1.0.0 test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/kieran/.npm/_logs/2019-09-13T20_22_09_135Z-debug.log
I have package.json, nightwatch.conf.js, cucumber.conf.js, hackernews.feature and hackernews.js files.
const { client } = require('nightwatch-api');
const { Given, Then } = require('cucumber');
Given(/^I open Hacker News's home page$/, () => {
return client
.url('https://news.ycombinator.com/')
.waitForElementVisible('body', 1000);
});
Then(/^the title is "([^"]*)"$/, title => {
return client.assert.title(title);
});
Then(/^the Hacker News search form exists$/, () => {
return client.assert.visible('input[name="q"]');
});
Feature: Hacker News Search
Scenario: Searching Hacker News
Given I open Hacker News's home page
Then the title is "Hacker News"
And the Hacker News search form exists
const chromedriver = require('chromedriver');
module.exports = {
"src_folders": ["tests"],
test_settings: {
default: {
webdriver: {
start_process: true,
server_path: chromedriver.path,
port: 4444,
cli_args: ['--port=4444']
},
desiredCapabilities: {
browserName: 'chrome'
}
}
}
};
{
"name": "cucumberpractice",
"version": "1.0.0",
"description": "Cucumber framework",
"main": "index.js",
"scripts": {
"test": "cucumber-js --require cucumber.conf.js --require step-definitions --format node_modules/cucumber-pretty"
},
"repository": {
"type": "git",
"url": "git+https://github.com/BinaryJava/nightwatch-testing.git"
},
"author": "Kieran Marriott",
"license": "ISC",
"bugs": {
"url": "https://github.com/BinaryJava/nightwatch-testing/issues"
},
"homepage": "https://github.com/BinaryJava/nightwatch-testing#readme",
"devDependencies": {
"chromedriver": "^76.0.1",
"nightwatch": "^1.2.2"
},
"dependencies": {
"cucumber": "^5.1.0",
"cucumber-pretty": "^1.5.2",
"nightwatch-api": "^2.3.0"
}
}
How do I fix this?
you might giving the path wrong for step definition file in your package.json file,
"scripts": {
"test": "cucumber-js --require cucumber.conf.js --require step-definitions --format node_modules/cucumber-pretty"
},
for example my, here is my code in package,json,
"scripts": {
"test": "cucumber-js --require cucumber.conf.js --require tests --format node_modules/cucumber-pretty"
},
"--require tests": here "test" is the location folder where my feature file and my step definition files are exist.
Instead of Scenario: Searching Hacker News
you have to put
Scenario Outline: Searching Hacker News
to add Examples

Resources