Proper Way to Import Dev Dependencies in Express Application with ESLint - node.js

ESLint has me second-guessing myself today. I am building a simple Express application and it's yelling because I am importing DevDependencies in my app.ts file (yes, I am using Typescript). Basically I want my app to use the npm packages dotenv and morgan only when in development. In production, I will not need either of these packages. So what is the proper way to include these in my project?
Here is my current setup:
Basic app.ts file:
import express from 'express';
import morgan from 'morgan';
import dotenv from 'dotenv';
import helmet from 'helmet';
import compression from 'compression';
import cookieParser from 'cookie-parser';
import https from 'https';
import path from 'path';
import fs from 'fs';
import logger, { stream } from './util/logger';
/**
* Express Application Class
*/
class App {
public app: express.Application;
public port: number;
constructor(port: number) {
this.app = express();
this.port = port;
this.registerMiddleware();
}
/**
* Registers middleware for use
*/
private registerMiddleware(): void {
/** Use dotenv for development env variables */
if (process.env.NODE_ENV !== 'production') {
dotenv.config();
this.app.use(morgan('dev', { stream }));
}
this.app.use(helmet());
this.app.use(compression());
this.app.use(express.json());
this.app.use(express.urlencoded({ extended: false }));
this.app.use(cookieParser());
}
/**
* Starts the Express.js server.
*/
public start(): void {
this.app.listen(this.port, () => {
logger.info(`Server started at https://localhost:${this.port}`);
});
}
/**
* Starts the secure Express.js server.
*/
public startDev(): void {
/** Start a secure Express server for local testing */
https
.createServer(
{
key: fs.readFileSync(path.resolve('server.key')),
cert: fs.readFileSync(path.resolve('server.crt')),
},
this.app
)
.listen(3000, () => {
logger.info(`Secure server started at https://localhost:${this.port}`);
});
}
}
export default App;
Basic server.ts file:
import App from './app';
/**
* Init Express.js server.
*/
const server = new App(3000);
/**
* Start Express.js server.
*/
if (process.env.NODE_ENV !== 'production') {
server.startDev();
} else {
server.start();
}

you can save them as optional dependencies other than dev dependencies using
npm install dotenv morgan --save-optional
Reference

Related

How can I use express app in Supertest request when it gets ready asynchronously?

I have a nodejs application which starts asynchronously because of graphql.
require('custom-env').env();
import { DateTruncAggregateGroupSpecsPlugin } from './subgraphs/db/date_trunc_aggregate_group_specs_plugin';
import PgAggregatesPlugin from "#graphile/pg-aggregates";
import FederationPlugin from "#graphile/federation";
import ConnectionFilterPlugin from "postgraphile-plugin-connection-filter";
const PostGraphileDerivedFieldPlugin = require("postgraphile-plugin-derived-field");
import express from "express";
import { ApolloServer, gql } from "apollo-server-express";
const { makeSchemaAndPlugin } = require("postgraphile-apollo-server");
import pg from 'pg';
import { makeExtendSchemaPlugin } from "graphile-utils";
import { readFileSync } from 'fs';
import { resolve } from 'path';
import resolvers from './resolvers';
export let app = express();
export let server: any;
const { PORT, NODE_ENV, SCHEMA, DATABASE_URL } = process.env;
async function main() {
const { schema, plugin } = await makeSchemaAndPlugin(
new pg.Pool({
connectionString: DATABASE_URL
}),
SCHEMA,
{
subscriptions: false,
appendPlugins: [
FederationPlugin,
ConnectionFilterPlugin,
PostGraphileDerivedFieldPlugin,
PgAggregatesPlugin,
DateTruncAggregateGroupSpecsPlugin,
makeExtendSchemaPlugin((build) => ({
typeDefs: gql(readFileSync(resolve(__dirname, '../graphs/custom.graphql'), { encoding: 'utf-8' })),
resolvers
}))
],
graphileBuildOptions: {
connectionFilterRelations: true
}
}
);
const graphql = new ApolloServer({
debug: false,
schema,
plugins: [plugin],
introspection: true
});
await graphql.start();
graphql.applyMiddleware({
app,
path: '/graphql'
});
server = this.app.listen(PORT, () => console.info(`🚀 Running on PORT ${PORT} 🚀`));
}
main();
The above is my express server that adds graphql to it.
As you can see, the starting of the server is asynchronous.
Now I am using supertest to test APIs end-to-end. Supertest requires app to be passed in.
I need server to start before all tests in my project and tests to be able to use app for supertest reuqest.
How do I do that. With regualar server it is easy as starting of server is not asynchronous, so my app is ready to use by tests. But not in this case. How do I carry out supertest requests.

