Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: add Nest + NATS example #55

Merged
merged 5 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions examples/nest-nats-microservices/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# NestJS REST-based Microservices with NATS

![NaNLABS Logo](./images/logo1.svg)
![NestJS Logo](https://nestjs.com/img/logo_text.svg)
![NATS Logo](https://nats.io/img/logos/nats-horizontal-color.png)

## Introduction

Welcome to the NestJS REST-based Microservices with NATS proof-of-concept (POC) repository! This project demonstrates the implementation of a microservices architecture using NestJS, a progressive Node.js framework, along with NATS for asynchronous event-based as well as synchronous request-reply messaging patterns.

This repository does not make use of Jeststream, the stream and persistence layer built on top of NATS. To see that in action please refer to [this repository](TBD)

## Table of Contents

- [NestJS REST-based Microservices with NATS](#nestjs-rest-based-microservices-with-nats)
- [Introduction](#introduction)
- [Table of Contents](#table-of-contents)
- [Technologies Used](#technologies-used)
- [Getting Started](#getting-started)
- [Project Structure](#project-structure)
- [Usage](#usage)
- [Contributing](#contributing)
- [Resources](#resources)

## Technologies Used

This POC showcases the utilization of the following technologies:

- [NestJS](https://nestjs.com/): A powerful Node.js framework crafted for building efficient and scalable server-side applications.
- [NATS](https://nats.io/): A lightweight and high-performance messaging system that provides various messaging patterns.

## Getting Started

To get started with this POC:

1. Clone the repository: `git clone [email protected]:nanlabs/backend-reference.git`
2. Navigate to the project directory: `cd examples/nest-nats-microservices`
3. Start NATS server and all 3 sample microservices in 🐳 Docker `docker-compose up`
4. (Optional) Activate compose `watch` mode `docker compose alpha watch`
5. Follow the instructions in the [Usage](#usage) section to run and test the microservices.

## Project Structure

The project is structured as follows:

```text
project-root/
├── service-a/
│ ├── src/
│ │ └── ...
│ └── ...
├── service-b/
│ ├── src/
│ │ └── ...
│ └── ...
|
├── service-c/
│ ├── src/
│ │ └── ...
│ └── ...
└── ...
```

Each microservice is contained within its own directory and follows a similar structure with controllers, services, and other relevant components.

## Usage

1. Start NATS server and all 3 sample microservices in 🐳 Docker `docker-compose up`
2. Navigate to a specific microservice directory: `cd service-a`
3. Explore the implemented REST-based endpoints and messaging patterns.
4. Refer to the [Resources](#resources) section for more in-depth information on NATS and NestJS.

Service **A** contains 2 resources (resource 1 and resource 2) and exposes a RESTful API with public CRUD methods.

### Event based communication

Sending a _POST_ http request to `/resource1` will broadcast a `resource1_created` event which will be handled by Service **B**, outputting data in the console. This is an example of event-based asynchronous communication.

### Request-response based communication

Sending a _GET_ http request to `/resource2` will send a message and await for a reply. Service **C** will handle the message and respond. Service **A** will output the response to the client. This is an example of syncronous communication.

## Contributing

Contributions are welcome! If you find any issues or want to enhance this POC, feel free to open a pull request. Please review our [Contribution Guidelines](CONTRIBUTING.md) before getting started.

## Resources

- [NestJS Documentation](https://docs.nestjs.com/)
- [NATS Documentation](https://docs.nats.io/)

---

**Disclaimer**: This repository is a proof-of-concept and should be used for educational and illustrative purposes. It does not represent a production-ready application. Use at your own risk.
50 changes: 50 additions & 0 deletions examples/nest-nats-microservices/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
version: '3.8'

services:
nats:
container_name: nats
entrypoint: '/nats-server -c nats-server.conf -DV'
image: nats
ports:
- '4222:4222'
- '6222:6222'
- '8222:8222'

service-a:
build: ./service-a
x-develop:
watch:
- action: sync
path: ./service-a/src
target: /app/src
- action: rebuild
path: package.json
container_name: service-a
ports:
- '3000:3000'

service-b:
build: ./service-b
x-develop:
watch:
- action: sync
path: ./service-b/src
target: /app/src
- action: rebuild
path: package.json
container_name: service-b
ports:
- '3001:3001'

service-c:
build: ./service-c
x-develop:
watch:
- action: sync
path: ./service-c/src
target: /app/src
- action: rebuild
path: package.json
container_name: service-c
ports:
- '3002:3002'
1 change: 1 addition & 0 deletions examples/nest-nats-microservices/images/logo1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions examples/nest-nats-microservices/service-a/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
tsconfigRootDir: __dirname,
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
};
35 changes: 35 additions & 0 deletions examples/nest-nats-microservices/service-a/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# compiled output
/dist
/node_modules

# Logs
logs
*.log
npm-debug.log*
pnpm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# OS
.DS_Store

# Tests
/coverage
/.nyc_output

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
4 changes: 4 additions & 0 deletions examples/nest-nats-microservices/service-a/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"singleQuote": true,
"trailingComma": "all"
}
6 changes: 6 additions & 0 deletions examples/nest-nats-microservices/service-a/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN yarn
CMD ["yarn", "start:dev"]
EXPOSE 3000
70 changes: 70 additions & 0 deletions examples/nest-nats-microservices/service-a/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<p align="center">
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="200" alt="Nest Logo" /></a>
</p>

<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
martin-aliverti marked this conversation as resolved.
Show resolved Hide resolved
<p align="center">
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
</p>
<!--[![Backers on Open Collective](https://opencollective.com/nest/backers/badge.svg)](https://opencollective.com/nest#backer)
[![Sponsors on Open Collective](https://opencollective.com/nest/sponsors/badge.svg)](https://opencollective.com/nest#sponsor)-->

## Description

[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.

## Installation

```bash
yarn install
```

## Running the app

```bash
# development
yarn run start

# watch mode
yarn run start:dev

# production mode
yarn run start:prod
```

## Test

```bash
# unit tests
yarn run test

# e2e tests
yarn run test:e2e

# test coverage
yarn run test:cov
```

## Support

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).

## Stay in touch

- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
- Website - [https://nestjs.com](https://nestjs.com/)
- Twitter - [@nestframework](https://twitter.com/nestframework)

## License

Nest is [MIT licensed](LICENSE).
8 changes: 8 additions & 0 deletions examples/nest-nats-microservices/service-a/nest-cli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true
}
}
73 changes: 73 additions & 0 deletions examples/nest-nats-microservices/service-a/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"name": "service-a",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0",
"@nestjs/mapped-types": "*",
"@nestjs/microservices": "^10.2.6",
"@nestjs/platform-express": "^10.0.0",
"nats": "^2.17.0",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",
"uuid": "^9.0.1"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
"@types/express": "^4.17.17",
"@types/jest": "^29.5.2",
"@types/node": "^20.3.1",
"@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"eslint": "^8.42.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.5.0",
"prettier": "^3.0.0",
"source-map-support": "^0.5.21",
"supertest": "^6.3.3",
"ts-jest": "^29.1.0",
"ts-loader": "^9.4.3",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.1.3"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
Loading
Loading