1) node.js download,
2) Create directory for your project,
3) npm init,
4) in package.json
"main": "dist/index.js",
"scripts": {
"build": "tsc",
"start": "node ."
}
5) npm install --save-dev typescript,
6) in tsconfig.json
{
"compilerOptions": {
"esModuleInterop": true,
"outDir": "dist",
"baseUrl": "."
}
}
8) npm install express,
9) npm install @types/express,
10) create src folder,
11) create src/index.ts with code below:
import express from 'express'
const app = express();
const port = 5000;
app.get('/', (request, response) => {
response.send('Hello world!');
});
app.listen(port, () => console.log(`Running on port ${port}`));
13) npm run build,
14) npm run start,
15) localhost:5000
1) in tsconfig.json add: "sourceMap": true
2) int package.json add: "prestart": "npm run build",
3) In IntelliJ IDEA in Run/Debug Configurations choose: "npm" and add script
4) npm i ts-node-dev --save-dev
5) int package.json add: "server:watch": "ts-node-dev --respawn --transpile-only src/index.ts"
6) add IntelliJ IDEA npm for "server:watch" script
7) npm install dotenv
8) in index.ts add: dotenv.config();
9) create .env file in root dir of your project and add text below in .env file:
PORT = 5000
const port = process.env.PORT;
1) npm install log4js
2) in index.ts file:
import log4js from 'log4js';
...
const logger = log4js.getLogger();
logger.level = process.env.LOG_LEVEL;
...
4) in .env file: LOG_LEVEL=error
5) in index.ts file:
...
logger.info('log4js log info');
logger.debug('log4js log debug');
logger.error('log4js log error');
...
6) npm install eslint --save-dev
7) eslint --init
8) "prebuild": "npm run lint"
9) "lint:fix": "eslint --cache --ext .ts . --fix",
10) "lint": "eslint --cache --ext .ts .",
!!! --cache (only changed), .
11) IntelliJ IDEA -- file -- setting -- eslint -- automatic
12) "rules": {
"semi": ["error", "always"]
}
1) npm install routing-controllers
2) npm install reflect-metadata
3) npm install express body-parser multer
4) npm install class-transformer class-validator
5) tsconfig.json
"compilerOptions": {
...
"emitDecoratorMetadata": true,
"experimentalDecorators": true
...
}
6) in index.ts
// const app = express();
// logger.info('log4js log info');
// logger.debug('log4js log debug');
// logger.error('log4js log error');
// app.get('/', (request, response) => {
// response.send('Hello world2!');
// });
7) in index.ts
import { createExpressServer } from 'routing-controllers';
import { UserController } from './UserController';
const app = createExpressServer({
controllers: [UserController], // we specify controllers we want to use
});
8) controller/user-controller.ts
import { Controller, Get, Param } from 'routing-controllers';
import 'reflect-metadata';
@Controller()
export class UserController {
@Get('/users/:id')
getOne (@Param('id') id: number) {
return 'This action returns user #' + id;
}
}
9) http://localhost:3001/users/1
1) middleware -- middleware.ts
2) middleware.ts
export function loggingBefore (request: any, response: any, next?: (err?: any) => any): any {
console.log('do something Before...');
next();
}
export function loggingAfter (request: any, response: any, next?: (err?: any) => any): any {
console.log('do something After...');
next();
}
3) user-controller.ts in class
@UseBefore(loggingBefore)
@UseAfter(loggingAfter)
console.log('do something in GET function...');
4) user-controller.ts in function
@UseBefore(loggingBefore)
@UseAfter(loggingAfter)
5) user-controller.ts in function
@UseInterceptor(function (action: Action, content: any) {
console.log('change response...');
return content;
})
6) npm install express-http-context
7) index.ts
const app: Express = express();
app.use(bodyParser.json());
app.use(httpContext.middleware);
useExpressServer(app, {
controllers: [UserController]
});
app.use((req, res, next) => {
httpContext.ns.bindEmitter(req);
httpContext.ns.bindEmitter(res);
});
8) middleware.ts loggingBefore
import httpContext from 'express-http-context';
console.log('set traceId = 123');
httpContext.set('traceId', 123);
9) middleware.ts loggingAfter
console.log(`tracedId = ${httpContext.get('traceId')}`);
1) in user-controller.ts add:
...
@Post('/users/:id')
@OnUndefined(204)
postOne (@Param('id') id: number, @Body() info: any) {
console.log(JSON.stringify(info));
}
...
2) in postman
http://localhost:3001/users/1
{
"country":"Russia",
"city":"SPb"
}
3) model -- info.ts
4)
import { IsDefined } from 'class-validator';
export class Info {
@IsDefined()
country: string;
@IsDefined()
city: string;
}
8) postOne (@Param('id') id: number, @Body() info: Info) {
9) middleware -- global-error-handler.ts
10)
import { ExpressErrorMiddlewareInterface, Middleware } from 'routing-controllers';
@Middleware({ type: 'after' })
export class GlobalErrorHandler implements ExpressErrorMiddlewareInterface {
error (error: any, request: any, response: any, next: () => any) {
response.send({ ERROR: error });
next();
}
}
11)
useExpressServer(app, {
controllers: [UserController], // we specify controllers we want to use
middlewares: [GlobalErrorHandler],
defaultErrorHandler: false
});
1) npm install swagger-ui-express
2) tsconfig.json -- "resolveJsonModule": true
3) src -- swagger -- openapi.json
4) index.ts
import swaggerUi from 'swagger-ui-express';
import * as swaggerDocument from '../src/swagger/openapi.json';
...
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
5) change port to 3000
in .env file set PORT=3000
6) npm install cors
7) npm install @types/cors
8) in index.ts
import cors from 'cors';
...
app.use(cors() as RequestHandler);
...
9) Swagger Editor (example for test project)
openapi
openapi: 3.0.1
info:
title: test API
version: v1
servers:
- url: 'http://localhost:3000'
tags:
- name: API functions
description: >-
API functions of our application
paths:
/users/{id}:
get:
summary: returns simple answer from get
tags:
- API functions
parameters:
- name: id
in: path
required: true
description: simple parameter
schema:
type : string
example: '1'
description: parameter id just for test
responses:
'200': #status code
description: OK
content:
document:
schema:
type: string
example: some text
post:
summary: returns simple answer from post
tags:
- API functions
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Info'
example:
country: Russia
city: Spb
parameters:
- name: id
in: path
required: true
description: simple parameter
schema:
type : string
example: '1'
description: parameter id just for test
responses:
'204': #status code
description: OK
components:
schemas:
Info:
type: object
properties:
country:
type: string
city:
type: string
0) in global-error-handler.ts
response.status(error.statusCode || error.httpCode).json(error);
next();
1) npm install --save-dev jest
2) npm i -D ts-jest @types/jest
3) npm i -D ts-jest
4) package.json --
{
...
scripts {
...
"test:unit": "jest --config=jest.config.js",
},
...
}
5) create jest.config.js with code below:
process.env.NODE_ENV = 'UNITTEST';
module.exports = {
clearMocks: true,
collectCoverage: true,
collectCoverageFrom: [
'./src/**/*.ts'
],
coverageDirectory: '<'rootDir>/test/coverage',
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
preset: 'ts-jest'
};
6) .eslintignore
*.js
node_modules
dist
coverage
}
7) .eslintrc.json
{
...
"env": {
"jest": true
}
...
}
8) test -- controller -- user-controller.test.ts
describe('UserController', () => {
afterEach(() => {
jest.restoreAllMocks();
});
it('postOne', () => {
const userController = new UserController();
const testBody = {
city: 'SPb'
};
const res = userController.postOne(1, testBody as Info);
expect(res).toBeUndefined();
});
}
9) in IDEA
add script - test:unit
set in environment - NODE_ENV=UNITTEST
10) Simple variant of jest.config.js for IDEA:
process.env.NODE_ENV = 'UNITTEST';
module.exports = {
clearMocks: true,
collectCoverage: false,
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
preset: 'ts-jest'
};
11) npm i -D supertest @types/supertest
12) in user-controller.test.ts
...
let server;
...
beforeAll(async () => {
server = express();
server.use(bodyParser.json());
useExpressServer(server, {
controllers: [UserController], // we specify controllers we want to use
middlewares: [GlobalErrorHandler],
defaultErrorHandler: false
});
});
...
it('postOne with validations', done => {
request(server)
.post('/users/1')
.send({
country: 'Russia',
city: 'SPb'
} as Info)
.expect(204)
.end((err, res) => {
if (err) throw new Error(JSON.stringify(res.body));
done();
});
});
1) npm install config
2) npm install @types/config
3) config
4) default.yaml PORT: 3000
DEV.yaml PORT: 3001
LOCAL.yaml PORT: 3002
5) index.ts
// const port = process.env.PORT;
const port = config.get('PORT');
6) IDEA server:watch -- Environment
NODE_ENV=DEV
NODE_ENV=LOCAL
-- packages:
husky - коммиты в гит
semantic-release - формат коммитов и контроль версий
pretty-quick - запускает prettier на измененных файлах
prettier - формат кода
eslint-config-prettier - разрешает конфликты между eslint и prettier
eslint-plugin-prettier - запускает prettier как правила eslint
mock-socket - мок для вебсокета
jest-websocket-mock - тестирование вебсокета
jest-sonar-reporter - конвертр из формата jest в формат sonar
jest-mock-extended - мок объектов и интерфейсов
ws - вебсокет
typescript-string-operations - String.format
lodash - библиотека дополнительных функций для js
http-status-codes - константы для HTTP статусов
moment - библиотека работы со временем в js
ncp - копирование файлов
js-yaml - загрузка yaml файлов
mongodb - функции для работы с Mongo
migrate-mongo - миграция для Mongo
log-timestamp - запись даты в лог
axios - HTTP клиент
applicationinsights - интеграция с Azure Application Insights
VK объявляет о приобретении 40% компании Intickets.ru (Интикетс). Это облачный сервис для контроля и управления продажей билетов на мероприятия. Сумма…
OpenAI готовится запустить собственную поисковую систему на базе ChatGPT. Информацию об этом публикуют западные издания. Ожидается, что новый поисковик может…
Центр управления связью общего пользования (ЦМУ ССОП) Роскомнадзора рекомендовал компаниям из реестра провайдеров ограничить доступ поисковых ботов к информации на российских сайтах.…
Apple возобновила переговоры с OpenAI о возможности внедрения ИИ-технологий в iOS 18, на основе данной операционной системы будут работать новые…
Конкурсный управляющий российской «дочки» Google подготовил 23 иска к участникам рекламного рынка. Общая сумма исков составляет 16 млрд рублей –…
Google завершил обновление основного алгоритма March 2024 Core Update. Раскатка обновлений была завершена 19 апреля, но сообщил об этом поисковик…