Setting up typeorm with nestjs not working migrations - javascript

Here is the config:
#Module({
imports: [
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
type: 'postgres',
host: configService.get('DB_HOST'),
port: configService.get('DB_PORT'),
username: configService.get('DB_USER'),
password: configService.get('DB_PASSWORD'),
database: configService.get('DB_NAME'),
entities: [
__dirname + '/../**/*.entity{.ts,.js}',
],
// synchronize: true,
})
}),
],
})
export class DatabaseModule {}
The connections with the database itself is working, but when I'm trying to set up the migrations it throws the errors. What I've tried is to add the migration options in the above config and to create additional ormconfig.js with the configurations. Here is what I have in package.json file:
"typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js"
The problem is when I try to create migration it is not being created in migrations folder as I want and is not using the config above, how to solve it?

First, you need to set the migrations path in the module config
TypeOrmModule.forRootAsync({
// other properties
entities: [
__dirname + '/../**/*.entity{.ts,.js}', // from the question
],
migrations:[/*I assume you already know migration file paths*/]
})
then, To generate a migration file
npx typeorm migration:create -n FileName -d src/migrations
At this point, you need to call runMigrations(). add the below code in your main.ts
const conn = await getConnection('default'); // connection name is "default"
await conn.runMigrations();

If you're using typeorm or 3.0 or newer versions you should do it straight on the cli:
typeorm migration:create src/migration_path
For older versions, you can add the following command to the ormconfig file:
"cli": {
"migrationDir": "./src/migration_path"
}

TypeORM CLI reads the configuration in a file ormconfig.json or ormconfig.js at the root of the project.
You need to extract this config in suck a file and then import this file in your DatabaseModule to have both things working.

Related

Node server not working in monorepo with babel compiler

I have a monorepo with the following folder structure.
packages/
- server
- src
- index.js
- build
- lib1
- lib2
My node server uses express and graphql, with a very simple setup.
index.js
const start = async () => {
const server = new ApolloServer({
schema: clientSchema,
tracing: true,
introspection: process.env.NODE_ENV !== "production",
});
await server.start()
const app = express();
app.use(express.json({limit: '10mb'}));
app.use(express.urlencoded({limit: '10mb', extended: true}));
server.applyMiddleware({ app });
app.listen({ port }, () =>
console.log(`🚀 Server ready at http://localhost:${port}${server.graphqlPath}`)
);
}
I am using babel to transpile the node server using a .babelrc file with the following config
{
"presets": ["#babel/preset-env"],
"plugins": ["#babel/plugin-transform-runtime"]
}
lib1 and lib2 are packages using import and export syntax.
When I build the node server using something like babel -d ./build ./src and then start the server using node ./build/index.js
I am presented with the error SyntaxError: Cannot use import statement outside a module for one of the files in package/lib1.
Now I have gotten this to work by changing index.js in the server package to be like the example below however im finding the server uses a lot of memory and takes a long time when initially starting up which makes my Heroku server cost really expensive as it will crash due to memory quotas going past 1GB.
require('#babel/register')({
presets: ['#babel/preset-env'],
ignore: ['node_modules'],
plugins: [
"#babel/plugin-transform-runtime"
]
});
// Import the rest of our application.
module.exports = require('./server.js');

dataSource flag in typeorm cli

