Full Code of devfullcycle/imersao12 for AI

main 09811339d58f cached
83 files
66.1 KB
23.9k tokens
64 symbols
1 requests
Download .txt
Repository: devfullcycle/imersao12
Branch: main
Commit: 09811339d58f
Files: 83
Total size: 66.1 KB

Directory structure:
gitextract__u_u31gc/

├── .gitignore
├── README.md
├── apache-kafka/
│   ├── README.md
│   ├── connectors/
│   │   └── elasticsearch.properties
│   └── docker-compose.yaml
├── k8s/
│   ├── backend/
│   │   ├── configmap.yaml
│   │   ├── deploy.yaml
│   │   └── service.yaml
│   ├── frontend/
│   │   ├── deploy.yaml
│   │   └── service.yaml
│   └── simulator/
│       ├── configmap.yaml
│       └── deploy.yaml
├── nest-api/
│   ├── .docker/
│   │   ├── entrypoint.sh
│   │   └── mongo/
│   │       └── init.js
│   ├── .eslintrc.js
│   ├── .gitignore
│   ├── .prettierrc
│   ├── .vscode/
│   │   └── settings.json
│   ├── Dockerfile
│   ├── Dockerfile.prod
│   ├── README.md
│   ├── api.http
│   ├── docker-compose.yaml
│   ├── nest-cli.json
│   ├── package.json
│   ├── src/
│   │   ├── app.controller.spec.ts
│   │   ├── app.controller.ts
│   │   ├── app.module.ts
│   │   ├── app.service.ts
│   │   ├── main.ts
│   │   └── routes/
│   │       ├── dto/
│   │       │   ├── create-route.dto.ts
│   │       │   └── update-route.dto.ts
│   │       ├── entities/
│   │       │   └── route.entity.ts
│   │       ├── routes.controller.spec.ts
│   │       ├── routes.controller.ts
│   │       ├── routes.gateway.spec.ts
│   │       ├── routes.gateway.ts
│   │       ├── routes.module.ts
│   │       ├── routes.service.spec.ts
│   │       └── routes.service.ts
│   ├── test/
│   │   ├── app.e2e-spec.ts
│   │   └── jest-e2e.json
│   ├── tsconfig.build.json
│   └── tsconfig.json
├── react-frontend/
│   ├── .docker/
│   │   └── entrypoint.sh
│   ├── .gitignore
│   ├── .vscode/
│   │   └── settings.json
│   ├── Dockerfile
│   ├── Dockerfile.prod
│   ├── README.md
│   ├── docker-compose.yaml
│   ├── package.json
│   ├── public/
│   │   ├── index.html
│   │   ├── manifest.json
│   │   └── robots.txt
│   ├── src/
│   │   ├── App.tsx
│   │   ├── components/
│   │   │   ├── Mapping.tsx
│   │   │   └── Navbar.tsx
│   │   ├── errors/
│   │   │   └── route-exists.error.ts
│   │   ├── index.css
│   │   ├── index.tsx
│   │   ├── react-app-env.d.ts
│   │   ├── reportWebVitals.ts
│   │   ├── setupTests.ts
│   │   ├── theme.ts
│   │   └── util/
│   │       ├── geolocation.ts
│   │       ├── map.ts
│   │       └── models.ts
│   └── tsconfig.json
└── simulator/
    ├── Dockerfile
    ├── Dockerfile.prod
    ├── README.md
    ├── application/
    │   ├── kafka/
    │   │   └── produce.go
    │   └── route/
    │       └── route.go
    ├── destinations/
    │   ├── 1.txt
    │   ├── 2.txt
    │   └── 3.txt
    ├── docker-compose.yaml
    ├── go.mod
    ├── go.sum
    ├── infra/
    │   └── kafka/
    │       ├── consumer.go
    │       └── producer.go
    └── main.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
simulator/.idea
simulator/.vscode
simulator/.env
.history/

