4 |
5 | ## Descrição
6 |
7 | Repositórios do Esquenta Maratona FullCycle 4.0
8 |
9 | ## Rodar a aplicação
10 |
11 | #### Antes de começar
12 |
13 | A aplicação foi construída utilizando os conceitos de microsserviços e arquitetada com Docker.
14 |
15 | Para roda-la será necessário basicamente rodar o comando **docker-compose up**.
16 |
17 | Acesse cada microsserviço respectivamente e leia o README.md para ver mais detalhes de como rodar o microsserviço.
18 |
19 | * [Backend API REST com Nest.js](https://github.com/codeedu/maratona4-esquenta/tree/master/backend-api)
20 |
21 | ### Para Windows
22 |
23 | Lembrar de instalar o WSL2 e Docker. Vejo o vídeo: [https://www.youtube.com/watch?v=g4HKttouVxA](https://www.youtube.com/watch?v=g4HKttouVxA)
24 |
25 | Siga o guia rápido de instalação: [https://github.com/codeedu/wsl2-docker-quickstart](https://github.com/codeedu/wsl2-docker-quickstart)
26 |
--------------------------------------------------------------------------------
/auth/.docker/mysql/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mysql:5.7
2 |
3 | RUN usermod -u 1000 mysql
--------------------------------------------------------------------------------
/auth/.gitgnore:
--------------------------------------------------------------------------------
1 | .docker/dbdata/
2 | .history/
--------------------------------------------------------------------------------
/auth/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.7"
2 |
3 | services:
4 |
5 | app:
6 | image: quay.io/keycloak/keycloak:11.0.0
7 | container_name: esquenta-4-auth-app
8 | environment:
9 | KEYCLOAK_USER: admin
10 | KEYCLOAK_PASSWORD: admin
11 | DB_ADDR: db
12 | DB_VENDOR: mysql
13 | DB_DATABASE: auth
14 | DB_PORT: 3306
15 | DB_USER: root
16 | DB_PASSWORD: root
17 | JDBC_PARAMS: 'useSSL=false'
18 | ports:
19 | - 8080:8080
20 | depends_on:
21 | - db
22 | networks:
23 | - esquenta-rede
24 |
25 | db:
26 | build: ./.docker/mysql
27 | container_name: esquenta-4-auth-db
28 | restart: always
29 | tty: true
30 | command: [mysqld, --default_authentication_plugin=mysql_native_password, --character-set-server=utf8, --collation-server=utf8_bin, --default-storage-engine=INNODB]
31 | ports:
32 | - "33007:3306"
33 | volumes:
34 | - ./.docker/dbdata:/var/lib/mysql
35 | environment:
36 | MYSQL_DATABASE: auth
37 | MYSQL_ROOT_PASSWORD: root
38 | MYSQL_USER: root
39 | networks:
40 | - esquenta-rede
41 |
42 | networks:
43 | esquenta-rede:
44 | driver: bridge
--------------------------------------------------------------------------------
/backend-api/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | // For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.128.0/containers/docker-existing-docker-compose
3 | // If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml.
4 | {
5 | "name": "nest-esquenta-4",
6 |
7 | // Update the 'dockerComposeFile' list if you have more compose files or use different names.
8 | // The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
9 | "dockerComposeFile": [
10 | "../docker-compose.yml",
11 | "docker-compose.yml"
12 | ],
13 |
14 | // The 'service' property is the name of the service for the container that VS Code should
15 | // use. Update this value and .devcontainer/docker-compose.yml to the real service name.
16 | "service": "app",
17 |
18 | // The optional 'workspaceFolder' property is the path VS Code should open by default when
19 | // connected. This is typically a file mount in .devcontainer/docker-compose.yml
20 | "workspaceFolder": "/nest",
21 |
22 | // Set *default* container specific settings.json values on container create.
23 | "settings": {
24 | "terminal.integrated.shell.linux": null
25 | },
26 |
27 | // Add the IDs of extensions you want installed when the container is created.
28 | "extensions": [
29 | "humao.rest-client"
30 | ]
31 |
32 | // Use 'forwardPorts' to make a list of ports inside the container available locally.
33 | // "forwardPorts": [],
34 |
35 | // Uncomment the next line if you want start specific services in your Docker Compose config.
36 | // "runServices": [],
37 |
38 | // Uncomment the next line if you want to keep your containers running after VS Code shuts down.
39 | // "shutdownAction": "none",
40 |
41 | // Uncomment the next line to run commands after the container is created - for example installing curl.
42 | // "postCreateCommand": "apt-get update && apt-get install -y curl",
43 |
44 | // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
45 | // "remoteUser": "vscode"
46 | }
47 |
--------------------------------------------------------------------------------
/backend-api/.devcontainer/docker-compose.yml:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------------------------------------------------------------------
2 | # Copyright (c) Microsoft Corporation. All rights reserved.
3 | # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
4 | #-------------------------------------------------------------------------------------------------------------
5 |
6 | version: '3'
7 | services:
8 | # Update this to the name of the service you want to work with in your docker-compose.yml file
9 | app:
10 | # If you want add a non-root user to your Dockerfile, you can use the "remoteUser"
11 | # property in devcontainer.json to cause VS Code its sub-processes (terminals, tasks,
12 | # debugging) to execute as the user. Uncomment the next line if you want the entire
13 | # container to run as this user instead. Note that, on Linux, you may need to
14 | # ensure the UID and GID of the container user you create matches your local user.
15 | # See https://aka.ms/vscode-remote/containers/non-root for details.
16 | #
17 | # user: vscode
18 |
19 | # Uncomment if you want to override the service's Dockerfile to one in the .devcontainer
20 | # folder. Note that the path of the Dockerfile and context is relative to the *primary*
21 | # docker-compose.yml file (the first in the devcontainer.json "dockerComposeFile"
22 | # array). The sample below assumes your primary file is in the root of your project.
23 | #
24 | # build:
25 | # context: .
26 | # dockerfile: .devcontainer/Dockerfile
27 |
28 | volumes:
29 | # Update this to wherever you want VS Code to mount the folder of your project
30 | - .:/nest:cached
31 |
32 | # Uncomment the next line to use Docker from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker-compose for details.
33 | # - /var/run/docker.sock:/var/run/docker.sock
34 |
35 | # Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust.
36 | # cap_add:
37 | # - SYS_PTRACE
38 | # security_opt:
39 | # - seccomp:unconfined
40 |
41 | # Overrides default command so things don't shut down after the process ends.
42 | command: /bin/sh -c "while sleep 1000; do :; done"
43 |
44 |
--------------------------------------------------------------------------------
/backend-api/.docker/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cd /home/node/app
4 |
5 | if [ ! -f ".env" ]; then
6 | cp .env.example .env
7 | fi
8 |
9 | npm install
10 | npm run typeorm migration:run
11 | npm run start:dev
12 |
--------------------------------------------------------------------------------
/backend-api/.docker/mysql/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mysql:5.7
2 |
3 | RUN usermod -u 1000 mysql
--------------------------------------------------------------------------------
/backend-api/.env.example:
--------------------------------------------------------------------------------
1 | TYPEORM_CONNECTION=mysql
2 | TYPEORM_HOST=db
3 | TYPEORM_USERNAME=root
4 | TYPEORM_PASSWORD=root
5 | TYPEORM_DATABASE=esquenta
6 | TYPEORM_PORT=3306
7 | TYPEORM_ENTITIES=src/**/*.entity.ts
8 | TYPEORM_ENTITIES_DIR=src/models
9 | TYPEORM_MIGRATIONS=src/migrations/**/*.ts
10 | TYPEORM_MIGRATIONS_DIR=src/migrations
--------------------------------------------------------------------------------
/backend-api/.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/eslint-recommended',
10 | 'plugin:@typescript-eslint/recommended',
11 | 'prettier',
12 | 'prettier/@typescript-eslint',
13 | ],
14 | root: true,
15 | env: {
16 | node: true,
17 | jest: true,
18 | },
19 | rules: {
20 | '@typescript-eslint/interface-name-prefix': 'off',
21 | '@typescript-eslint/explicit-function-return-type': 'off',
22 | '@typescript-eslint/no-explicit-any': 'off',
23 | },
24 | };
25 |
--------------------------------------------------------------------------------
/backend-api/.gitignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | /dist
3 | /node_modules
4 |
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 | yarn-debug.log*
10 | yarn-error.log*
11 | lerna-debug.log*
12 |
13 | # OS
14 | .DS_Store
15 |
16 | # Tests
17 | /coverage
18 | /.nyc_output
19 |
20 | # IDEs and editors
21 | /.idea
22 | .project
23 | .classpath
24 | .c9/
25 | *.launch
26 | .settings/
27 | *.sublime-workspace
28 |
29 | # IDE - VSCode
30 | .vscode/*
31 | !.vscode/settings.json
32 | !.vscode/tasks.json
33 | !.vscode/launch.json
34 | !.vscode/extensions.json
35 |
36 | .env
37 | .npm-cache
38 | .docker/dbdata
39 | .history
40 | .idea
--------------------------------------------------------------------------------
/backend-api/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all"
4 | }
--------------------------------------------------------------------------------
/backend-api/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:12.14.0-alpine3.11
2 |
3 | RUN apk add --no-cache bash git
4 |
5 | RUN touch /home/node/.bashrc | echo "PS1='\w\$ '" >> /home/node/.bashrc
6 |
7 | RUN npm config set cache /home/node/app/.npm-cache --global
8 |
9 | RUN npm i -g @nestjs/cli@7.4.1
10 |
11 | USER node
12 |
13 | WORKDIR /home/node/app
14 |
--------------------------------------------------------------------------------
/backend-api/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ## Descrição
6 |
7 | API Rest com Nest.js
8 |
9 | ## Rodar a aplicação
10 |
11 | #### Crie os containers com Docker
12 |
13 | ```bash
14 | $ docker-compose up
15 | ```
16 |
17 | #### Accesse no browser
18 |
19 | ```
20 | http://localhost:3000/api
21 | ```
22 |
--------------------------------------------------------------------------------
/backend-api/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 |
5 | app:
6 | build: .
7 | entrypoint: ./.docker/entrypoint.sh
8 | container_name: esquenta-4-app
9 | environment:
10 | - CHOKIDAR_USEPOLLING=true
11 | ports:
12 | - 3000:3000
13 | volumes:
14 | - .:/home/node/app
15 |
16 | db:
17 | build: ./.docker/mysql
18 | container_name: esquenta-4-db
19 | restart: always
20 | tty: true
21 | ports:
22 | - "33006:3306"
23 | volumes:
24 | - ./.docker/dbdata:/var/lib/mysql
25 | environment:
26 | - MYSQL_DATABASE=esquenta
27 | - MYSQL_ROOT_PASSWORD=root
28 | - MYSQL_USER=root
--------------------------------------------------------------------------------
/backend-api/keycloak.http:
--------------------------------------------------------------------------------
1 | GET http://host.docker.internal:3000/rooms
2 | Content-Type: application/json
3 | Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ4TW4wRHU4ZHdOZlotbWpVcklYYkRLTk5OZkdMOWJZWUwxc2JrNHV4bERJIn0.eyJleHAiOjE1OTc4ODQ5NDMsImlhdCI6MTU5Nzg4NDY0MywiYXV0aF90aW1lIjoxNTk3ODgyODI0LCJqdGkiOiI2YjdlZGE5ZS1mYmVjLTQ0ZGMtYjUwNC1jZTYzMWQxMjM1ZDQiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvQ2hhdCIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiJjNzdmM2U2OC1mNDZjLTRhYWItOGNmZi1lM2M3ODQ3NDI0MTkiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJyZWFjdCIsIm5vbmNlIjoiNzM2OTQyNGEtYWRmNi00OWIzLTlkMDQtNmM3NjBkMTZhZmM3Iiwic2Vzc2lvbl9zdGF0ZSI6IjdhZDk0NDBjLTNiZGMtNDRkMS04NjE4LTE3ZTUxNzI4ZmFkMyIsImFjciI6IjAiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovL2hvc3QuZG9ja2VyLmludGVybmFsOjMwMDEiLCJodHRwOi8vbG9jYWxob3N0OjMwMDEiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsIm5hbWUiOiJUZXN0MSIsInByZWZlcnJlZF91c2VybmFtZSI6InRlc3QxQHRlc3QuY29tIiwiZ2l2ZW5fbmFtZSI6IlRlc3QxIiwiZW1haWwiOiJ0ZXN0MkB0ZXN0LmNvbSJ9.kfWCrCnZapmLiQHakpUCXQv4SHHMJvvzWkZewqhspeEXV48QZxlMy2PNj9apMAjhatfgibV0REC0uctplwdqojfq_BiHNd5JtPKzDQNtnvFLODR3Cfcd9xcP_wgaMLp9r-IBm1SiBIRyxfr9YcKxWJ3X63c2u2pmQl6qvjMG2jHPLxEj6o2K23VTDmO9kEqDnQZHnLJ7YN76MmQbcZ5JIKrNo2_JDlz1UAvaJ2vf3M-PL1JBHtNHZLMAxRjB6Kb-ynSq0SgYzFzX7h9OMsHzDyPqokIsb3UOeRidqL1ALFvofMq5l5fpPGp6zpy0N-_Z8uKrzjVmWo63AOVgmotlQQ
--------------------------------------------------------------------------------
/backend-api/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "collection": "@nestjs/schematics",
3 | "sourceRoot": "src"
4 | }
5 |
--------------------------------------------------------------------------------
/backend-api/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "backend-api",
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 | "typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js"
23 | },
24 | "dependencies": {
25 | "@nestjs/common": "^7.0.0",
26 | "@nestjs/config": "^0.5.0",
27 | "@nestjs/core": "^7.0.0",
28 | "@nestjs/platform-express": "^7.0.0",
29 | "@nestjs/platform-socket.io": "^7.4.2",
30 | "@nestjs/swagger": "^4.5.12",
31 | "@nestjs/typeorm": "^7.1.0",
32 | "@nestjs/websockets": "^7.4.2",
33 | "class-transformer": "^0.3.1",
34 | "class-validator": "^0.12.2",
35 | "mysql": "^2.18.1",
36 | "nestjs-keycloak-admin": "^1.3.1",
37 | "reflect-metadata": "^0.1.13",
38 | "rimraf": "^3.0.2",
39 | "rxjs": "^6.5.4",
40 | "swagger-ui-express": "^4.1.4",
41 | "typeorm": "^0.2.25"
42 | },
43 | "devDependencies": {
44 | "@nestjs/cli": "^7.0.0",
45 | "@nestjs/schematics": "^7.0.0",
46 | "@nestjs/testing": "^7.0.0",
47 | "@types/express": "^4.17.3",
48 | "@types/jest": "25.2.3",
49 | "@types/node": "^13.9.1",
50 | "@types/socket.io": "^2.1.11",
51 | "@types/supertest": "^2.0.8",
52 | "@typescript-eslint/eslint-plugin": "3.0.2",
53 | "@typescript-eslint/parser": "3.0.2",
54 | "eslint": "7.1.0",
55 | "eslint-config-prettier": "^6.10.0",
56 | "eslint-plugin-import": "^2.20.1",
57 | "jest": "26.0.1",
58 | "prettier": "^1.19.1",
59 | "supertest": "^4.0.2",
60 | "ts-jest": "26.1.0",
61 | "ts-loader": "^6.2.1",
62 | "ts-node": "^8.6.2",
63 | "tsconfig-paths": "^3.9.0",
64 | "typescript": "^3.7.4"
65 | },
66 | "jest": {
67 | "moduleFileExtensions": [
68 | "js",
69 | "json",
70 | "ts"
71 | ],
72 | "rootDir": "src",
73 | "testRegex": ".spec.ts$",
74 | "transform": {
75 | "^.+\\.(t|j)s$": "ts-jest"
76 | },
77 | "coverageDirectory": "../coverage",
78 | "testEnvironment": "node"
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/backend-api/room.http:
--------------------------------------------------------------------------------
1 | POST http://localhost:3000/rooms
2 | Content-type: application/json
3 |
4 | {
5 | "name": "Sala 2"
6 | }
7 |
8 | ###
9 |
10 | GET http://localhost:3000/rooms
11 |
12 | ###
13 | GET http://localhost:3000/rooms/1
--------------------------------------------------------------------------------
/backend-api/src/api-doc/room.response.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from "@nestjs/swagger";
2 |
3 | export class RoomResponse {
4 |
5 | @ApiProperty({
6 | description: 'Id of User'
7 | })
8 | id: number;
9 |
10 | @ApiProperty()
11 | name: string;
12 |
13 | @ApiProperty()
14 | created_at: Date
15 | }
16 |
--------------------------------------------------------------------------------
/backend-api/src/api-doc/user.response.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from "@nestjs/swagger";
2 |
3 | export class UserResponse {
4 | @ApiProperty()
5 | id: number;
6 |
7 | @ApiProperty({
8 | type: String,
9 | description: 'name of user'
10 | })
11 | name: string;
12 |
13 | @ApiProperty()
14 | email: string;
15 |
16 | @ApiProperty()
17 | created_at:Date
18 | }
--------------------------------------------------------------------------------
/backend-api/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 |
--------------------------------------------------------------------------------
/backend-api/src/app.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get } from '@nestjs/common';
2 | import { AppService } from './app.service';
3 |
4 | @Controller()
5 | export class AppController {
6 | constructor(private readonly appService: AppService) {}
7 |
8 | @Get()
9 | getHello(): string {
10 | return this.appService.getHello();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend-api/src/app.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { AppController } from './app.controller';
3 | import { AppService } from './app.service';
4 | import { TypeOrmModule } from '@nestjs/typeorm';
5 | import { User } from './models/user.model';
6 | import { ConfigModule } from '@nestjs/config';
7 | import { UserController } from './controllers/user/user.controller';
8 | import { RoomController } from './controllers/room/room.controller';
9 | import { Room } from './models/room.model';
10 | import { WebsocketService } from './websocket/websocket.service';
11 | import KeycloakModule, { AuthGuard } from 'nestjs-keycloak-admin';
12 | import { APP_GUARD } from '@nestjs/core';
13 | @Module({
14 | imports: [
15 | ConfigModule.forRoot(),
16 | TypeOrmModule.forRoot({
17 | // @ts-ignore
18 | type: process.env.TYPEORM_CONNECTION,
19 | host: process.env.TYPEORM_HOST,
20 | port: parseInt(process.env.TYPEORM_PORT),
21 | username: process.env.TYPEORM_USERNAME,
22 | password: process.env.TYPEORM_PASSWORD,
23 | database: process.env.TYPEORM_DATABASE,
24 | entities: [User, Room],
25 | }),
26 | TypeOrmModule.forFeature([User, Room]),
27 | KeycloakModule.registerAsync({
28 | useFactory: () => {
29 | const keycloakConfig = JSON.parse(process.env.KEYCLOAK_JSON);
30 | return {
31 | baseUrl: keycloakConfig['auth-server-url'],
32 | realmName: keycloakConfig['realm'],
33 | clientId: keycloakConfig['resource'],
34 | clientSecret: keycloakConfig['credentials']['secret'],
35 | };
36 | },
37 | }),
38 | ],
39 | controllers: [AppController, UserController, RoomController],
40 | providers: [AppService, WebsocketService, {provide: APP_GUARD, useClass: AuthGuard}],
41 | })
42 | export class AppModule {}
43 |
--------------------------------------------------------------------------------
/backend-api/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 |
--------------------------------------------------------------------------------
/backend-api/src/controllers/room/room.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { RoomController } from './room.controller';
3 |
4 | describe('Room Controller', () => {
5 | let controller: RoomController;
6 |
7 | beforeEach(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | controllers: [RoomController],
10 | }).compile();
11 |
12 | controller = module.get(RoomController);
13 | });
14 |
15 | it('should be defined', () => {
16 | expect(controller).toBeDefined();
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/backend-api/src/controllers/room/room.controller.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Controller,
3 | Param,
4 | Body,
5 | Get,
6 | Post,
7 | Put,
8 | Delete,
9 | HttpCode,
10 | UseInterceptors,
11 | ClassSerializerInterceptor,
12 | ValidationPipe,
13 | } from '@nestjs/common';
14 | import { Repository } from 'typeorm';
15 | import { Room } from 'src/models/room.model';
16 | import { InjectRepository } from '@nestjs/typeorm';
17 | import { RoomDto } from 'src/dto/room.dto';
18 | import {
19 | ApiOkResponse,
20 | ApiCreatedResponse,
21 | ApiNoContentResponse,
22 | } from '@nestjs/swagger';
23 | import { RoomResponse } from 'src/api-doc/room.response';
24 | import { Public } from 'nestjs-keycloak-admin';
25 |
26 | @UseInterceptors(ClassSerializerInterceptor)
27 | @Controller('rooms')
28 | export class RoomController {
29 | constructor(
30 | @InjectRepository(Room)
31 | private roomRepo: Repository,
32 | ) {}
33 |
34 | // @Public()
35 | @ApiOkResponse({ type: RoomResponse })
36 | @Get()
37 | async index(): Promise {
38 | return this.roomRepo.find();
39 | }
40 |
41 | @ApiOkResponse({
42 | type: RoomResponse,
43 | })
44 | @Get(':id')
45 | async show(@Param('id') id: string): Promise {
46 | return this.roomRepo.findOneOrFail(+id);
47 | }
48 |
49 | @ApiCreatedResponse({
50 | type: RoomResponse,
51 | status: 201,
52 | })
53 | @Post()
54 | async store(@Body(new ValidationPipe()) roomDto: RoomDto): Promise {
55 | const room = this.roomRepo.create(roomDto);
56 | return this.roomRepo.save(room);
57 | }
58 |
59 | @ApiOkResponse({
60 | type: RoomResponse,
61 | })
62 | @Put(':id')
63 | async update(
64 | @Param('id') id: string,
65 | @Body(new ValidationPipe()) roomDto: RoomDto,
66 | ): Promise {
67 | await this.roomRepo.findOneOrFail(+id);
68 | this.roomRepo.update({ id: +id }, roomDto);
69 | return this.roomRepo.findOneOrFail(+id);
70 | }
71 |
72 | @ApiNoContentResponse()
73 | @Delete(':id')
74 | @HttpCode(204)
75 | async destroy(@Param('id') id: string): Promise {
76 | await this.roomRepo.findOneOrFail(+id);
77 | this.roomRepo.delete(+id);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/backend-api/src/controllers/user/user.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { UserController } from './user.controller';
3 |
4 | describe('User Controller', () => {
5 | let controller: UserController;
6 |
7 | beforeEach(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | controllers: [UserController],
10 | }).compile();
11 |
12 | controller = module.get(UserController);
13 | });
14 |
15 | it('should be defined', () => {
16 | expect(controller).toBeDefined();
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/backend-api/src/controllers/user/user.controller.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Controller,
3 | Get,
4 | Post,
5 | Put,
6 | Delete,
7 | Body,
8 | Param,
9 | HttpCode,
10 | ValidationPipe,
11 | UseInterceptors,
12 | ClassSerializerInterceptor,
13 | } from '@nestjs/common';
14 | import { Repository } from 'typeorm';
15 | import { User } from 'src/models/user.model';
16 | import { InjectRepository } from '@nestjs/typeorm';
17 | import { ApiOkResponse, ApiCreatedResponse } from '@nestjs/swagger';
18 | import { UserResponse } from 'src/api-doc/user.response';
19 | import { UserDto } from 'src/dto/user.dto';
20 |
21 | //API REST - POST users
22 | @UseInterceptors(ClassSerializerInterceptor)
23 | @Controller('users')
24 | export class UserController {
25 | constructor(
26 | @InjectRepository(User)
27 | private userRepo: Repository, //Generic
28 | ) {}
29 |
30 | @Get()
31 | async index(): Promise {
32 | return this.userRepo.find();
33 | }
34 |
35 | @ApiOkResponse({
36 | type: UserResponse
37 | })
38 | @Get(':id')
39 | show(@Param('id') id: string): Promise {
40 | return this.userRepo.findOneOrFail(id);
41 | }
42 |
43 | @ApiCreatedResponse({
44 | type: UserResponse
45 | })
46 | @Post()
47 | async store(@Body(new ValidationPipe({
48 | errorHttpStatusCode: 422
49 | })) body: UserDto): Promise {
50 | const user = this.userRepo.create(body);
51 | return this.userRepo.save(user);
52 | }
53 |
54 | @Put(':id')
55 | async update(@Param('id') id: string, @Body() body: User): Promise {
56 | await this.userRepo.findOneOrFail(+id);
57 | this.userRepo.update({id: +id}, body);
58 | return this.userRepo.findOneOrFail(+id);
59 | }
60 |
61 | @Delete(':id')
62 | @HttpCode(204)
63 | async destroy(@Param('id') id: string): Promise { ///204 - No content
64 | await this.userRepo.findOneOrFail(+id);
65 | this.userRepo.delete(id);
66 | }
67 | }
--------------------------------------------------------------------------------
/backend-api/src/dto/room.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsString, IsNotEmpty } from 'class-validator';
2 | import { ApiProperty } from '@nestjs/swagger';
3 |
4 | export class RoomDto {
5 | @ApiProperty({
6 | type: String,
7 | description: "Name of room",
8 | })
9 | @IsString()
10 | @IsNotEmpty()
11 | readonly name: string;
12 | }
--------------------------------------------------------------------------------
/backend-api/src/dto/user.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from "@nestjs/swagger";
2 | import {IsString, IsNotEmpty, IsEmail} from 'class-validator';
3 |
4 | export class UserDto{
5 |
6 | @ApiProperty({
7 | type: String,
8 | description: 'name of user'
9 | })
10 | @IsString()
11 | @IsNotEmpty()
12 | name: string;
13 |
14 | @ApiProperty()
15 | @IsEmail()
16 | @IsNotEmpty()
17 | email: string;
18 | }
--------------------------------------------------------------------------------
/backend-api/src/exception-filters/entity-not-found.exception-filter.ts:
--------------------------------------------------------------------------------
1 | import { ExceptionFilter, ArgumentsHost } from '@nestjs/common';
2 | import { EntityNotFoundError } from 'typeorm/error/EntityNotFoundError';
3 | import { Response } from 'express';
4 |
5 | export class EntityNotFoundExceptionFilter implements ExceptionFilter {
6 | catch(exception: EntityNotFoundError, host: ArgumentsHost) {
7 | const ctx = host.switchToHttp();
8 | const response = ctx.getResponse();
9 | return response
10 | .status(404)
11 | .json({
12 | message: {
13 | statusCode: 404,
14 | error: 'Not Found',
15 | message: exception.message,
16 | },
17 | });
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/backend-api/src/main.ts:
--------------------------------------------------------------------------------
1 | import { NestFactory } from '@nestjs/core';
2 | import { AppModule } from './app.module';
3 | import {DocumentBuilder, SwaggerModule} from '@nestjs/swagger';
4 | import { EntityNotFoundExceptionFilter } from './exception-filters/entity-not-found.exception-filter';
5 |
6 | async function bootstrap() {
7 | const app = await NestFactory.create(AppModule, {cors: true});
8 | app.useGlobalFilters(new EntityNotFoundExceptionFilter());
9 |
10 | const options = new DocumentBuilder()
11 | .setTitle('Nest.js API Fullcycle')
12 | .setDescription('Documentação da API do Nest.js')
13 | .build();
14 |
15 | const document = SwaggerModule.createDocument(app, options);
16 | SwaggerModule.setup('api', app, document);
17 |
18 | await app.listen(3000);
19 | }
20 | bootstrap();
21 |
--------------------------------------------------------------------------------
/backend-api/src/migrations/1597362274197-CreateUserTable.ts:
--------------------------------------------------------------------------------
1 | import {MigrationInterface, QueryRunner, Table} from "typeorm";
2 |
3 | export class CreateUserTable1597362274197 implements MigrationInterface {
4 |
5 | public async up(queryRunner: QueryRunner): Promise {
6 | await queryRunner.createTable(new Table({
7 | name: 'user',
8 | columns: [
9 | {
10 | name: 'id',
11 | type: 'int',
12 | isPrimary: true,
13 | isGenerated: true,
14 | generationStrategy: 'increment'
15 | },
16 | {
17 | name: 'name',
18 | type: 'varchar',
19 | },
20 | {
21 | name: 'email',
22 | type: 'varchar',
23 | },
24 | {
25 | name: 'created_at',
26 | type: 'timestamp',
27 | default: 'CURRENT_TIMESTAMP'
28 | }
29 | ]
30 | }))
31 | }
32 |
33 | public async down(queryRunner: QueryRunner): Promise {
34 | await queryRunner.dropTable('user');
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/backend-api/src/migrations/1597518554584-CreateRoomTable.ts:
--------------------------------------------------------------------------------
1 | import {MigrationInterface, QueryRunner, Table} from "typeorm";
2 |
3 | export class CreateRoomTable1597518554584 implements MigrationInterface {
4 |
5 | public async up(queryRunner: QueryRunner): Promise {
6 | await queryRunner.createTable(new Table({
7 | name: 'room',
8 | columns: [
9 | {
10 | name: 'id',
11 | type: 'int',
12 | isPrimary: true,
13 | isGenerated: true,
14 | generationStrategy: 'increment'
15 | },
16 | {
17 | name: 'name',
18 | type: 'text'
19 | },
20 | {
21 | name: 'created_at',
22 | type: 'timestamp',
23 | default: 'CURRENT_TIMESTAMP'
24 | }
25 | ]
26 | }))
27 | }
28 |
29 | public async down(queryRunner: QueryRunner): Promise {
30 | await queryRunner.dropTable('room')
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/backend-api/src/models/room.model.ts:
--------------------------------------------------------------------------------
1 | import {Entity, PrimaryGeneratedColumn, Column, CreateDateColumn} from "typeorm";
2 |
3 | @Entity()
4 | export class Room {
5 |
6 | @PrimaryGeneratedColumn()
7 | id: number;
8 |
9 | @Column()
10 | name: string;
11 |
12 | @CreateDateColumn({type: 'timestamp'})
13 | created_at: Date;
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/backend-api/src/models/user.model.ts:
--------------------------------------------------------------------------------
1 | import {Entity, PrimaryGeneratedColumn, Column, CreateDateColumn} from "typeorm";
2 | import {Exclude} from 'class-transformer';
3 | //
4 | @Entity()
5 | export class User{
6 |
7 | @PrimaryGeneratedColumn()
8 | id: number;
9 |
10 | @Column()
11 | name: string;
12 |
13 | @Column()
14 | email: string;
15 |
16 | @Exclude()
17 | @CreateDateColumn({type: 'timestamp'})
18 | created_at: Date
19 | }
--------------------------------------------------------------------------------
/backend-api/src/websocket/websocket.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { WebsocketService } from './websocket.service';
3 |
4 | describe('WebsocketService', () => {
5 | let service: WebsocketService;
6 |
7 | beforeEach(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | providers: [WebsocketService],
10 | }).compile();
11 |
12 | service = module.get(WebsocketService);
13 | });
14 |
15 | it('should be defined', () => {
16 | expect(service).toBeDefined();
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/backend-api/src/websocket/websocket.service.ts:
--------------------------------------------------------------------------------
1 | import {
2 | WebSocketGateway,
3 | WebSocketServer,
4 | OnGatewayConnection,
5 | SubscribeMessage,
6 | MessageBody,
7 | ConnectedSocket,
8 | } from '@nestjs/websockets';
9 | import { Server, Socket } from 'socket.io';
10 |
11 | @WebSocketGateway(0, { namespace: 'room' })
12 | export class WebsocketService implements OnGatewayConnection {
13 | @WebSocketServer()
14 | private server: Server;
15 |
16 | private users = {};
17 |
18 | handleConnection(client: Socket, ...args: any[]) {
19 | client.disconnect(true)
20 | // const {name} = client.handshake.query;
21 | // this.users[client.id] = {name};
22 | // console.log(this.users);
23 | }
24 | //web - Nginx | Apache - Aplicação
25 | @SubscribeMessage('join')
26 | joinRoom(
27 | @ConnectedSocket() client: Socket,
28 | @MessageBody() body: { name: string; room_id: string },
29 | ): void {
30 | //varro o array de users e todos da room_id 23
31 | //contar, número é atual 2 disconnect
32 | //
33 | const { name, room_id } = body;
34 | this.users[client.id] = { name, room_id };
35 | client.join(room_id);
36 |
37 | console.log('join', client.id, body);
38 | }
39 |
40 | @SubscribeMessage('send-message')
41 | sendMessage(
42 | @ConnectedSocket() client: Socket,
43 | @MessageBody() body: { message: string },
44 | ): void {
45 | const { name, room_id } = this.users[client.id];
46 | client.broadcast.to(room_id).emit('receive-message', { ...body, name });
47 | console.log(body);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/backend-api/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 |
--------------------------------------------------------------------------------
/backend-api/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 |
--------------------------------------------------------------------------------
/backend-api/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/backend-api/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 | }
15 | }
16 |
--------------------------------------------------------------------------------
/backend-api/user.http:
--------------------------------------------------------------------------------
1 | POST http://localhost:3000/users
2 | Content-type: application/json
3 |
4 | {
5 | "name": "Luiz Carlos",
6 | "email": "argentinaluiz@gmail.com"
7 | }
8 |
9 | ###
10 |
11 | GET http://localhost:3000/users
12 |
13 | ###
14 | GET http://localhost:3000/users/1
15 |
16 | ###
17 | PUT http://localhost:3000/users/1
18 | Content-type: application/json
19 |
20 | {
21 | "name": "Luiz Carlos - teste44444",
22 | "email": "argentinaluiz1@gmail.com"
23 | }
24 |
25 | ###
26 | DELETE http://localhost:3000/users/1
27 |
28 | ###
29 | POST http://localhost:3000/users
30 | Content-type: application/json
31 |
32 | {
33 | "name": "adfadsf",
34 | "email": "teste@teste.com"
35 | }
--------------------------------------------------------------------------------
/frontend/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | // For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.134.0/containers/docker-existing-docker-compose
3 | // If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml.
4 | {
5 | "name": "react-esquenta-4",
6 |
7 | // Update the 'dockerComposeFile' list if you have more compose files or use different names.
8 | // The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
9 | "dockerComposeFile": [
10 | "../docker-compose.yml",
11 | "docker-compose.yml"
12 | ],
13 |
14 | // The 'service' property is the name of the service for the container that VS Code should
15 | // use. Update this value and .devcontainer/docker-compose.yml to the real service name.
16 | "service": "app",
17 |
18 | // The optional 'workspaceFolder' property is the path VS Code should open by default when
19 | // connected. This is typically a file mount in .devcontainer/docker-compose.yml
20 | "workspaceFolder": "/react",
21 |
22 | // Set *default* container specific settings.json values on container create.
23 | "settings": {
24 | "terminal.integrated.shell.linux": null
25 | },
26 |
27 | // Add the IDs of extensions you want installed when the container is created.
28 | "extensions": []
29 |
30 | // Use 'forwardPorts' to make a list of ports inside the container available locally.
31 | // "forwardPorts": [],
32 |
33 | // Uncomment the next line if you want start specific services in your Docker Compose config.
34 | // "runServices": [],
35 |
36 | // Uncomment the next line if you want to keep your containers running after VS Code shuts down.
37 | // "shutdownAction": "none",
38 |
39 | // Uncomment the next line to run commands after the container is created - for example installing curl.
40 | // "postCreateCommand": "apt-get update && apt-get install -y curl",
41 |
42 | // Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
43 | // "remoteUser": "vscode"
44 | }
45 |
--------------------------------------------------------------------------------
/frontend/.devcontainer/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | # Update this to the name of the service you want to work with in your docker-compose.yml file
4 | app:
5 | # If you want add a non-root user to your Dockerfile, you can use the "remoteUser"
6 | # property in devcontainer.json to cause VS Code its sub-processes (terminals, tasks,
7 | # debugging) to execute as the user. Uncomment the next line if you want the entire
8 | # container to run as this user instead. Note that, on Linux, you may need to
9 | # ensure the UID and GID of the container user you create matches your local user.
10 | # See https://aka.ms/vscode-remote/containers/non-root for details.
11 | #
12 | # user: vscode
13 |
14 | # Uncomment if you want to override the service's Dockerfile to one in the .devcontainer
15 | # folder. Note that the path of the Dockerfile and context is relative to the *primary*
16 | # docker-compose.yml file (the first in the devcontainer.json "dockerComposeFile"
17 | # array). The sample below assumes your primary file is in the root of your project.
18 | #
19 | # build:
20 | # context: .
21 | # dockerfile: .devcontainer/Dockerfile
22 |
23 | volumes:
24 | # Update this to wherever you want VS Code to mount the folder of your project
25 | - .:/react:cached
26 |
27 | # Uncomment the next line to use Docker from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker-compose for details.
28 | # - /var/run/docker.sock:/var/run/docker.sock
29 |
30 | # Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust.
31 | # cap_add:
32 | # - SYS_PTRACE
33 | # security_opt:
34 | # - seccomp:unconfined
35 |
36 | # Overrides default command so things don't shut down after the process ends.
37 | command: /bin/sh -c "while sleep 1000; do :; done"
38 |
39 |
--------------------------------------------------------------------------------
/frontend/.docker/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #if [ ! -f ".env" ]; then
3 | # cp .env.example .env
4 | #fi
5 |
6 | npm install
7 |
8 | npm start
--------------------------------------------------------------------------------
/frontend/.env:
--------------------------------------------------------------------------------
1 | REACT_APP_KEYCLOAK_JSON={"realm":"Chat","auth-server-url":"http://host.docker.internal:8080/auth/","ssl-required":"external","resource":"react","public-client":true,"confidential-port":0}
--------------------------------------------------------------------------------
/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 | .npm-cache/
25 | .history/
26 |
--------------------------------------------------------------------------------
/frontend/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:12.14.0-alpine3.11
2 |
3 | RUN apk add --no-cache bash
4 |
5 | RUN touch /home/node/.bashrc | echo "PS1='\w\$ '" >> /home/node/.bashrc
6 |
7 | RUN npm config set cache /home/node/app/.npm-cache --global
8 |
9 | USER node
10 |
11 | WORKDIR /home/node/app
12 |
--------------------------------------------------------------------------------
/frontend/README.md:
--------------------------------------------------------------------------------
1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
2 |
3 | ## Available Scripts
4 |
5 | In the project directory, you can run:
6 |
7 | ### `npm start`
8 |
9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
11 |
12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console.
14 |
15 | ### `npm test`
16 |
17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
19 |
20 | ### `npm run build`
21 |
22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance.
24 |
25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed!
27 |
28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
29 |
30 | ### `npm run eject`
31 |
32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
33 |
34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
35 |
36 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
37 |
38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
39 |
40 | ## Learn More
41 |
42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
43 |
44 | To learn React, check out the [React documentation](https://reactjs.org/).
45 |
--------------------------------------------------------------------------------
/frontend/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 |
5 | app:
6 | build: .
7 | container_name: esquenta-4-frontend
8 | entrypoint: ./.docker/entrypoint.sh
9 | environment:
10 | - CHOKIDAR_USEPOLLING=true
11 | ports:
12 | - 3001:3000
13 | volumes:
14 | - .:/home/node/app
15 | tty: true
--------------------------------------------------------------------------------
/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "frontend",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@react-keycloak/web": "^2.1.3",
7 | "@testing-library/jest-dom": "^4.2.4",
8 | "@testing-library/react": "^9.5.0",
9 | "@testing-library/user-event": "^7.2.1",
10 | "@types/jest": "^24.9.1",
11 | "@types/node": "^12.12.54",
12 | "@types/react": "^16.9.46",
13 | "@types/react-dom": "^16.9.8",
14 | "@types/react-router-dom": "^5.1.5",
15 | "@types/socket.io-client": "^1.4.33",
16 | "axios": "^0.19.2",
17 | "keycloak-js": "^11.0.0",
18 | "react": "^16.13.1",
19 | "react-dom": "^16.13.1",
20 | "react-router-dom": "^5.2.0",
21 | "react-scripts": "3.4.3",
22 | "socket.io-client": "^2.3.0",
23 | "typescript": "^3.7.5"
24 | },
25 | "scripts": {
26 | "start": "react-scripts start",
27 | "build": "react-scripts build",
28 | "test": "react-scripts test",
29 | "eject": "react-scripts eject"
30 | },
31 | "eslintConfig": {
32 | "extends": "react-app"
33 | },
34 | "browserslist": {
35 | "production": [
36 | ">0.2%",
37 | "not dead",
38 | "not op_mini all"
39 | ],
40 | "development": [
41 | "last 1 chrome version",
42 | "last 1 firefox version",
43 | "last 1 safari version"
44 | ]
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/frontend/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeedu/maratona4-esquenta/f04199435be783afeb62e974f8165c43bc9c09f8/frontend/public/favicon.ico
--------------------------------------------------------------------------------
/frontend/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/frontend/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeedu/maratona4-esquenta/f04199435be783afeb62e974f8165c43bc9c09f8/frontend/public/logo192.png
--------------------------------------------------------------------------------
/frontend/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeedu/maratona4-esquenta/f04199435be783afeb62e974f8165c43bc9c09f8/frontend/public/logo512.png
--------------------------------------------------------------------------------
/frontend/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/frontend/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/frontend/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/frontend/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 | import App from './App';
4 |
5 | test('renders learn react link', () => {
6 | const { getByText } = render();
7 | const linkElement = getByText(/learn react/i);
8 | expect(linkElement).toBeInTheDocument();
9 | });
10 |
--------------------------------------------------------------------------------
/frontend/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { KeycloakProvider } from "@react-keycloak/web";
3 | import { keycloak, keycloakProviderInitConfig } from "./utils/auth";
4 | import { AppRouter } from "./AppRouter";
5 | //JSX
6 | function App() {
7 | return (
8 |
9 |
10 |
11 | );
12 | }
13 |
14 | export default App;
15 |
--------------------------------------------------------------------------------
/frontend/src/AppRouter.tsx:
--------------------------------------------------------------------------------
1 | // @flow
2 | import * as React from "react";
3 | import { BrowserRouter, Switch, Route } from "react-router-dom";
4 | import { Room } from "./components/Room";
5 | import { Chat } from "./components/Chat";
6 | import { useKeycloak } from "@react-keycloak/web";
7 | import { PrivateRoute } from "./components/PrivateRoute";
8 | import { Login } from "./components/Login";
9 | type Props = {};
10 | export const AppRouter = (props: Props) => {
11 | const {initialized} = useKeycloak();
12 |
13 | if(!initialized){
14 | return