I'm starting a project with typeorm. My configuration file looks like this:
ormconfig.js
import dotenv from 'dotenv'
dotenv.config();
const {
DATABASE_HOST,
DATABASE_PORT,
DATABASE_NAME,
DATABASE_PASSWORD
} = process.env
export default {
type: 'postgres',
host: DATABASE_HOST,
port: DATABASE_PORT,
database: DATABASE_NAME,
password: DATABASE_PASSWORD,
entities: [
"./api/modules/documents/entity/*.js",
],
migrations: [
"./api/database/migrations/*.js",
],
cli: {
migrationsDir: "./api/database/migrations",
entitiesDir: "api/database/modules/**/entity"
}
}
package.json scripts
"scripts": {
"gulp": "node_modules/gulp-cli/bin/gulp.js",
"start": "nodemon ./src/app.js",
"start:api": "nodemon ./api/server.js",
"typeorm": "node ./node_modules/typeorm/cli.js --config ./ormconfig.js"
},
When i try to run the command yarn typeorm migration:run its show this message:
Runs all pending migrations.
Opções:
-h, --help Exibe ajuda [booleano]
-d, --dataSource Path to the file where your DataSource instance is defined.
[obrigatório]
-t, --transaction Indicates if transaction should be used or not for
migration run. Enabled by default. [padrão: "default"]
-v, --version Exibe a versão [booleano]
Missing required argument: dataSource
What would be datasource flag?
I tried with typeorm cli installed globally, same problem happens
Looks like you are using typeorm 0.3.x in your project while you are following 0.2.x configurations. Check your installed version on your package.json.
If you are using 0.3.x and want to keep with the current version you should follow the documentation: https://typeorm.io/data-source
Otherwise you can just downgrade your version executing:
npm install typeorm#0.2.45

How to set up configuration of Type ORM with .env file in Nest.JS

I want to set up configuration of TypeORM with .env file, but i have problem when I am trying to run migration script.
What i did:
1.Added scripts to package.json
"migration:generate": "node_modules/.bin/typeorm migration:generate -n",
"migration:run": "node_modules/.bin/typeorm migration:run",
"migration:revert": "node_modules/.bin/typeorm migration:revert",
2.Imported TypeOrmModule in app.module*
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
type: 'mysql',
host: configService.get('HOST'),
port: +configService.get<number>('PORT'),
username: configService.get('DATABASE_USERNAME'),
password: configService.get('DATABASE_PASSWORD'),
database: configService.get('DATABASE'),
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
})
}
)],
3. Creaded .env file in root folder
HOST=localhost
PORT=5432
DATABASE_USER=dbuser
DATABASE_PASSWORD=dbpassword
DATABASE=dbname
now I am trying to run migration script like this:
npm run migration:generate -n AddUserTable
and I reciving error like this:
Error during migration generation:
Error: No connection options were found in any orm configuration files.
According to documentation it shuld be some ormconfig.json but it should also working with .env. Please tell me, what is wrong in my case?
Regarding the error message, you should add ormconfig.json in the root project. The .env file does not relate in this case.
Check import ConfigModule.forRoot(). It should be imported first
You can not use forRootAsync for TypeOrmModule if you use these variables in the env file
TYPEORM_CONNECTION = postgres
TYPEORM_HOST = localhost
TYPEORM_PORT = 5432
TYPEORM_USERNAME = postgres
TYPEORM_PASSWORD = 12345
TYPEORM_DATABASE = postgres
TYPEORM_SYNCHRONIZE = false
TYPEORM_MIGRATIONS_RUN = false
TYPEORM_ENTITIES = src/modules/**/*.entity.ts
TYPEORM_MIGRATIONS = db/migrations/*.ts
TYPEORM_LOGGING = true
https://github.com/typeorm/typeorm/blob/master/docs/using-ormconfig.md#using-environment-variables
You can also try such scripts:
"migration:run": "ts-node --project ./tsconfig.json -r tsconfig-paths/register node_modules/typeorm/cli.js migration:run",
"migration:revert": "ts-node --project ./tsconfig.json -r tsconfig-paths/register node_modules/typeorm/cli.js migration:revert",
"migration:create": "ts-node --project ./tsconfig.json -r tsconfig-paths/register node_modules/typeorm/cli.js migration:create",
"migration:generate": "ts-node --project ./tsconfig.json -r tsconfig-paths/register node_modules/typeorm/cli.js migration:generate"
I was having the same problem. I solved it by following the config instructions in this article, which shows you how to generate a dynamic ormconfig.json file:
https://medium.com/#gausmann.simon/nestjs-typeorm-and-postgresql-full-example-development-and-project-setup-working-with-database-c1a2b1b11b8f
The extra setup is a bit annoying, but it works.
Just a note if you are using typescript - the article is from 2019 and per 2020 updates to nestjs, you'll want to change the src paths to allow for src or dist in the config.service.ts file, eg. change to something like this (depending on your file structure):
entities: ['**/*.entity{.ts,.js}'],
migrationsTableName: 'migration',
migrations: ['src/migration/*.ts'],
cli: {
migrationsDir: 'src/migration',
},
to
entities: [__dirname + '/../**/*.entity{.ts,.js}'],
migrationsTableName: 'migration',
migrations: [__dirname + '/../migration/*{.ts,.js}'],
cli: {
migrationsDir: 'src/migration',
},

