Using different ormconfig.json files depending on env - node.js

My ormconfig.json is static of course, it looks like:
{
"type": "mariadb",
"host": "localhost",
"port": 3306,
"username": "root",
"password": "moove",
"database": "moove_db",
"synchronize": true,
"logging": false,
"entities": [
"dist/entity/**/*.js"
],
"migrations": [
"dist/migration/**/*.js"
],
"subscribers": [
"dist/subscriber/**/*.js"
],
"cli": {
"entitiesDir": "dist/entity",
"migrationsDir": "dist/migration",
"subscribersDir": "dist/subscriber"
}
}
but what if I want to create another config for our production server?
Do I create another config file? How do I point typeorm to the other config file?

For the moment, I was able to just change ormconfig.json, to ormconfig.js, and then use env variables, like this:
module.exports = {
"port": process.env.port,
"entities": [
// ...
],
"migrations": [
// ...
],
"subscribers": [
// ...
],
"cli": {
// ...
}
}

Don't use the ormconfig.json. You can pass a config object directly to createConnection() like
import { createConnection } from "typeorm";
const config:any = {
"port": process.env.port || "28017",
"entities": [
// ...
],
"migrations": [
// ...
],
"subscribers": [
// ...
],
"cli": {
// ...
}
}
createConnection(config).then(async connection => {
await loadPosts(connection);
}).catch(error => console.log(error));

Related

Replace a json object array value dynamically in AzureDevops pipeline

A json file in my repository has object arrays.
In Azure pipeline I want to read the file and replace certain object values before proceeding with other tasks like publishing, etc.
Example json file :
"Routes": [
{
"UpstreamPathTemplate": "/product",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7133
}
]
},
{
"UpstreamPathTemplate": "/product/delete",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7133
}
]
},
{
"UpstreamPathTemplate": "/order",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7203
}
]
}
]
Now I want to pick the first unique word after '/' from UpstreamPathTemplate for each object and replace DownstreamHostAndPorts[0].Host with that word.
Also all Port value should be 80.
So after replacement above Json would look like
"Routes": [
{
"UpstreamPathTemplate": "/product",
"DownstreamHostAndPorts": [
{
"Host": "product",
"Port": 80
}
]
},
{
"UpstreamPathTemplate": "/product/delete",
"DownstreamHostAndPorts": [
{
"Host": "product",
"Port": 80
}
]
},
{
"UpstreamPathTemplate": "/order",
"DownstreamHostAndPorts": [
{
"Host": "order",
"Port": 80
}
]
}
]

Using outputTemplate argument in Serilog with Azure Application Insights

I'm currently implementing Azure Application Insights logging with Serilog which is working fine except for when I use an output template in my Serilog configuration. It seems like the template is ignored when passing the Serilog data to Application insights.
My serilog config in appsetting.json:
"Serilog": {
"Using": [ "Serilog.Sinks.ApplicationInsights" ],
"MinimumLevel": "Debug",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "RollingFile",
"Args": {
"pathFormat": "logs\\log-{Date}.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}"
}
},
{
"Name": "ApplicationInsights",
"Args": {
"restrictedToMinimumLevel": "Information",
"telemetryConverter": "Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights",
"outputTemplate": "Test Template - {Message}"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "app"
}
},
The logging statement:
logger.Error("Test Serilog Error For AI - " + DateTime.Now);
The output within application insights:
Is this the correct approach to customising an error message for Application insights?
After checking the source code serilog-sinks-applicationinsights, you will find it did not read the outputTemplate from appsetting.json.
For a workaround, you may implement custom TemplateTraceTelemetryConverter.
TemplateTraceTelemetryConverter
public class TemplateTraceTelemetryConverter : TraceTelemetryConverter
{
public override IEnumerable<ITelemetry> Convert(LogEvent logEvent, IFormatProvider formatProvider)
{
var templateParser = new MessageTemplateParser();
var template = templateParser.Parse($"Test Template - {logEvent.MessageTemplate.Text}");
LogEvent newLogEvent = new LogEvent(logEvent.Timestamp
, logEvent.Level
, logEvent.Exception
, template
, logEvent.Properties.Select(p => new LogEventProperty(p.Key, p.Value)));
return base.Convert(newLogEvent, formatProvider);
}
}
Use TemplateTraceTelemetryConverter
"Serilog": {
"Using": [
"Serilog.Sinks.ApplicationInsights",
],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "Test Template - {Message}"
}
},
{
"Name": "RollingFile",
"Args": {
"pathFormat": "logs\\log-{Date}.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}"
}
},
{
"Name": "ApplicationInsights",
"Args": {
"restrictedToMinimumLevel": "Error",
"telemetryConverter": "YourProjectNamespace.TemplateTraceTelemetryConverter, YourProjectNamespace"
//"outputTemplate": "Test Template - {Message}"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "app"
}
}

