How can I annotate nested objects with interfaces for configuration check? - javascript

Was looking into typescript to have type check on a configuration file like the following:
const _config = {
local: {
host: 'localhost',
port: 1234
},
dev: {
host: 'https://dev.myapp.com',
port: 80
},
prod: {
host: 'https://prod.myapp.com',
port: 80
},
}
export const config = _config[process.env.NODE_ENV || 'dev'];
I would like to annotate the nested objects to conform to an interface, basically to check that there are no missing configuration properties at compile time (instead of runtime):
interface IConfig {
host: string;
port: number;
}
const _config = {
local: { // <-- I would like to annotate this object with type IConfig
host: 'localhost',
port: 1234
},
dev: { // <-- I would like to annotate this object with type IConfig
host: 'https://dev.myapp.com',
port: 80
},
prod: { // <-- I would like to annotate this object with type IConfig
host: 'https://prod.myapp.com',
port: 80
},
}
export const config = _config[process.env.NODE_ENV || 'dev'];
Is this possible? Or any alternative way to achieve the same thing?

You could use an index signature and provide an interface for the entire configuration.
interface Environment {
host: string;
port: number;
}
interface Config {
[name: string]: Environment;
}
const _config: Config = {
local: {
host: 'localhost',
port: 1234
},
dev: {
host: 'https://dev.myapp.com',
port: 80
},
prod: {
host: 'https://prod.myapp.com',
port: 80
},
}
export const config = _config[process.env.NODE_ENV || 'dev'];

Have you tried to use an interface for the config object itself? So you could do something like
interface IConfigProperty {
host: string
port: number
}
interface IConfig {
local: IConfigProperty
dev: IConfigProperty
prod: IConfigProperty
}
const _config: IConfig = {
local: {
host: 'localhost',
port: 1234
},
dev: {
host: 'https://dev.myapp.com',
port: 80
},
prod: {
host: 'https://prod.myapp.com',
port: 80
},
}
export const config = _config[process.env.NODE_ENV || 'dev'];

For further type-safety, I would recommend this instead. We can make use of type aliases to provided typings for host.
type Host = 'localhost' | 'https://dev.myapp.com' | 'https://prod.myapp.com';
interface Config {
[name: string]: IConfig;
}
interface IConfig {
host: Host;
port: number;
}
const _config: Config = {
local: {
host: 'localhost',
port: 1234
},
dev: {
host: 'https://dev.myapp.com',
port: 80
},
prod: {
host: 'https://prod.myapp.com',
port: 80
},
};
If you wish, you can even declare type aliases for the name of your configs(local, dev, prod)

One possible solution is to annotate the parent object:
interface IConfig {
host: string;
port: number;
}
const _config: { local: IConfig, dev: IConfig, prod: IConfig } = {
local:
host: 'localhost',
port: 1234
},
dev:
host: 'https://dev.myapp.com',
port: 80
},
prod:
host: 'https://prod.myapp.com',
port: 80
},
}
export const config: IConfig = _config[process.env.NODE_ENV || 'dev'];

Related

Lost connection to server - Peer.js

Sometimes, in a very random way, the error "Lost connection to server" appears
Peerjs server code:
const { PeerServer } = require('peer');
const peerServer = PeerServer({ port: 80, host: 'ip' });
Peerjs connection code:
this.peer = new Peer('', {
host: 'peerjs server domain (uses cloudflare)',
port: 443,
debug: 2,
pingInterval: 2500,
secure: true,
path: '/',
config: {
iceServers: [
{
urls: [
'turn:coturnServerIP:3478',
'stun:coturnServerIP:3478'
],
username,
credential
}
]
}
});

exporting consts from CommonJS app amd require them in another file