How can i import additional files into server.js using sapper?

In my sapper app, i try to import a file into the server.js file like this:
import sirv from 'sirv';
import polka from 'polka';
import compression from 'compression';
import * as sapper from '#sapper/server';
const { PORT, NODE_ENV } = process.env;
const dev = NODE_ENV === 'development';
const pushController = require('./backend/controllers/push');
polka()
.use(
compression({ threshold: 0 }),
sirv('static', { dev }),
sapper.middleware()
)
.post('/something/route', pushController.subscribe)
.listen(PORT, err => {
if (err) console.log('error', err);
});
But i always get the Error on console:
Error: Cannot find module './backend/controllers/push
my root folder looks like this:
- src
- backend
- controllers
- push.js
- client.js
- server.js
- service-worker.js
- template.html
I am using sapper with the default rollup config. Could the error therefore be related to rollup? How can I fix it?
A quick test shows it's ok with your structure. Please make sure you have
# push.js
function pushController() {
...
}
...
module.exports = { pushController }
and use import instead of require
# server.js
import { pushController } from './backend/controllers/push'

Cannot use TypeOrm with express "connection "Default" not found

I'm currently having a bad time with typeOrm, I don't know why but express is getting initialized before my connection to the database with typeOrm So I get an error "Connection default not found"
here's the code
Typeorm.config.ts
import {Connection, createConnection} from 'typeorm';
export function connectToDb(): Promise<Connection> {
return createConnection({
type: 'postgres',
url: process.env.TYPEORM_URL,
synchronize: false,
logging: true,
entities: [process.env.TYPEORM_ENTITIES],
migrations: ["../../migrations/*.ts"],
cli: {migrationsDir: process.env.TYPEORM_MIGRATIONS_DIR}
})
}
Room.repository
import {getRepository} from 'typeorm';
import {Room} from '../entities/Room';
const roomRepository = getRepository(Room)
export async function getAllRooms(): Promise<Room[]> {
return await roomRepository.find()
}
this repo is used by my router, here's my app.ts
import * as express from 'express'
import * as bodyParser from 'body-parser';
import * as PassportJs from './passport';
import cors from 'cors';
import logger from './config/logger';
import "reflect-metadata";
import * as dotenv from 'dotenv';
dotenv.config();
import roomRouter from './routes/room.route';
import {connectToDb} from './config/typeorm.config';
const passport = PassportJs.initPassport();
async function main(): Promise<void> {
logger.info('connecting to database...')
await connectToDb()
logger.info('connected to database')
const app = express();
app.use(bodyParser.json());
app.use(passport.initialize());
app.use(cors());
app.use(roomRouter);
app.listen(3000, () => {
logger.info(`API is running on port ${3000}`);
});
}
main().catch(error => {
logger.error(error)
process.exit(1)
})
Can you help me?
Thank
From the code snippets you have share, I guess const roomRepository = getRepository(Room) is being called before the await connectToDb(). Creating a repo needs connection.

React JS + Apollo client query error: “Network error: Failed to fetch” . when call from mobile phone