================================================
FILE: README.md
================================================
# Imersão Fullcycle 12 - Codelivery
![Imersão Full Stack && Full Cycle](https://events-fullcycle.s3.amazonaws.com/events-fullcycle/static/site/img/grupo_4417.png)

Participe gratuitamente: https://imersao.fullcycle.com.br/

## Sobre o repositório
Esse repositório contém todo código utilizado durante as aulas para referência.

Faça seu fork e também nos dê uma estrelinha para nos ajudar a divulgar o projeto.

As instruções de instalações estão no README.md de cada projeto.

## Se tiver dificuldades de como conectar o Kafka nos microsserviços

Nesta aula, o professor Luiz, explicou como conectar o Kafka nos microsserviços, então, criamos um vídeo explicando como fazer isso.

[https://www.youtube.com/watch?v=XsngzcsdnXQ](https://www.youtube.com/watch?v=XsngzcsdnXQ)


================================================
FILE: apache-kafka/README.md
================================================
# Imersão Full Stack & FullCycle - Codelivery

## Descrição

Repositório do Apache Kafka (Backend)

## Configurar /etc/hosts

A comunicação entre as aplicações se dá de forma direta através da rede da máquina.
Para isto é necessário configurar um endereços que todos os containers Docker consigam acessar.

Acrescente no seu /etc/hosts (para Windows o caminho é C:\Windows\system32\drivers\etc\hosts):
```
127.0.0.1 host.docker.internal
```
Em todos os sistemas operacionais é necessário abrir o programa para editar o *hosts* como Administrator da máquina ou root.

## Rodar a aplicação

Execute os comandos:

```
docker-compose up
```

Quando parar os containers do Kafka, lembre-se antes de rodar o **docker-compose up**, rodar o **docker-compose down** para limpar o armazenamento, senão lançará erro ao subir novamente.

### Para Windows 

Lembrar de instalar o WSL2 e Docker. Vejo o vídeo: [https://www.youtube.com/watch?v=usF0rYCcj-E](https://www.youtube.com/watch?v=usF0rYCcj-E) 

Siga o guia rápido de instalação: [https://github.com/codeedu/wsl2-docker-quickstart](https://github.com/codeedu/wsl2-docker-quickstart) 

## Se tiver dificuldades de como conectar o Kafka nos microsserviços

Nesta aula, o professor Luiz, explicou como conectar o Kafka nos microsserviços, então, criamos um vídeo explicando como fazer isso.

[https://www.youtube.com/watch?v=XsngzcsdnXQ](https://www.youtube.com/watch?v=XsngzcsdnXQ)

================================================
FILE: apache-kafka/connectors/elasticsearch.properties
================================================
name=elasticsearch-sink
connector.class=io.confluent.connect.elasticsearch.ElasticsearchSinkConnector
topics=route.new-direction,route.new-position
connection.url=http://es01:9200
type.name=_doc
value.converter=org.apache.kafka.connect.json.JsonConverter
value.converter.schemas.enable=false
schema.ignore=true
key.ignore=true
transforms=InsertField
transforms.InsertField.type=org.apache.kafka.connect.transforms.InsertField$Value
transforms.InsertField.timestamp.field=timestamp

================================================
FILE: apache-kafka/docker-compose.yaml
================================================
version: "3"

services:  

  zookeeper:
    image: confluentinc/cp-zookeeper:latest
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
    extra_hosts:
      - "host.docker.internal:172.17.0.1"

  kafka:
    image: confluentinc/cp-kafka:latest
    depends_on:
      - zookeeper
    ports:
      - "9092:9092"
      - "9094:9094"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
      KAFKA_LISTENERS: INTERNAL://:9092,OUTSIDE://:9094
      KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:9092,OUTSIDE://host.docker.internal:9094
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,OUTSIDE:PLAINTEXT
    extra_hosts:
      - "host.docker.internal:172.17.0.1"

  kafka-topics-generator:
    image: confluentinc/cp-kafka:latest
    depends_on:
      - kafka
    command: >
      bash -c
        "sleep 5s &&
        kafka-topics --create --topic=route.new-direction --if-not-exists --bootstrap-server=kafka:9092 &&
        kafka-topics --create --topic=route.new-position --if-not-exists --bootstrap-server=kafka:9092"

  control-center:
    image: confluentinc/cp-enterprise-control-center:6.0.1
    hostname: control-center
    depends_on:
      - kafka
    ports:
      - "9021:9021"
    environment:
      CONTROL_CENTER_BOOTSTRAP_SERVERS: 'kafka:9092'
      CONTROL_CENTER_REPLICATION_FACTOR: 1
      CONTROL_CENTER_CONNECT_CLUSTER: http://kafka-connect:8083
      PORT: 9021
    extra_hosts:
      - "host.docker.internal:172.17.0.1"

  kafka-connect:
    image: confluentinc/cp-kafka-connect-base:6.0.0
    container_name: kafka-connect
    depends_on:
      - zookeeper
      - kafka
    ports:
      - 8083:8083
    environment:
      CONNECT_BOOTSTRAP_SERVERS: "kafka:9092"
      CONNECT_REST_PORT: 8083
      CONNECT_GROUP_ID: kafka-connect
      CONNECT_CONFIG_STORAGE_TOPIC: _connect-configs
      CONNECT_OFFSET_STORAGE_TOPIC: _connect-offsets
      CONNECT_STATUS_STORAGE_TOPIC: _connect-status
      CONNECT_KEY_CONVERTER: org.apache.kafka.connect.storage.StringConverter
      CONNECT_VALUE_CONVERTER: org.apache.kafka.connect.json.JsonConverter
      CONNECT_INTERNAL_KEY_CONVERTER: "org.apache.kafka.connect.json.JsonConverter"
      CONNECT_INTERNAL_VALUE_CONVERTER: "org.apache.kafka.connect.json.JsonConverter"
      CONNECT_REST_ADVERTISED_HOST_NAME: "kafka-connect"
      CONNECT_LOG4J_ROOT_LOGLEVEL: "INFO"
      CONNECT_LOG4J_LOGGERS: "org.apache.kafka.connect.runtime.rest=WARN,org.reflections=ERROR"
      CONNECT_LOG4J_APPENDER_STDOUT_LAYOUT_CONVERSIONPATTERN: "[%d] %p %X{connector.context}%m (%c:%L)%n"
      CONNECT_CONFIG_STORAGE_REPLICATION_FACTOR: "1"
      CONNECT_OFFSET_STORAGE_REPLICATION_FACTOR: "1"
      CONNECT_STATUS_STORAGE_REPLICATION_FACTOR: "1"
      # # Optional settings to include to support Confluent Control Center
      #   CONNECT_PRODUCER_INTERCEPTOR_CLASSES: "io.confluent.monitoring.clients.interceptor.MonitoringProducerInterceptor"
      #   CONNECT_CONSUMER_INTERCEPTOR_CLASSES: "io.confluent.monitoring.clients.interceptor.MonitoringConsumerInterceptor"
      #  ---------------
      CONNECT_PLUGIN_PATH: /usr/share/java,/usr/share/confluent-hub-components,/data/connect-jars
    # If you want to use the Confluent Hub installer to d/l component, but make them available
    # when running this offline, spin up the stack once and then run :
    #   docker cp kafka-connect:/usr/share/confluent-hub-components ./data/connect-jars
    volumes:
      - $PWD/data:/data
    # In the command section, $ are replaced with $$ to avoid the error 'Invalid interpolation format for "command" option'
    command:
      - bash
      - -c
      - |
        echo "Installing Connector"
        confluent-hub install --no-prompt confluentinc/kafka-connect-elasticsearch:10.0.1
        #
        echo "Launching Kafka Connect worker"
        /etc/confluent/docker/run &
        #
        sleep infinity
    extra_hosts:
      - "host.docker.internal:172.17.0.1"

  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.11.2
    container_name: es01
    environment:
      - node.name=es01
      - cluster.name=es-docker-cluster
      - cluster.initial_master_nodes=es01
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - ./es01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    extra_hosts:
      - "host.docker.internal:172.17.0.1"

  kibana:
    image: docker.elastic.co/kibana/kibana:7.11.2
    container_name: kib01
    ports:
      - 5601:5601
    environment:
      ELASTICSEARCH_URL: http://es01:9200
      ELASTICSEARCH_HOSTS: '["http://es01:9200"]'
    extra_hosts:
      - "host.docker.internal:172.17.0.1"

================================================
FILE: k8s/backend/configmap.yaml
================================================
apiVersion: v1
kind: ConfigMap
metadata:
  name: backend-conf
data:
  env: |
    MONGO_DSN=mongodb://root:root@mongodb/nest?authSource=admin
    KAFKA_CLIENT_ID=code-delivery
    KAFKA_BROKER=pkc-lzvrd.us-west4.gcp.confluent.cloud:9092
    KAFKA_CONSUMER_GROUP_ID=code-delivery
    KAFKA_SASL_USERNAME=EBNIKUAMEB2PJ2TZ
    KAFKA_SASL_PASSWORD=59VVz1gr7l4tl4ikK4Lzlk/vLZB++7ek5vOC73cxtNsKLW7oUtbfxj/PicpbZ9rq

================================================
FILE: k8s/backend/deploy.yaml
================================================
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
        - name: backend
          image: wesleywillians/imersao2-backend
          ports:
            - containerPort: 3000
          volumeMounts:
            - name: backend-volume
              mountPath: /home/node/app/.env
              subPath: .env
      volumes:
        - name: backend-volume
          configMap:
            name: backend-conf
            items:
              - key: env
                path: .env
          
        

================================================
FILE: k8s/backend/service.yaml
================================================
apiVersion: v1  
kind: Service
metadata:
  name: backend-service
spec:
  type: LoadBalancer
  selector:
    app: backend
  ports:
  - port: 3000



================================================
FILE: k8s/frontend/deploy.yaml
================================================
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
        - name: frontend
          image: wesleywillians/imersao2-frontend:latest
          ports:
            - containerPort: 80


================================================
FILE: k8s/frontend/service.yaml
================================================
apiVersion: v1  
kind: Service
metadata:
  name: frontend-service
spec:
  type: LoadBalancer
  selector:
    app: frontend
  ports:
  - port: 80
  



================================================
FILE: k8s/simulator/configmap.yaml
================================================
apiVersion: v1
kind: ConfigMap
metadata:
  name: simulator-conf
data:
  env: |
    KafkaReadTopic=route.new-direction
    KafkaProduceTopic=route.new-position
    KafkaBootstrapServers=pkc-lzvrd.us-west4.gcp.confluent.cloud:9092
    KafkaConsumerGroupId=simulator
    security.protocol="SASL_SSL"
    sasl.mechanisms="PLAIN"
    sasl.username="EBNIKUAMEB2PJ2TZ"
    sasl.password="59VVz1gr7l4tl4ikK4Lzlk/vLZB++7ek5vOC73cxtNsKLW7oUtbfxj/PicpbZ9rq"

================================================
FILE: k8s/simulator/deploy.yaml
================================================
apiVersion: apps/v1
kind: Deployment
metadata:
  name: simulator
spec:
  replicas: 1
  selector:
    matchLabels:
      app: simulator
  template:
    metadata:
      labels:
        app: simulator
    spec:
      containers:
        - name: simulator
          image: wesleywillians/imersao2-simulator:latest
          volumeMounts:
            - name: simulator-volume
              mountPath: /go/src/.env
              subPath: .env
              

      volumes:
        - name: simulator-volume
          configMap:
            name: simulator-conf
            items:
              - key: env
                path: .env
          
        

================================================
FILE: nest-api/.docker/entrypoint.sh
================================================
#!/bin/bash

if [ ! -f ".env" ]; then
  cp .env.example .env
fi

npm install

npm run start:dev

================================================
FILE: nest-api/.docker/mongo/init.js
================================================
db.routes.insertMany([
  {
    _id: '1',
    title: 'Primeiro',
    startPosition: { lat: -15.82594, lng: -47.92923 },
    endPosition: { lat: -15.82942, lng: -47.92765 },
  },
  {
    _id: '2',
    title: 'Segundo',
    startPosition: { lat: -15.82449, lng: -47.92756 },
    endPosition: { lat: -15.8276, lng: -47.92621 },
  },
  {
    _id: '3',
    title: 'Terceiro',
    startPosition: { lat: -15.82331, lng: -47.92588 },
    endPosition: { lat: -15.82758, lng: -47.92532 },
  },
]);


================================================
FILE: nest-api/.eslintrc.js
================================================
module.exports = {
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: 'tsconfig.json',
    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',
  },
};


================================================
FILE: nest-api/.gitignore
================================================
# compiled output
/dist
/node_modules

# Logs
logs
*.log
npm-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

.docker/dbdata/

.history/

.env

================================================
FILE: nest-api/.prettierrc
================================================
{
  "singleQuote": true,
  "trailingComma": "all"
}

================================================
FILE: nest-api/.vscode/settings.json
================================================
{
    "workbench.colorCustomizations": {
        "activityBar.activeBackground": "#b61a3d",
        "activityBar.activeBorder": "#133808",
        "activityBar.background": "#b61a3d",
        "activityBar.foreground": "#e7e7e7",
        "activityBar.inactiveForeground": "#e7e7e799",
        "activityBarBadge.background": "#133808",
        "activityBarBadge.foreground": "#e7e7e7",
        "statusBar.background": "#b61a3d",
        "statusBar.foreground": "#e7e7e7",
        "statusBarItem.hoverBackground": "#e0234e"
    },
    "peacock.remoteColor": "#e0234e"
}

================================================
FILE: nest-api/Dockerfile
================================================
FROM node:12.14.0-alpine3.11

RUN apk add --no-cache bash

RUN npm install -g @nestjs/cli@7.5.6

USER node

WORKDIR /home/node/app

================================================
FILE: nest-api/Dockerfile.prod
================================================
FROM node:14.15.4-slim

USER node

RUN mkdir -p /home/node/app

WORKDIR /home/node/app

COPY --chown=node package*.json ./

RUN npm install

COPY --chown=node ./ .

RUN npm run build

EXPOSE 3000

CMD ["npm", "run", "start:prod"]

================================================
FILE: nest-api/README.md
================================================
# Imersão Full Stack & FullCycle - Codelivery

## Descrição

Repositório do front-end feito com Nest.js (Backend)

**Importante**: A aplicação do Apache Kafka, Golang deve estar rodando primeiro.

## Configurar /etc/hosts

A comunicação entre as aplicações se dá de forma direta através da rede da máquina.
Para isto é necessário configurar um endereços que todos os containers Docker consigam acessar.

Acrescente no seu /etc/hosts (para Windows o caminho é C:\Windows\system32\drivers\etc\hosts):
```
127.0.0.1 host.docker.internal
```
Em todos os sistemas operacionais é necessário abrir o programa para editar o *hosts* como Administrator da máquina ou root.

## Rodar a aplicação

Execute os comandos:

```
docker-compose up
```

Acessar http://localhost:3000/routes.

### Para Windows 

Lembrar de instalar o WSL2 e Docker. Vejo o vídeo: [https://www.youtube.com/watch?v=usF0rYCcj-E](https://www.youtube.com/watch?v=usF0rYCcj-E) 

Siga o guia rápido de instalação: [https://github.com/codeedu/wsl2-docker-quickstart](https://github.com/codeedu/wsl2-docker-quickstart) 


================================================
FILE: nest-api/api.http
================================================
GET http://localhost:3000/routes

###
GET http://localhost:3000/routes/1/start

================================================
FILE: nest-api/docker-compose.yaml
================================================
version: '3'

services:
  
  app:
    build: .
    entrypoint: ./.docker/entrypoint.sh
    ports: 
      - 3000:3000
    volumes:
      - .:/home/node/app
    extra_hosts:
      - "host.docker.internal:172.17.0.1"
    depends_on:
      - db
  
  db:
    image: mongo:4.4.4
    restart: always
    volumes:
      - ./.docker/dbdata:/data/db
      - ./.docker/mongo:/docker-entrypoint-initdb.d
    environment:
      - MONGO_INITDB_ROOT_USERNAME=root
      - MONGO_INITDB_ROOT_PASSWORD=root
      - MONGO_INITDB_DATABASE=nest
  
  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    environment:
      - ME_CONFIG_MONGODB_SERVER=db
      - ME_CONFIG_MONGODB_AUTH_USERNAME=root
      - ME_CONFIG_MONGODB_AUTH_PASSWORD=root
      - ME_CONFIG_MONGODB_ADMINUSERNAME=root
      - ME_CONFIG_MONGODB_ADMINPASSWORD=root
    depends_on:
      - db


================================================
FILE: nest-api/nest-cli.json
================================================
{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src"
}


================================================
FILE: nest-api/package.json
================================================
{
  "name": "nest-api",
  "version": "0.0.1",
  "description": "",
  "author": "",
  "private": true,
  "license": "UNLICENSED",
  "scripts": {
    "prebuild": "rimraf dist",
    "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": "^7.6.15",
    "@nestjs/config": "^0.6.3",
    "@nestjs/core": "^7.6.15",
    "@nestjs/mapped-types": "*",
    "@nestjs/microservices": "^7.6.15",
    "@nestjs/mongoose": "^7.2.4",
    "@nestjs/platform-express": "^7.6.15",
    "@nestjs/platform-socket.io": "^7.6.15",
    "@nestjs/websockets": "^7.6.15",
    "kafkajs": "^1.15.0",
    "mongoose": "^5.12.3",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.2",
    "rxjs": "^6.6.6"
  },
  "devDependencies": {
    "@nestjs/cli": "^7.6.0",
    "@nestjs/schematics": "^7.3.0",
    "@nestjs/testing": "^7.6.15",
    "@types/express": "^4.17.11",
    "@types/jest": "^26.0.22",
    "@types/node": "^14.14.36",
    "@types/socket.io": "^2.1.13",
    "@types/supertest": "^2.0.10",
    "@typescript-eslint/eslint-plugin": "^4.19.0",
    "@typescript-eslint/parser": "^4.19.0",
    "eslint": "^7.22.0",
    "eslint-config-prettier": "^8.1.0",
    "eslint-plugin-prettier": "^3.3.1",
    "jest": "^26.6.3",
    "prettier": "^2.2.1",
    "supertest": "^6.1.3",
    "ts-jest": "^26.5.4",
    "ts-loader": "^8.0.18",
    "ts-node": "^9.1.1",
    "tsconfig-paths": "^3.9.0",
    "typescript": "^4.2.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"
  }
}


================================================
FILE: nest-api/src/app.controller.spec.ts
================================================
import { Test, TestingModule } from '@nestjs/testing';
import { AppController } from './app.controller';
import { AppService } from './app.service';

describe('AppController', () => {
  let appController: AppController;

  beforeEach(async () => {
    const app: TestingModule = await Test.createTestingModule({
      controllers: [AppController],
      providers: [AppService],
    }).compile();

    appController = app.get<AppController>(AppController);
  });

  describe('root', () => {
    it('should return "Hello World!"', () => {
      expect(appController.getHello()).toBe('Hello World!');
    });
  });
});


================================================
FILE: nest-api/src/app.controller.ts
================================================
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller('/prefixo')
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

//HTTP - Get, Post, Put, Patch, Delete e

================================================
FILE: nest-api/src/app.module.ts
================================================
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { MongooseModule } from '@nestjs/mongoose';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { RoutesModule } from './routes/routes.module';
//ES7 decorators
@Module({
  imports: [
    ConfigModule.forRoot(),
    RoutesModule,
    MongooseModule.forRoot(process.env.MONGO_DSN, {
      useNewUrlParser: true,
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}


================================================
FILE: nest-api/src/app.service.ts
================================================
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World222!';
  }
}


================================================
FILE: nest-api/src/main.ts
================================================
import { NestFactory } from '@nestjs/core';
import { Transport } from '@nestjs/microservices';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, { cors: true });

  app.connectMicroservice({
    transport: Transport.KAFKA,
    options: {
      client: {
        clientId: process.env.KAFKA_CLIENT_ID,
        brokers: [process.env.KAFKA_BROKER],
        // ssl: true,
        // sasl: {
        //   mechanism: 'plain', // scram-sha-256 or scram-sha-512
        //   username: process.env.KAFKA_SASL_USERNAME,
        //   password: process.env.KAFKA_SASL_PASSWORD,
        // },
      },
      consumer: {
        groupId:
          !process.env.KAFKA_CONSUMER_GROUP_ID ||
          process.env.KAFKA_CONSUMER_GROUP_ID === ''
            ? 'my-consumer-' + Math.random()
            : process.env.KAFKA_CONSUMER_GROUP_ID,
      },
    },
  });

  await app.startAllMicroservicesAsync();
  await app.listen(3000);
}
bootstrap();


================================================
FILE: nest-api/src/routes/dto/create-route.dto.ts
================================================
export class CreateRouteDto {}


================================================
FILE: nest-api/src/routes/dto/update-route.dto.ts
================================================
import { PartialType } from '@nestjs/mapped-types';
import { CreateRouteDto } from './create-route.dto';

export class UpdateRouteDto extends PartialType(CreateRouteDto) {}


================================================
FILE: nest-api/src/routes/entities/route.entity.ts
================================================
import { Prop, Schema, raw, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';

export type RouteDocument = Route & Document;

@Schema()
export class Route {
  @Prop()
  _id: string;

  @Prop()
  title: string;

  @Prop(
    raw({
      lat: { type: Number },
      lng: { type: Number },
    }),
  )
  startPosition: { lat: number; lng: number };

  @Prop(
    raw({
      lat: { type: Number },
      lng: { type: Number },
    }),
  )
  endPosition: { lat: number; lng: number };
}

export const RouteSchema = SchemaFactory.createForClass(Route);


================================================
FILE: nest-api/src/routes/routes.controller.spec.ts
================================================
import { Test, TestingModule } from '@nestjs/testing';
import { RoutesController } from './routes.controller';
import { RoutesService } from './routes.service';

describe('RoutesController', () => {
  let controller: RoutesController;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      controllers: [RoutesController],
      providers: [RoutesService],
    }).compile();

    controller = module.get<RoutesController>(RoutesController);
  });

  it('should be defined', () => {
    expect(controller).toBeDefined();
  });
});


================================================
FILE: nest-api/src/routes/routes.controller.ts
================================================
import {
  Controller,
  Get,
  Post,
  Body,
  Patch,
  Param,
  Delete,
  Inject,
  OnModuleInit,
} from '@nestjs/common';
import { RoutesService } from './routes.service';
import { CreateRouteDto } from './dto/create-route.dto';
import { UpdateRouteDto } from './dto/update-route.dto';
import { ClientKafka, MessagePattern, Payload } from '@nestjs/microservices';
import { Producer } from '@nestjs/microservices/external/kafka.interface';
import { RoutesGateway } from './routes.gateway';

@Controller('routes')
export class RoutesController implements OnModuleInit {
  private kafkaProducer: Producer;

  constructor(
    private readonly routesService: RoutesService,
    @Inject('KAFKA_SERVICE')
    private kafkaClient: ClientKafka,
    private routeGateway: RoutesGateway,
  ) {}

  @Post()
  create(@Body() createRouteDto: CreateRouteDto) {
    return this.routesService.create(createRouteDto);
  }

  @Get()
  findAll() {
    return this.routesService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.routesService.findOne(+id);
  }

  @Patch(':id')
  update(@Param('id') id: string, @Body() updateRouteDto: UpdateRouteDto) {
    return this.routesService.update(+id, updateRouteDto);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.routesService.remove(+id);
  }

  async onModuleInit() {
    this.kafkaProducer = await this.kafkaClient.connect();
  }

  @Get(':id/start')
  startRoute(@Param('id') id: string) {
    this.kafkaProducer.send({
      topic: 'route.new-direction',
      messages: [
        {
          key: 'route.new-direction',
          value: JSON.stringify({ routeId: id, clientId: '' }),
        },
      ],
    });
  }

  @MessagePattern('route.new-position')
  consumeNewPosition(
    @Payload()
    message: {
      value: {
        routeId: string;
        clientId: string;
        position: [number, number];
        finished: boolean;
      };
    },
  ) {
    
  this.routeGateway.sendPosition({
    ...message.value,
    position: [message.value.position[1], message.value.position[0]],
  });
  }
}


================================================
FILE: nest-api/src/routes/routes.gateway.spec.ts
================================================
import { Test, TestingModule } from '@nestjs/testing';
import { RoutesGateway } from './routes.gateway';

describe('RoutesGateway', () => {
  let gateway: RoutesGateway;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [RoutesGateway],
    }).compile();

    gateway = module.get<RoutesGateway>(RoutesGateway);
  });

  it('should be defined', () => {
    expect(gateway).toBeDefined();
  });
});


