├── .gitignore
├── README.md
├── docker-compose.yml
├── docker
├── Dockerfile.dev
├── env-app-sample
├── env-sample
└── rabbitmq
│ └── enabled_plugins
└── src
├── app
├── .gitignore
├── .prettierrc
├── README.md
├── certs
│ ├── server.crt
│ └── server.key
├── nodemon-debug.json
├── nodemon.json
├── package-lock.json
├── package.json
├── src
│ ├── app.module.ts
│ ├── config
│ │ └── global.env.ts
│ ├── controllers
│ │ └── contrived.controller.ts
│ ├── event-bus-transport
│ │ ├── abstract.publisher.ts
│ │ ├── event.bus.transport.module.ts
│ │ ├── event.bus.transport.ts
│ │ ├── interface
│ │ │ └── event.with.transport.interface.ts
│ │ ├── publishers
│ │ │ ├── rabbit.publisher.ts
│ │ │ └── redis.publisher.ts
│ │ └── transport.enum.ts
│ ├── events
│ │ └── contrived
│ │ │ ├── contrived.event.handler.ts
│ │ │ └── contrived.event.ts
│ └── main.ts
├── tsconfig.build.json
├── tsconfig.json
└── tslint.json
├── event-service-rabbit
├── .gitignore
├── .prettierrc
├── README.md
├── nodemon-debug.json
├── nodemon.json
├── package-lock.json
├── package.json
├── src
│ ├── app.module.ts
│ ├── config
│ │ └── global.env.ts
│ ├── events
│ │ └── contrived
│ │ │ ├── contrived.event.handler.ts
│ │ │ └── contrived.event.ts
│ ├── main.ts
│ ├── pipes
│ │ └── json.parse.pipe.ts
│ └── services
│ │ └── event.subscriber.service.ts
├── tsconfig.build.json
├── tsconfig.json
└── tslint.json
└── event-service-redis
├── .gitignore
├── .prettierrc
├── README.md
├── nodemon-debug.json
├── nodemon.json
├── package-lock.json
├── package.json
├── src
├── app.module.ts
├── config
│ └── global.env.ts
├── events
│ └── contrived
│ │ ├── contrived.event.handler.ts
│ │ └── contrived.event.ts
├── main.ts
├── pipes
│ └── json.parse.pipe.ts
└── services
│ └── event.subscriber.service.ts
├── tsconfig.build.json
├── tsconfig.json
└── tslint.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Don't check auto-generated stuff into git
2 | coverage
3 | build
4 | src/node_modules
5 | storage
6 | stats.json
7 |
8 | # Cruft
9 | .DS_Store
10 | npm-debug.log
11 | .idea
12 | .awcache
13 | .env
14 | .env.app
15 | .env.docker
16 | .vscode
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # nestjs-external-eventbus
2 | [done nestjs module](https://github.com/sergey-telpuk/nestjs-transport-eventbus)
3 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.7'
2 |
3 | services:
4 |
5 | app:
6 | container_name: nestjs-app
7 | restart: always
8 | build:
9 | context: ./docker
10 | dockerfile: Dockerfile.dev
11 | command: npm run start
12 | tty: true
13 | ports:
14 | - 3000:3000
15 | volumes:
16 | - ./src/app:/app
17 | links:
18 | - rabbitmq
19 | - redis
20 | depends_on:
21 | - rabbitmq
22 | - redis
23 |
24 | event-service-rabbit:
25 | container_name: nestjs-event-service-rabbit
26 | restart: always
27 | build:
28 | context: ./docker
29 | dockerfile: Dockerfile.dev
30 | command: npm run start
31 | tty: true
32 | volumes:
33 | - ./src/event-service-rabbit:/app
34 | links:
35 | - rabbitmq
36 | depends_on:
37 | - rabbitmq
38 |
39 | event-service-redis:
40 | container_name: nestjs-event-service-redis
41 | restart: always
42 | build:
43 | context: ./docker
44 | dockerfile: Dockerfile.dev
45 | command: npm run start
46 | tty: true
47 | volumes:
48 | - ./src/event-service-redis:/app
49 | links:
50 | - redis
51 | depends_on:
52 | - redis
53 |
54 | redis:
55 | image: redis:latest
56 | restart: always
57 | command: redis-server --requirepass password123
58 | environment:
59 | - REDIS_PASSWORD=password123
60 |
61 | rabbitmq:
62 | image: rabbitmq:3-management
63 | restart: always
64 | environment:
65 | RABBITMQ_ERLANG_COOKIE: SWQOKODSQALRPCLNMEQG
66 | RABBITMQ_DEFAULT_USER: rabbit
67 | RABBITMQ_DEFAULT_PASS: rabbit
68 | volumes:
69 | - ./docker/rabbitmq/enabled_plugins:/etc/rabbitmq/enabled_plugins
--------------------------------------------------------------------------------
/docker/Dockerfile.dev:
--------------------------------------------------------------------------------
1 | FROM node:latest
2 |
3 |
4 | #RUN echo fs.inotify.max_user_watches=524288 | tee -a /etc/sysctl.conf && sysctl -p
5 |
6 | WORKDIR /app
7 |
8 |
9 |
10 | RUN npm install nodemon -g
11 |
12 | EXPOSE 9229
13 |
14 | CMD ["node","--v"]
15 |
--------------------------------------------------------------------------------
/docker/env-app-sample:
--------------------------------------------------------------------------------
1 | ### RABBITMQ_
2 | RABBITMQ_URL=amqp://rabbit:rabbit@rabbitmq:5672
3 | RABBITMQ_QUEUE=event_service_queue
4 |
5 | ### EVENT_SERVICE
6 | EVENT_SERVICE_PATTERN=event_bus
--------------------------------------------------------------------------------
/docker/env-sample:
--------------------------------------------------------------------------------
1 | ### Mode of running
2 | MODE_RUNNING=dev #dev|debug
3 |
4 | ### Rabbit
5 | RABBITMQ_PORT=56720
6 | RABBITMQ_USER=rabbit
7 | RABBITMQ_PASSWORD=rabbit
8 | RABBITMQ_PORT_UI=8085
--------------------------------------------------------------------------------
/docker/rabbitmq/enabled_plugins:
--------------------------------------------------------------------------------
1 | [rabbitmq_management, rabbitmq_management_visualiser].
--------------------------------------------------------------------------------
/src/app/.gitignore:
--------------------------------------------------------------------------------
1 | # Don't check auto-generated stuff into git
2 | coverage
3 | build
4 | node_modules
5 | dist
6 | stats.json
7 |
8 | # Cruft
9 | .DS_Store
10 | npm-debug.log
11 | .idea
12 | .env
13 |
--------------------------------------------------------------------------------
/src/app/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "tabWidth": 4,
4 | "semi": true,
5 | "singleQuote": true
6 | }
--------------------------------------------------------------------------------
/src/app/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master
6 | [travis-url]: https://travis-ci.org/nestjs/nest
7 | [linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux
8 | [linux-url]: https://travis-ci.org/nestjs/nest
9 |
10 | A progressive Node.js framework for building efficient and scalable server-side applications, heavily inspired by Angular.
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
26 |
27 | ## Description
28 |
29 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
30 |
31 | ## Installation
32 |
33 | ```bash
34 | $ npm install
35 | ```
36 |
37 | ## Running the app
38 |
39 | ```bash
40 | # development
41 | $ npm run start
42 |
43 | # watch mode
44 | $ npm run start:dev
45 |
46 | # production mode
47 | $ npm run start:prod
48 | ```
49 |
50 | ## Test
51 |
52 | ```bash
53 | # unit tests
54 | $ npm run test
55 |
56 | # e2e tests
57 | $ npm run test:e2e
58 |
59 | # test coverage
60 | $ npm run test:cov
61 | ```
62 |
63 | ## Support
64 |
65 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
66 |
67 | ## Stay in touch
68 |
69 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
70 | - Website - [https://nestjs.com](https://nestjs.com/)
71 | - Twitter - [@nestframework](https://twitter.com/nestframework)
72 |
73 | ## License
74 |
75 | Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE).
76 |
--------------------------------------------------------------------------------
/src/app/certs/server.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICXjCCAcegAwIBAgIJAPoZXCIUDVU9MA0GCSqGSIb3DQEBBQUAMEgxCzAJBgNV
3 | BAYTAlVTMRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQHDAhUU05JRU1BTjER
4 | MA8GA1UECgwIVFNOSUVNQU4wHhcNMTgwNDE0MjMwMTMwWhcNMTkwNDE0MjMwMTMw
5 | WjBIMQswCQYDVQQGEwJVUzETMBEGA1UECAwKU29tZS1TdGF0ZTERMA8GA1UEBwwI
6 | VFNOSUVNQU4xETAPBgNVBAoMCFRTTklFTUFOMIGfMA0GCSqGSIb3DQEBAQUAA4GN
7 | ADCBiQKBgQCprHdYtD8jlBQwuVr5WEpWNb1bnGnmwFq4Ii3zh63Jd+stc3KXJhcJ
8 | ja0WjCAPHcksLBdNcpZAs7t16YhD5eKqrpPyPApcXAxgSg8lc1NcdKsgDvd1u5Dp
9 | HpoO4bYmnFKnEgaKhvPfWxulFWB/O9EjY+qwGwVh3vQwTN5+24ptGwIDAQABo1Aw
10 | TjAdBgNVHQ4EFgQUaDGJYVN2avltLh2WIlzj1ZkzGUkwHwYDVR0jBBgwFoAUaDGJ
11 | YVN2avltLh2WIlzj1ZkzGUkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOB
12 | gQAi2GipMiPG/FBLJaJjxVRccELcbKqViF5Ow3rPpODE8OLdsLn516dPoOBIMxas
13 | kajd9hPYgSgAHg4c60p3dHp19U47cFWOKk8vLdvaJVmDkVblYbCeAda98oR/oCMr
14 | YxWr4GZmxsq9mlnpLkeCocusaXMEZs+Gw1mSu80Hl3ofOQ==
15 | -----END CERTIFICATE-----
--------------------------------------------------------------------------------
/src/app/certs/server.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIICXQIBAAKBgQCprHdYtD8jlBQwuVr5WEpWNb1bnGnmwFq4Ii3zh63Jd+stc3KX
3 | JhcJja0WjCAPHcksLBdNcpZAs7t16YhD5eKqrpPyPApcXAxgSg8lc1NcdKsgDvd1
4 | u5DpHpoO4bYmnFKnEgaKhvPfWxulFWB/O9EjY+qwGwVh3vQwTN5+24ptGwIDAQAB
5 | AoGAVjnQOOL4x0Lkc9JuehK1TFRpE5pMczjDoZm1EnKcDauEd4eY71krEe7OzIuP
6 | az8u0eTiPriBxQXRuV1ho2e7JUBASblX4prmWBLJOEdRMawd5Ky4FMR3AlAtKOYE
7 | +GzEP+CtuS7qYukyHsM+fy6PQFhw0reJ8ZED+hmSC+BYMKECQQDWvZ5BwjxoOqoQ
8 | H0MC/MNZiWInI3NWcHiUG99eBYvD6T7RWYBQdMN5gjbuFiuuMwfdjR/Xie9AiDPo
9 | s+QMg4PrAkEAykYm5CurbxSxRnLPCqRNIzisHzYls+hgMLffWaVBkXughrvsDb7u
10 | ePBzKYxVxi/qArWQwLTF6RG60DEcnanfkQJBANC6YxecC0dsrl0ZZfODaQag6U0N
11 | wlBk5m9gYE9tqJr3Ht4y1uxdcpurHGV0G2UpqR2KzUaehnX9bidko+gd9Z0CQQDJ
12 | Ok0KhV9BXMaXnTPYFGgg+ApT6pxLhIvdK69pEXxPbTvfjihh7GZ1rlADL3dNePFG
13 | zLY64Bxbp6W/5HvhZdPhAkA/sSS6kOMPCPY+IWnACviVyL10Gq62JQlavhk93vpp
14 | BneessNzgUosn1wBPEzJlrX4l9WNkihht4tCDmyoKkV2
15 | -----END RSA PRIVATE KEY-----
--------------------------------------------------------------------------------
/src/app/nodemon-debug.json:
--------------------------------------------------------------------------------
1 | {
2 | "watch": ["src"],
3 | "ext": "ts",
4 | "ignore": ["src/**/*.spec.ts"],
5 | "exec": "node --inspect-brk=0.0.0.0:9229 -r tsconfig-paths/register -r ts-node/register src/main.ts"
6 | }
--------------------------------------------------------------------------------
/src/app/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "watch": ["dist"],
3 | "ext": "js",
4 | "exec": "node dist/main"
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nest-typescript-starter",
3 | "version": "1.0.0",
4 | "description": "Nest TypeScript starter repository",
5 | "license": "MIT",
6 | "scripts": {
7 | "build": "tsc -p tsconfig.build.json",
8 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
9 | "start": "ts-node -r tsconfig-paths/register src/main.ts",
10 | "start:dev": "concurrently --handle-input \"wait-on dist/main.js && nodemon\" \"tsc -w -p tsconfig.build.json\" ",
11 | "start:debug": "nodemon --config nodemon-debug.json",
12 | "prestart:prod": "rimraf dist && npm run build",
13 | "start:prod": "node dist/main.js",
14 | "lint": "tslint -p tsconfig.json -c tslint.json",
15 | "lint:fix": "tslint -p tsconfig.json -c tslint.json --fix",
16 | "test": "jest --detectOpenHandles --config ./test/jest.json --forceExit",
17 | "test:watch": "jest --watch",
18 | "test:cov": "jest --coverage",
19 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
20 | "test:e2e": "jest --detectOpenHandles --config ./test/e2e/jest-e2e.json --forceExit",
21 | "test:int": "jest --detectOpenHandles --config ./test/int/jest-int.json --forceExit",
22 | "test:unit": "jest --detectOpenHandles --config ./test/unit/jest-unit.json --forceExit",
23 | "console:dev": "ts-node -r tsconfig-paths/register src/cli/cli.module.ts",
24 | "fixtures": "fixtures ./fixtures/entities --config ./fixtures/typeorm.config.ts --debug --sync --require=ts-node/register --require=tsconfig-paths/register"
25 | },
26 | "dependencies": {
27 | "@elastic/elasticsearch": "^7.2.0",
28 | "@grpc/proto-loader": "^0.5.1",
29 | "@nestjs/common": "^6.5.2",
30 | "@nestjs/core": "^6.5.2",
31 | "@nestjs/cqrs": "^6.0.1",
32 | "@nestjs/jwt": "^6.1.1",
33 | "@nestjs/microservices": "^6.5.3",
34 | "@nestjs/passport": "^6.1.0",
35 | "@nestjs/platform-express": "^6.5.2",
36 | "@nestjs/platform-fastify": "^6.5.2",
37 | "@nestjs/typeorm": "^6.1.2",
38 | "@nestjsx/api-version": "^0.1.1",
39 | "@types/elasticsearch": "^5.0.34",
40 | "@types/faker": "^4.1.5",
41 | "@types/fastify-multipart": "^0.7.0",
42 | "@types/fs-extra": "^8.0.0",
43 | "@types/moment-timezone": "^0.5.12",
44 | "@types/multer": "^1.3.7",
45 | "@types/passport-jwt": "^3.0.1",
46 | "activedirectory": "^0.7.2",
47 | "amqp-connection-manager": "^3.0.0",
48 | "amqplib": "^0.5.5",
49 | "chai": "^4.2.0",
50 | "class-transformer": "^0.2.3",
51 | "class-validator": "^0.9.1",
52 | "cloneable-ts": "^1.0.18",
53 | "config": "^3.1.0",
54 | "csvtojson": "^2.0.10",
55 | "faker": "^4.1.0",
56 | "fastify-swagger": "^2.4.0",
57 | "grpc": "^1.22.2",
58 | "moment-timezone": "^0.5.26",
59 | "nestjs-i18n": "^3.0.0",
60 | "nestjs-redis": "^1.2.1",
61 | "npm": "^6.10.3",
62 | "ow": "^0.13.2",
63 | "passport": "^0.4.0",
64 | "passport-http-bearer": "^1.0.1",
65 | "passport-jwt": "^4.0.0",
66 | "pg": "^7.11.0",
67 | "pre-commit": "^1.2.2",
68 | "redis": "^2.8.0",
69 | "reflect-metadata": "0.1.13",
70 | "rimraf": "2.6.3",
71 | "rxjs": "6.5.2"
72 | },
73 | "devDependencies": {
74 | "@nestjs/cli": "^6.5.0",
75 | "@nestjs/swagger": "^3.0.2",
76 | "@nestjs/testing": "6.3.2",
77 | "@types/express": "4.17.0",
78 | "@types/jest": "24.0.15",
79 | "@types/node": "12.0.10",
80 | "@types/supertest": "2.0.7",
81 | "concurrently": "^4.1.0",
82 | "jest": "24.8.0",
83 | "nestjs-console": "^1.1.4",
84 | "nodemon": "1.19.1",
85 | "prettier": "1.18.2",
86 | "supertest": "4.0.2",
87 | "swagger-ui-express": "^4.0.6",
88 | "ts-jest": "24.0.2",
89 | "ts-node": "^8.3.0",
90 | "tsconfig-paths": "3.8.0",
91 | "tslint": "5.18.0",
92 | "typeorm-fixtures-cli": "^1.3.5",
93 | "typescript": "^3.5.3",
94 | "wait-on": "^3.2.0"
95 | },
96 | "jest": {
97 | "moduleFileExtensions": [
98 | "js",
99 | "json",
100 | "ts"
101 | ],
102 | "rootDir": "src",
103 | "testRegex": ".spec.ts$",
104 | "transform": {
105 | "^.+\\.(t|j)s$": "ts-jest"
106 | },
107 | "collectCoverageFrom": [
108 | "**/*.(t|j)s"
109 | ],
110 | "coverageDirectory": "../coverage",
111 | "testEnvironment": "node"
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/app/src/app.module.ts:
--------------------------------------------------------------------------------
1 | import {Module} from '@nestjs/common';
2 | import {ContrivedController} from './controllers/contrived.controller';
3 | import {EventBusTransportModule} from './event-bus-transport/event.bus.transport.module';
4 | import {CqrsModule} from '@nestjs/cqrs';
5 | import {RabbitPublisher} from './event-bus-transport/publishers/rabbit.publisher';
6 | import {ContrivedEventHandler} from './events/contrived/contrived.event.handler';
7 | import {RedisPublisher} from "./event-bus-transport/publishers/redis.publisher";
8 |
9 | @Module({
10 | imports: [
11 | CqrsModule,
12 | EventBusTransportModule.forRoot(
13 | [
14 | RabbitPublisher,
15 | RedisPublisher
16 | ],
17 | [
18 | ContrivedEventHandler,
19 | ]),
20 | ],
21 | controllers: [
22 | ContrivedController,
23 | ],
24 | providers: [
25 |
26 | ],
27 | })
28 | export class AppModule {
29 | }
30 |
--------------------------------------------------------------------------------
/src/app/src/config/global.env.ts:
--------------------------------------------------------------------------------
1 | export const EVENT_SERVICE = {
2 | PATTERN: process.env.EVENT_SERVICE_PATTERN,
3 | };
4 |
5 | export const RABBIT_SERVICE = {
6 | URLS: [
7 | process.env.RABBITMQ_URL,
8 | ],
9 | QUEUE: process.env.RABBITMQ_QUEUE,
10 | QUEUE_OPTIONS: {
11 | durable: true,
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/src/app/src/controllers/contrived.controller.ts:
--------------------------------------------------------------------------------
1 | import {Controller, Get} from '@nestjs/common';
2 | import {EventBusTransport} from '../event-bus-transport/event.bus.transport';
3 | import {ContrivedEvent} from '../events/contrived/contrived.event';
4 |
5 | @Controller('/')
6 | export class ContrivedController {
7 |
8 | constructor(
9 | readonly eventBusTransport: EventBusTransport,
10 | ) {}
11 |
12 | @Get('/contrived')
13 | contrived() {
14 | this.eventBusTransport.publish(new ContrivedEvent());
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/app/src/event-bus-transport/abstract.publisher.ts:
--------------------------------------------------------------------------------
1 | import {IEvent, IEventPublisher} from '@nestjs/cqrs';
2 | import {Transport} from './transport.enum';
3 | import {Injectable, Logger} from '@nestjs/common';
4 |
5 | @Injectable()
6 | export abstract class AbstractPublisher implements IEventPublisher {
7 | abstract TRANSPORT: Transport;
8 | abstract PATTERN: string;
9 |
10 | constructor(
11 | protected readonly log: Logger,
12 | ) {
13 |
14 | }
15 |
16 | publish(event: T): void {
17 |
18 | const data = {
19 | payload: event,
20 | event: event.constructor.name,
21 | };
22 |
23 | this.send(this.PATTERN, data);
24 | }
25 |
26 | protected abstract send(pattern: any, data: any): any;
27 | }
28 |
--------------------------------------------------------------------------------
/src/app/src/event-bus-transport/event.bus.transport.module.ts:
--------------------------------------------------------------------------------
1 | import {DynamicModule, Logger, Module} from '@nestjs/common';
2 | import {RabbitPublisher} from './publishers/rabbit.publisher';
3 | import {CqrsModule, EventBus} from '@nestjs/cqrs';
4 | import {EventBusTransport} from './event.bus.transport';
5 | import {DefaultPubSub} from '@nestjs/cqrs/dist/helpers/default-pubsub';
6 | import {ModuleRef} from '@nestjs/core';
7 |
8 | @Module({
9 | imports: [
10 | CqrsModule,
11 | ],
12 | providers: [
13 | RabbitPublisher,
14 | DefaultPubSub,
15 | ],
16 | exports: [],
17 |
18 | })
19 | export class EventBusTransportModule {
20 |
21 | static forRoot(publishers: any[], handlers: any[]): DynamicModule {
22 |
23 | return {
24 | module: EventBusTransportModule,
25 | providers: [
26 | Logger,
27 | ...publishers,
28 | {
29 | provide: EventBusTransport,
30 | useFactory: (eventBus: EventBus, moduleRef: ModuleRef) => {
31 | return new EventBusTransport(
32 | eventBus,
33 | moduleRef,
34 | publishers,
35 | );
36 | },
37 | inject: [EventBus, ModuleRef],
38 | },
39 | ...handlers,
40 | ],
41 | exports: [
42 | EventBusTransport,
43 | ],
44 | };
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/app/src/event-bus-transport/event.bus.transport.ts:
--------------------------------------------------------------------------------
1 | import {EventBus, IEvent} from '@nestjs/cqrs';
2 | import {Injectable} from '@nestjs/common';
3 | import {ModuleRef} from '@nestjs/core';
4 | import {AbstractPublisher} from './abstract.publisher';
5 | import {Transport} from './transport.enum';
6 |
7 | @Injectable()
8 | export class EventBusTransport {
9 |
10 | constructor(
11 | private readonly eventBus: EventBus,
12 | private readonly moduleRef: ModuleRef,
13 | private readonly publishers: any[],
14 | ) {
15 | }
16 |
17 | publish(event: T) {
18 | this.publishViaPublisher(event);
19 | }
20 |
21 | private publishViaPublisher(event: any) {
22 | const transports: [] = event.TRANSPORTS ? event.TRANSPORTS : [];
23 |
24 | delete event.TRANSPORTS;
25 |
26 | // @ts-ignore
27 | if (transports.length === 0 || transports.includes(Transport.DEF)) {
28 | this.eventBus.publish(event);
29 | }
30 |
31 | for (const publisher of this.publishers) {
32 | const pub = this.moduleRef.get(publisher);
33 | // @ts-ignore
34 | if (transports.includes(pub.TRANSPORT)) {
35 | pub.publish(event);
36 | }
37 | }
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/app/src/event-bus-transport/interface/event.with.transport.interface.ts:
--------------------------------------------------------------------------------
1 | import {IEvent} from '@nestjs/cqrs';
2 | import {Transport} from '../transport.enum';
3 |
4 | export interface IEventWithTransport extends IEvent {
5 | TRANSPORTS: Transport[];
6 | }
7 |
--------------------------------------------------------------------------------
/src/app/src/event-bus-transport/publishers/rabbit.publisher.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@nestjs/common';
2 | import {Client, ClientProxy, Transport} from '@nestjs/microservices';
3 | import {AbstractPublisher} from '../abstract.publisher';
4 |
5 | @Injectable()
6 | export class RabbitPublisher extends AbstractPublisher {
7 | TRANSPORT = Transport.RMQ;
8 | PATTERN = 'event_bus';
9 |
10 | @Client({
11 | transport: Transport.RMQ,
12 | options: {
13 | urls: ['amqp://rabbit:rabbit@rabbitmq:5672'],
14 | queue: 'event_service_queue',
15 | queueOptions: {
16 | durable: true,
17 | },
18 | },
19 | })
20 | client: ClientProxy;
21 |
22 | protected async send(pattern: any, data: any) {
23 | try {
24 | await this.client.send(pattern, data).toPromise();
25 | } catch (e) {
26 | this.log.error(e);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/app/src/event-bus-transport/publishers/redis.publisher.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@nestjs/common';
2 | import {Client, ClientProxy, Transport} from '@nestjs/microservices';
3 | import {AbstractPublisher} from '../abstract.publisher';
4 |
5 |
6 | @Injectable()
7 | export class RedisPublisher extends AbstractPublisher {
8 | TRANSPORT = Transport.REDIS;
9 | PATTERN = 'event_bus';
10 |
11 | @Client({
12 | transport: Transport.REDIS,
13 | options: {
14 | url: 'redis://:password123@redis:6379',
15 | },
16 | })
17 | client: ClientProxy;
18 |
19 | protected async send(pattern: any, data: any) {
20 | // try {
21 | await this.client.send(pattern, data).toPromise();
22 | console.log('============');
23 | // } catch (e) {
24 | // this.log.error(e);
25 | // }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/app/src/event-bus-transport/transport.enum.ts:
--------------------------------------------------------------------------------
1 |
2 | export enum Transport {
3 | TCP = 0,
4 | REDIS = 1,
5 | NATS = 2,
6 | MQTT = 3,
7 | GRPC = 4,
8 | RMQ = 5,
9 | DEF = 6,
10 | }
11 |
--------------------------------------------------------------------------------
/src/app/src/events/contrived/contrived.event.handler.ts:
--------------------------------------------------------------------------------
1 | import {EventsHandler, IEventHandler} from '@nestjs/cqrs';
2 | import {ContrivedEvent} from './contrived.event';
3 | import {Logger} from '@nestjs/common';
4 |
5 | @EventsHandler(ContrivedEvent)
6 | export class ContrivedEventHandler implements IEventHandler {
7 | constructor(
8 | private readonly log: Logger,
9 | ) {
10 |
11 | }
12 |
13 | handle(event: ContrivedEvent) {
14 | this.log.verbose('ContrivedEventHandler: event\n');
15 | this.log.log(event);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/app/src/events/contrived/contrived.event.ts:
--------------------------------------------------------------------------------
1 | import {IEventWithTransport} from '../../event-bus-transport/interface/event.with.transport.interface';
2 | import {Transport} from '../../event-bus-transport/transport.enum';
3 |
4 | export class ContrivedEvent implements IEventWithTransport {
5 | TRANSPORTS = [Transport.RMQ, Transport.DEF, Transport.REDIS];
6 |
7 | constructor(
8 | ) {}
9 | }
10 |
--------------------------------------------------------------------------------
/src/app/src/main.ts:
--------------------------------------------------------------------------------
1 | import {NestFactory} from '@nestjs/core';
2 | import {AppModule} from './app.module';
3 | import {INestApplication, Logger, ValidationPipe} from '@nestjs/common';
4 | import fs from 'fs';
5 | import {FastifyAdapter, NestFastifyApplication} from '@nestjs/platform-fastify';
6 | const log = new Logger('app: ');
7 |
8 | (async function bootstrap() {
9 | const fastifyAdapter = new FastifyAdapter({
10 | http2: true,
11 | logger: log,
12 | https: {
13 | allowHTTP1: true, // fallback support for HTTP1
14 | key: fs.readFileSync('/app/certs/server.key'),
15 | cert: fs.readFileSync('/app/certs/server.crt'),
16 | },
17 | });
18 |
19 | const app: INestApplication = await NestFactory.create(
20 | AppModule,
21 | fastifyAdapter,
22 | );
23 | app.enableCors();
24 | app.useGlobalPipes(
25 | new ValidationPipe({
26 | disableErrorMessages: false,
27 | }),
28 | );
29 |
30 | await app.listen(3000, '0.0.0.0');
31 | })();
32 |
--------------------------------------------------------------------------------
/src/app/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": [
4 | "node_modules",
5 | "dist",
6 | "test",
7 | "fixtures",
8 | "grpc",
9 | "cli",
10 | "**/*spec.ts"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/src/app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "esModuleInterop": true,
7 | "emitDecoratorMetadata": true,
8 | "experimentalDecorators": true,
9 | "target": "es6",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "baseUrl": "./",
13 | "incremental": true
14 | },
15 | "exclude": [
16 | "node_modules",
17 | "dist",
18 | "test",
19 | "fixtures",
20 | "grpc"
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/src/app/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultSeverity": "error",
3 | "extends": ["tslint:recommended"],
4 | "jsRules": {
5 | "no-unused-expression": true
6 | },
7 | "rules": {
8 | "quotemark": [true, "single"],
9 | "member-access": [false],
10 | "ordered-imports": [false],
11 | "max-line-length": [true, 150],
12 | "member-ordering": [false],
13 | "interface-name": [false],
14 | "arrow-parens": false,
15 | "object-literal-sort-keys": false
16 | },
17 | "rulesDirectory": []
18 | }
19 |
--------------------------------------------------------------------------------
/src/event-service-rabbit/.gitignore:
--------------------------------------------------------------------------------
1 | # Don't check auto-generated stuff into git
2 | coverage
3 | build
4 | node_modules
5 | dist
6 | stats.json
7 |
8 | # Cruft
9 | .DS_Store
10 | npm-debug.log
11 | .idea
12 | .env
13 |
--------------------------------------------------------------------------------
/src/event-service-rabbit/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "tabWidth": 4,
4 | "semi": true,
5 | "singleQuote": true
6 | }
--------------------------------------------------------------------------------
/src/event-service-rabbit/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master
6 | [travis-url]: https://travis-ci.org/nestjs/nest
7 | [linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux
8 | [linux-url]: https://travis-ci.org/nestjs/nest
9 |
10 | A progressive Node.js framework for building efficient and scalable server-side applications, heavily inspired by Angular.
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
26 |
27 | ## Description
28 |
29 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
30 |
31 | ## Installation
32 |
33 | ```bash
34 | $ npm install
35 | ```
36 |
37 | ## Running the app
38 |
39 | ```bash
40 | # development
41 | $ npm run start
42 |
43 | # watch mode
44 | $ npm run start:dev
45 |
46 | # production mode
47 | $ npm run start:prod
48 | ```
49 |
50 | ## Test
51 |
52 | ```bash
53 | # unit tests
54 | $ npm run test
55 |
56 | # e2e tests
57 | $ npm run test:e2e
58 |
59 | # test coverage
60 | $ npm run test:cov
61 | ```
62 |
63 | ## Support
64 |
65 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
66 |
67 | ## Stay in touch
68 |
69 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
70 | - Website - [https://nestjs.com](https://nestjs.com/)
71 | - Twitter - [@nestframework](https://twitter.com/nestframework)
72 |
73 | ## License
74 |
75 | Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE).
76 |
--------------------------------------------------------------------------------
/src/event-service-rabbit/nodemon-debug.json:
--------------------------------------------------------------------------------
1 | {
2 | "watch": ["src"],
3 | "ext": "ts",
4 | "ignore": ["src/**/*.spec.ts"],
5 | "exec": "node --inspect-brk=0.0.0.0:9229 -r tsconfig-paths/register -r ts-node/register src/main.ts"
6 | }
--------------------------------------------------------------------------------
/src/event-service-rabbit/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "watch": ["dist"],
3 | "ext": "js",
4 | "exec": "node dist/main"
5 | }
6 |
--------------------------------------------------------------------------------
/src/event-service-rabbit/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nest-typescript-starter",
3 | "version": "1.0.0",
4 | "description": "Nest TypeScript starter repository",
5 | "license": "MIT",
6 | "scripts": {
7 | "build": "tsc -p tsconfig.build.json",
8 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
9 | "start": "ts-node -r tsconfig-paths/register src/main.ts",
10 | "start:dev": "concurrently --handle-input \"wait-on dist/main.js && nodemon\" \"tsc -w -p tsconfig.build.json\" ",
11 | "start:debug": "nodemon --config nodemon-debug.json",
12 | "prestart:prod": "rimraf dist && npm run build",
13 | "start:prod": "node dist/main.js",
14 | "lint": "tslint -p tsconfig.json -c tslint.json",
15 | "lint:fix": "tslint -p tsconfig.json -c tslint.json --fix",
16 | "test": "jest --detectOpenHandles --config ./test/jest.json --forceExit",
17 | "test:watch": "jest --watch",
18 | "test:cov": "jest --coverage",
19 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
20 | "test:e2e": "jest --detectOpenHandles --config ./test/e2e/jest-e2e.json --forceExit",
21 | "test:int": "jest --detectOpenHandles --config ./test/int/jest-int.json --forceExit",
22 | "test:unit": "jest --detectOpenHandles --config ./test/unit/jest-unit.json --forceExit",
23 | "console:dev": "ts-node -r tsconfig-paths/register src/cli/cli.module.ts",
24 | "fixtures": "fixtures ./fixtures/entities --config ./fixtures/typeorm.config.ts --debug --sync --require=ts-node/register --require=tsconfig-paths/register"
25 | },
26 | "dependencies": {
27 | "@elastic/elasticsearch": "^7.2.0",
28 | "@grpc/proto-loader": "^0.5.1",
29 | "@nestjs/common": "^6.5.2",
30 | "@nestjs/core": "^6.5.2",
31 | "@nestjs/cqrs": "^6.0.1",
32 | "@nestjs/jwt": "^6.1.1",
33 | "@nestjs/microservices": "^6.5.3",
34 | "@nestjs/passport": "^6.1.0",
35 | "@nestjs/platform-express": "^6.5.2",
36 | "@nestjs/platform-fastify": "^6.5.2",
37 | "@nestjs/typeorm": "^6.1.2",
38 | "@nestjsx/api-version": "^0.1.1",
39 | "@types/elasticsearch": "^5.0.34",
40 | "@types/faker": "^4.1.5",
41 | "@types/fastify-multipart": "^0.7.0",
42 | "@types/fs-extra": "^8.0.0",
43 | "@types/moment-timezone": "^0.5.12",
44 | "@types/multer": "^1.3.7",
45 | "@types/passport-jwt": "^3.0.1",
46 | "activedirectory": "^0.7.2",
47 | "amqp-connection-manager": "^3.0.0",
48 | "amqplib": "^0.5.5",
49 | "chai": "^4.2.0",
50 | "class-transformer": "^0.2.3",
51 | "class-validator": "^0.9.1",
52 | "cloneable-ts": "^1.0.18",
53 | "config": "^3.1.0",
54 | "csvtojson": "^2.0.10",
55 | "faker": "^4.1.0",
56 | "fastify-swagger": "^2.4.0",
57 | "grpc": "^1.22.2",
58 | "moment-timezone": "^0.5.26",
59 | "nestjs-i18n": "^3.0.0",
60 | "nestjs-redis": "^1.2.1",
61 | "npm": "^6.10.3",
62 | "ow": "^0.13.2",
63 | "passport": "^0.4.0",
64 | "passport-http-bearer": "^1.0.1",
65 | "passport-jwt": "^4.0.0",
66 | "pg": "^7.11.0",
67 | "pre-commit": "^1.2.2",
68 | "redis": "^2.8.0",
69 | "reflect-metadata": "0.1.13",
70 | "rimraf": "2.6.3",
71 | "rxjs": "6.5.2"
72 | },
73 | "devDependencies": {
74 | "@nestjs/cli": "^6.5.0",
75 | "@nestjs/swagger": "^3.0.2",
76 | "@nestjs/testing": "6.3.2",
77 | "@types/express": "4.17.0",
78 | "@types/jest": "24.0.15",
79 | "@types/node": "12.0.10",
80 | "@types/supertest": "2.0.7",
81 | "concurrently": "^4.1.0",
82 | "jest": "24.8.0",
83 | "nestjs-console": "^1.1.4",
84 | "nodemon": "1.19.1",
85 | "prettier": "1.18.2",
86 | "supertest": "4.0.2",
87 | "swagger-ui-express": "^4.0.6",
88 | "ts-jest": "24.0.2",
89 | "ts-node": "^8.3.0",
90 | "tsconfig-paths": "3.8.0",
91 | "tslint": "5.18.0",
92 | "typeorm-fixtures-cli": "^1.3.5",
93 | "typescript": "^3.5.3",
94 | "wait-on": "^3.2.0"
95 | },
96 | "jest": {
97 | "moduleFileExtensions": [
98 | "js",
99 | "json",
100 | "ts"
101 | ],
102 | "rootDir": "src",
103 | "testRegex": ".spec.ts$",
104 | "transform": {
105 | "^.+\\.(t|j)s$": "ts-jest"
106 | },
107 | "collectCoverageFrom": [
108 | "**/*.(t|j)s"
109 | ],
110 | "coverageDirectory": "../coverage",
111 | "testEnvironment": "node"
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/event-service-rabbit/src/app.module.ts:
--------------------------------------------------------------------------------
1 | import {Logger, Module} from '@nestjs/common';
2 | import {EventBusSubscriberService} from './services/event.subscriber.service';
3 | import {ContrivedEventHandler} from './events/contrived/contrived.event.handler';
4 | import {ContrivedEvent} from './events/contrived/contrived.event';
5 | import {CqrsModule} from '@nestjs/cqrs';
6 |
7 | // events handlers
8 | export const EventHandlers = [
9 | ContrivedEventHandler,
10 | ];
11 |
12 | // events
13 | export const Events = {ContrivedEvent};
14 |
15 | @Module({
16 | imports: [
17 | CqrsModule,
18 | ],
19 | controllers: [
20 | EventBusSubscriberService,
21 | ],
22 | providers: [
23 | ...EventHandlers,
24 | Logger,
25 | ],
26 | })
27 | export class AppModule {
28 | }
29 |
--------------------------------------------------------------------------------
/src/event-service-rabbit/src/config/global.env.ts:
--------------------------------------------------------------------------------
1 | export const EVENT_SERVICE = {
2 | PATTERN: process.env.EVENT_SERVICE_PATTERN,
3 | };
4 |
5 | export const RABBIT_SERVICE = {
6 | URLS: [
7 | process.env.RABBITMQ_URL,
8 | ],
9 | QUEUE: process.env.RABBITMQ_QUEUE,
10 | QUEUE_OPTIONS: {
11 | durable: true,
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/src/event-service-rabbit/src/events/contrived/contrived.event.handler.ts:
--------------------------------------------------------------------------------
1 | import {EventsHandler, IEventHandler} from '@nestjs/cqrs';
2 | import {ContrivedEvent} from './contrived.event';
3 | import {Logger} from '@nestjs/common';
4 |
5 | @EventsHandler(ContrivedEvent)
6 | export class ContrivedEventHandler implements IEventHandler {
7 | constructor(
8 | private readonly log: Logger,
9 | ) {
10 |
11 | }
12 |
13 | handle(event: ContrivedEvent) {
14 | this.log.verbose('ContrivedEventHandler: event\n');
15 | this.log.log(event);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/event-service-rabbit/src/events/contrived/contrived.event.ts:
--------------------------------------------------------------------------------
1 |
2 | export class ContrivedEvent {
3 |
4 | constructor(
5 | ) {}
6 | }
7 |
--------------------------------------------------------------------------------
/src/event-service-rabbit/src/main.ts:
--------------------------------------------------------------------------------
1 | import {NestFactory} from '@nestjs/core';
2 | import {AppModule} from './app.module';
3 | import {Transport} from '@nestjs/microservices';
4 | import {Logger} from '@nestjs/common';
5 |
6 | const log = new Logger('event-service: ');
7 |
8 | (async function bootstrap() {
9 | const app = await NestFactory.createMicroservice(AppModule, {
10 | logger: log,
11 | transport: Transport.RMQ,
12 | options: {
13 | urls: ['amqp://rabbit:rabbit@rabbitmq:5672'],
14 | queue: 'event_service_queue',
15 | queueOptions: {
16 | durable: true,
17 | },
18 | },
19 | });
20 |
21 | await app.listen(() => {
22 | log.verbose('Event Service is running.');
23 | });
24 | })();
25 |
--------------------------------------------------------------------------------
/src/event-service-rabbit/src/pipes/json.parse.pipe.ts:
--------------------------------------------------------------------------------
1 | import {ArgumentMetadata, Injectable, PipeTransform} from '@nestjs/common';
2 |
3 | @Injectable()
4 | export class JsonParsePipe implements PipeTransform {
5 | transform(value: any, metadata: ArgumentMetadata) {
6 | if (typeof value === 'string') {
7 | return JSON.parse(value);
8 | }
9 | return value;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/event-service-rabbit/src/services/event.subscriber.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable, UsePipes} from '@nestjs/common';
2 | import {EventPattern} from '@nestjs/microservices';
3 | import {EventBus} from '@nestjs/cqrs';
4 | import {plainToClass} from 'class-transformer';
5 | import {Events} from '../app.module';
6 | import {JsonParsePipe} from '../pipes/json.parse.pipe';
7 |
8 | @Injectable()
9 | export class EventBusSubscriberService {
10 |
11 | constructor(
12 | private readonly eventBus: EventBus,
13 | ) {
14 |
15 | }
16 |
17 | @EventPattern('event_bus')
18 | @UsePipes(new JsonParsePipe())
19 | async subscribe(data: any) {
20 | try {
21 | const event = Events[data.event];
22 |
23 | if (!event) {
24 | throw new Error(`Not such ${data.event}.`);
25 | }
26 |
27 | this.eventBus.publish(plainToClass(event, data.payload));
28 | } catch {
29 | // TODO
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/event-service-rabbit/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": [
4 | "node_modules",
5 | "dist",
6 | "test",
7 | "fixtures",
8 | "grpc",
9 | "cli",
10 | "**/*spec.ts"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/src/event-service-rabbit/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "esModuleInterop": true,
7 | "emitDecoratorMetadata": true,
8 | "experimentalDecorators": true,
9 | "target": "es6",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "baseUrl": "./",
13 | "incremental": true
14 | },
15 | "exclude": [
16 | "node_modules",
17 | "dist",
18 | "test",
19 | "fixtures",
20 | "grpc"
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/src/event-service-rabbit/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultSeverity": "error",
3 | "extends": ["tslint:recommended"],
4 | "jsRules": {
5 | "no-unused-expression": true
6 | },
7 | "rules": {
8 | "quotemark": [true, "single"],
9 | "member-access": [false],
10 | "ordered-imports": [false],
11 | "max-line-length": [true, 150],
12 | "member-ordering": [false],
13 | "interface-name": [false],
14 | "arrow-parens": false,
15 | "object-literal-sort-keys": false
16 | },
17 | "rulesDirectory": []
18 | }
19 |
--------------------------------------------------------------------------------
/src/event-service-redis/.gitignore:
--------------------------------------------------------------------------------
1 | # Don't check auto-generated stuff into git
2 | coverage
3 | build
4 | node_modules
5 | dist
6 | stats.json
7 |
8 | # Cruft
9 | .DS_Store
10 | npm-debug.log
11 | .idea
12 | .env
13 |
--------------------------------------------------------------------------------
/src/event-service-redis/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "tabWidth": 4,
4 | "semi": true,
5 | "singleQuote": true
6 | }
--------------------------------------------------------------------------------
/src/event-service-redis/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master
6 | [travis-url]: https://travis-ci.org/nestjs/nest
7 | [linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux
8 | [linux-url]: https://travis-ci.org/nestjs/nest
9 |
10 | A progressive Node.js framework for building efficient and scalable server-side applications, heavily inspired by Angular.
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
26 |
27 | ## Description
28 |
29 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
30 |
31 | ## Installation
32 |
33 | ```bash
34 | $ npm install
35 | ```
36 |
37 | ## Running the app
38 |
39 | ```bash
40 | # development
41 | $ npm run start
42 |
43 | # watch mode
44 | $ npm run start:dev
45 |
46 | # production mode
47 | $ npm run start:prod
48 | ```
49 |
50 | ## Test
51 |
52 | ```bash
53 | # unit tests
54 | $ npm run test
55 |
56 | # e2e tests
57 | $ npm run test:e2e
58 |
59 | # test coverage
60 | $ npm run test:cov
61 | ```
62 |
63 | ## Support
64 |
65 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
66 |
67 | ## Stay in touch
68 |
69 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
70 | - Website - [https://nestjs.com](https://nestjs.com/)
71 | - Twitter - [@nestframework](https://twitter.com/nestframework)
72 |
73 | ## License
74 |
75 | Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE).
76 |
--------------------------------------------------------------------------------
/src/event-service-redis/nodemon-debug.json:
--------------------------------------------------------------------------------
1 | {
2 | "watch": ["src"],
3 | "ext": "ts",
4 | "ignore": ["src/**/*.spec.ts"],
5 | "exec": "node --inspect-brk=0.0.0.0:9229 -r tsconfig-paths/register -r ts-node/register src/main.ts"
6 | }
--------------------------------------------------------------------------------
/src/event-service-redis/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "watch": ["dist"],
3 | "ext": "js",
4 | "exec": "node dist/main"
5 | }
6 |
--------------------------------------------------------------------------------
/src/event-service-redis/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nest-typescript-starter",
3 | "version": "1.0.0",
4 | "description": "Nest TypeScript starter repository",
5 | "license": "MIT",
6 | "scripts": {
7 | "build": "tsc -p tsconfig.build.json",
8 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
9 | "start": "ts-node -r tsconfig-paths/register src/main.ts",
10 | "start:dev": "concurrently --handle-input \"wait-on dist/main.js && nodemon\" \"tsc -w -p tsconfig.build.json\" ",
11 | "start:debug": "nodemon --config nodemon-debug.json",
12 | "prestart:prod": "rimraf dist && npm run build",
13 | "start:prod": "node dist/main.js",
14 | "lint": "tslint -p tsconfig.json -c tslint.json",
15 | "lint:fix": "tslint -p tsconfig.json -c tslint.json --fix",
16 | "test": "jest --detectOpenHandles --config ./test/jest.json --forceExit",
17 | "test:watch": "jest --watch",
18 | "test:cov": "jest --coverage",
19 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
20 | "test:e2e": "jest --detectOpenHandles --config ./test/e2e/jest-e2e.json --forceExit",
21 | "test:int": "jest --detectOpenHandles --config ./test/int/jest-int.json --forceExit",
22 | "test:unit": "jest --detectOpenHandles --config ./test/unit/jest-unit.json --forceExit",
23 | "console:dev": "ts-node -r tsconfig-paths/register src/cli/cli.module.ts",
24 | "fixtures": "fixtures ./fixtures/entities --config ./fixtures/typeorm.config.ts --debug --sync --require=ts-node/register --require=tsconfig-paths/register"
25 | },
26 | "dependencies": {
27 | "@elastic/elasticsearch": "^7.2.0",
28 | "@grpc/proto-loader": "^0.5.1",
29 | "@nestjs/common": "^6.5.2",
30 | "@nestjs/core": "^6.5.2",
31 | "@nestjs/cqrs": "^6.0.1",
32 | "@nestjs/jwt": "^6.1.1",
33 | "@nestjs/microservices": "^6.5.3",
34 | "@nestjs/passport": "^6.1.0",
35 | "@nestjs/platform-express": "^6.5.2",
36 | "@nestjs/platform-fastify": "^6.5.2",
37 | "@nestjs/typeorm": "^6.1.2",
38 | "@nestjsx/api-version": "^0.1.1",
39 | "@types/elasticsearch": "^5.0.34",
40 | "@types/faker": "^4.1.5",
41 | "@types/fastify-multipart": "^0.7.0",
42 | "@types/fs-extra": "^8.0.0",
43 | "@types/moment-timezone": "^0.5.12",
44 | "@types/multer": "^1.3.7",
45 | "@types/passport-jwt": "^3.0.1",
46 | "activedirectory": "^0.7.2",
47 | "amqp-connection-manager": "^3.0.0",
48 | "amqplib": "^0.5.5",
49 | "chai": "^4.2.0",
50 | "class-transformer": "^0.2.3",
51 | "class-validator": "^0.9.1",
52 | "cloneable-ts": "^1.0.18",
53 | "config": "^3.1.0",
54 | "csvtojson": "^2.0.10",
55 | "faker": "^4.1.0",
56 | "fastify-swagger": "^2.4.0",
57 | "grpc": "^1.22.2",
58 | "moment-timezone": "^0.5.26",
59 | "nestjs-i18n": "^3.0.0",
60 | "nestjs-redis": "^1.2.1",
61 | "npm": "^6.10.3",
62 | "ow": "^0.13.2",
63 | "passport": "^0.4.0",
64 | "passport-http-bearer": "^1.0.1",
65 | "passport-jwt": "^4.0.0",
66 | "pg": "^7.11.0",
67 | "pre-commit": "^1.2.2",
68 | "redis": "^2.8.0",
69 | "reflect-metadata": "0.1.13",
70 | "rimraf": "2.6.3",
71 | "rxjs": "6.5.2"
72 | },
73 | "devDependencies": {
74 | "@nestjs/cli": "^6.5.0",
75 | "@nestjs/swagger": "^3.0.2",
76 | "@nestjs/testing": "6.3.2",
77 | "@types/express": "4.17.0",
78 | "@types/jest": "24.0.15",
79 | "@types/node": "12.0.10",
80 | "@types/supertest": "2.0.7",
81 | "concurrently": "^4.1.0",
82 | "jest": "24.8.0",
83 | "nestjs-console": "^1.1.4",
84 | "nodemon": "1.19.1",
85 | "prettier": "1.18.2",
86 | "supertest": "4.0.2",
87 | "swagger-ui-express": "^4.0.6",
88 | "ts-jest": "24.0.2",
89 | "ts-node": "^8.3.0",
90 | "tsconfig-paths": "3.8.0",
91 | "tslint": "5.18.0",
92 | "typeorm-fixtures-cli": "^1.3.5",
93 | "typescript": "^3.5.3",
94 | "wait-on": "^3.2.0"
95 | },
96 | "jest": {
97 | "moduleFileExtensions": [
98 | "js",
99 | "json",
100 | "ts"
101 | ],
102 | "rootDir": "src",
103 | "testRegex": ".spec.ts$",
104 | "transform": {
105 | "^.+\\.(t|j)s$": "ts-jest"
106 | },
107 | "collectCoverageFrom": [
108 | "**/*.(t|j)s"
109 | ],
110 | "coverageDirectory": "../coverage",
111 | "testEnvironment": "node"
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/event-service-redis/src/app.module.ts:
--------------------------------------------------------------------------------
1 | import {Logger, Module} from '@nestjs/common';
2 | import {EventBusSubscriberService} from './services/event.subscriber.service';
3 | import {ContrivedEventHandler} from './events/contrived/contrived.event.handler';
4 | import {ContrivedEvent} from './events/contrived/contrived.event';
5 | import {CqrsModule} from '@nestjs/cqrs';
6 |
7 | // events handlers
8 | export const EventHandlers = [
9 | ContrivedEventHandler,
10 | ];
11 |
12 | // events
13 | export const Events = {ContrivedEvent};
14 |
15 | @Module({
16 | imports: [
17 | CqrsModule,
18 | ],
19 | controllers: [
20 | EventBusSubscriberService,
21 | ],
22 | providers: [
23 | ...EventHandlers,
24 | Logger,
25 | ],
26 | })
27 | export class AppModule {
28 | }
29 |
--------------------------------------------------------------------------------
/src/event-service-redis/src/config/global.env.ts:
--------------------------------------------------------------------------------
1 | export const EVENT_SERVICE = {
2 | PATTERN: process.env.EVENT_SERVICE_PATTERN,
3 | };
4 |
5 | export const RABBIT_SERVICE = {
6 | URLS: [
7 | process.env.RABBITMQ_URL,
8 | ],
9 | QUEUE: process.env.RABBITMQ_QUEUE,
10 | QUEUE_OPTIONS: {
11 | durable: true,
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/src/event-service-redis/src/events/contrived/contrived.event.handler.ts:
--------------------------------------------------------------------------------
1 | import {EventsHandler, IEventHandler} from '@nestjs/cqrs';
2 | import {ContrivedEvent} from './contrived.event';
3 | import {Logger} from '@nestjs/common';
4 |
5 | @EventsHandler(ContrivedEvent)
6 | export class ContrivedEventHandler implements IEventHandler {
7 | constructor(
8 | private readonly log: Logger,
9 | ) {
10 |
11 | }
12 |
13 | handle(event: ContrivedEvent) {
14 | this.log.verbose('ContrivedEventHandler: event\n');
15 | this.log.log(event);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/event-service-redis/src/events/contrived/contrived.event.ts:
--------------------------------------------------------------------------------
1 |
2 | export class ContrivedEvent {
3 |
4 | constructor(
5 | ) {}
6 | }
7 |
--------------------------------------------------------------------------------
/src/event-service-redis/src/main.ts:
--------------------------------------------------------------------------------
1 | import {NestFactory} from '@nestjs/core';
2 | import {AppModule} from './app.module';
3 | import {Transport} from '@nestjs/microservices';
4 | import {Logger} from '@nestjs/common';
5 |
6 | const log = new Logger('event-service: ');
7 |
8 | (async function bootstrap() {
9 | const app = await NestFactory.createMicroservice(AppModule, {
10 | logger: log,
11 | transport: Transport.REDIS,
12 | options: {
13 | url: 'redis://:password123@redis:6379',
14 | },
15 | });
16 |
17 | await app.listen(() => {
18 | log.verbose('Redis Event Service is running.');
19 | });
20 | })();
21 |
--------------------------------------------------------------------------------
/src/event-service-redis/src/pipes/json.parse.pipe.ts:
--------------------------------------------------------------------------------
1 | import {ArgumentMetadata, Injectable, PipeTransform} from '@nestjs/common';
2 |
3 | @Injectable()
4 | export class JsonParsePipe implements PipeTransform {
5 | transform(value: any, metadata: ArgumentMetadata) {
6 | if (typeof value === 'string') {
7 | return JSON.parse(value);
8 | }
9 | return value;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/event-service-redis/src/services/event.subscriber.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable, UsePipes} from '@nestjs/common';
2 | import {EventPattern} from '@nestjs/microservices';
3 | import {EventBus} from '@nestjs/cqrs';
4 | import {plainToClass} from 'class-transformer';
5 | import {Events} from '../app.module';
6 | import {JsonParsePipe} from '../pipes/json.parse.pipe';
7 |
8 | @Injectable()
9 | export class EventBusSubscriberService {
10 |
11 | constructor(
12 | private readonly eventBus: EventBus,
13 | ) {
14 |
15 | }
16 |
17 | @EventPattern('event_bus')
18 | @UsePipes(new JsonParsePipe())
19 | async subscribe(data: any) {
20 | console.log('===dsdsd========',data);
21 | try {
22 | const event = Events[data.event];
23 |
24 | if (!event) {
25 | throw new Error(`Not such ${data.event}.`);
26 | }
27 |
28 | this.eventBus.publish(plainToClass(event, data.payload));
29 | } catch {
30 | // TODO
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/event-service-redis/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": [
4 | "node_modules",
5 | "dist",
6 | "test",
7 | "fixtures",
8 | "grpc",
9 | "cli",
10 | "**/*spec.ts"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/src/event-service-redis/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "esModuleInterop": true,
7 | "emitDecoratorMetadata": true,
8 | "experimentalDecorators": true,
9 | "target": "es6",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "baseUrl": "./",
13 | "incremental": true
14 | },
15 | "exclude": [
16 | "node_modules",
17 | "dist",
18 | "test",
19 | "fixtures",
20 | "grpc"
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/src/event-service-redis/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultSeverity": "error",
3 | "extends": ["tslint:recommended"],
4 | "jsRules": {
5 | "no-unused-expression": true
6 | },
7 | "rules": {
8 | "quotemark": [true, "single"],
9 | "member-access": [false],
10 | "ordered-imports": [false],
11 | "max-line-length": [true, 150],
12 | "member-ordering": [false],
13 | "interface-name": [false],
14 | "arrow-parens": false,
15 | "object-literal-sort-keys": false
16 | },
17 | "rulesDirectory": []
18 | }
19 |
--------------------------------------------------------------------------------