I have an test application running in a EC2 in Amazon. Its a react app, with Apollo, GraphQl and Sequelize. It works perfect through google chrome of my notebook, but when I open the page from a Mobile Phone with Android this error apears
Error Network error: Failed to fetch
localhost:9000/graphql:1 Failed to load resource: net::ERR_CONNECTION_REFUSED
Version of "react-apollo": "^2.5.6"
My Client index
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import {RootSession} from './App';
import * as serviceWorker from './serviceWorker';
import ApolloClient, { InMemoryCache } from 'apollo-boost';
import { ApolloProvider } from 'react-apollo';
const client = new ApolloClient({
uri: "http://localhost:9000/graphql",
fetchOptions:{
credentials: 'include'
},
request: operation =>{
const token = localStorage.getItem('token');
operation.setContext({
headers:{
authorization:token ? token : null,
}
})
},
cache: new InMemoryCache({
addTypename:false
}),
onError: ({networkError,graphQLErrors,response,operation,forward})=>{
if (networkError){
console.log("network",networkError) ;
}
if (graphQLErrors){
for(let err of graphQLErrors){
switch (err.extensions.code){
case 'UNAUTHENTICATED':
localStorage.removeItem('token');
}
}
}
}
});
ReactDOM.render(
<ApolloProvider client={client}>
<RootSession />
</ApolloProvider>,
document.getElementById('root'));
serviceWorker.unregister();
My Server Index
import express from 'express';
import { ApolloServer, AuthenticationError } from 'apollo-server-express';
import { typeDefs } from './data/schema';
import { resolvers } from './data/resolvers';
import jwt from 'jsonwebtoken';
import dotenv from 'dotenv';
import db from "./models";
dotenv.config({path:'variables.env'});
const app = express();
//const cors = require('cors');
//app.use(cors());
const addToken = async (req) =>{
}
const server= new ApolloServer({
typeDefs,
resolvers,
context:async ({req})=>{
const token = req.headers['authorization'];
let currentUser = null;
if (token !== 'null' && token !== 'undefined' && token !== '' && token !== null && token !== undefined){
try{
currentUser = await jwt.verify(token,process.env.SECRET);
req.currentUser = currentUser;
}catch (err){
throw new AuthenticationError('Your session expired. Sign in again.');
}
}
return {user:currentUser,db} ;
}
});
server.applyMiddleware({app});
app.listen({port:9000},()=> console.log(`Server Corriendo http://localhost:9000${server.graphqlPath}`));
In my server index, I also tried
const cors = require('cors');
app.use(cors());
but I dont have luck
Im Serving the Client with serve -s build (serve npm package)
Im Serving the Server with npm start
What about, that this line could break in a mobile phone? (localhost)
const client = new ApolloClient({
uri: "http://localhost:9000/graphql",
I believe the problem is that you are using localhost as your server URL. That works when your browser is running on the same machine that is hosting the servers, but that's not the case anymore when you are running the client on a mobile device. Try using the local or public IP of the machine being used to host the server in your client URL, like http://192.168.0.8:9000/.
This answer has an explanation for how to get your local IP address on linux: https://stackoverflow.com/a/13322549/11804768

How to disable ssl3 that used by express + mongodb

I have a troubles with express.js it's trying to use ssl3 but I didn't use it anywhere. I see next error then running the server:
(node:7920) [DEP0026] DeprecationWarning: util.print is deprecated.
Use console.log instead. Error: 4776:error:1408F10B:SSL
routines:ssl3_get_record:wrong version
number:openssl\ssl\record\ssl3_record.c:252:
The server.js file looks like this:
// import npm modules
import fs from 'fs';
import path from 'path';
import express from 'express';
import bodyParser from 'body-parser';
import cors from 'cors';
import winston from 'winston';
import compression from 'compression';
import expressWinston from 'express-winston';
import winstonPapertrail from 'winston-papertrail';
import jwt from 'express-jwt';
import http from 'http';
// import custom configuration and utilities
import config from './config';
import logger from './utils/logger';
import db from './utils/db';
import routes from './routes';
// initialize the api
const api = express();
// initialize middleware
api.use(cors());
api.use(compression());
api.use(bodyParser.urlencoded({ extended: true }));
api.use(bodyParser.json());
// ignore authentication on the following routes
api.use(
jwt({ secret: config.jwt.secret }).unless({
path: [
'/',
'/auth/signup',
'/auth/login',
'/auth/forgot-password',
'/auth/reset-password',
],
}),
);
// throw an error if a jwt is not passed in the request
api.use((err, req, res, next) => {
if (err.name === 'UnauthorizedError') {
res.status(401).send('Missing authentication credentials.');
}
});
// initialize our logger (in our case, winston + papertrail)
api.use(
expressWinston.logger({
transports: [
new winston.transports.Papertrail({
host: config.logger.host,
port: config.logger.port,
level: 'error',
}),
],
meta: true,
}),
);
// listen on the designated port found in the configuration
api.listen(config.server.port, err => {
if (err) {
logger.error(err);
process.exit(1);
}
// require the database library (which instantiates a connection to mongodb)
db();
// loop through all routes and dynamically require them – passing api
Object.entries(routes).forEach(([ key, route ]) => {
route(api);
});
// output the status of the api in the terminal
logger.info(`API is now running on port ${config.server.port} in ${config.env} mode`);
});
export default api;
├───dist
└───src
├───config
├───controllers
├───models
├───routes
└───utils
How can I solve this problem? I wont use ssl right now. Thanks

Resources