I want to export const config from config.js file in CommonJs app.
const config = {
development: {
client: 'pg',
connection: {
database: 'myDatabase',
user: 'myUser',
host: 'localhost',
password: 'password',
port: PORT,
ssl: {
rejectUnauthorized: false
}
},
server: {
host: '127.0.0.1',
port: 'PORT2'
}
}
module.exports = config;
and in index.js I require that like
var env = process.env.NODE_ENV || 'development';
const config = require('./config')[env];
const knexDB = knex({
client: config.client,
connection: {
database: config.database,
user: config.user,
host: config.host,
password: config.password,
port: config.port,
ssl: {
rejectUnauthorized: false
}
}
});
But in the config file. IntelliSense recommends changing module.exports to ES export which I don't want to do and keep the app CommonJS. also, config object in index.js I have this error :
Property 'host' does not exist on type '{ development: { client: string; connection: { database: string; user: string; host: string; password: string; port: number; ssl: { rejectUnauthorized: boolean; }; }; server: { host: string; port: string; }; }; production: { ...; }; }'.ts(2339)
How can I export config from config.js?
You're getting the wrong property of config. It must be config.development.host . give up on the vscode requesting a CommonJS module.leave it alone. You also have 2 options more to configure your constant data.
yarn add dotenv
npm install config
Check config file you Db details is inside config.development.connection but you are reading it from config.
const knexDB = knex({
client: config.development.client,
connection: {
database: config.development.connection.database,
user: config.development.connection.user,
host: config.development.connection.host,
password: config.development.connection.password,
port: config.development.connection.port,
ssl: {
rejectUnauthorized: false
}
}
But instead of this use config or env
well, I found a way to work around it. I removed connection from development and it worked! just mention I used config.connection.client and config.development.connection.client or other variables in the connection but still not working in the index.js.
so it looks like
const config = {
development: {
client: 'pg',
database: 'myDatabase',
user: 'myUser',
host: 'localhost',
password: 'password',
port: PORT,
ssl: {
rejectUnauthorized: false
}
server: {
host: '127.0.0.1',
port: 'PORT2'
}
}
module.exports = config;
and in index.js I access that like
const configure = require('./config.js')[env];
const knexDB = knex({
client: configure.client,
connection: {
database: configure.database,
user: configure.user,
host: configure.host,
password: configure.password,
port: configure.port,
ssl: {
rejectUnauthorized: false
}
}
});
thanks for everyone for thier contribution.

Heroku with Strapi, Application is not using production database

I've deployed my app to Heroku. It gives an Application Error message upon visit.
The logs gave me this:
[2021-02-15T01:04:05.882Z] debug ⛔️ Server wasn't able to start properly.
[2021-02-15T01:04:05.883Z] error Error: connect ECONNREFUSED 127.0.0.1:5432
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1146:16)
Which according to my guess, is that its trying to use local database. I think the app is not using the database.js located in config/env/production. The application runs fine with heroku local.
Below is the database.js I set for production env:
const parse = require("pg-connection-string").parse;
const config = parse(process.env.DATABASE_URL);
module.exports = ({ env }) => ({
defaultConnection: "default",
connections: {
default: {
connector: "bookshelf",
settings: {
client: "postgres",
host: config.host,
port: config.port,
database: config.database,
username: config.user,
password: config.password,
ssl: {
rejectUnauthorized: false,
},
},
options: {
ssl: true,
},
},
},
});
Creating and printing the config var on heroku console results in expected values.
For some reason the deployment method in the strapi docs to heroku does not seem to work when you initially have set up your local database as Postgres.
I had the same problem as you and I fixed it using the NODE_ENV env variable.
Instead of creating a new production database config file in ./config/production/database.js you can simply extend the config file in ./config/database.js with the prod config and decide based on what NODE_ENV is set which one to return.
As example:
module.exports = ({ env }) => {
const parse = require("pg-connection-string").parse;
const config = parse(env("DATABASE_URL", "127.0.0.1"));
const devConfig = {
client: "postgres",
connection: {
host: env("DATABASE_HOST", "127.0.0.1"),
port: env.int("DATABASE_PORT", 5432),
database: env("DATABASE_NAME", "db_name"),
user: env("DATABASE_USERNAME", "root"),
password: env("LOCAL_DB_PASSWORD"),
ssl: env.bool("DATABASE_SSL", false),
},
};
const prodConfig = {
client: "postgres",
connection: {
host: config.host,
port: config.port,
database: config.database,
user: config.user,
password: config.password,
ssl: {
rejectUnauthorized: false,
},
},
debug: false,
};
return
env("NODE_ENV", "development") === "production" ? prodConfig : devConfig
};

How to work with more than one sequelize DB connection in NestJS

I am using the example from the NestJS Documentation on how to setup the Sequelize DB connection. How can I setup connections to more than two databases using Sequelize and TypeScript for NestJS.
You can just setup multiple Sequelize connections in your databaseProviders:
export const databaseProviders = [
{
provide: 'SequelizeCatToken',
useFactory: async () => {
const sequelize = new Sequelize({
dialect: 'mysql',
host: 'localhost',
port: 3306,
username: 'catroot',
password: 'catpassword',
database: 'cats',
});
sequelize.addModels([Cat]);
await sequelize.sync();
return sequelize;
},
},
{
provide: 'SequelizeDogToken',
useFactory: async () => {
const sequelize = new Sequelize({
dialect: 'mysql',
host: 'localhost',
port: 3306,
username: 'doogroot',
password: 'dogpassword',
database: 'dogs',
});
sequelize.addModels([Dog]);
await sequelize.sync();
return sequelize;
},
},
];
You must use name for the connection, its mandatory.
const defaultOptions = {
dialect: 'postgres',
port: 5432,
username: 'user',
password: 'password',
database: 'db',
synchronize: true,
};
#Module({
imports: [
SequelizeModule.forRoot({
...defaultOptions,
host: 'user_db_host',
models: [User],
}),
SequelizeModule.forRoot({
...defaultOptions,
name: 'albumsConnection',
host: 'album_db_host',
models: [Album],
}),
],
})
export class AppModule {}
Here is the documentation in Nest

How to export database connection string node / node.js

I am trying to turn the following database connection string into a module:
require('dotenv').load();
var knex = require('knex')({
client: 'pg',
connection: {
host: 'localhost',
user: process.env.DB_USER,
password: process.env.DB_USER_PASSWORD,
database: process.env.DB_NAME
},
pool: {
min: 0,
max: 7
}
});
So far I tried:
require('dotenv').load();
module.exports = {
knex : require('knex')({
client: 'pg',
connection: {
host: 'localhost',
user: process.env.DB_USER,
password: process.env.DB_USER_PASSWORD,
database: process.env.DB_NAME
},
pool: {
min: 0,
max: 7
}
})
}
In my app.js file:
var knex = require('./models/database');
knex.select().table('users').then(function(result) {
result.forEach(function(value) {
console.log(value.first_name);
});
});
This returns the error 'knex' is undefined. I think the way my module is being exported is incorrect... can someone help?
Thank you!
It's because you're exporting an object containing knex.
Either add knex to the require:
var knex = require('./models/database').knex;
or change your export to
module.exports = require('knex')({ ... })

Categories

Resources