================================================
FILE: nest-api/src/routes/routes.gateway.ts
================================================
import { Inject, OnModuleInit } from '@nestjs/common';
import { ClientKafka } from '@nestjs/microservices';
import { Producer } from '@nestjs/microservices/external/kafka.interface';
import {
  SubscribeMessage,
  WebSocketGateway,
  WebSocketServer,
} from '@nestjs/websockets';
import { Socket, Server } from 'socket.io';

@WebSocketGateway()
export class RoutesGateway implements OnModuleInit {
  private kafkaProducer: Producer;

  @WebSocketServer()
  server: Server;

  constructor(
    @Inject('KAFKA_SERVICE')
    private kafkaClient: ClientKafka,
  ) {}

  async onModuleInit() {
    this.kafkaProducer = await this.kafkaClient.connect();
  }

  @SubscribeMessage('new-direction')
  handleMessage(client: Socket, payload: { routeId: string }) {
    this.kafkaProducer.send({
      topic: 'route.new-direction',
      messages: [
        {
          key: 'route.new-direction',
          value: JSON.stringify({
            routeId: payload.routeId,
            clientId: client.id,
          }),
        },
      ],
    });
    console.log(payload);
  }

  sendPosition(data: {
    clientId: string;
    routeId: string;
    position: [number, number];
    finished: boolean;
  }) {
    const { clientId, ...rest } = data;
    const clients = this.server.sockets.connected;
    if (!(clientId in clients)) {
      console.error(
        'Client not exists, refresh React Application and resend new direction again.',
      );
      return;
    }
    clients[clientId].emit('new-position', rest);
  }
}


================================================
FILE: nest-api/src/routes/routes.module.ts
================================================
import { Module } from '@nestjs/common';
import { RoutesService } from './routes.service';
import { RoutesController } from './routes.controller';
import { MongooseModule } from '@nestjs/mongoose';
import { Route, RouteSchema } from './entities/route.entity';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { RoutesGateway } from './routes.gateway';

@Module({
  imports: [
    MongooseModule.forFeature([{ name: Route.name, schema: RouteSchema }]),
    ClientsModule.registerAsync([
      {
        name: 'KAFKA_SERVICE',
        useFactory: (): any => ({
          transport: Transport.KAFKA,
          options: {
            client: {
              clientId: process.env.KAFKA_CLIENT_ID,
              brokers: [process.env.KAFKA_BROKER],
              // ssl: true,
              // sasl: {
              //   mechanism: 'plain', // scram-sha-256 or scram-sha-512
              //   username: process.env.KAFKA_SASL_USERNAME,
              //   password: process.env.KAFKA_SASL_PASSWORD,
              // },
            },
            consumer: {
              groupId:
                !process.env.KAFKA_CONSUMER_GROUP_ID ||
                process.env.KAFKA_CONSUMER_GROUP_ID === ''
                  ? 'my-consumer-' + Math.random()
                  : process.env.KAFKA_CONSUMER_GROUP_ID,
            },
          },
        }),
      },
    ]),
  ],
  controllers: [RoutesController],
  providers: [RoutesService, RoutesGateway],
})
export class RoutesModule {}


================================================
FILE: nest-api/src/routes/routes.service.spec.ts
================================================
import { Test, TestingModule } from '@nestjs/testing';
import { RoutesService } from './routes.service';

describe('RoutesService', () => {
  let service: RoutesService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [RoutesService],
    }).compile();

    service = module.get<RoutesService>(RoutesService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });
});


================================================
FILE: nest-api/src/routes/routes.service.ts
================================================
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { CreateRouteDto } from './dto/create-route.dto';
import { UpdateRouteDto } from './dto/update-route.dto';
import { Route, RouteDocument } from './entities/route.entity';

@Injectable()
export class RoutesService {
  constructor(
    @InjectModel(Route.name) private routeModel: Model<RouteDocument>,
  ) {}

  create(createRouteDto: CreateRouteDto) {
    return 'This action adds a new route';
  }

  findAll(): Promise<RouteDocument[]> {
    return this.routeModel.find().exec();
  }

  findOne(id: number) {
    return `This action returns a #${id} route`;
  }

  update(id: number, updateRouteDto: UpdateRouteDto) {
    return `This action updates a #${id} route`;
  }

  remove(id: number) {
    return `This action removes a #${id} route`;
  }
}


================================================
FILE: nest-api/test/app.e2e-spec.ts
================================================
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from './../src/app.module';

describe('AppController (e2e)', () => {
  let app: INestApplication;

  beforeEach(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    await app.init();
  });

  it('/ (GET)', () => {
    return request(app.getHttpServer())
      .get('/')
      .expect(200)
      .expect('Hello World!');
  });
});


================================================
FILE: nest-api/test/jest-e2e.json
================================================
{
  "moduleFileExtensions": ["js", "json", "ts"],
  "rootDir": ".",
  "testEnvironment": "node",
  "testRegex": ".e2e-spec.ts$",
  "transform": {
    "^.+\\.(t|j)s$": "ts-jest"
  }
}


================================================
FILE: nest-api/tsconfig.build.json
================================================
{
  "extends": "./tsconfig.json",
  "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
}


================================================
FILE: nest-api/tsconfig.json
================================================
{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "es2017",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true
  },
  "include": [
    "src"
  ],
  "exclude": [
    "node_modules",
    "dist",
    ".docker"
  ]
}

================================================
FILE: react-frontend/.docker/entrypoint.sh
================================================
#!/bin/bash

if [ ! -f ".env" ]; then
  cp .env.example .env
fi

npm install

npm start

================================================
FILE: react-frontend/.gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

.env

.history/

================================================
FILE: react-frontend/.vscode/settings.json
================================================
{
    "workbench.colorCustomizations": {
        "activityBar.activeBackground": "#2fcefa",
        "activityBar.activeBorder": "#da05ac",
        "activityBar.background": "#2fcefa",
        "activityBar.foreground": "#15202b",
        "activityBar.inactiveForeground": "#15202b99",
        "activityBarBadge.background": "#da05ac",
        "activityBarBadge.foreground": "#e7e7e7",
        "statusBar.background": "#2fcefa",
        "statusBar.foreground": "#15202b",
        "statusBarItem.hoverBackground": "#06bdf0"
    },
    "peacock.remoteColor": "#61dafb"
}

================================================
FILE: react-frontend/Dockerfile
================================================
FROM node:12.14.0-alpine3.11

RUN apk add --no-cache bash

USER node

WORKDIR /home/node/app

================================================
FILE: react-frontend/Dockerfile.prod
================================================
#build
FROM node:14.15.4-slim as build

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

RUN npm run build

#production
FROM nginx:1.15

COPY --from=build /app/build /usr/share/nginx/html

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

================================================
FILE: react-frontend/README.md
================================================
# Imersão Full Stack & FullCycle - Codelivery

## Descrição

Repositório do front-end feito com React.js (Front-end)

**Importante**: A aplicação do Apache Kafka, Golang e Nest.js deve estar rodando primeiro.

## Configurar /etc/hosts

A comunicação entre as aplicações se dá de forma direta através da rede da máquina.
Para isto é necessário configurar um endereços que todos os containers Docker consigam acessar.

Acrescente no seu /etc/hosts (para Windows o caminho é C:\Windows\system32\drivers\etc\hosts):
```
127.0.0.1 host.docker.internal
```
Em todos os sistemas operacionais é necessário abrir o programa para editar o *hosts* como Administrator da máquina ou root.

## Rodar a aplicação

Execute os comandos:

```
docker-compose up
```

Acessar http://localhost:3001.

### Para Windows 