NestJs TypeORM configuration using env files

I have two .env files like dev.env and staging.env. I am using typeorm as my database ORM. I would like to know how to let typeorm read either of the config file whenever I run the application. Error: No connection options were found in any of configurations file from typeormmodule.
You can create a ConfigService that reads in the file corresponding to the environment variable NODE_ENV:
1) Set the NODE_ENV variable in your start scripts:
"start:dev": "cross-env NODE_ENV=dev ts-node -r tsconfig-paths/register src/main.ts",
"start:staging": "cross-env NODE_ENV=staging node dist/src/main.js",
2) Read the corresponding .env file in the ConfigService
#Injectable()
export class ConfigService {
private readonly envConfig: EnvConfig;
constructor() {
this.envConfig = dotenv.parse(fs.readFileSync(`${process.env.NODE_ENV}.env`));
}
get databaseHost(): string {
return this.envConfig.DATABASE_HOST;
}
}
3) Use the ConfigService to set up your database connection:
TypeOrmModule.forRootAsync({
imports:[ConfigModule],
useFactory: async (configService: ConfigService) => ({
type: configService.getDatabase()
// ...
}),
inject: [ConfigService]
}),

How to get node package consumer directory from node_modules?

I am trying to create a simple node module that creates a set of folders in the app that consumes it. I exported a simple createLayout function that creates the folders. I pushed my changes to git and did an npm i from another folder. Lets call the modules creator and consumer for the sake of explanation. When I try to call createLayout in consumer I am running in to several issues. I am in E:\ drive.
Below is the index.js in creator:
import {sync} from 'mkdirp';
export function createLayout(config) {
sync('./folder1');
}
And index.js in consumer:
var createLayout = require('creator').createLayout;
createLayout();
// with config createLayout({path: __dirname})
This results in creating a folder in E:\ not relative to consumer. So I tried including __dirname:
sync(__dirname + '/folder1');
Once again, this also creates a folder in E:\ not relative to consumer. I searched for bit like in various modules to see how they are doing when they are reading the config file, for instance webpack uses process.cwd. So I tried that too.
sync(process.cwd() + '/folder1');
Same, results in creating a folder in E:\ not relative to consumer. Then I tried to pass the __dirname or cwd through a config object.
// get __dirname from the `consumer` in config.path
sync(config.path + '/folder1');
But it ends up in following error:
Error: EPERM: operation not permitted, mkdir 'E:\'
I tried logging all the values in both creator and consumer:
console.log(__dirname, process.cwd(), config.path)
// creator: / / E:\projects\consumer
// consumer: E:\projects\consumer E:\projects\consumer E:\projects\consumer
I am using webpack with babel to pack the creator, plain js in consumer. I do not know what am I doing wrong. I am pretty new to nodejs ways of working.
Update
I am noticing that this is occurring only when I use webpack to build the creator. A simple module.exports works normally as anyone would expect. So I am including my webpack config file:
module.exports = {
entry: [
'./index.js'
],
output: {
filename: 'creator.js',
path: __dirname + '/dist',
library: 'creator',
libraryTarget: 'umd'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel'
}
]
},
externals: {
fs: 'fs'
}
};
Correct solution is adding this line in config:
target: 'node'
this will make webpack to ignore modules like fs and mkdirp and some other.
Now no longer need to specify externals.
Incorrect solution given before:
Just add mkdirp to externals and it will resolve you problem:
externals: {
fs: 'fs',
mkdirp: 'mkdirp'
}

Categories