First, setting up the file tsconfig.json
to compile the typescript files into javascript files.
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "ESNext",
"noImplicitAny": false,
"experimentalDecorators": true,
"allowJs": true,
"emitDecoratorMetadata": true,
"resolveJsonModule": true,
"sourceMap": true,
"rootDir": "./",
"outDir": "./dist",
"types": [
"node"
],
},
"include": [
"./src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
Then, install the typescript compiler tsc
and the typescript node module ts-node
as dev dependencies.
npm i -D nodemon ts-node @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint prettier typescript @types/node
Now, create a file to live reloading in development mode, nodemon.json
:
{
"watch": ["src"],
"ext": "ts",
"ignore": [
"src/**/*.spec.ts",
"src/**/*.test.ts",
"src/**/*.d.ts",
"node_modules"
],
"exec": "ts-node ./src/index.ts"
}
- In case that live reload not working, try to add the following line to the
nodemon.json
file:
"legacyWatch": true
Now, we need create 2 separate files .eslintrc.
and .prettierrc
to configure ESLint and Prettier.
{
"parser": "typescript",
"printWidth": 120,
"singleQuote": true,
"trailingComma": "all",
"useTabs": true
}
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json",
"tsconfigRootDir": "./"
},
"plugins": [
"@typescript-eslint"
],
"rules": {
"no-async-promise-executor": "off",
"no-mixed-spaces-and-tabs": "off"
}
}
"dev": "nodemon",
"start": "node ./dist/src/index.js",
"build": "tsc",
"build:watch": "tsc -w",
"lint": "eslint src/**/*.ts",
"lint:fix": "eslint --fix src/**/*.ts",
"format": "prettier --write \"src/**/*.ts\"",
"format:check": "prettier --check \"src/**/*.ts\""
Create a file logger.ts
with the following content
import winston from 'winston';
import { version } from '../../package.json'; // Import version from package.json
const logger = winston.createLogger({
format: winston.format.combine(
winston.format.timestamp(),
winston.format.colorize(),
winston.format.label({ label: "OUR-Service-" + version }),
winston.format.printf((info) => {
const meta = info[Symbol.for('splat')];
info.message = `${info.timestamp} [${info.label}] ${info.level}: ${info.message}`;
if (meta) info.message += ` - ${JSON.stringify({ metadata: meta })}`;
return info.message;
}),
),
transports: [
new winston.transports.Console(),
new winston.transports.File({
filename: 'logs/error.log',
level: 'error',
format: winston.format.uncolorize(),
}),
new winston.transports.File({
filename: 'logs/combined.log',
format: winston.format.uncolorize(),
}),
],
exceptionHandlers: [
new winston.transports.File({
filename: 'logs/exceptions.log',
}),
],
exitOnError: false,
});
export default logger;
In our index.ts
or entrypoint file of the application, at the end of file, add the following code, to replace all console.*
by the new implementation
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-explicit-any
console.log = (...args: any[]) => logger.info.call(logger, ...args);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-explicit-any
console.error = (...args: any[]) => logger.error.call(logger, ...args);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-explicit-any
console.warn = (...args: any[]) => logger.warn.call(logger, ...args);