├── .dockerignore
├── .gitignore
├── LICENSE
├── README.md
├── consumer
├── .eslintrc.js
├── .prettierrc
├── README.md
├── nest-cli.json
├── package.json
├── src
│ ├── app.controller.spec.ts
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ └── main.ts
├── test
│ ├── app.e2e-spec.ts
│ └── jest-e2e.json
├── tsconfig.build.json
├── tsconfig.json
└── yarn.lock
├── docker-compose.yml
└── producer
├── .eslintrc.js
├── .prettierrc
├── README.md
├── nest-cli.json
├── package.json
├── src
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── app.service.ts
└── main.ts
├── test
├── app.e2e-spec.ts
└── jest-e2e.json
├── tsconfig.build.json
├── tsconfig.json
└── yarn.lock
/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .gitignore
3 | .git
4 | .vscode
5 | .idea
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | /dist
3 | /node_modules
4 | **/node_modules
5 | **/dist
6 |
7 |
8 | # Logs
9 | logs
10 | *.log
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | lerna-debug.log*
15 |
16 | # OS
17 | .DS_Store
18 |
19 | # Tests
20 | /coverage
21 | /.nyc_output
22 |
23 | # IDEs and editors
24 | /.idea
25 | .project
26 | .classpath
27 | .c9/
28 | *.launch
29 | .settings/
30 | *.sublime-workspace
31 |
32 | # IDE - VSCode
33 | .vscode/*
34 | !.vscode/settings.json
35 | !.vscode/tasks.json
36 | !.vscode/launch.json
37 | !.vscode/extensions.json
38 |
39 | .env
40 |
41 | .history
42 |
43 | .env.production
44 | .env.stage
45 |
46 | data/
47 | data
48 | data/*
49 | .docker-data
50 |
51 | .kafka.config
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Marcos Silva
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # nestjs-kafka-tutorial
2 |
3 | Source code for my medium [Article](https://makinhs.medium.com/a-beginners-introduction-to-kafka-with-typescript-using-nestjs-7c92fe78f638)
4 |
5 | ## How to run Kafka locally
6 |
7 | You need to have docker installed and do
8 |
9 | ```
10 | run docker compose up -d
11 | ```
12 |
13 | It will serve a kafka ui dashboard in port 8080
14 |
15 | ## Running the producer
16 |
17 | The producer code is in the producer folder and serves a small scaffold that contains the configuration of the producer.
18 |
19 | Inside the producer folder make sure to `yarn install` and after `yarn start`
20 |
21 | ## Running the consumer
22 |
23 | The consumer code is in the consumer folder and serves a small scaffold that contains the configuration of the consumer.
24 |
25 | Inside the consumer folder make sure to `yarn install` and after `yarn start`
26 |
27 | ### I need more help!
28 |
29 | A detailed how to use this project is written on my [Article](https://makinhs.medium.com/a-beginners-introduction-to-kafka-with-typescript-using-nestjs-7c92fe78f638)
30 |
--------------------------------------------------------------------------------
/consumer/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | parserOptions: {
4 | project: 'tsconfig.json',
5 | sourceType: 'module',
6 | },
7 | plugins: ['@typescript-eslint/eslint-plugin'],
8 | extends: [
9 | 'plugin:@typescript-eslint/recommended',
10 | 'plugin:prettier/recommended',
11 | ],
12 | root: true,
13 | env: {
14 | node: true,
15 | jest: true,
16 | },
17 | ignorePatterns: ['.eslintrc.js'],
18 | rules: {
19 | '@typescript-eslint/interface-name-prefix': 'off',
20 | '@typescript-eslint/explicit-function-return-type': 'off',
21 | '@typescript-eslint/explicit-module-boundary-types': 'off',
22 | '@typescript-eslint/no-explicit-any': 'off',
23 | },
24 | };
25 |
--------------------------------------------------------------------------------
/consumer/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all"
4 | }
--------------------------------------------------------------------------------
/consumer/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
6 | [circleci-url]: https://circleci.com/gh/nestjs/nest
7 |
8 | A progressive Node.js framework for building efficient and scalable server-side applications.
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
24 |
25 | ## Description
26 |
27 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
28 |
29 | ## Installation
30 |
31 | ```bash
32 | $ npm install
33 | ```
34 |
35 | ## Running the app
36 |
37 | ```bash
38 | # development
39 | $ npm run start
40 |
41 | # watch mode
42 | $ npm run start:dev
43 |
44 | # production mode
45 | $ npm run start:prod
46 | ```
47 |
48 | ## Test
49 |
50 | ```bash
51 | # unit tests
52 | $ npm run test
53 |
54 | # e2e tests
55 | $ npm run test:e2e
56 |
57 | # test coverage
58 | $ npm run test:cov
59 | ```
60 |
61 | ## Support
62 |
63 | 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).
64 |
65 | ## Stay in touch
66 |
67 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
68 | - Website - [https://nestjs.com](https://nestjs.com/)
69 | - Twitter - [@nestframework](https://twitter.com/nestframework)
70 |
71 | ## License
72 |
73 | Nest is [MIT licensed](LICENSE).
74 |
--------------------------------------------------------------------------------
/consumer/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "collection": "@nestjs/schematics",
3 | "sourceRoot": "src"
4 | }
5 |
--------------------------------------------------------------------------------
/consumer/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "consumer",
3 | "version": "0.0.1",
4 | "description": "",
5 | "author": "",
6 | "private": true,
7 | "license": "UNLICENSED",
8 | "scripts": {
9 | "prebuild": "rimraf dist",
10 | "build": "nest build",
11 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
12 | "start": "nest start",
13 | "start:dev": "nest start --watch",
14 | "start:debug": "nest start --debug --watch",
15 | "start:prod": "node dist/main",
16 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
17 | "test": "jest",
18 | "test:watch": "jest --watch",
19 | "test:cov": "jest --coverage",
20 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
21 | "test:e2e": "jest --config ./test/jest-e2e.json"
22 | },
23 | "dependencies": {
24 | "@nestjs/common": "^8.0.0",
25 | "@nestjs/core": "^8.0.0",
26 | "@nestjs/microservices": "^8.0.6",
27 | "@nestjs/platform-express": "^8.0.0",
28 | "kafkajs": "^1.15.0",
29 | "reflect-metadata": "^0.1.13",
30 | "rimraf": "^3.0.2",
31 | "rxjs": "^7.2.0"
32 | },
33 | "devDependencies": {
34 | "@nestjs/cli": "^8.0.0",
35 | "@nestjs/schematics": "^8.0.0",
36 | "@nestjs/testing": "^8.0.0",
37 | "@types/express": "^4.17.13",
38 | "@types/jest": "^26.0.24",
39 | "@types/node": "^16.0.0",
40 | "@types/supertest": "^2.0.11",
41 | "@typescript-eslint/eslint-plugin": "^4.28.2",
42 | "@typescript-eslint/parser": "^4.28.2",
43 | "eslint": "^7.30.0",
44 | "eslint-config-prettier": "^8.3.0",
45 | "eslint-plugin-prettier": "^3.4.0",
46 | "jest": "27.0.6",
47 | "prettier": "^2.3.2",
48 | "supertest": "^6.1.3",
49 | "ts-jest": "^27.0.3",
50 | "ts-loader": "^9.2.3",
51 | "ts-node": "^10.0.0",
52 | "tsconfig-paths": "^3.10.1",
53 | "typescript": "^4.3.5"
54 | },
55 | "jest": {
56 | "moduleFileExtensions": [
57 | "js",
58 | "json",
59 | "ts"
60 | ],
61 | "rootDir": "src",
62 | "testRegex": ".*\\.spec\\.ts$",
63 | "transform": {
64 | "^.+\\.(t|j)s$": "ts-jest"
65 | },
66 | "collectCoverageFrom": [
67 | "**/*.(t|j)s"
68 | ],
69 | "coverageDirectory": "../coverage",
70 | "testEnvironment": "node"
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/consumer/src/app.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { AppController } from './app.controller';
3 | import { AppService } from './app.service';
4 |
5 | describe('AppController', () => {
6 | let appController: AppController;
7 |
8 | beforeEach(async () => {
9 | const app: TestingModule = await Test.createTestingModule({
10 | controllers: [AppController],
11 | providers: [AppService],
12 | }).compile();
13 |
14 | appController = app.get(AppController);
15 | });
16 |
17 | describe('root', () => {
18 | it('should return "Hello World!"', () => {
19 | expect(appController.getHello()).toBe('Hello World!');
20 | });
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/consumer/src/app.controller.ts:
--------------------------------------------------------------------------------
1 | import {Controller} from '@nestjs/common';
2 | import {
3 | Ctx,
4 | KafkaContext,
5 | MessagePattern,
6 | Payload,
7 | } from '@nestjs/microservices';
8 |
9 | @Controller()
10 | export class AppController {
11 | constructor() {
12 | }
13 |
14 | @MessagePattern('medium.rocks')
15 | readMessage(@Payload() message: any, @Ctx() context: KafkaContext) {
16 | const originalMessage = context.getMessage();
17 | const response =
18 | `Receiving a new message from topic: medium.rocks: ` +
19 | JSON.stringify(originalMessage.value);
20 | console.log(response);
21 | return response;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/consumer/src/app.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { AppController } from './app.controller';
3 | import { AppService } from './app.service';
4 | import { ClientsModule, Transport } from '@nestjs/microservices';
5 |
6 | @Module({
7 | imports: [
8 | ClientsModule.register([
9 | {
10 | name: 'any_name_i_want',
11 | transport: Transport.KAFKA,
12 | options: {
13 | client: {
14 | clientId: 'any_client_id_i_want',
15 | brokers: ['localhost:29092'],
16 | },
17 | consumer: {
18 | groupId: 'an_unique_string_id',
19 | },
20 | },
21 | },
22 | ]),
23 | ],
24 | controllers: [AppController],
25 | providers: [AppService],
26 | })
27 | export class AppModule {}
28 |
--------------------------------------------------------------------------------
/consumer/src/app.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 |
3 | @Injectable()
4 | export class AppService {
5 | getHello(): string {
6 | return 'Hello World!';
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/consumer/src/main.ts:
--------------------------------------------------------------------------------
1 | import { NestFactory } from '@nestjs/core';
2 | import { AppModule } from './app.module';
3 | import {MicroserviceOptions, Transport} from '@nestjs/microservices';
4 |
5 | async function bootstrap() {
6 | const app = await NestFactory.createMicroservice(
7 | AppModule,
8 | {
9 | transport: Transport.KAFKA,
10 | options: {
11 | client: {
12 | brokers: ['localhost:29092'],
13 | },
14 | },
15 | },
16 | );
17 | await app.listen();
18 | }
19 | bootstrap();
20 |
--------------------------------------------------------------------------------
/consumer/test/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { INestApplication } from '@nestjs/common';
3 | import * as request from 'supertest';
4 | import { AppModule } from './../src/app.module';
5 |
6 | describe('AppController (e2e)', () => {
7 | let app: INestApplication;
8 |
9 | beforeEach(async () => {
10 | const moduleFixture: TestingModule = await Test.createTestingModule({
11 | imports: [AppModule],
12 | }).compile();
13 |
14 | app = moduleFixture.createNestApplication();
15 | await app.init();
16 | });
17 |
18 | it('/ (GET)', () => {
19 | return request(app.getHttpServer())
20 | .get('/')
21 | .expect(200)
22 | .expect('Hello World!');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/consumer/test/jest-e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "moduleFileExtensions": ["js", "json", "ts"],
3 | "rootDir": ".",
4 | "testEnvironment": "node",
5 | "testRegex": ".e2e-spec.ts$",
6 | "transform": {
7 | "^.+\\.(t|j)s$": "ts-jest"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/consumer/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/consumer/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "allowSyntheticDefaultImports": true,
9 | "target": "es2017",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "baseUrl": "./",
13 | "incremental": true,
14 | "skipLibCheck": true
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | zookeeper:
4 | image: confluentinc/cp-zookeeper:latest
5 | environment:
6 | ZOOKEEPER_CLIENT_PORT: 2181
7 | ZOOKEEPER_TICK_TIME: 2000
8 | ports:
9 | - 22181:2181
10 |
11 | kafka:
12 | image: confluentinc/cp-kafka:latest
13 | depends_on:
14 | - zookeeper
15 | ports:
16 | - 29092:29092
17 | environment:
18 | KAFKA_BROKER_ID: 1
19 | KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
20 | KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092
21 | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
22 | KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
23 | KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
24 |
25 | kafka_ui:
26 | image: provectuslabs/kafka-ui:latest
27 | depends_on:
28 | - kafka
29 | ports:
30 | - 8080:8080
31 | environment:
32 | KAFKA_CLUSTERS_0_ZOOKEEPER: zookeeper:2181
33 | KAFKA_CLUSTERS_0_NAME: local
34 | KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092
35 |
--------------------------------------------------------------------------------
/producer/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | parserOptions: {
4 | project: 'tsconfig.json',
5 | sourceType: 'module',
6 | },
7 | plugins: ['@typescript-eslint/eslint-plugin'],
8 | extends: [
9 | 'plugin:@typescript-eslint/recommended',
10 | 'plugin:prettier/recommended',
11 | ],
12 | root: true,
13 | env: {
14 | node: true,
15 | jest: true,
16 | },
17 | ignorePatterns: ['.eslintrc.js'],
18 | rules: {
19 | '@typescript-eslint/interface-name-prefix': 'off',
20 | '@typescript-eslint/explicit-function-return-type': 'off',
21 | '@typescript-eslint/explicit-module-boundary-types': 'off',
22 | '@typescript-eslint/no-explicit-any': 'off',
23 | },
24 | };
25 |
--------------------------------------------------------------------------------
/producer/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all"
4 | }
--------------------------------------------------------------------------------
/producer/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
6 | [circleci-url]: https://circleci.com/gh/nestjs/nest
7 |
8 | A progressive Node.js framework for building efficient and scalable server-side applications.
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
24 |
25 | ## Description
26 |
27 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
28 |
29 | ## Installation
30 |
31 | ```bash
32 | $ npm install
33 | ```
34 |
35 | ## Running the app
36 |
37 | ```bash
38 | # development
39 | $ npm run start
40 |
41 | # watch mode
42 | $ npm run start:dev
43 |
44 | # production mode
45 | $ npm run start:prod
46 | ```
47 |
48 | ## Test
49 |
50 | ```bash
51 | # unit tests
52 | $ npm run test
53 |
54 | # e2e tests
55 | $ npm run test:e2e
56 |
57 | # test coverage
58 | $ npm run test:cov
59 | ```
60 |
61 | ## Support
62 |
63 | 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).
64 |
65 | ## Stay in touch
66 |
67 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
68 | - Website - [https://nestjs.com](https://nestjs.com/)
69 | - Twitter - [@nestframework](https://twitter.com/nestframework)
70 |
71 | ## License
72 |
73 | Nest is [MIT licensed](LICENSE).
74 |
--------------------------------------------------------------------------------
/producer/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "collection": "@nestjs/schematics",
3 | "sourceRoot": "src"
4 | }
5 |
--------------------------------------------------------------------------------
/producer/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "producer",
3 | "version": "0.0.1",
4 | "description": "",
5 | "author": "",
6 | "private": true,
7 | "license": "UNLICENSED",
8 | "scripts": {
9 | "prebuild": "rimraf dist",
10 | "build": "nest build",
11 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
12 | "start": "nest start",
13 | "start:dev": "nest start --watch",
14 | "start:debug": "nest start --debug --watch",
15 | "start:prod": "node dist/main",
16 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
17 | "test": "jest",
18 | "test:watch": "jest --watch",
19 | "test:cov": "jest --coverage",
20 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
21 | "test:e2e": "jest --config ./test/jest-e2e.json"
22 | },
23 | "dependencies": {
24 | "@nestjs/common": "^8.0.0",
25 | "@nestjs/core": "^8.0.0",
26 | "@nestjs/microservices": "^8.0.6",
27 | "@nestjs/platform-express": "^8.0.0",
28 | "kafkajs": "^1.15.0",
29 | "reflect-metadata": "^0.1.13",
30 | "rimraf": "^3.0.2",
31 | "rxjs": "^7.2.0"
32 | },
33 | "devDependencies": {
34 | "@nestjs/cli": "^8.0.0",
35 | "@nestjs/schematics": "^8.0.0",
36 | "@nestjs/testing": "^8.0.0",
37 | "@types/express": "^4.17.13",
38 | "@types/jest": "^26.0.24",
39 | "@types/node": "^16.0.0",
40 | "@types/supertest": "^2.0.11",
41 | "@typescript-eslint/eslint-plugin": "^4.28.2",
42 | "@typescript-eslint/parser": "^4.28.2",
43 | "eslint": "^7.30.0",
44 | "eslint-config-prettier": "^8.3.0",
45 | "eslint-plugin-prettier": "^3.4.0",
46 | "jest": "27.0.6",
47 | "prettier": "^2.3.2",
48 | "supertest": "^6.1.3",
49 | "ts-jest": "^27.0.3",
50 | "ts-loader": "^9.2.3",
51 | "ts-node": "^10.0.0",
52 | "tsconfig-paths": "^3.10.1",
53 | "typescript": "^4.3.5"
54 | },
55 | "jest": {
56 | "moduleFileExtensions": [
57 | "js",
58 | "json",
59 | "ts"
60 | ],
61 | "rootDir": "src",
62 | "testRegex": ".*\\.spec\\.ts$",
63 | "transform": {
64 | "^.+\\.(t|j)s$": "ts-jest"
65 | },
66 | "collectCoverageFrom": [
67 | "**/*.(t|j)s"
68 | ],
69 | "coverageDirectory": "../coverage",
70 | "testEnvironment": "node"
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/producer/src/app.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { AppController } from './app.controller';
3 | import { AppService } from './app.service';
4 |
5 | describe('AppController', () => {
6 | let appController: AppController;
7 |
8 | beforeEach(async () => {
9 | const app: TestingModule = await Test.createTestingModule({
10 | controllers: [AppController],
11 | providers: [AppService],
12 | }).compile();
13 |
14 | appController = app.get(AppController);
15 | });
16 |
17 | describe('root', () => {
18 | it('should return "Hello World!"', () => {
19 | expect(appController.getHello()).toBe('Hello World!');
20 | });
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/producer/src/app.controller.ts:
--------------------------------------------------------------------------------
1 | import {Controller, Get, Inject, OnModuleDestroy, OnModuleInit} from '@nestjs/common';
2 | import { AppService } from './app.service';
3 | import { ClientKafka } from '@nestjs/microservices';
4 |
5 | @Controller()
6 | export class AppController implements OnModuleInit, OnModuleDestroy{
7 | constructor(
8 | private readonly appService: AppService,
9 | @Inject('any_name_i_want') private readonly client: ClientKafka,
10 | ) {}
11 |
12 | async onModuleInit() {
13 | ['medium.rocks'].forEach((key) => this.client.subscribeToResponseOf(`${key}`));
14 | await this.client.connect();
15 | }
16 |
17 | async onModuleDestroy() {
18 | await this.client.close();
19 | }
20 |
21 | @Get()
22 | getHello(): string {
23 | return this.appService.getHello();
24 | }
25 |
26 | @Get('kafka-test')
27 | testKafka(){
28 | return this.client.emit('medium.rocks', {foo:'bar', data: new Date().toString()})
29 | }
30 |
31 |
32 | @Get('kafka-test-with-response')
33 | testKafkaWithResponse(){
34 | return this.client.send('medium.rocks', {foo:'bar', data: new Date().toString()})
35 | }
36 |
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/producer/src/app.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { AppController } from './app.controller';
3 | import { AppService } from './app.service';
4 | import { ClientsModule, Transport } from '@nestjs/microservices';
5 |
6 | @Module({
7 | imports: [
8 | ClientsModule.register([
9 | {
10 | name: 'any_name_i_want',
11 | transport: Transport.KAFKA,
12 | options: {
13 | client: {
14 | clientId: 'any_client_id_i_want',
15 | brokers: ['localhost:29092'],
16 | },
17 | consumer: {
18 | groupId: 'an_unique_string_id',
19 | },
20 | },
21 | },
22 | ]),
23 | ],
24 | controllers: [AppController],
25 | providers: [AppService],
26 | })
27 | export class AppModule {}
28 |
--------------------------------------------------------------------------------
/producer/src/app.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 |
3 | @Injectable()
4 | export class AppService {
5 | getHello(): string {
6 | return 'Hello World!';
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/producer/src/main.ts:
--------------------------------------------------------------------------------
1 | import { NestFactory } from '@nestjs/core';
2 | import { AppModule } from './app.module';
3 |
4 | async function bootstrap() {
5 | const app = await NestFactory.create(AppModule);
6 | await app.listen(3000);
7 | }
8 | bootstrap();
9 |
--------------------------------------------------------------------------------
/producer/test/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { INestApplication } from '@nestjs/common';
3 | import * as request from 'supertest';
4 | import { AppModule } from './../src/app.module';
5 |
6 | describe('AppController (e2e)', () => {
7 | let app: INestApplication;
8 |
9 | beforeEach(async () => {
10 | const moduleFixture: TestingModule = await Test.createTestingModule({
11 | imports: [AppModule],
12 | }).compile();
13 |
14 | app = moduleFixture.createNestApplication();
15 | await app.init();
16 | });
17 |
18 | it('/ (GET)', () => {
19 | return request(app.getHttpServer())
20 | .get('/')
21 | .expect(200)
22 | .expect('Hello World!');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/producer/test/jest-e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "moduleFileExtensions": ["js", "json", "ts"],
3 | "rootDir": ".",
4 | "testEnvironment": "node",
5 | "testRegex": ".e2e-spec.ts$",
6 | "transform": {
7 | "^.+\\.(t|j)s$": "ts-jest"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/producer/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/producer/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "allowSyntheticDefaultImports": true,
9 | "target": "es2017",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "baseUrl": "./",
13 | "incremental": true,
14 | "skipLibCheck": true
15 | }
16 | }
17 |
--------------------------------------------------------------------------------