The .Net core extension SeriLog filtering is not working

I'm using .net Core 2.0.9 and Serilog.Filters.Expressions 2.0.0.
I configured my appsettings.json to write in a log table in the Database.The data are recorded successfuly in the database but the RequestPath property is always null :
"Serilog": {
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Debug"
}
},
"WriteTo": [
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "myconnectionString",
"tableName": "Log"
}
}
],
"WriteTo:Async": {
"Name": "Async",
"Args": {
"configure": [
{
"Name": "File",
"Args": {
"path": "..\\output\\log.txt",
"rollingInterval": "Day"
}
}
]
}
},
"Using": [ "Serilog.Settings.Configuration" ]
"Filter": [
{
"Name": "ByIncludingOnly",
"Args": {
"expression": "RequestPath like '%/api/book%'"
}
}
]
},
But i want to filter and save only log entries that have a specific api path. In this case, just entries that contain the api/user path in the RequestPath. But no data are saved anymore and i have no log errors, any idea why ?
Here are working steps for me, check the difference:
appsettings.json
"Serilog": {
"MinimumLevel": "Information",
"Override": {
"Microsoft": "Critical"
},
"WriteTo": [
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "Data Source=xx",
"autoCreateSqlTable ": true,
"tableName": "Logs",
"autoCreateSqlTable": true,
"columnOptionsSection": {
"removeStandardColumns": [ "Properties" ],
"customColumns": [
{
"ColumnName": "Release",
"DataType": "varchar",
"DataLength": 32
},
{
"ColumnName": "RequestPath",
"DataType": "varchar"
},
{
"ColumnName": "ConnectionId",
"DataType": "varchar"
}
]
}
}
},
{
"Name": "RollingFile",
"Args": {
"pathFormat": "Logs/app-{Date}.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message} {UserName} {ActionName} {NewLine} {Exception}"
}
}
],
"Using": [ "Serilog.Settings.Configuration" ],
"Filter": [
{
"Name": "ByIncludingOnly",
"Args": {
"expression": "RequestPath like '%/api%'"
}
}
]
},
Startup.cs
Log.Logger = new LoggerConfiguration()
.ReadFrom.ConfigurationSection(Configuration.GetSection("Serilog"))
.CreateLogger();
For checking serilog error, adding code below:
Log.Logger = new LoggerConfiguration()
.ReadFrom.ConfigurationSection(Configuration.GetSection("Serilog"))
.CreateLogger();
Serilog.Debugging.SelfLog.Enable(msg =>
{
Debug.Print(msg);
Debugger.Break();
});

TypeORM with multiple env setups