Lembrar de instalar o WSL2 e Docker. Vejo o vídeo: [https://www.youtube.com/watch?v=usF0rYCcj-E](https://www.youtube.com/watch?v=usF0rYCcj-E) 

Siga o guia rápido de instalação: [https://github.com/codeedu/wsl2-docker-quickstart](https://github.com/codeedu/wsl2-docker-quickstart) 


================================================
FILE: react-frontend/docker-compose.yaml
================================================
version: '3'

services:
  
  app:
    build: .
    entrypoint: ./.docker/entrypoint.sh
    ports: 
      - 3001:3000
    volumes:
      - .:/home/node/app

================================================
FILE: react-frontend/package.json
================================================
{
  "name": "react-frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@material-ui/core": "^4.11.3",
    "@material-ui/icons": "^4.11.2",
    "@testing-library/jest-dom": "^5.11.10",
    "@testing-library/react": "^11.2.6",
    "@testing-library/user-event": "^12.8.3",
    "@types/jest": "^26.0.22",
    "@types/lodash": "^4.14.168",
    "@types/node": "^12.20.7",
    "@types/react": "^17.0.3",
    "@types/react-dom": "^17.0.3",
    "@types/socket.io-client": "^1.4.36",
    "google-maps": "^4.3.3",
    "notistack": "^1.0.5",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "4.0.3",
    "socket.io-client": "^2.4.0",
    "typescript": "^4.2.3",
    "web-vitals": "^1.1.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}


================================================
FILE: react-frontend/public/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>Codelivery - Imersão Fullcycle</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>


================================================
FILE: react-frontend/public/manifest.json
================================================
{
  "short_name": "Codelivery - Imersão Fullcycle",
  "name": "Codelivery - Imersão Fullcycle",
  "icons": [
    {
      "src": "favicon.ico",
      "sizes": "64x64 32x32 24x24 16x16",
      "type": "image/x-icon"
    },
    {
      "src": "logo192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "logo512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": ".",
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff"
}


================================================
FILE: react-frontend/public/robots.txt
================================================
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:


================================================
FILE: react-frontend/src/App.tsx
================================================
import { CssBaseline, MuiThemeProvider } from "@material-ui/core";
import { SnackbarProvider } from "notistack";
import { Mapping } from "./components/Mapping";
import theme from "./theme";

function App() {
  return (
    <MuiThemeProvider theme={theme}>
      <SnackbarProvider maxSnack={3}>
        <CssBaseline />
        <Mapping />
      </SnackbarProvider>
    </MuiThemeProvider>
  );
}

export default App;
//TS + JSX


================================================
FILE: react-frontend/src/components/Mapping.tsx
================================================
import { Button, Grid, makeStyles, MenuItem, Select } from "@material-ui/core";
import { Loader } from "google-maps";
import {
  FormEvent,
  FunctionComponent,
  useCallback,
  useEffect,
  useRef,
  useState,
} from "react";
import { getCurrentPosition } from "../util/geolocation";
import { makeCarIcon, makeMarkerIcon, Map } from "../util/map";
import { Route } from "../util/models";
import { sample, shuffle } from "lodash";
import { RouteExistsError } from "../errors/route-exists.error";
import { useSnackbar } from "notistack";
import { Navbar } from "./Navbar";
import io from "socket.io-client";

const API_URL = process.env.REACT_APP_API_URL as string;

const googleMapsLoader = new Loader(process.env.REACT_APP_GOOGLE_API_KEY);

const colors = [
  "#b71c1c",
  "#4a148c",
  "#2e7d32",
  "#e65100",
  "#2962ff",
  "#c2185b",
  "#FFCD00",
  "#3e2723",
  "#03a9f4",
  "#827717",
];

const useStyles = makeStyles({
  root: {
    width: "100%",
    height: "100%",
  },
  form: {
    margin: "16px",
  },
  btnSubmitWrapper: {
    textAlign: "center",
    marginTop: "8px",
  },
  map: {
    width: "100%",
    height: "100%",
  },
});

export const Mapping: FunctionComponent = () => {
  const classes = useStyles();
  const [routes, setRoutes] = useState<Route[]>([]);
  const [routeIdSelected, setRouteIdSelected] = useState<string>("");
  const mapRef = useRef<Map>();
  const socketIORef = useRef<SocketIOClient.Socket>();
  const { enqueueSnackbar } = useSnackbar();

  const finishRoute = useCallback(
    (route: Route) => {
      enqueueSnackbar(`${route.title} finalizou!`, {
        variant: "success",
      });
      mapRef.current?.removeRoute(route._id);
    },
    [enqueueSnackbar]
  );

  useEffect(() => {
    if (!socketIORef.current?.connected) {
      socketIORef.current = io.connect(API_URL);
      socketIORef.current.on("connect", () => console.log("conectou"));
    }

    const handler = (data: {
      routeId: string;
      position: [number, number];
      finished: boolean;
    }) => {
      console.log(data);
      mapRef.current?.moveCurrentMarker(data.routeId, {
        lat: data.position[0],
        lng: data.position[1],
      });
      const route = routes.find((route) => route._id === data.routeId) as Route;
      if (data.finished) {
        finishRoute(route);
      }
    };
    socketIORef.current?.on("new-position", handler);
    return () => {
      socketIORef.current?.off("new-position", handler);
    };
  }, [finishRoute, routes, routeIdSelected]);

  useEffect(() => {
    fetch(`${API_URL}/routes`)
      .then((data) => data.json())
      .then((data) => setRoutes(data));
  }, []);

  useEffect(() => {
    (async () => {
      const [, position] = await Promise.all([
        googleMapsLoader.load(),
        getCurrentPosition({ enableHighAccuracy: true }),
      ]);
      const divMap = document.getElementById("map") as HTMLElement;
      mapRef.current = new Map(divMap, {
        zoom: 15,
        center: position,
      });
    })();
  }, []);

  const startRoute = useCallback(
    (event: FormEvent) => {
      event.preventDefault();
      const route = routes.find((route) => route._id === routeIdSelected);
      const color = sample(shuffle(colors)) as string;
      try {
        mapRef.current?.addRoute(routeIdSelected, {
          currentMarkerOptions: {
            position: route?.startPosition,
            icon: makeCarIcon(color),
          },
          endMarkerOptions: {
            position: route?.endPosition,
            icon: makeMarkerIcon(color),
          },
        });
        socketIORef.current?.emit("new-direction", {
          routeId: routeIdSelected,
        });
      } catch (error) {
        if (error instanceof RouteExistsError) {
          enqueueSnackbar(`${route?.title} já adicionado, espere finalizar.`, {
            variant: "error",
          });
          return;
        }
        throw error;
      }
    },
    [routeIdSelected, routes, enqueueSnackbar]
  );

  return (
    <Grid className={classes.root} container>
      <Grid item xs={12} sm={3}>
        <Navbar />
        <form onSubmit={startRoute} className={classes.form}>
          <Select
            fullWidth
            displayEmpty
            value={routeIdSelected}
            onChange={(event) => setRouteIdSelected(event.target.value + "")}
          >
            <MenuItem value="">
              <em>Selecione uma corrida</em>
            </MenuItem>
            {routes.map((route, key) => (
              <MenuItem key={key} value={route._id}>
                {route.title}
              </MenuItem>
            ))}
          </Select>
          <div className={classes.btnSubmitWrapper}>
            <Button type="submit" color="primary" variant="contained">
              Iniciar uma corrida
            </Button>
          </div>
        </form>
      </Grid>
      <Grid item xs={12} sm={9}>
        <div id="map" className={classes.map} />
      </Grid>
    </Grid>
  );
};


================================================
FILE: react-frontend/src/components/Navbar.tsx
================================================
import { AppBar, IconButton, Toolbar, Typography } from "@material-ui/core";
import { FunctionComponent } from "react";
import DriverIcon from "@material-ui/icons/DriveEta";

export const Navbar: FunctionComponent = () => {
  return (
    <AppBar position="static">
      <Toolbar>
        <IconButton edge="start" color="inherit" aria-label="menu">
          <DriverIcon />
        </IconButton>
        <Typography variant="h6">Code Delivery</Typography>
      </Toolbar>
    </AppBar>
  );
};


================================================
FILE: react-frontend/src/errors/route-exists.error.ts
================================================
export class RouteExistsError extends Error {}


================================================
FILE: react-frontend/src/index.css
================================================
html, body, #root{
  height: 100%;
  margin: 0;
}

================================================
FILE: react-frontend/src/index.tsx
================================================
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App'; //ES6 Modules
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();


================================================
FILE: react-frontend/src/react-app-env.d.ts
================================================
/// <reference types="react-scripts" />


================================================
FILE: react-frontend/src/reportWebVitals.ts
================================================
import { ReportHandler } from 'web-vitals';

const reportWebVitals = (onPerfEntry?: ReportHandler) => {
  if (onPerfEntry && onPerfEntry instanceof Function) {
    import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
      getCLS(onPerfEntry);
      getFID(onPerfEntry);
      getFCP(onPerfEntry);
      getLCP(onPerfEntry);
      getTTFB(onPerfEntry);
    });
  }
};

export default reportWebVitals;


================================================
FILE: react-frontend/src/setupTests.ts
================================================
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';


================================================
FILE: react-frontend/src/theme.ts
================================================
import { createMuiTheme } from "@material-ui/core";
import { PaletteOptions } from "@material-ui/core/styles/createPalette";

const palette: PaletteOptions = {
  type: "dark",
  primary: {
    main: "#FFCD00",
    contrastText: "#242526",
  },
  background: {
    default: "#242526",
  },
};

const theme = createMuiTheme({
  palette,
});

export default theme;


================================================
FILE: react-frontend/src/util/geolocation.ts
================================================
export function getCurrentPosition(
  options?: PositionOptions
): Promise<{ lat: number; lng: number }> {
  return new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(
      (position) =>
        resolve({
          lat: position.coords.latitude,
          lng: position.coords.longitude,
        }),
      (error) => reject(error),
      options
    );
  });
}


================================================
FILE: react-frontend/src/util/map.ts
================================================
import { RouteExistsError } from "../errors/route-exists.error";

export class Route {
  public currentMarker: google.maps.Marker;
  public endMarker: google.maps.Marker;
  private directionsRenderer: google.maps.DirectionsRenderer;

  constructor(options: {
    currentMarkerOptions: google.maps.ReadonlyMarkerOptions;
    endMarkerOptions: google.maps.ReadonlyMarkerOptions;
  }) {
    const { currentMarkerOptions, endMarkerOptions } = options;
    this.currentMarker = new google.maps.Marker(currentMarkerOptions);
    this.endMarker = new google.maps.Marker(endMarkerOptions);

    const strokeColor = (this.currentMarker.getIcon() as google.maps.ReadonlySymbol)
      .strokeColor;
    this.directionsRenderer = new google.maps.DirectionsRenderer({
      suppressMarkers: true,
      polylineOptions: {
        strokeColor,
        strokeOpacity: 0.5,
        strokeWeight: 5,
      },
    });
    this.directionsRenderer.setMap(
      this.currentMarker.getMap() as google.maps.Map
    );

    this.calculateRoute();
  }

  private calculateRoute() {
    const currentPosition = this.currentMarker.getPosition() as google.maps.LatLng;
    const endPosition = this.endMarker.getPosition() as google.maps.LatLng;

    new google.maps.DirectionsService().route(
      {
        origin: currentPosition,
        destination: endPosition,
        travelMode: google.maps.TravelMode.DRIVING,
      },
      (result, status) => {
        if (status === "OK") {
          this.directionsRenderer.setDirections(result);
          return;
        }

        throw new Error(status);
      }
    );
  }

  delete() {
    this.currentMarker.setMap(null);
    this.endMarker.setMap(null);
    this.directionsRenderer.setMap(null);
  }
}

export class Map {
  public map: google.maps.Map;
  private routes: { [id: string]: Route } = {};
  constructor(element: Element, options: google.maps.MapOptions) {
    this.map = new google.maps.Map(element, options);
  }

  moveCurrentMarker(id: string, position: google.maps.LatLngLiteral) {
    this.routes[id].currentMarker.setPosition(position);
  }

  removeRoute(id: string) {
    const route = this.routes[id];
    route.delete();
    delete this.routes[id];
  }

  addRoute(
    id: string,
    routeOptions: {
      currentMarkerOptions: google.maps.ReadonlyMarkerOptions;
      endMarkerOptions: google.maps.ReadonlyMarkerOptions;
    }
  ) {
    if (id in this.routes) {
      throw new RouteExistsError();
    }

    const { currentMarkerOptions, endMarkerOptions } = routeOptions;
    this.routes[id] = new Route({
      currentMarkerOptions: { ...currentMarkerOptions, map: this.map },
      endMarkerOptions: { ...endMarkerOptions, map: this.map },
    });

    this.fitBounds();
  }

  private fitBounds() {
    const bounds = new google.maps.LatLngBounds();

    Object.keys(this.routes).forEach((id: string) => {
      const route = this.routes[id];
      bounds.extend(route.currentMarker.getPosition() as any);
      bounds.extend(route.endMarker.getPosition() as any);
    });

    this.map.fitBounds(bounds);
  }
}

export const makeCarIcon = (color: string) => ({
  path:
    "M23.5 7c.276 0 .5.224.5.5v.511c0 .793-.926.989-1.616.989l-1.086-2h2.202zm-1.441 3.506c.639 1.186.946 2.252.946 3.666 0 1.37-.397 2.533-1.005 3.981v1.847c0 .552-.448 1-1 1h-1.5c-.552 0-1-.448-1-1v-1h-13v1c0 .552-.448 1-1 1h-1.5c-.552 0-1-.448-1-1v-1.847c-.608-1.448-1.005-2.611-1.005-3.981 0-1.414.307-2.48.946-3.666.829-1.537 1.851-3.453 2.93-5.252.828-1.382 1.262-1.707 2.278-1.889 1.532-.275 2.918-.365 4.851-.365s3.319.09 4.851.365c1.016.182 1.45.507 2.278 1.889 1.079 1.799 2.101 3.715 2.93 5.252zm-16.059 2.994c0-.828-.672-1.5-1.5-1.5s-1.5.672-1.5 1.5.672 1.5 1.5 1.5 1.5-.672 1.5-1.5zm10 1c0-.276-.224-.5-.5-.5h-7c-.276 0-.5.224-.5.5s.224.5.5.5h7c.276 0 .5-.224.5-.5zm2.941-5.527s-.74-1.826-1.631-3.142c-.202-.298-.515-.502-.869-.566-1.511-.272-2.835-.359-4.441-.359s-2.93.087-4.441.359c-.354.063-.667.267-.869.566-.891 1.315-1.631 3.142-1.631 3.142 1.64.313 4.309.497 6.941.497s5.301-.184 6.941-.497zm2.059 4.527c0-.828-.672-1.5-1.5-1.5s-1.5.672-1.5 1.5.672 1.5 1.5 1.5 1.5-.672 1.5-1.5zm-18.298-6.5h-2.202c-.276 0-.5.224-.5.5v.511c0 .793.926.989 1.616.989l1.086-2z",
  fillColor: color,
  strokeColor: color,
  strokeWeight: 1,
  fillOpacity: 1,
  anchor: new google.maps.Point(26, 20),
});

export const makeMarkerIcon = (color: string) => ({
  path:
    "M66.9,41.8c0-11.3-9.1-20.4-20.4-20.4c-11.3,0-20.4,9.1-20.4,20.4c0,11.3,20.4,32.4,20.4,32.4S66.9,53.1,66.9,41.8z    M37,41.4c0-5.2,4.3-9.5,9.5-9.5c5.2,0,9.5,4.2,9.5,9.5c0,5.2-4.2,9.5-9.5,9.5C41.3,50.9,37,46.6,37,41.4z",
  strokeColor: color,
  fillColor: color,
  strokeOpacity: 1,
  strokeWeight: 1,
  fillOpacity: 1,
  anchor: new google.maps.Point(46, 70),
});


================================================
FILE: react-frontend/src/util/models.ts
================================================
export interface Position {
  lat: number;
  lng: number;
}
export interface Route {
  _id: string;
  title: string;
  startPosition: Position;
  endPosition: Position;
}


================================================
FILE: react-frontend/tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": [
    "src"
  ]
}


================================================
FILE: simulator/Dockerfile
================================================
FROM golang:1.16

WORKDIR /go/src
ENV PATH="/go/bin:${PATH}"

RUN apt-get update && \
    apt-get install build-essential librdkafka-dev -y

CMD ["tail", "-f", "/dev/null"]

================================================
FILE: simulator/Dockerfile.prod
================================================
FROM golang:1.16

WORKDIR /go/src
ENV PATH="/go/bin:${PATH}"

RUN apt-get update && \
    apt-get install build-essential librdkafka-dev -y

COPY . .
RUN GOOS=linux go build -ldflags="-s -w" -o simulator
ENTRYPOINT ["./simulator"]

================================================
FILE: simulator/README.md
================================================
# Imersão Full Stack & FullCycle - Codelivery

