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

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',
},

Related

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

Setting up typeorm with nestjs not working migrations

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.

Run typescript build with tsconfig-paths using pm2

I am trying to run the build (.js files) of typescript with the tsconfig-paths in production, I have no problem running typescript with paths. Just when running the build on production with pm2.
I have tried:
apps: [
{
name: 'app',
script: './dist/index.js',
node_args: '-r ts-node/register -r tsconfig-paths/register',
},
],
TLDR: If as I assume you run info *the* common misunderstanding about tsconfig you may try:
{
apps: [
{
name: 'app',
script: './dist/index.js',
node_args: '-r ts-node/register -r tsconfig-paths/register',
env: {
"TS_NODE_BASEURL": "./dist"
}
},
}
Explanation:
Typescript allows us to specify path aliases so that we don'y have to use ugly relative paths like ../../../../config. To use this feature typically you would have a tsconfig.json like this:
...
"outDir": "./dist",
"baseUrl": "./src", /* if your code sits in the /src directory */
"paths": {
"#/*": ["*"]
},
...
Now you can do the following:
import config from "#/config";
It will compile without errors. During the compilation the requested modules are in the src directory. However:
$ node -r tsconfig-paths/register dist/index.js
Failure! Cannot find module '#/config'
Why is that? Because at runtime config no longer sits inside ./src but instead can be found in ./dist.
So how do we handle this?
Fortunately tsconfig-paths allows us to override baseUrl with TS_NODE_BASEURL env:
$ TS_NODE_BASEURL=./dist node -r tsconfig-paths/register dist/index.js
Success!

How To Setup Custom ESBuild with SCSS, PurgeCSS & LiveServer?

Background:
I have a Webpack setup that I use to preprocess SCSS with PurgeCSS with a live HMR server with esbuild-loader for speeding up compiles in Webpack but even then my compile times are still slow and I would like the raw-speed of ESBuild and remove Webpack setup altogether.
The basic setup of ESBuild is easy, you install esbuild using npm and add the following code in your package.json:
{
...
"scripts": {
...
"watch": "esbuild --bundle src/script.js --outfile=dist/script.js --watch"
},
...
}
and run it by using the following command:
npm run watch
This single-line configuration will bundle your scripts and styles (you can import style.css in script.js) and output the files in the dist directory but this doesn't allow advance configuration for ESBuild like outputting a different name for your stylesheet and script files or using plugins.
Problems:
How to configure ESBuild using an external config file?
ESBuild doesn't support SCSS out-of-the-box. How to configure external plugins like esbuild-sass-plugin and to go even further, how to setup PostCSS and its plugins like Autoprefixer?
How to setup dev server with auto-rebuild?
How to setup PurgeCSS?
Solutions:
1. How to configure ESBuild using an external config file?
Create a new file in root: esbuild.js with the following contents:
import esbuild from "esbuild";
esbuild
.build({
entryPoints: ["src/styles/style.css", "src/scripts/script.js"],
outdir: "dist",
bundle: true,
plugins: [],
})
.then(() => console.log("⚡ Build complete! ⚡"))
.catch(() => process.exit(1));
Add the following code in your package.json:
{
...
"scripts": {
...
"build": "node esbuild.js"
},
...
}
Run the build by using npm run build command and this would bundle up your stylesheets and scripts and output them in dist directory.
For more details and/or adding custom build options, please refer to ESBuild's Build API documentation.
2. ESBuild doesn't support SCSS out-of-the-box. How to configure external plugins like esbuild-sass-plugin and to go even further, how to setup PostCSS and plugins like Autoprefixer?
Install npm dependencies: npm i -D esbuild-sass-plugin postcss autoprefixer
Edit your esbuild.js to the following code:
import esbuild from "esbuild";
import { sassPlugin } from "esbuild-sass-plugin";
import postcss from 'postcss';
import autoprefixer from 'autoprefixer';
// Generate CSS/JS Builds
esbuild
.build({
entryPoints: ["src/styles/style.scss", "src/scripts/script.js"],
outdir: "dist",
bundle: true,
metafile: true,
plugins: [
sassPlugin({
async transform(source) {
const { css } = await postcss([autoprefixer]).process(source);
return css;
},
}),
],
})
.then(() => console.log("⚡ Build complete! ⚡"))
.catch(() => process.exit(1));
3. How to setup dev server with auto-rebuild?
ESBuild has a limitation on this end, you can either pass in watch: true or run its server. It doesn't allow both.
ESBuild also has another limitation, it doesn't have HMR support like Webpack does.
So to live with both limitations and still allowing a server, we can use Live Server. Install it using npm i -D #compodoc/live-server.
Create a new file in root: esbuild_watch.js with the following contents:
import liveServer from '#compodoc/live-server';
import esbuild from 'esbuild';
import { sassPlugin } from 'esbuild-sass-plugin';
import postcss from 'postcss';
import autoprefixer from 'autoprefixer';
// Turn on LiveServer on http://localhost:7000
liveServer.start({
port: 7000,
host: 'localhost',
root: '',
open: true,
ignore: 'node_modules',
wait: 0,
});
// Generate CSS/JS Builds
esbuild
.build({
logLevel: 'debug',
metafile: true,
entryPoints: ['src/styles/style.scss', 'src/scripts/script.js'],
outdir: 'dist',
bundle: true,
watch: true,
plugins: [
sassPlugin({
async transform(source) {
const { css } = await postcss([autoprefixer]).process(
source
);
return css;
},
}),
],
})
.then(() => console.log('⚡ Styles & Scripts Compiled! ⚡ '))
.catch(() => process.exit(1));
Edit the scripts in your package.json:
{
...
"scripts": {
...
"build": "node esbuild.js",
"watch": "node esbuild_watch.js"
},
...
}
To run build use this command npm run build.
To run dev server with auto-rebuild run npm run watch. This is a "hacky" way to do things but does a fair-enough job.
4. How to setup PurgeCSS?
I found a great plugin for this: esbuild-plugin-purgecss by peteryuan but it wasn't allowing an option to be passed for the html/views paths that need to be parsed so I
created esbuild-plugin-purgecss-2 that does the job. To set it up, read below:
Install dependencies npm i -D esbuild-plugin-purgecss-2 glob-all.
Add the following code to your esbuild.js and esbuild_watch.js files:
// Import Dependencies
import glob from 'glob-all';
import purgecssPlugin2 from 'esbuild-plugin-purgecss-2';
esbuild
.build({
plugins: [
...
purgecssPlugin2({
content: glob.sync([
// Customize the following URLs to match your setup
'./*.html',
'./views/**/*.html'
]),
}),
],
})
...
Now running the npm run build or npm run watch will purgeCSS from the file paths mentioned in glob.sync([...] in the code above.
TL;DR:
Create an external config file in root esbuild.js and add the command to run it in package.json inside scripts: {..} e.g. "build": "node esbuild.js" to reference and run the config file by using npm run build.
ESBuild doesn't support HMR. Also, you can either watch or serve with ESBuild, not both. To overcome, use a separate dev server library like Live Server.
For the complete setup, please refer to my custom-esbuild-with-scss-purgecss-and-liveserver repository on github.
Final Notes:
I know this is a long thread but it took me a lot of time to figure these out. My intention is to have this here for others looking into the same problems and trying to figure out where to get started.
Thanks.
Adding to Arslan's terrific answer, you can use the PurgeCSS plug-in for postcss to totally eliminate Step 4.
First, install the postcss-purgecss package: npm install #fullhuman/postcss-purgecss
Then, replace the code from Step 2 in Arslan's answer with the code shown below (which eliminates the need for Step 4).
import esbuild from "esbuild";
import { sassPlugin } from "esbuild-sass-plugin";
import postcss from "postcss";
import autoprefixer from "autoprefixer";
import purgecss from "#fullhuman/postcss-purgecss";
// Generate CSS/JS Builds
esbuild
.build({
entryPoints: [
"roomflows/static/sass/project.scss",
"roomflows/static/js/project.js",
],
outdir: "dist",
bundle: true,
loader: {
".png": "dataurl",
".woff": "dataurl",
".woff2": "dataurl",
".eot": "dataurl",
".ttf": "dataurl",
".svg": "dataurl",
},
plugins: [
sassPlugin({
async transform(source) {
const { css } = await postcss([
purgecss({
content: ["roomflows/templates/**/*.html"],
}),
autoprefixer,
]).process(source, {
from: "roomflows/static/sass/project.scss",
});
return css;
},
}),
],
minify: true,
metafile: true,
sourcemap: true,
})
.then(() => console.log("⚡ Build complete! ⚡"))
.catch(() => process.exit(1));

Error: knex: Required configuration option 'client' is missing

I'm new to Node.js, please help me.
What is wrong?
Using typescript, SQLite3 and Knex, with migration.
I get the error when running "yarn knex: migrate" or "knex migrate: latest":
$ knex migrate:latest
Requiring external module ts-node/register
Error: knex: Required configuration option 'client' is missing
These are my files:
package.json:
{
"name": "backend",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "ts-node-dev --transpile-only --ignore-watch node-modules --respawn
src/server.ts",
"knex:migrate": "knex --knexfile knexfile.ts migrate:latest",
"knex:migrate:rollback": "knex --knexfile knexfile.ts migrate:rollback"
},
"devDependencies": {
"#types/express": "^4.17.11",
"ts-node": "^9.1.1",
"ts-node-dev": "^1.1.6",
"typescript": "^4.2.4"
},
"dependencies": {
"espress": "^0.0.0",
"express": "^4.17.1",
"knex": "^0.95.4",
"sqlite3": "^5.0.2"
}
}
knexfile.ts:
import path from'path';
module.exports = {
cliente: 'sqlite3',
connection: {
filename: path.resolve(__dirname, 'src', 'database', 'resp.sqlite')
},
migrations: {
directory: path.resolve(__dirname, 'src', 'database', 'migrations'),
},
useNullAsDefault: true,
};
Migration 00_create_organizacoes.ts:
import knex from 'knex';
export async function up(knex: knex) {
return knex.schema.createTable('organizacoes', table => {
table.increments('id').primary();
table.string('razaosocial_org').notNullable();
table.integer('atividade_org').notNullable();
table.timestamp('criacao_org').defaultTo(knex.fn.now());
table.timestamp('atualizacao_org').defaultTo(knex.fn.now());
});
}
export async function down(knex: knex) {
return knex.schema.droptable('organizacoes');
};
My file structure:
enter image description here
Unsuccessful in other treatments.
Looks like you have a typo in your knexfile.ts
The name of the missing property is client and not cliente
The Requiring external module ts-node/register message you get is not the issue, the issue is that in the knexfile.ts the client property is not read. From the example above change the cliente property to client and it is fixed.
What if you have no spelling error, client exist in your configuration, and you are getting this message? Are you using a env file? If yes, In your knexfile.ts print the value from your env file. If it returns undefined, it means that no value was read for the env file. Check if you have the dotenv package installed and configured properly. Also check that your env file has a key called client and the value is available and in the knexfile.ts ensure you are calling the right key from your env.
Finally if the problem is not solved and every other thing is in-place, require dotenv in your package.json file before running a command as shown below.
"migrate:latest": "ts-node -r dotenv/config ./node_modules/knex/bin/cli.js migrate:latest
The ts-node -r dotenv/config ensures that the details in the env file are added to the environment.
The ./node_modules/knex/bin/cli.js starts the knex cli so that the remaining part which is a knex command can be executed.

Categories