I want to use a separate database for running tests. So I tried to configure TypeORM for multiple environments (dev and test) but it's not working. It only use the 'dev' configuration.
This is my npm scripts:
"scripts": {
"start": "NODE_ENV=dev node dist/index.js",
"test": "NODE_ENV=test mocha --reporter spec --compilers ts:ts-node/register 'test/**/*.test.ts'"
}
If I console.log(process.env.NODE_ENV) I get the correct results ("dev" / "test").
This is my ormconfig.json
[
{
"environment": "dev",
"name": "default",
"driver": {
"type": "mysql",
"host": "localhost",
"port": 3306,
"username": "root",
"password": "",
"database": "api"
},
"entities": [ "dist/model/*.js" ],
"autoSchemaSync": true
},
{
"environment": "test",
"name": "default",
"driver": {
"type": "mysql",
"host": "localhost",
"port": 3306,
"username": "root",
"password": "",
"database": "api_test"
},
"entities": [ "dist/model/*.js" ],
"autoSchemaSync": true
}
]
I connect with createConnection();. I manually created both databases api and api_test beforehand.
Why is TypeORM not using the "test" configuration when I set NODE_ENV=test?
You could change your ormconfig.json to a js file then do something similar to this:
require('dotenv/config');
const database = {
development: "dev-db",
production: 'prod-db',
test: 'test-db'
}
module.exports = {
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'ur-username',
password: 'password',
database: database[process.env.NODE_ENV],
entities: ['dist/**/*.entity{.ts,.js}'],
synchronize: true,
migrationsTableName: 'migration',
migrations: ['migration/*.js'],
cli: {
migrationsDir: 'migration',
},
};
Then when running your tests, don't forget to set the appropriate environment. NODE_ENV=test should do.
I had a similar problem. I got this to work by using different 'name' fields for each connection. For my run-time connection, I kept name=default, and for my test connection I used name=test. So:
[
{
"environment": "dev",
"name": "default",
"driver": {
"type": "mysql",
"host": "localhost",
"port": 3306,
"username": "root",
"password": "",
"database": "api"
},
"entities": [ "dist/model/*.js" ],
"autoSchemaSync": true
},
{
"environment": "test",
"name": "test", //// CHANGED
"driver": {
"type": "mysql",
"host": "localhost",
"port": 3306,
"username": "root",
"password": "",
"database": "api_test"
},
"entities": [ "dist/model/*.js" ],
"autoSchemaSync": true
}
]
In my application, I would simply use createConnection(), which would automatically use the connection with name=default.
For my tests, I used typeorm's createConnections() (notice the s). This loads all connections. Once loaded, I would immediately after use getConnection('test'), which would get the test connection. My beforeAll in my tests looked like this in typescript:
beforeAll(async () => {
await createConnections();
getConnection('test');
});
In javascript, it would probably look something like:
beforeAll(() => {
createConnections().then(() => {
getConnection('test');
});
});
Then my tests started to pass. Hope that helps.
I had the same problem and I solved it by installing cross-env and the dotenv-flow package.
My typeorm script looked like this:
"typeorm": "cross-env NODE_ENV=development ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli -d src/core/database/ormconfig.ts",
And I created an ormconfig.ts file, where I define the database connection variables through process.env, and all I had to do was add the "require" related to "dotenv-flow".
My ormconfig.ts
import { DataSource } from "typeorm";
require('dotenv-flow').config();
export const AppDataSource = new DataSource({
type: 'postgres',
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT) || 5432,
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
entities: [
],
migrations: [
],
migrationsRun: false,
migrationsTableName: 'history'
});
This option is no longer available.
You can see the pull request that removed it from the TypeORM docs, in Aug, 2017, here:
https://github.com/typeorm/typeorm.github.io/pull/13/files
The functionality itself seems to have been removed in a commit with other changes to fix another (unrelated?) issue. It is not immediately clear what the intent was in removing it.

Browserstack not serving index.html by default

bs-config.json
{
"port": 8000,
"server": {
"baseDir": "./dist",
"serveStaticOptions": {
"extensions": [
"html",
"js"
]
}
},
"startPath": "/my-app"
}
When I load localhost:8000/my-app it says Cannot GET /my-app, yet loading localhost:8000/my-app/index.html works.
It also isn't picking up localhost:8000/my-app/index or Javascript files that index.html tries to load, unless I explicitly put the .js extension.
According to the options guide, maybe you can try this config:
{
"port": 8000,
"server": {
"baseDir": "./dist/my-app",
"index": "index.html",
"serveStaticOptions": {
"extensions": [
"html",
"js"
]
}
}
}

Resources