## Descrição

Repositório do front-end feito com Golang (Backend)

**Importante**: A aplicação do Apache Kafka deve estar rodando primeiro.

## Configurar /etc/hosts

A comunicação entre as aplicações se dá de forma direta através da rede da máquina.
Para isto é necessário configurar um endereços que todos os containers Docker consigam acessar.

Acrescente no seu /etc/hosts (para Windows o caminho é C:\Windows\system32\drivers\etc\hosts):
```
127.0.0.1 host.docker.internal
```
Em todos os sistemas operacionais é necessário abrir o programa para editar o *hosts* como Administrator da máquina ou root.

## Rodar a aplicação

Execute os comandos:

```
docker-compose up -d
# Entrar no container
docker-compose exec app bash
# Rodar a aplicação Golang
go run main.go
```

### Para Windows 

Lembrar de instalar o WSL2 e Docker. Vejo o vídeo: [https://www.youtube.com/watch?v=usF0rYCcj-E](https://www.youtube.com/watch?v=usF0rYCcj-E) 

Siga o guia rápido de instalação: [https://github.com/codeedu/wsl2-docker-quickstart](https://github.com/codeedu/wsl2-docker-quickstart) 


================================================
FILE: simulator/application/kafka/produce.go
================================================
package kafka

import (
	"encoding/json"
	route2 "github.com/codeedu/imersaofsfc2-simulator/application/route"
	"github.com/codeedu/imersaofsfc2-simulator/infra/kafka"
	ckafka "github.com/confluentinc/confluent-kafka-go/kafka"
	"log"
	"os"
	"time"
)

// Produce is responsible to publish the positions of each request
// Example of a json request:
//{"clientId":"1","routeId":"1"}
//{"clientId":"2","routeId":"2"}
//{"clientId":"3","routeId":"3"}
func Produce(msg *ckafka.Message) {
	producer := kafka.NewKafkaProducer()
	route := route2.NewRoute()
	json.Unmarshal(msg.Value, &route)
	route.LoadPositions()
	positions, err := route.ExportJsonPositions()
	if err != nil {
		log.Println(err.Error())
	}
	for _, p := range positions {
		kafka.Publish(p, os.Getenv("KafkaProduceTopic"), producer)
		time.Sleep(time.Millisecond * 500)
	}
}

================================================
FILE: simulator/application/route/route.go
================================================
package route

import (
	"bufio"
	"encoding/json"
	"errors"
	"os"
	"strconv"
	"strings"
)

// Route represents a request of new delivery request
type Route struct {
	ID        string     `json:"routeId"`
	ClientID  string     `json:"clientId"`
	Positions []Position `json:"position"`
}

// Position is a type which contains the lat and long
type Position struct {
	Lat  float64 `json:"lat"`
	Long float64 `json:"long"`
}

// PartialRoutePosition is the actual response which the system will return
type PartialRoutePosition struct {
	ID       string    `json:"routeId"`
	ClientID string    `json:"clientId"`
	Position []float64 `json:"position"`
	Finished bool      `json:"finished"`
}

// NewRoute creates a *Route struct
func NewRoute() *Route {
	return &Route{}
}

// LoadPositions loads from a .txt file all positions (lat and long) to the Position attribute of the struct
func (r *Route) LoadPositions() error {
	if r.ID == "" {
		return errors.New("route id not informed")
	}
	f, err := os.Open("destinations/" + r.ID + ".txt")
	if err != nil {
		return err
	}
	defer f.Close()
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		data := strings.Split(scanner.Text(), ",")
		lat, err := strconv.ParseFloat(data[1], 64)
		if err != nil {
			return nil
		}
		long, err := strconv.ParseFloat(data[0], 64)
		if err != nil {
			return nil
		}
		r.Positions = append(r.Positions, Position{
			Lat:  lat,
			Long: long,
		})
	}
	return nil
}

// ExportJsonPositions generates a slice of string in Json using PartialRoutePosition struct
func (r *Route) ExportJsonPositions() ([]string, error) {
	var route PartialRoutePosition
	var result []string
	total := len(r.Positions)
	for k, v := range r.Positions {
		route.ID = r.ID
		route.ClientID = r.ClientID
		route.Position = []float64{v.Lat, v.Long}
		route.Finished = false
		if total-1 == k {
			route.Finished = true
		}
		jsonRoute, err := json.Marshal(route)
		if err != nil {
			return nil, err
		}
		result = append(result, string(jsonRoute))
	}
	return result, nil
}


================================================
FILE: simulator/destinations/1.txt
================================================
-15.82594,-47.92923
-15.8261,-47.92911
-15.82615,-47.92907
-15.82637,-47.92889
-15.82651,-47.92878
-15.82655,-47.92875
-15.82665,-47.92867
-15.82636,-47.92827
-15.82615,-47.92798
-15.82651,-47.9277
-15.82658,-47.92765
-15.82701,-47.92732
-15.82733,-47.92706
-15.82749,-47.92694
-15.8272,-47.92653
-15.82717,-47.9265
-15.82686,-47.92607
-15.82683,-47.92603
-15.82678,-47.92596
-15.82676,-47.92594
-15.82671,-47.92586
-15.82666,-47.92578
-15.82659,-47.92569
-15.82644,-47.92548
-15.8262,-47.92515
-15.82614,-47.92506
-15.82596,-47.92482
-15.8259,-47.92474
-15.82587,-47.9247
-15.82579,-47.92457
-15.82568,-47.92442
-15.8261,-47.92412
-15.82642,-47.92387
-15.82643,-47.92386
-15.82644,-47.92385
-15.82645,-47.92384
-15.82647,-47.92382
-15.82648,-47.9238
-15.82648,-47.92378
-15.82649,-47.92376
-15.82649,-47.92375
-15.8265,-47.92373
-15.8265,-47.92372
-15.8265,-47.9237
-15.8265,-47.92369
-15.82649,-47.92363
-15.8265,-47.92352
-15.8265,-47.92351
-15.8265,-47.92349
-15.82651,-47.92348
-15.82651,-47.92346
-15.82652,-47.92345
-15.82652,-47.92344
-15.82653,-47.92342
-15.82653,-47.92341
-15.82654,-47.9234
-15.82655,-47.92339
-15.82656,-47.92338
-15.82663,-47.92334
-15.8267,-47.92329
-15.82685,-47.92317
-15.827,-47.92305
-15.82711,-47.92298
-15.82721,-47.92291
-15.82731,-47.92283
-15.82741,-47.92274
-15.8275,-47.92267
-15.82758,-47.9226
-15.82761,-47.92257
-15.82764,-47.92255
-15.82775,-47.92246
-15.82787,-47.92238
-15.8281,-47.92222
-15.8281,-47.92223
-15.82811,-47.92223
-15.82812,-47.92224
-15.82812,-47.92225
-15.82813,-47.92225
-15.82814,-47.92226
-15.82815,-47.92226
-15.82816,-47.92227
-15.82817,-47.92227
-15.82818,-47.92228
-15.82819,-47.92228
-15.8282,-47.92228
-15.82821,-47.92228
-15.82822,-47.92228
-15.82823,-47.92228
-15.82824,-47.92227
-15.82825,-47.92227
-15.82826,-47.92227
-15.82826,-47.92226
-15.82827,-47.92226
-15.82828,-47.92225
-15.82847,-47.92251
-15.82853,-47.9226
-15.82923,-47.92354
-15.82935,-47.92373
-15.82947,-47.92391
-15.82947,-47.92392
-15.82946,-47.92393
-15.82946,-47.92394
-15.82946,-47.92395
-15.82945,-47.92396
-15.82945,-47.92397
-15.82945,-47.92398
-15.82946,-47.92399
-15.82946,-47.924
-15.82946,-47.92401
-15.82946,-47.92402
-15.82947,-47.92402
-15.82947,-47.92403
-15.82948,-47.92404
-15.82949,-47.92405
-15.8295,-47.92405
-15.8295,-47.92406
-15.82951,-47.92406
-15.82952,-47.92407
-15.82953,-47.92407
-15.82954,-47.92407
-15.82955,-47.92407
-15.82956,-47.92407
-15.82964,-47.92423
-15.82974,-47.92444
-15.82979,-47.9245
-15.82998,-47.92475
-15.82997,-47.92477
-15.82997,-47.92478
-15.82996,-47.92479
-15.82996,-47.9248
-15.82996,-47.92482
-15.82996,-47.92483
-15.82996,-47.92484
-15.82996,-47.92486
-15.82996,-47.92487
-15.82997,-47.92488
-15.82997,-47.92489
-15.82998,-47.9249
-15.82999,-47.92492
-15.82999,-47.92493
-15.83,-47.92494
-15.83001,-47.92495
-15.83002,-47.92496
-15.83003,-47.92497
-15.83004,-47.92497
-15.83005,-47.92498
-15.83006,-47.92499
-15.83008,-47.92499
-15.83009,-47.92499
-15.8301,-47.925
-15.83011,-47.925
-15.83013,-47.925
-15.83015,-47.925
-15.83022,-47.92511
-15.83034,-47.92529
-15.83041,-47.92536
-15.83047,-47.92543
-15.83063,-47.92564
-15.83063,-47.92565
-15.83062,-47.92565
-15.83062,-47.92566
-15.83061,-47.92566
-15.83061,-47.92567
-15.83061,-47.92568
-15.8306,-47.92568
-15.8306,-47.92569
-15.8306,-47.9257
-15.8306,-47.92571
-15.8306,-47.92572
-15.8306,-47.92573
-15.83061,-47.92573
-15.83061,-47.92574
-15.83061,-47.92575
-15.83062,-47.92575
-15.83062,-47.92576
-15.83063,-47.92576
-15.83063,-47.92577
-15.83064,-47.92577
-15.83068,-47.92593
-15.83068,-47.92596
-15.83068,-47.92599
-15.83065,-47.92606
-15.83044,-47.92624
-15.83041,-47.92626
-15.83038,-47.92628
-15.83035,-47.92631
-15.83033,-47.92634
-15.8303,-47.92636
-15.83029,-47.92637
-15.83028,-47.9264
-15.83027,-47.92642
-15.83025,-47.92644
-15.83024,-47.92646
-15.83024,-47.92648
-15.83023,-47.9265
-15.83022,-47.92651
-15.8302,-47.92656
-15.83018,-47.92661
-15.83015,-47.92665
-15.83012,-47.9267
-15.8301,-47.92674
-15.83006,-47.9268
-15.83003,-47.92684
-15.83001,-47.92686
-15.83,-47.92688
-15.82998,-47.9269
-15.82995,-47.92692
-15.82993,-47.92694
-15.82991,-47.92696
-15.82988,-47.92698
-15.82985,-47.92701
-15.82983,-47.92703
-15.8298,-47.92705
-15.82979,-47.92706
-15.82966,-47.92716
-15.82972,-47.92723
-15.8298,-47.92735
-15.82966,-47.92746
-15.82942,-47.92765

================================================
FILE: simulator/destinations/2.txt
================================================
-15.82449,-47.92756
-15.82404,-47.9269
-15.82397,-47.9268
-15.82386,-47.92661
-15.82418,-47.92636
-15.8243,-47.92627
-15.82436,-47.92623
-15.82441,-47.92619
-15.82452,-47.92611
-15.82465,-47.92601
-15.82478,-47.9259
-15.825,-47.9257
-15.82501,-47.92573
-15.82527,-47.92552
-15.82537,-47.92546
-15.82546,-47.92538
-15.82554,-47.92532
-15.82568,-47.92522
-15.8257,-47.9252
-15.82588,-47.92501
-15.82601,-47.9252
-15.82636,-47.92569
-15.82648,-47.92584
-15.82651,-47.92589
-15.82656,-47.92596
-15.8267,-47.92615
-15.82733,-47.92706
-15.82759,-47.9274
-15.82807,-47.92805
-15.82836,-47.92845
-15.82843,-47.92839
-15.82851,-47.92833
-15.82825,-47.92797
-15.82796,-47.92759
-15.82773,-47.92727
-15.82795,-47.92712
-15.82804,-47.92703
-15.82814,-47.92695
-15.82812,-47.92692
-15.8276,-47.92621

================================================
FILE: simulator/destinations/3.txt
================================================
-15.82331,-47.92588
-15.82327,-47.92584
-15.82306,-47.92553
-15.82284,-47.92522
-15.82281,-47.92519
-15.82277,-47.92513
-15.82271,-47.92504
-15.82262,-47.92492
-15.8225,-47.92476
-15.82235,-47.92454
-15.8219,-47.92394
-15.82185,-47.92387
-15.82174,-47.92372
-15.82164,-47.92357
-15.82152,-47.92342
-15.82105,-47.92377
-15.8211,-47.92384
-15.82119,-47.92395
-15.82127,-47.92406
-15.82133,-47.92413
-15.82136,-47.92419
-15.82159,-47.92451
-15.82186,-47.92488
-15.82188,-47.92491
-15.82196,-47.92502
-15.82208,-47.92519
-15.82218,-47.92533
-15.82229,-47.92548
-15.82234,-47.92555
-15.82237,-47.9256
-15.82241,-47.92564
-15.82261,-47.92592
-15.82276,-47.92612
-15.82278,-47.92615
-15.82303,-47.9265
-15.82311,-47.92663
-15.82314,-47.92668
-15.8232,-47.92687
-15.8232,-47.92688
-15.8232,-47.92689
-15.8232,-47.9269
-15.8232,-47.92691
-15.8232,-47.92692
-15.8232,-47.92693
-15.8232,-47.92694
-15.8232,-47.92695
-15.82321,-47.92696
-15.82321,-47.92697
-15.82322,-47.92698
-15.82322,-47.92699
-15.82323,-47.927
-15.82323,-47.92701
-15.82324,-47.92701
-15.82325,-47.92702
-15.82325,-47.92703
-15.82326,-47.92703
-15.82327,-47.92704
-15.82328,-47.92704
-15.82329,-47.92705
-15.8233,-47.92705
-15.82331,-47.92705
-15.82333,-47.92706
-15.82335,-47.92706
-15.82336,-47.92705
-15.82337,-47.92705
-15.82338,-47.92705
-15.82339,-47.92705
-15.8234,-47.92704
-15.82341,-47.92703
-15.82342,-47.92703
-15.82343,-47.92702
-15.82343,-47.92701
-15.82344,-47.927
-15.82345,-47.92699
-15.82345,-47.92698
-15.82346,-47.92697
-15.82346,-47.92696
-15.82346,-47.92695
-15.82346,-47.92694
-15.82347,-47.92694
-15.82347,-47.92693
-15.82375,-47.92669
-15.8238,-47.92665
-15.82386,-47.92661
-15.82418,-47.92636
-15.8243,-47.92627
-15.82436,-47.92623
-15.82441,-47.92619
-15.82452,-47.92611
-15.82465,-47.92601
-15.82478,-47.9259
-15.825,-47.9257
-15.82501,-47.92573
-15.82527,-47.92552
-15.82537,-47.92546
-15.82546,-47.92538
-15.82554,-47.92532
-15.82568,-47.92522
-15.8257,-47.9252
-15.82588,-47.92501
-15.82596,-47.92482
-15.8259,-47.92474
-15.82587,-47.9247
-15.82579,-47.92457
-15.82568,-47.92442
-15.8261,-47.92412
-15.82642,-47.92387
-15.82643,-47.92386
-15.82644,-47.92385
-15.82645,-47.92384
-15.82647,-47.92382
-15.82648,-47.9238
-15.82648,-47.92378
-15.82649,-47.92376
-15.82649,-47.92375
-15.8265,-47.92373
-15.8265,-47.92372
-15.8265,-47.9237
-15.8265,-47.92369
-15.82649,-47.92363
-15.8265,-47.92352
-15.8265,-47.92351
-15.8265,-47.92349
-15.82651,-47.92348
-15.82651,-47.92346
-15.82652,-47.92345
-15.82652,-47.92344
-15.82653,-47.92342
-15.82653,-47.92341
-15.82654,-47.9234
-15.82655,-47.92339
-15.82656,-47.92338
-15.82663,-47.92334
-15.8267,-47.92329
-15.82685,-47.92317
-15.827,-47.923
-15.82711,-47.92298
-15.82721,-47.92291
-15.82731,-47.92283
-15.82741,-47.92274
-15.8275,-47.92267
-15.82758,-47.9226
-15.82761,-47.92257
-15.82764,-47.92255
-15.82775,-47.92246
-15.82787,-47.92238
-15.8281,-47.92222
-15.8281,-47.92223
-15.82811,-47.92223
-15.82812,-47.92224
-15.82812,-47.92225
-15.82813,-47.92225
-15.82814,-47.92226
-15.82815,-47.92226
-15.82816,-47.92227
-15.82817,-47.92227
-15.82818,-47.92228
-15.82819,-47.92228
-15.8282,-47.92228
-15.82821,-47.92228
-15.82822,-47.92228
-15.82823,-47.92228
-15.82824,-47.92227
-15.82825,-47.92227
-15.82826,-47.92227
-15.82826,-47.92226
-15.82827,-47.92226
-15.82828,-47.92225
-15.82847,-47.92251
-15.82853,-47.9226
-15.82923,-47.92354
-15.82935,-47.92373
-15.82947,-47.92391
-15.82947,-47.92392
-15.82946,-47.92393
-15.82946,-47.92394
-15.82946,-47.92395
-15.82945,-47.92396
-15.82945,-47.92397
-15.82938,-47.924
-15.82931,-47.92406
-15.82925,-47.92412
-15.82921,-47.92417
-15.82917,-47.92423
-15.82905,-47.92434
-15.82897,-47.9244
-15.82888,-47.92443
-15.82879,-47.92445
-15.8286,-47.92446
-15.8286,-47.92445
-15.8286,-47.92444
-15.8286,-47.92443
-15.82859,-47.92443
-15.82859,-47.92442
-15.82859,-47.92441
-15.82858,-47.92441
-15.82858,-47.9244
-15.82857,-47.9244
-15.82856,-47.9244
-15.82856,-47.92439
-15.82855,-47.92439
-15.82854,-47.92439
-15.82853,-47.92439
-15.82853,-47.9244
-15.82852,-47.9244
-15.82851,-47.9244
-15.82841,-47.92424
-15.82826,-47.92405
-15.82821,-47.92406
-15.82815,-47.92407
-15.8281,-47.92407
-15.828,-47.924
-15.82797,-47.92409
-15.82794,-47.92409
-15.8279,-47.9241
-15.82787,-47.92411
-15.82786,-47.92412
-15.82784,-47.92412
-15.82782,-47.92414
-15.82781,-47.92415
-15.82779,-47.92416
-15.82777,-47.92418
-15.82775,-47.92419
-15.82773,-47.92422
-15.82771,-47.92423
-15.8277,-47.92425
-15.82767,-47.92429
-15.82766,-47.9243
-15.82765,-47.92432
-15.82764,-47.92434
-15.82762,-47.92436
-15.82761,-47.92438
-15.8276,-47.9244
-15.82759,-47.92442
-15.82758,-47.92445
-15.82757,-47.92447
-15.82757,-47.92449
-15.82756,-47.92452
-15.82756,-47.92455
-15.82755,-47.92457
-15.82755,-47.92461
-15.82754,-47.92466
-15.82753,-47.92471
-15.82749,-47.92478
-15.82747,-47.92481
-15.82747,-47.92483
-15.82746,-47.92485
-15.82746,-47.92486
-15.82746,-47.92489
-15.82745,-47.92491
-15.82745,-47.92494
-15.82745,-47.92495
-15.82745,-47.92498
-15.82745,-47.92501
-15.82745,-47.92504
-15.82746,-47.92505
-15.82746,-47.92507
-15.82746,-47.9251
-15.82747,-47.92512
-15.82747,-47.92514
-15.82748,-47.92516
-15.8275,-47.92519
-15.82751,-47.92521
-15.82752,-47.92523
-15.82758,-47.92532


================================================
FILE: simulator/docker-compose.yaml
================================================
version: "3"

services:
  app:
    build: .
    container_name: simulator
    volumes:
      - .:/go/src/
    extra_hosts:
      - "host.docker.internal:172.17.0.1"

================================================
FILE: simulator/go.mod
================================================
module github.com/codeedu/imersaofsfc2-simulator

go 1.16

require (
	github.com/confluentinc/confluent-kafka-go v1.6.1
	github.com/joho/godotenv v1.3.0
)


================================================
FILE: simulator/go.sum
================================================
github.com/confluentinc/confluent-kafka-go v1.6.1 h1:YxM/UtMQ2vgJX2gIgeJFUD0ANQYTEvfo4Cs4qKUlmGE=
github.com/confluentinc/confluent-kafka-go v1.6.1/go.mod h1:u2zNLny2xq+5rWeTQjFHbDzzNuba4P1vo31r9r4uAdg=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=


================================================
FILE: simulator/infra/kafka/consumer.go
================================================
package kafka

import (
	"fmt"
	"log"
	"os"

	ckafka "github.com/confluentinc/confluent-kafka-go/kafka"
)

// KafkaConsumer holds all consumer logic and settings of Apache Kafka connections/
// Also has a Message channel which is a channel where the messages are going to be pushed
type KafkaConsumer struct {
	MsgChan chan *ckafka.Message
}

// NewKafkaConsumer creates a new KafkaConsumer struct with its message channel as dependency
func NewKafkaConsumer(msgChan chan *ckafka.Message) *KafkaConsumer {
	return &KafkaConsumer{
		MsgChan: msgChan,
	}
}

// Consume consumes all message pulled from apache kafka and sent it to message channel
func (k *KafkaConsumer) Consume() {
	configMap := &ckafka.ConfigMap{
		"bootstrap.servers": os.Getenv("KafkaBootstrapServers"),
		"group.id":          os.Getenv("KafkaConsumerGroupId"),
		// "security.protocol": os.Getenv("security.protocol"),
		// "sasl.mechanisms":   os.Getenv("sasl.mechanisms"),
		// "sasl.username":     os.Getenv("sasl.username"),
		// "sasl.password":     os.Getenv("sasl.password"),
	}
	c, err := ckafka.NewConsumer(configMap)
	if err != nil {
		log.Fatalf("error consuming kafka message:" + err.Error())
	}
	topics := []string{os.Getenv("KafkaReadTopic")}
	c.SubscribeTopics(topics, nil)
	fmt.Println("Kafka consumer has been started")
	for {
		msg, err := c.ReadMessage(-1)
		if err == nil {
			k.MsgChan <- msg
		}
	}
}


================================================
FILE: simulator/infra/kafka/producer.go
================================================
package kafka

import (
	"log"
	"os"

	ckafka "github.com/confluentinc/confluent-kafka-go/kafka"
)

// NewKafkaProducer creates a ready to go kafka.Producer instance
func NewKafkaProducer() *ckafka.Producer {
	configMap := &ckafka.ConfigMap{
		"bootstrap.servers": os.Getenv("KafkaBootstrapServers"),
		// "security.protocol": os.Getenv("security.protocol"),
		// "sasl.mechanisms":   os.Getenv("sasl.mechanisms"),
		// "sasl.username":     os.Getenv("sasl.username"),
		// "sasl.password":     os.Getenv("sasl.password"),
	}
	p, err := ckafka.NewProducer(configMap)
	if err != nil {
		log.Println(err.Error())
	}
	return p
}

// Publish is simple function created to publish new message to kafka
func Publish(msg string, topic string, producer *ckafka.Producer) error {
	message := &ckafka.Message{
		TopicPartition: ckafka.TopicPartition{Topic: &topic, Partition: ckafka.PartitionAny},
		Value:          []byte(msg),
	}
	err := producer.Produce(message, nil)
	if err != nil {
		return err
	}
	return nil
}


================================================
FILE: simulator/main.go
================================================
package main

import (
	"fmt"
	kafka2 "github.com/codeedu/imersaofsfc2-simulator/application/kafka"
	"github.com/codeedu/imersaofsfc2-simulator/infra/kafka"
	ckafka "github.com/confluentinc/confluent-kafka-go/kafka"
	"github.com/joho/godotenv"
	"log"
)

func init() {
	err := godotenv.Load()
	if err != nil {
		log.Fatal("error loading .env file")
	}
}

func main() {
	msgChan := make(chan *ckafka.Message)
	consumer := kafka.NewKafkaConsumer(msgChan)
	go consumer.Consume()
	for msg := range msgChan {
		fmt.Println(string(msg.Value))
		go kafka2.Produce(msg)
	}
}
Download .txt
gitextract__u_u31gc/

├── .gitignore
├── README.md
├── apache-kafka/
│   ├── README.md
│   ├── connectors/
│   │   └── elasticsearch.properties
│   └── docker-compose.yaml
├── k8s/
│   ├── backend/
│   │   ├── configmap.yaml
│   │   ├── deploy.yaml
│   │   └── service.yaml
│   ├── frontend/
│   │   ├── deploy.yaml
│   │   └── service.yaml
│   └── simulator/
│       ├── configmap.yaml
│       └── deploy.yaml
├── nest-api/
│   ├── .docker/
│   │   ├── entrypoint.sh
│   │   └── mongo/
│   │       └── init.js
│   ├── .eslintrc.js
│   ├── .gitignore
│   ├── .prettierrc
│   ├── .vscode/
│   │   └── settings.json
│   ├── Dockerfile
│   ├── Dockerfile.prod
│   ├── README.md
│   ├── api.http
│   ├── docker-compose.yaml
│   ├── nest-cli.json
│   ├── package.json
│   ├── src/
│   │   ├── app.controller.spec.ts
│   │   ├── app.controller.ts
│   │   ├── app.module.ts
│   │   ├── app.service.ts
│   │   ├── main.ts
│   │   └── routes/
│   │       ├── dto/
│   │       │   ├── create-route.dto.ts
│   │       │   └── update-route.dto.ts
│   │       ├── entities/
│   │       │   └── route.entity.ts
│   │       ├── routes.controller.spec.ts
│   │       ├── routes.controller.ts
│   │       ├── routes.gateway.spec.ts
│   │       ├── routes.gateway.ts
│   │       ├── routes.module.ts
│   │       ├── routes.service.spec.ts
│   │       └── routes.service.ts
│   ├── test/
│   │   ├── app.e2e-spec.ts
│   │   └── jest-e2e.json
│   ├── tsconfig.build.json
│   └── tsconfig.json
├── react-frontend/
│   ├── .docker/
│   │   └── entrypoint.sh
│   ├── .gitignore
│   ├── .vscode/
│   │   └── settings.json
│   ├── Dockerfile
│   ├── Dockerfile.prod
│   ├── README.md
│   ├── docker-compose.yaml
│   ├── package.json
│   ├── public/
│   │   ├── index.html
│   │   ├── manifest.json
│   │   └── robots.txt
│   ├── src/
│   │   ├── App.tsx
│   │   ├── components/
│   │   │   ├── Mapping.tsx
│   │   │   └── Navbar.tsx
│   │   ├── errors/
│   │   │   └── route-exists.error.ts
│   │   ├── index.css
│   │   ├── index.tsx
│   │   ├── react-app-env.d.ts
│   │   ├── reportWebVitals.ts
│   │   ├── setupTests.ts
│   │   ├── theme.ts
│   │   └── util/
│   │       ├── geolocation.ts
│   │       ├── map.ts
│   │       └── models.ts
│   └── tsconfig.json
└── simulator/
    ├── Dockerfile
    ├── Dockerfile.prod
    ├── README.md
    ├── application/
    │   ├── kafka/
    │   │   └── produce.go
    │   └── route/
    │       └── route.go
    ├── destinations/
    │   ├── 1.txt
    │   ├── 2.txt
    │   └── 3.txt
    ├── docker-compose.yaml
    ├── go.mod
    ├── go.sum
    ├── infra/
    │   └── kafka/
    │       ├── consumer.go
    │       └── producer.go
    └── main.go
Download .txt
SYMBOL INDEX (64 symbols across 22 files)

FILE: nest-api/src/app.controller.ts
  class AppController (line 5) | class AppController {
    method constructor (line 6) | constructor(private readonly appService: AppService) {}
    method getHello (line 9) | getHello(): string {

FILE: nest-api/src/app.module.ts
  class AppModule (line 19) | class AppModule {}

FILE: nest-api/src/app.service.ts
  class AppService (line 4) | class AppService {
    method getHello (line 5) | getHello(): string {

FILE: nest-api/src/main.ts
  function bootstrap (line 5) | async function bootstrap() {

FILE: nest-api/src/routes/dto/create-route.dto.ts
  class CreateRouteDto (line 1) | class CreateRouteDto {}

FILE: nest-api/src/routes/dto/update-route.dto.ts
  class UpdateRouteDto (line 4) | class UpdateRouteDto extends PartialType(CreateRouteDto) {}

FILE: nest-api/src/routes/entities/route.entity.ts
  type RouteDocument (line 4) | type RouteDocument = Route & Document;
  class Route (line 7) | class Route {

FILE: nest-api/src/routes/routes.controller.ts
  class RoutesController (line 20) | class RoutesController implements OnModuleInit {
    method constructor (line 23) | constructor(
    method create (line 31) | create(@Body() createRouteDto: CreateRouteDto) {
    method findAll (line 36) | findAll() {
    method findOne (line 41) | findOne(@Param('id') id: string) {
    method update (line 46) | update(@Param('id') id: string, @Body() updateRouteDto: UpdateRouteDto) {
    method remove (line 51) | remove(@Param('id') id: string) {
    method onModuleInit (line 55) | async onModuleInit() {
    method startRoute (line 60) | startRoute(@Param('id') id: string) {
    method consumeNewPosition (line 73) | consumeNewPosition(

FILE: nest-api/src/routes/routes.gateway.ts
  class RoutesGateway (line 12) | class RoutesGateway implements OnModuleInit {
    method constructor (line 18) | constructor(
    method onModuleInit (line 23) | async onModuleInit() {
    method handleMessage (line 28) | handleMessage(client: Socket, payload: { routeId: string }) {
    method sendPosition (line 44) | sendPosition(data: {

FILE: nest-api/src/routes/routes.module.ts
  class RoutesModule (line 43) | class RoutesModule {}

FILE: nest-api/src/routes/routes.service.ts
  class RoutesService (line 9) | class RoutesService {
    method constructor (line 10) | constructor(
    method create (line 14) | create(createRouteDto: CreateRouteDto) {
    method findAll (line 18) | findAll(): Promise<RouteDocument[]> {
    method findOne (line 22) | findOne(id: number) {
    method update (line 26) | update(id: number, updateRouteDto: UpdateRouteDto) {
    method remove (line 30) | remove(id: number) {

FILE: react-frontend/src/App.tsx
  function App (line 6) | function App() {

FILE: react-frontend/src/components/Mapping.tsx
  constant API_URL (line 20) | const API_URL = process.env.REACT_APP_API_URL as string;

FILE: react-frontend/src/errors/route-exists.error.ts
  class RouteExistsError (line 1) | class RouteExistsError extends Error {}

FILE: react-frontend/src/util/geolocation.ts
  function getCurrentPosition (line 1) | function getCurrentPosition(

FILE: react-frontend/src/util/map.ts
  class Route (line 3) | class Route {
    method constructor (line 8) | constructor(options: {
    method calculateRoute (line 33) | private calculateRoute() {
    method delete (line 54) | delete() {
  class Map (line 61) | class Map {
    method constructor (line 64) | constructor(element: Element, options: google.maps.MapOptions) {
    method moveCurrentMarker (line 68) | moveCurrentMarker(id: string, position: google.maps.LatLngLiteral) {
    method removeRoute (line 72) | removeRoute(id: string) {
    method addRoute (line 78) | addRoute(
    method fitBounds (line 98) | private fitBounds() {

FILE: react-frontend/src/util/models.ts
  type Position (line 1) | interface Position {
  type Route (line 5) | interface Route {

FILE: simulator/application/kafka/produce.go
  function Produce (line 18) | func Produce(msg *ckafka.Message) {

FILE: simulator/application/route/route.go
  type Route (line 13) | type Route struct
    method LoadPositions (line 39) | func (r *Route) LoadPositions() error {
    method ExportJsonPositions (line 68) | func (r *Route) ExportJsonPositions() ([]string, error) {
  type Position (line 20) | type Position struct
  type PartialRoutePosition (line 26) | type PartialRoutePosition struct
  function NewRoute (line 34) | func NewRoute() *Route {

FILE: simulator/infra/kafka/consumer.go
  type KafkaConsumer (line 13) | type KafkaConsumer struct
    method Consume (line 25) | func (k *KafkaConsumer) Consume() {
  function NewKafkaConsumer (line 18) | func NewKafkaConsumer(msgChan chan *ckafka.Message) *KafkaConsumer {

FILE: simulator/infra/kafka/producer.go
  function NewKafkaProducer (line 11) | func NewKafkaProducer() *ckafka.Producer {
  function Publish (line 27) | func Publish(msg string, topic string, producer *ckafka.Producer) error {

FILE: simulator/main.go
  function init (line 12) | func init() {
  function main (line 19) | func main() {
Condensed preview — 83 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (77K chars).
[
  {
    "path": ".gitignore",
    "chars": 58,
    "preview": "simulator/.idea\nsimulator/.vscode\nsimulator/.env\n.history/"
  },
  {
    "path": "README.md",
    "chars": 773,
    "preview": "# Imersão Fullcycle 12 - Codelivery\n![Imersão Full Stack && Full Cycle](https://events-fullcycle.s3.amazonaws.com/events"
  },
  {
    "path": "apache-kafka/README.md",
    "chars": 1422,
    "preview": "# Imersão Full Stack & FullCycle - Codelivery\n\n## Descrição\n\nRepositório do Apache Kafka (Backend)\n\n## Configurar /etc/h"
  },
  {
    "path": "apache-kafka/connectors/elasticsearch.properties",
    "chars": 480,
    "preview": "name=elasticsearch-sink\nconnector.class=io.confluent.connect.elasticsearch.ElasticsearchSinkConnector\ntopics=route.new-d"
  },
  {
    "path": "apache-kafka/docker-compose.yaml",
    "chars": 4838,
    "preview": "version: \"3\"\n\nservices:  \n\n  zookeeper:\n    image: confluentinc/cp-zookeeper:latest\n    environment:\n      ZOOKEEPER_CLI"
  },
  {
    "path": "k8s/backend/configmap.yaml",
    "chars": 407,
    "preview": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: backend-conf\ndata:\n  env: |\n    MONGO_DSN=mongodb://root:root@mongodb/n"
  },
  {
    "path": "k8s/backend/deploy.yaml",
    "chars": 664,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: backend\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      ap"
  },
  {
    "path": "k8s/backend/service.yaml",
    "chars": 146,
    "preview": "apiVersion: v1  \nkind: Service\nmetadata:\n  name: backend-service\nspec:\n  type: LoadBalancer\n  selector:\n    app: backend"
  },
  {
    "path": "k8s/frontend/deploy.yaml",
    "chars": 354,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: frontend\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      a"
  },
  {
    "path": "k8s/frontend/service.yaml",
    "chars": 149,
    "preview": "apiVersion: v1  \nkind: Service\nmetadata:\n  name: frontend-service\nspec:\n  type: LoadBalancer\n  selector:\n    app: fronte"
  },
  {
    "path": "k8s/simulator/configmap.yaml",
    "chars": 446,
    "preview": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: simulator-conf\ndata:\n  env: |\n    KafkaReadTopic=route.new-direction\n  "
  },
  {
    "path": "k8s/simulator/deploy.yaml",
    "chars": 645,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: simulator\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      "
  },
  {
    "path": "nest-api/.docker/entrypoint.sh",
    "chars": 95,
    "preview": "#!/bin/bash\n\nif [ ! -f \".env\" ]; then\n  cp .env.example .env\nfi\n\nnpm install\n\nnpm run start:dev"
  },
  {
    "path": "nest-api/.docker/mongo/init.js",
    "chars": 487,
    "preview": "db.routes.insertMany([\n  {\n    _id: '1',\n    title: 'Primeiro',\n    startPosition: { lat: -15.82594, lng: -47.92923 },\n "
  },
  {
    "path": "nest-api/.eslintrc.js",
    "chars": 631,
    "preview": "module.exports = {\n  parser: '@typescript-eslint/parser',\n  parserOptions: {\n    project: 'tsconfig.json',\n    sourceTyp"
  },
  {
    "path": "nest-api/.gitignore",
    "chars": 409,
    "preview": "# compiled output\n/dist\n/node_modules\n\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*"
  },
  {
    "path": "nest-api/.prettierrc",
    "chars": 51,
    "preview": "{\n  \"singleQuote\": true,\n  \"trailingComma\": \"all\"\n}"
  },
  {
    "path": "nest-api/.vscode/settings.json",
    "chars": 566,
    "preview": "{\n    \"workbench.colorCustomizations\": {\n        \"activityBar.activeBackground\": \"#b61a3d\",\n        \"activityBar.activeB"
  },
  {
    "path": "nest-api/Dockerfile",
    "chars": 130,
    "preview": "FROM node:12.14.0-alpine3.11\n\nRUN apk add --no-cache bash\n\nRUN npm install -g @nestjs/cli@7.5.6\n\nUSER node\n\nWORKDIR /hom"
  },
  {
    "path": "nest-api/Dockerfile.prod",
    "chars": 229,
    "preview": "FROM node:14.15.4-slim\n\nUSER node\n\nRUN mkdir -p /home/node/app\n\nWORKDIR /home/node/app\n\nCOPY --chown=node package*.json "
  },
  {
    "path": "nest-api/README.md",
    "chars": 1075,
    "preview": "# Imersão Full Stack & FullCycle - Codelivery\n\n## Descrição\n\nRepositório do front-end feito com Nest.js (Backend)\n\n**Imp"
  },
  {
    "path": "nest-api/api.http",
    "chars": 78,
    "preview": "GET http://localhost:3000/routes\n\n###\nGET http://localhost:3000/routes/1/start"
  },
  {
    "path": "nest-api/docker-compose.yaml",
    "chars": 878,
    "preview": "version: '3'\n\nservices:\n  \n  app:\n    build: .\n    entrypoint: ./.docker/entrypoint.sh\n    ports: \n      - 3000:3000\n   "
  },
  {
    "path": "nest-api/nest-cli.json",
    "chars": 64,
    "preview": "{\n  \"collection\": \"@nestjs/schematics\",\n  \"sourceRoot\": \"src\"\n}\n"
  },
  {
    "path": "nest-api/package.json",
    "chars": 2279,
    "preview": "{\n  \"name\": \"nest-api\",\n  \"version\": \"0.0.1\",\n  \"description\": \"\",\n  \"author\": \"\",\n  \"private\": true,\n  \"license\": \"UNLI"
  },
  {
    "path": "nest-api/src/app.controller.spec.ts",
    "chars": 617,
    "preview": "import { Test, TestingModule } from '@nestjs/testing';\nimport { AppController } from './app.controller';\nimport { AppSer"
  },
  {
    "path": "nest-api/src/app.controller.ts",
    "chars": 325,
    "preview": "import { Controller, Get } from '@nestjs/common';\nimport { AppService } from './app.service';\n\n@Controller('/prefixo')\ne"
  },
  {
    "path": "nest-api/src/app.module.ts",
    "chars": 556,
    "preview": "import { Module } from '@nestjs/common';\nimport { ConfigModule } from '@nestjs/config';\nimport { MongooseModule } from '"
  },
  {
    "path": "nest-api/src/app.service.ts",
    "chars": 145,
    "preview": "import { Injectable } from '@nestjs/common';\n\n@Injectable()\nexport class AppService {\n  getHello(): string {\n    return "
  },
  {
    "path": "nest-api/src/main.ts",
    "chars": 1001,
    "preview": "import { NestFactory } from '@nestjs/core';\nimport { Transport } from '@nestjs/microservices';\nimport { AppModule } from"
  },
  {
    "path": "nest-api/src/routes/dto/create-route.dto.ts",
    "chars": 31,
    "preview": "export class CreateRouteDto {}\n"
  },
  {
    "path": "nest-api/src/routes/dto/update-route.dto.ts",
    "chars": 173,
    "preview": "import { PartialType } from '@nestjs/mapped-types';\nimport { CreateRouteDto } from './create-route.dto';\n\nexport class U"
  },
  {
    "path": "nest-api/src/routes/entities/route.entity.ts",
    "chars": 577,
    "preview": "import { Prop, Schema, raw, SchemaFactory } from '@nestjs/mongoose';\nimport { Document } from 'mongoose';\n\nexport type R"
  },
  {
    "path": "nest-api/src/routes/routes.controller.spec.ts",
    "chars": 576,
    "preview": "import { Test, TestingModule } from '@nestjs/testing';\nimport { RoutesController } from './routes.controller';\nimport { "
  },
  {
    "path": "nest-api/src/routes/routes.controller.ts",
    "chars": 2100,
    "preview": "import {\n  Controller,\n  Get,\n  Post,\n  Body,\n  Patch,\n  Param,\n  Delete,\n  Inject,\n  OnModuleInit,\n} from '@nestjs/comm"
  },
  {
    "path": "nest-api/src/routes/routes.gateway.spec.ts",
    "chars": 460,
    "preview": "import { Test, TestingModule } from '@nestjs/testing';\nimport { RoutesGateway } from './routes.gateway';\n\ndescribe('Rout"
  },
  {
    "path": "nest-api/src/routes/routes.gateway.ts",
    "chars": 1511,
    "preview": "import { Inject, OnModuleInit } from '@nestjs/common';\nimport { ClientKafka } from '@nestjs/microservices';\nimport { Pro"
  },
  {
    "path": "nest-api/src/routes/routes.module.ts",
    "chars": 1497,
    "preview": "import { Module } from '@nestjs/common';\nimport { RoutesService } from './routes.service';\nimport { RoutesController } f"
  },
  {
    "path": "nest-api/src/routes/routes.service.spec.ts",
    "chars": 460,
    "preview": "import { Test, TestingModule } from '@nestjs/testing';\nimport { RoutesService } from './routes.service';\n\ndescribe('Rout"
  },
  {
    "path": "nest-api/src/routes/routes.service.ts",
    "chars": 886,
    "preview": "import { Injectable } from '@nestjs/common';\nimport { InjectModel } from '@nestjs/mongoose';\nimport { Model } from 'mong"
  },
  {
    "path": "nest-api/test/app.e2e-spec.ts",
    "chars": 630,
    "preview": "import { Test, TestingModule } from '@nestjs/testing';\nimport { INestApplication } from '@nestjs/common';\nimport * as re"
  },
  {
    "path": "nest-api/test/jest-e2e.json",
    "chars": 183,
    "preview": "{\n  \"moduleFileExtensions\": [\"js\", \"json\", \"ts\"],\n  \"rootDir\": \".\",\n  \"testEnvironment\": \"node\",\n  \"testRegex\": \".e2e-sp"
  },
  {
    "path": "nest-api/tsconfig.build.json",
    "chars": 97,
    "preview": "{\n  \"extends\": \"./tsconfig.json\",\n  \"exclude\": [\"node_modules\", \"test\", \"dist\", \"**/*spec.ts\"]\n}\n"
  },
  {
    "path": "nest-api/tsconfig.json",
    "chars": 434,
    "preview": "{\n  \"compilerOptions\": {\n    \"module\": \"commonjs\",\n    \"declaration\": true,\n    \"removeComments\": true,\n    \"emitDecorat"
  },
  {
    "path": "react-frontend/.docker/entrypoint.sh",
    "chars": 87,
    "preview": "#!/bin/bash\n\nif [ ! -f \".env\" ]; then\n  cp .env.example .env\nfi\n\nnpm install\n\nnpm start"
  },
  {
    "path": "react-frontend/.gitignore",
    "chars": 326,
    "preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
  },
  {
    "path": "react-frontend/.vscode/settings.json",
    "chars": 566,
    "preview": "{\n    \"workbench.colorCustomizations\": {\n        \"activityBar.activeBackground\": \"#2fcefa\",\n        \"activityBar.activeB"
  },
  {
    "path": "react-frontend/Dockerfile",
    "chars": 92,
    "preview": "FROM node:12.14.0-alpine3.11\n\nRUN apk add --no-cache bash\n\nUSER node\n\nWORKDIR /home/node/app"
  },
  {
    "path": "react-frontend/Dockerfile.prod",
    "chars": 249,
    "preview": "#build\nFROM node:14.15.4-slim as build\n\nWORKDIR /app\n\nCOPY package*.json ./\n\nRUN npm install\n\nCOPY . .\n\nRUN npm run buil"
  },
  {
    "path": "react-frontend/README.md",
    "chars": 1081,
    "preview": "# Imersão Full Stack & FullCycle - Codelivery\n\n## Descrição\n\nRepositório do front-end feito com React.js (Front-end)\n\n**"
  },
  {
    "path": "react-frontend/docker-compose.yaml",
    "chars": 154,
    "preview": "version: '3'\n\nservices:\n  \n  app:\n    build: .\n    entrypoint: ./.docker/entrypoint.sh\n    ports: \n      - 3001:3000\n   "
  },
  {
    "path": "react-frontend/package.json",
    "chars": 1213,
    "preview": "{\n  \"name\": \"react-frontend\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"@material-ui/core\": \"^4."
  },
  {
    "path": "react-frontend/public/index.html",
    "chars": 1948,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" href=\"%PUBLIC_URL%/favicon.i"
  },
  {
    "path": "react-frontend/public/manifest.json",
    "chars": 520,
    "preview": "{\n  \"short_name\": \"Codelivery - Imersão Fullcycle\",\n  \"name\": \"Codelivery - Imersão Fullcycle\",\n  \"icons\": [\n    {\n     "
  },
  {
    "path": "react-frontend/public/robots.txt",
    "chars": 67,
    "preview": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n"
  },
  {
    "path": "react-frontend/src/App.tsx",
    "chars": 427,
    "preview": "import { CssBaseline, MuiThemeProvider } from \"@material-ui/core\";\nimport { SnackbarProvider } from \"notistack\";\nimport "
  },
  {
    "path": "react-frontend/src/components/Mapping.tsx",
    "chars": 4984,
    "preview": "import { Button, Grid, makeStyles, MenuItem, Select } from \"@material-ui/core\";\nimport { Loader } from \"google-maps\";\nim"
  },
  {
    "path": "react-frontend/src/components/Navbar.tsx",
    "chars": 496,
    "preview": "import { AppBar, IconButton, Toolbar, Typography } from \"@material-ui/core\";\nimport { FunctionComponent } from \"react\";\n"
  },
  {
    "path": "react-frontend/src/errors/route-exists.error.ts",
    "chars": 47,
    "preview": "export class RouteExistsError extends Error {}\n"
  },
  {
    "path": "react-frontend/src/index.css",
    "chars": 49,
    "preview": "html, body, #root{\n  height: 100%;\n  margin: 0;\n}"
  },
  {
    "path": "react-frontend/src/index.tsx",
    "chars": 514,
    "preview": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App'; //ES6 Module"
  },
  {
    "path": "react-frontend/src/react-app-env.d.ts",
    "chars": 40,
    "preview": "/// <reference types=\"react-scripts\" />\n"
  },
  {
    "path": "react-frontend/src/reportWebVitals.ts",
    "chars": 425,
    "preview": "import { ReportHandler } from 'web-vitals';\n\nconst reportWebVitals = (onPerfEntry?: ReportHandler) => {\n  if (onPerfEntr"
  },
  {
    "path": "react-frontend/src/setupTests.ts",
    "chars": 241,
    "preview": "// jest-dom adds custom jest matchers for asserting on DOM nodes.\n// allows you to do things like:\n// expect(element).to"
  },
  {
    "path": "react-frontend/src/theme.ts",
    "chars": 362,
    "preview": "import { createMuiTheme } from \"@material-ui/core\";\nimport { PaletteOptions } from \"@material-ui/core/styles/createPalet"
  },
  {
    "path": "react-frontend/src/util/geolocation.ts",
    "chars": 391,
    "preview": "export function getCurrentPosition(\n  options?: PositionOptions\n): Promise<{ lat: number; lng: number }> {\n  return new "
  },
  {
    "path": "react-frontend/src/util/map.ts",
    "chars": 4762,
    "preview": "import { RouteExistsError } from \"../errors/route-exists.error\";\n\nexport class Route {\n  public currentMarker: google.ma"
  },
  {
    "path": "react-frontend/src/util/models.ts",
    "chars": 171,
    "preview": "export interface Position {\n  lat: number;\n  lng: number;\n}\nexport interface Route {\n  _id: string;\n  title: string;\n  s"
  },
  {
    "path": "react-frontend/tsconfig.json",
    "chars": 535,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"es5\",\n    \"lib\": [\n      \"dom\",\n      \"dom.iterable\",\n      \"esnext\"\n    ],\n    "
  },
  {
    "path": "simulator/Dockerfile",
    "chars": 172,
    "preview": "FROM golang:1.16\n\nWORKDIR /go/src\nENV PATH=\"/go/bin:${PATH}\"\n\nRUN apt-get update && \\\n    apt-get install build-essentia"
  },
  {
    "path": "simulator/Dockerfile.prod",
    "chars": 230,
    "preview": "FROM golang:1.16\n\nWORKDIR /go/src\nENV PATH=\"/go/bin:${PATH}\"\n\nRUN apt-get update && \\\n    apt-get install build-essentia"
  },
  {
    "path": "simulator/README.md",
    "chars": 1123,
    "preview": "# Imersão Full Stack & FullCycle - Codelivery\n\n## Descrição\n\nRepositório do front-end feito com Golang (Backend)\n\n**Impo"
  },
  {
    "path": "simulator/application/kafka/produce.go",
    "chars": 834,
    "preview": "package kafka\n\nimport (\n\t\"encoding/json\"\n\troute2 \"github.com/codeedu/imersaofsfc2-simulator/application/route\"\n\t\"github."
  },
  {
    "path": "simulator/application/route/route.go",
    "chars": 2027,
    "preview": "package route\n\nimport (\n\t\"bufio\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// Route represents a request"
  },
  {
    "path": "simulator/destinations/1.txt",
    "chars": 4313,
    "preview": "-15.82594,-47.92923\n-15.8261,-47.92911\n-15.82615,-47.92907\n-15.82637,-47.92889\n-15.82651,-47.92878\n-15.82655,-47.92875\n-"
  },
  {
    "path": "simulator/destinations/2.txt",
    "chars": 786,
    "preview": "-15.82449,-47.92756\n-15.82404,-47.9269\n-15.82397,-47.9268\n-15.82386,-47.92661\n-15.82418,-47.92636\n-15.8243,-47.92627\n-15"
  },
  {
    "path": "simulator/destinations/3.txt",
    "chars": 5221,
    "preview": "-15.82331,-47.92588\n-15.82327,-47.92584\n-15.82306,-47.92553\n-15.82284,-47.92522\n-15.82281,-47.92519\n-15.82277,-47.92513\n"
  },
  {
    "path": "simulator/docker-compose.yaml",
    "chars": 164,
    "preview": "version: \"3\"\n\nservices:\n  app:\n    build: .\n    container_name: simulator\n    volumes:\n      - .:/go/src/\n    extra_host"
  },
  {
    "path": "simulator/go.mod",
    "chars": 155,
    "preview": "module github.com/codeedu/imersaofsfc2-simulator\n\ngo 1.16\n\nrequire (\n\tgithub.com/confluentinc/confluent-kafka-go v1.6.1\n"
  },
  {
    "path": "simulator/go.sum",
    "chars": 370,
    "preview": "github.com/confluentinc/confluent-kafka-go v1.6.1 h1:YxM/UtMQ2vgJX2gIgeJFUD0ANQYTEvfo4Cs4qKUlmGE=\ngithub.com/confluentin"
  },
  {
    "path": "simulator/infra/kafka/consumer.go",
    "chars": 1392,
    "preview": "package kafka\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tckafka \"github.com/confluentinc/confluent-kafka-go/kafka\"\n)\n\n// KafkaConsu"
  },
  {
    "path": "simulator/infra/kafka/producer.go",
    "chars": 1008,
    "preview": "package kafka\n\nimport (\n\t\"log\"\n\t\"os\"\n\n\tckafka \"github.com/confluentinc/confluent-kafka-go/kafka\"\n)\n\n// NewKafkaProducer "
  },
  {
    "path": "simulator/main.go",
    "chars": 566,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\tkafka2 \"github.com/codeedu/imersaofsfc2-simulator/application/kafka\"\n\t\"github.com/codeedu"
  }
]

About this extraction

This page contains the full source code of the devfullcycle/imersao12 GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 83 files (66.1 KB), approximately 23.9k tokens, and a symbol index with 64 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!