├── .gitattributes ├── .github └── workflows │ └── ci-validation.yml ├── .gitignore ├── .run ├── Angular classic unit test.run.xml ├── Angular cypress unit test.run.xml ├── Angular serve.run.xml ├── ChatApiApplication.run.xml ├── Cypress open.run.xml ├── Cypress run.run.xml ├── React serve .run.xml └── Vue serve.run.xml ├── LICENSE ├── README.md ├── angular-chat ├── .editorconfig ├── .gitignore ├── README.md ├── angular.json ├── cypress.config.ts ├── cypress │ ├── fixtures │ │ └── example.json │ └── support │ │ ├── commands.ts │ │ ├── component-index.html │ │ └── component.ts ├── package-lock.json ├── package.json ├── src │ ├── app │ │ ├── app.component.cy.ts │ │ ├── app.component.html │ │ ├── app.component.scss │ │ ├── app.component.ts │ │ ├── app.compponent.spec.ts │ │ ├── app.module.ts │ │ ├── messages │ │ │ ├── message.component.cy.ts │ │ │ ├── message.interface.ts │ │ │ ├── message.service.ts │ │ │ ├── messages.component.html │ │ │ ├── messages.component.scss │ │ │ └── messages.component.ts │ │ └── user │ │ │ ├── user.interface.ts │ │ │ └── user.service.ts │ ├── assets │ │ └── .gitkeep │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── index.html │ ├── main.ts │ ├── polyfills.ts │ └── styles.scss ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.spec.json └── tslint.json ├── chat-api ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── wandrillecorp │ │ │ └── chatapi │ │ │ ├── ChatApiApplication.java │ │ │ ├── api │ │ │ ├── WebSocketConfig.java │ │ │ ├── message │ │ │ │ ├── MessageController.java │ │ │ │ ├── MessageCreatedCommand.java │ │ │ │ └── WebSocketMessage.java │ │ │ └── user │ │ │ │ ├── UserController.java │ │ │ │ └── UserCreatedCommand.java │ │ │ ├── application │ │ │ ├── MessageManager.java │ │ │ └── UserManager.java │ │ │ ├── domain │ │ │ ├── ValueObject.java │ │ │ ├── bus │ │ │ │ └── ChatMessageBus.java │ │ │ ├── message │ │ │ │ ├── Message.java │ │ │ │ └── MessageRepository.java │ │ │ └── user │ │ │ │ ├── User.java │ │ │ │ └── UserRepository.java │ │ │ └── infrastructure │ │ │ ├── messageBus │ │ │ ├── KafkaEmission.java │ │ │ └── KafkaEventHandler.java │ │ │ └── repository │ │ │ ├── message │ │ │ ├── DefaultMongoMessageRepository.java │ │ │ └── MongoMessageRepository.java │ │ │ └── user │ │ │ ├── DefaultMongoUserRepository.java │ │ │ └── MongoUserRepository.java │ └── resources │ │ ├── application.yml │ │ └── avro │ │ └── message.avsc │ └── test │ └── java │ └── com │ └── wandrillecorp │ └── chatapi │ └── ChatApiApplicationTests.java ├── deploy ├── deploy.iml └── docker-compose.yml ├── doc ├── message_screen.jpg └── user_screen.jpg ├── e2e-tests ├── .cypress-cucumber-preprocessorrc.json ├── .gitignore ├── cypress.config.ts ├── cypress │ ├── e2e │ │ ├── chat-access.feature │ │ ├── chat-access.ts │ │ ├── common-step-definitions │ │ │ ├── common.ts │ │ │ └── system.ts │ │ ├── messages.feature │ │ └── messages.ts │ ├── fixtures │ │ └── example.json │ └── support │ │ ├── commands.ts │ │ └── e2e.ts ├── package-lock.json ├── package.json └── tsconfig.json ├── react-chat ├── .eslintrc.json ├── .gitignore ├── README.md ├── next.config.js ├── package-lock.json ├── package.json ├── postcss.config.js ├── public │ ├── favicon.ico │ ├── next.svg │ └── vercel.svg ├── src │ ├── interface │ │ ├── message.interface.ts │ │ └── user.interface.ts │ ├── pages │ │ ├── _app.tsx │ │ ├── _document.tsx │ │ ├── index.tsx │ │ └── messages │ │ │ └── Messages.tsx │ └── styles │ │ ├── Message.module.scss │ │ └── globals.scss └── tsconfig.json └── vue-chat ├── .eslintrc.cjs ├── .gitignore ├── .prettierrc.json ├── README.md ├── env.d.ts ├── index.html ├── package-lock.json ├── package.json ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── assets │ └── logo.png ├── components │ ├── Messages.vue │ ├── __tests__ │ │ └── Messages.spec.ts │ └── message.interface.ts ├── main.ts └── user.interface.ts ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.node.json ├── tsconfig.vitest.json ├── vite.config.ts └── vitest.config.ts /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/ci-validation.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs 3 | 4 | name: CI Deployment Github Action 5 | 6 | on: 7 | workflow_dispatch: 8 | push: 9 | branches: [ "test-ci", "master" ] 10 | 11 | jobs: 12 | Check-Angular: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | - name: Use Node.js 17 | uses: actions/setup-node@v3 18 | with: 19 | cache: 'npm' 20 | cache-dependency-path: | 21 | angular-chat/package-lock.json 22 | - name: Install 23 | run: npm ci 24 | working-directory: angular-chat 25 | - name: Build 26 | run: npm run build 27 | working-directory: angular-chat 28 | - name: Test karma 29 | run: npm run test:prod 30 | working-directory: angular-chat 31 | - name: Test Cypress 32 | run: npm run test:cypress 33 | working-directory: angular-chat 34 | Check-React: 35 | runs-on: ubuntu-latest 36 | steps: 37 | - uses: actions/checkout@v3 38 | - name: Use Node.js 39 | uses: actions/setup-node@v3 40 | with: 41 | cache: 'npm' 42 | cache-dependency-path: | 43 | react-chat/package-lock.json 44 | - name: Install 45 | run: npm ci 46 | working-directory: react-chat 47 | - name: Build 48 | run: npm run build 49 | working-directory: react-chat 50 | Check-Vue: 51 | runs-on: ubuntu-latest 52 | steps: 53 | - uses: actions/checkout@v3 54 | - name: Use Node.js 55 | uses: actions/setup-node@v3 56 | with: 57 | cache: 'npm' 58 | cache-dependency-path: | 59 | vue-chat/package-lock.json 60 | - name: Install 61 | run: npm ci 62 | working-directory: vue-chat 63 | - name: Build 64 | run: npm run build 65 | working-directory: vue-chat 66 | - name: Test 67 | run: npm run test:unit 68 | working-directory: vue-chat 69 | Run-E2E: 70 | needs: [ Check-Vue,Check-Angular,Check-React ] 71 | runs-on: ubuntu-latest 72 | steps: 73 | - uses: actions/checkout@v3 74 | - name: Use Node.js 75 | uses: actions/setup-node@v3 76 | with: 77 | cache: 'npm' 78 | cache-dependency-path: | 79 | vue-chat/package-lock.json 80 | react-chat/package-lock.json 81 | angular-chat/package-lock.json 82 | - name: Use Java 83 | uses: actions/setup-java@v3 84 | with: 85 | distribution: 'adopt' 86 | cache: 'maven' 87 | java-version: '17' 88 | - name: Start Angular 89 | run: | 90 | cd angular-chat && 91 | npm ci && 92 | npm run start & 93 | sleep 5 94 | - name: Start React 95 | run: | 96 | cd react-chat && 97 | npm ci && 98 | npm run dev & 99 | sleep 5 100 | - name: Start React 101 | run: | 102 | cd vue-chat && 103 | npm ci && 104 | npm run dev & 105 | sleep 5 106 | - name: Run docker-compose 107 | run: | 108 | cd deploy && 109 | docker compose -f docker-compose.yml up -d 110 | - name: Install mvn packages 111 | run: | 112 | cd chat-api 113 | mvn compile 114 | - name: Start backend 115 | run: | 116 | cd chat-api 117 | mvn spring-boot:run & 118 | sleep 5 119 | - name: Install and run cypress 120 | run: | 121 | cd e2e-tests 122 | npm ci 123 | npm run start 124 | 125 | 126 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea/* 3 | target 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /.run/Angular classic unit test.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /vue-chat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-chat", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "run-p type-check build-only", 8 | "preview": "vite preview", 9 | "test:unit": "vitest", 10 | "build-only": "vite build", 11 | "type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false", 12 | "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", 13 | "format": "prettier --write src/" 14 | }, 15 | "dependencies": { 16 | "@stomp/stompjs": "^7.0.0", 17 | "axios": "^1.3.6", 18 | "vue": "^3.2.47" 19 | }, 20 | "devDependencies": { 21 | "@rushstack/eslint-patch": "^1.2.0", 22 | "@types/jsdom": "^21.1.0", 23 | "@types/node": "^18.14.2", 24 | "@vitejs/plugin-vue": "^4.0.0", 25 | "@vitejs/plugin-vue-jsx": "^3.0.0", 26 | "@vue/eslint-config-prettier": "^7.1.0", 27 | "@vue/eslint-config-typescript": "^11.0.2", 28 | "@vue/test-utils": "^2.3.0", 29 | "@vue/tsconfig": "^0.1.3", 30 | "eslint": "^8.34.0", 31 | "eslint-plugin-vue": "^9.9.0", 32 | "jsdom": "^21.1.0", 33 | "npm-run-all": "^4.1.5", 34 | "prettier": "^2.8.4", 35 | "sass": "^1.62.0", 36 | "typescript": "~4.8.4", 37 | "vite": "^4.1.4", 38 | "vitest": "^0.29.1", 39 | "vue-tsc": "^1.2.0" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /vue-chat/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wandri/chat-spring-kafka-angular-react-vue/58eb6d42b6e7b9d93e40f3a8f97b3223f618accc/vue-chat/public/favicon.ico -------------------------------------------------------------------------------- /vue-chat/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /vue-chat/src/App.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 45 | 46 | 167 | -------------------------------------------------------------------------------- /vue-chat/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wandri/chat-spring-kafka-angular-react-vue/58eb6d42b6e7b9d93e40f3a8f97b3223f618accc/vue-chat/src/assets/logo.png -------------------------------------------------------------------------------- /vue-chat/src/components/Messages.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 114 | 115 | 237 | -------------------------------------------------------------------------------- /vue-chat/src/components/__tests__/Messages.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest' 2 | 3 | import { mount } from '@vue/test-utils' 4 | import App from "../../App.vue"; 5 | 6 | describe('App', () => { 7 | it('renders properly', () => { 8 | const wrapper = mount(App) 9 | 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /vue-chat/src/components/message.interface.ts: -------------------------------------------------------------------------------- 1 | export interface Message { 2 | id: string; 3 | text: string; 4 | userId: string; 5 | userName: string; 6 | date: Date; 7 | } 8 | -------------------------------------------------------------------------------- /vue-chat/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from "vue"; 2 | import App from "./App.vue"; 3 | 4 | createApp(App).mount("#app"); 5 | -------------------------------------------------------------------------------- /vue-chat/src/user.interface.ts: -------------------------------------------------------------------------------- 1 | export class User { 2 | name: string; 3 | id: string; 4 | 5 | constructor(name: string, id: string) { 6 | this.name = name; 7 | this.id = id; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /vue-chat/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.web.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], 4 | "exclude": ["src/**/__tests__/*"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "baseUrl": ".", 8 | "paths": { 9 | "@/*": ["./src/*"] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /vue-chat/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { 5 | "path": "./tsconfig.node.json" 6 | }, 7 | { 8 | "path": "./tsconfig.app.json" 9 | }, 10 | { 11 | "path": "./tsconfig.vitest.json" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /vue-chat/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.node.json", 3 | "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"], 4 | "compilerOptions": { 5 | "composite": true, 6 | "types": ["node"] 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /vue-chat/tsconfig.vitest.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.app.json", 3 | "exclude": [], 4 | "compilerOptions": { 5 | "composite": true, 6 | "lib": [], 7 | "types": ["node", "jsdom"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /vue-chat/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | import vueJsx from '@vitejs/plugin-vue-jsx' 6 | 7 | // https://vitejs.dev/config/ 8 | export default defineConfig({ 9 | plugins: [vue(), vueJsx()], 10 | resolve: { 11 | alias: { 12 | '@': fileURLToPath(new URL('./src', import.meta.url)) 13 | } 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /vue-chat/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'node:url' 2 | import { mergeConfig } from 'vite' 3 | import { configDefaults, defineConfig } from 'vitest/config' 4 | import viteConfig from './vite.config' 5 | 6 | export default mergeConfig( 7 | viteConfig, 8 | defineConfig({ 9 | test: { 10 | environment: 'jsdom', 11 | exclude: [...configDefaults.exclude, 'e2e/*'], 12 | root: fileURLToPath(new URL('./', import.meta.url)) 13 | } 14 | }) 15 | ) 16 | --------------------------------------------------------------------------------