'TypeORM CLI: No changes in database schema were found
I'm am developing an application using NestJS and TypeORM. Whenever I try to generate migrations from my entities (by running typeorm migration:generate
) I get the following message:
No changes in database schema were found - cannot generate a migration. To create a new empty migration use "typeorm migration:create" command
I even deleted all the existing migration files (from migrations folder) to exclude any possibility of conflict.
The problem begun after I changed my application's modules folders structure to:
src
|- config
| |- database
| |- mysql
| |- cli-configuration.ts
|- migrations
|- module1
|- controller
|- entity
|- service
As can be seen, the migrations
folder is right under src
and each module has an entity
folder, where the entities for that module are placed. All the ormconfig settings come from cli-configuration.ts
file.
In package.json
file I added the following to scripts
:
{
...
"scripts": {
...
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js --config src/config/database/mysql/cli-configuration.ts",
"typeorm:migrate": "npm run typeorm migration:generate -- -n",
"typeorm:run": "npm run typeorm migration:run"
}
}
The content of src/config/database/mysql/cli-configuration.ts
file is:
import * as path from 'path';
import * as dotenv from 'dotenv';
dotenv.config({
// Path relative to project root folder (because cli command is invoked from there)
path: path.resolve('environment', (process.env.NODE_ENV === "production") ? ".env.production" : ".env")
});
const config = {
type: "mysql",
host: process.env.TYPEORM_HOST,
port: Number(process.env.TYPEORM_PORT),
username: process.env.TYPEORM_USERNAME,
password: process.env.TYPEORM_PASSWORD,
database: process.env.TYPEORM_DATABASE,
entities: [path.resolve('src', process.env.TYPEORM_ENTITIES)],
// We are using migrations, synchronize should be set to false.
synchronize: false,
// Run migrations automatically,
// you can disable this if you prefer running migration manually.
migrationsRun: true,
logging: process.env.TYPEORM_LOGGING,
// Allow both start:prod and start:dev to use migrations
// __dirname is either dist or src folder, meaning either
// the compiled js in prod or the ts in dev.
migrations: [path.resolve('src', process.env.TYPEORM_MIGRATIONS)],
cli: {
// Location of migration should be inside src folder
// to be compiled into dist/ folder.
// entitiesDir: process.env.TYPEORM_ENTITIES_DIR,
migrationsDir: path.resolve('src', process.env.TYPEORM_MIGRATIONS_DIR),
// subscribersDir: process.env.TYPEORM_SUBSCRIBERS_DIR,
},
dropSchema: false
};
export = config;
Running console.log(config)
I get:
{
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: 'root',
database: 'myapp',
entities: [ '/var/www/html/myapp/src/**/*.entity{.ts,.js}' ],
synchronize: false,
migrationsRun: true,
logging: 'all',
migrations: [ '/var/www/html/myapp/src/migrations/**/*{.ts,.js}' ],
cli: { migrationsDir: '/var/www/html/myapp/src/migrations' },
dropSchema: false
}
Last but not least.... After spending hours on this issue (making changes to migrations and entities paths, hard-coding values besides getting them from process.env, etc), I tried to execute yarn run typeorm schema:log
(npm run
works as well). I got surprised when I saw that all the content that I expected to be in the migration file I am trying to generate was output to console.
CREATE TABLE `permission_permission` (`id` varchar(36) NOT NULL, `name` varchar(100) NOT NULL, `code` text NOT NULL, `create_date` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `update_date` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `delete_date` datetime(6) NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE `permission_role` (`id` varchar(36) NOT NULL, `name` varchar(100) NOT NULL, `code` varchar(255) NOT NULL, `create_date` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `update_date` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `delete_date` datetime(6) NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE `user_user` (`id` varchar(36) NOT NULL, `email` varchar(255) NOT NULL, `password` varchar(255) NOT NULL, `first_name` varchar(255) NOT NULL, `last_name` varchar(255) NOT NULL, `is_active` tinyint NOT NULL DEFAULT 0, `create_date` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `update_date` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `delete_date` datetime(6) NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE `permission_role_permission` (`permission_id` varchar(36) NOT NULL, `role_id` varchar(36) NOT NULL, INDEX `IDX_3247040996395a5faea3c9b3a5` (`permission_id`), INDEX `IDX_7d9cfbfd027256ab08658bcf6e` (`role_id`), PRIMARY KEY (`permission_id`, `role_id`)) ENGINE=InnoDB;
CREATE TABLE `user_user_role` (`role_id` varchar(36) NOT NULL, `user_id` varchar(36) NOT NULL, INDEX `IDX_c0c2bbb31e8e8708efc6dd5a64` (`role_id`), INDEX `IDX_beb8c39c852f4d132ba44b483c` (`user_id`), PRIMARY KEY (`role_id`, `user_id`)) ENGINE=InnoDB;
ALTER TABLE `permission_role_permission` ADD CONSTRAINT `FK_3247040996395a5faea3c9b3a54` FOREIGN KEY (`permission_id`) REFERENCES `permission_role`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION;
ALTER TABLE `permission_role_permission` ADD CONSTRAINT `FK_7d9cfbfd027256ab08658bcf6e1` FOREIGN KEY (`role_id`) REFERENCES `permission_permission`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION;
ALTER TABLE `user_user_role` ADD CONSTRAINT `FK_c0c2bbb31e8e8708efc6dd5a64b` FOREIGN KEY (`role_id`) REFERENCES `user_user`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION;
ALTER TABLE `user_user_role` ADD CONSTRAINT `FK_beb8c39c852f4d132ba44b483c0` FOREIGN KEY (`user_id`) REFERENCES `permission_role`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION;
Can anyone tell me why is schema:log
detecting the changes in my entities, but migration:generate
is not working?
Solution 1:[1]
For me this hint helped. Just run npm run build
before generating with npm run typeorm -- migration:generate -n migration_name
the new migration. Somehow an up to date dist
folder needs to be present.
Solution 2:[2]
These are the steps that i took to make it work:
- Add an empty migration and on the
up
method add a query to drop all your tables.
Example:
await queryRunner.query(
DROP TABLE "table_name"
);
Remove this migration
Remove your
dist
folderRemove your
.idea
folderStart your service - i used
nest start
(this should add a new and cleandist
folder)Check your
ormconfig.json
file for your "migrations" location.
Mine was:
"migrations": [ "dist/database/migration/*.js" ]
Check this path in the
dist
folder - i had no folder there with the name "migration".Add the folder
migration
(or use the name you have in theormconfig.json
)Run your migration:generate like before and it should work
(npm run typeorm -- migration:generate -n migration_name
)
Hope it helped!
Solution 3:[3]
This problem appears when something wrong with paths.
I have created a small working project using your configurations and directory style. Here is the link.
https://github.com/nairi-abgaryan/typeorm-mysql-nestjs
Quick overview.
Updated the cli-configuration.ts
file a little bit.
The typeorm lib will use this configuration as you described in package.json.
import * as dotenv from 'dotenv';
import {TypeOrmModuleOptions} from '@nestjs/typeorm/dist/interfaces/typeorm-options.interface';
dotenv.config({
path: '.env',
});
const config: TypeOrmModuleOptions = {
type: 'mysql',
host: process.env.TYPEORM_HOST,
port: Number(process.env.TYPEORM_PORT),
username: process.env.TYPEORM_USERNAME,
password: process.env.TYPEORM_PASSWORD,
database: process.env.TYPEORM_DATABASE,
autoLoadEntities: true,
entities: [`${__dirname}/../../../../src/**/*.entity{.ts,.js}`],
migrations: [`${__dirname}/../../../migrations`],
cli: {
migrationsDir: `${__dirname}/../../../migrations`,
},
dropSchema: false,
};
export = config;
.env
TYPEORM_TYPE='mysql'
TYPEORM_HOST=localhost
TYPEORM_PORT=3306
TYPEORM_USERNAME='root'
TYPEORM_PASSWORD='root'
TYPEORM_DATABASE='myapp'
TYPEORM_MIGRATIONS='migrations'
Also, I created an ormconfig.json file which is for nest js connection to DB. As it says in the documentation when you don't want to config it in the app.module.
Note that the ormconfig.json file is loaded by the typeorm library. Thus, any of the extra properties described above (which are supported internally by way of the forRoot() method - for example, autoLoadEntities and retryDelay) won't be applied. Luckily, TypeORM provides the getConnectionOptions function that reads connection options from the ormconfig file or environment variables. With this, you can still use the configuration file and set Nest-specific options, as follows:
TypeOrmModule.forRootAsync({
useFactory: async () =>
Object.assign(await getConnectionOptions(), {
autoLoadEntities: true,
}),
});
Solution 4:[4]
We had a similar issue on projects with Nestjs + TypeORM + PostgreSQL.
We have found out that TypeORM had a conflict when you have an environment variable with the same value of type.
Check this example: https://imgur.com/a/pgR6OGJ
In this case, we have TYPEORM_TYPE = postgres
and the type: 'postgres'
for some unknown reason TypeORM cannot resolve and does not find your Database.
So to fix it try to remove it from your .env and try run again!
Hope I could help you or someone ;)
Solution 5:[5]
I was getting exactly the same thing and it seems that an older 0.2.x
version is off. I've been using 0.2.34
and I was getting the issue there.
Moving to 0.2.45
fixed the issue for me.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | Nairi Abgaryan |
Solution 4 | Felipe Lorenzoni |
Solution 5 | g_kou |