https://github.com/normyee/geospot-api
A robust backend API built with Clean Architecture and DDD principles, featuring MongoDB, JWT authentication, OpenStreetMap integration, and Docker containerization.
https://github.com/normyee/geospot-api
clean-architecture ddd docker-compose geospatial jwt-authentication logging mongo-session mongodb openstreetmap-api repository-pattern routing-controllers typescript
Last synced: 3 months ago
JSON representation
A robust backend API built with Clean Architecture and DDD principles, featuring MongoDB, JWT authentication, OpenStreetMap integration, and Docker containerization.
- Host: GitHub
- URL: https://github.com/normyee/geospot-api
- Owner: normyee
- Created: 2025-03-05T18:13:54.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2025-03-20T14:34:12.000Z (3 months ago)
- Last Synced: 2025-03-22T20:18:23.586Z (3 months ago)
- Topics: clean-architecture, ddd, docker-compose, geospatial, jwt-authentication, logging, mongo-session, mongodb, openstreetmap-api, repository-pattern, routing-controllers, typescript
- Language: TypeScript
- Homepage:
- Size: 197 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
## š **Solução**
Desenvolvi o Backend utilizando `Clean Architecture` e modelagem `DDD`, aplicando injeção de dependências pelo módulo `app-geo.module.ts` e implementando inversão de dependências. Usei o padrão `Repository` para abstrair a persistência e `MongoDB` com `sessions` para garantir a atomicidade das transações. A autenticação é implementada com `JWT`. Para conteinerização, utilizei `Docker Compose`.
Integrei a `API` `OpenStreetMap` para conversão entre coordenadas e endereços. As rotas foram criadas com decorators e implementei um logger eficiente usando Pino. A solução conta com vÔrias abstrações para garantir flexibilidade e manutenção fÔcil.
## š **Funcionalidades Implementadas**
### š§āš» UsuĆ”rios
- **CRUD completo**.
- Conversão entre endereço e coordenadas via API de geolocalização.
- Validação para evitar envio de ambos ou nenhum dos dados.
- Atualização de localização segue a mesma regra.
- Integração com API OpenStreetMap para conversĆ£o entre endereƧo e coordenadas geogrĆ”ficas.### š RegiƵes
- **CRUD completo**.
- RegiƵes representadas como polĆgonos em GeoJSON, associadas a um usuĆ”rio.
- Listagem de regiƵes contendo um ponto especĆfico ou dentro de um raio definido.
- Listar regiões a uma certa distância de um ponto, com opção de filtrar regiões não pertencentes ao usuÔrio que fez a requisição.
- **Geospatial Queries**:
- OperaƧƵes avanƧadas utilizando Ćndices `2dsphere` para suportar consultas espaciais eficientes.
- Implementação de consultas para localização de regiƵes e otimização de busca com indexação geoespacial.### š Extras
- Autenticação com JsonWebToken (usuĆ”rio pode ser passado na requisição de criação ou obtido no `/users/login`). āļø
- Container do MongoDB configurado com ReplicaSet SingleNode āļø.
- Utilização de **Mongo Sessions** para transaƧƵes. āļø
- Documentação completa da API por āļø.
- Cobertura de código (baixa cobertura de testes) ā ļø.
- Injeção de dependĆŖncias utilizando `typedi` para melhor modularidade e testabilidade āļø
- Implementação de logs estruturados com `Pino` para melhor monitoramento āļø.
- Uso do `Zod` para garantir a integridade das configuraƧƵes das variĆ”veis de ambiente. āļø### Como executar em minha mĆ”quina?
- Clone o projeto em sua mƔquina: `git clone https://github.com/normyee/ozmap-challenge.git`
- Entre no projeto: `cd ozmap-challenge`
`
- Crie um arquivo no pasta raiz com nome de `.env`
- Abra o `.env.example` e passe no `.env` as mesmas variƔveis
- Instale as dependĆŖncias: `yarn install`
- Inicialize o contĆŖiner: `docker-compose up --wait`
- Inicialize a aplicação: `yarn start:prod`
#### Pronto š
- Agora pode criar seu usuƔrio em `localhost:3003/users`
## Documentação
- [Como o Backend estĆ” estruturado?](doc/API-STRUCTURE.md/)### Endpoints
- Utilize `https://geojson.io/` para obter `coordenadas` de um local nas endpoints de criação de usuÔrio (`POST /users`) caso passe `coordinates` em vez do `address`. Se apenas passar o nome de um endereço vÔlido, e automaticamente as coordenadas do endereço serão obtidas. Também use `https://geojson.io/` para obter pontos geométricos para criação de `regions`.- **CRUD completo para rota /users**.
`POST - /users`
```
http://localhost:3000/users -> Cria um novo usuÔrio no sistema e retorna um Bearer Token de autenticação em todas as outras rotas, exceto esta rota e a de 'localhost:3003/users/login'
```
#### Exemplo Request:
```
{
"name": "fulano",
"email": "[email protected]",
"coordinates": [-48.47821611448057,-1.4229724705990219]
}
```
#### Response esperada:
```
{
"status": "success",
"message": "User has been created successfully",
"data": {
"id": "67d503d379222fd1a1bba282",
"name": "fulano",
"email": "[email protected]",
"address": "Passagem Marinho, Sacramenta, Belém, Região GeogrÔfica Imediata de Belém, Região GeogrÔfica IntermediÔria de Belém, ParÔ, Região Norte, 66083-000, Brasil",
"coordinates": [
-48.47821611448057,
-1.4229724705990219
]
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2N2Q1MDNkMzc5MjIyZmQxYTFiYmEyODIiLCJpYXQiOjE3NDIwMTMzOTUsImV4cCI6MTc0MjAzMTM5NX0.--pZDPTGmMO9u6ASWyWggna4YkbP3-dTGEcDtIevpM4"
}```
----------------------------------------------------------------------------------
`POST - /login`
```
http://localhost:3003/auth/login-> Retorna um Bearer Token que usaremos para acessar todas as outras rotas. *OBS*: O Bearer Token tem expiração de 5h
```#### Exemplo Request:
```
{
"email": "[email protected]",
}
```#### Response esperada:
```
{
"status": "success",
"message": "User has signed in successfully",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2N2Q1MDNkMzc5MjIyZmQxYTFiYmEyODIiLCJpYXQiOjE3NDIwMTM5NjAsImV4cCI6MTc0MjAzMTk2MH0.-pG-4UP2YEob-6sPWW8ikFBf28_4CBoxZ5WDbfEjSvc"
}
```
----------------------------------------------------------------------------------
- **CRUD completo para rota /regions**.
`POST - /regions`
```
http://localhost:3003/regions-> Cria uma região nova associada a um user. *OBS*: à necessÔrio passar o Bearer Token obtido em POST "/login" ou POST "/users"
```
#### Exemplo Request:
```
{
"name": "BelƩm Ponto",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-48.53588241001793,
-1.289183889687223
],
[
-48.53588241001793,
-1.496723909393296
],
[
-48.22618185632396,
-1.496723909393296
],
[
-48.22618185632396,
-1.289183889687223
],
[
-48.53588241001793,
-1.289183889687223
]
]
]
}
}
```#### Response esperada:
```
{
"status": "success",
"message": "Region has been created successfully",
"data": {
"id": "67d5075179222fd1a1bba285",
"name": "BelƩm Ponto",
"userId": "67d503d379222fd1a1bba282",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-48.53588241001793,
-1.289183889687223
],
[
-48.53588241001793,
-1.496723909393296
],
[
-48.22618185632396,
-1.496723909393296
],
[
-48.22618185632396,
-1.289183889687223
],
[
-48.53588241001793,
-1.289183889687223
]
]
]
}
}
}
```
----------------------------------------------------------------------------------
`GET - /regions/containing?lng=-48.4782055&lat=-1.4229802&page=1&limit=30`
```
http://localhost:3003/containing -> Retorna listagem de regiƵes contendo um ponto especĆfico ou dentro de um raio definido
```
- **Parâmetros da rota**
- `lng` -> longitude
- `lat` -> latitude
- `page` -> pƔgina atual da busca
- `limit` -> limitar a quantidade por pƔgina#### Response esperado:
```
{
"status": "success",
"message": "Regions containing the point [-48.4782055, -1.4229802] have been found successfully.",
"data": [
{
"_id": "67d5075179222fd1a1bba285",
"_name": "BelƩm Ponto",
"_userId": "67d503d379222fd1a1bba282",
"_geometry": {
"type": "Polygon",
"coordinates": [
[
[
-48.53588241001793,
-1.289183889687223
],
[
-48.53588241001793,
-1.496723909393296
],
[
-48.22618185632396,
-1.496723909393296
],
[
-48.22618185632396,
-1.289183889687223
],
[
-48.53588241001793,
-1.289183889687223
]
]
]
}
}
]
}
```
----------------------------------------------------------------------------------
`GET - /regions/near?lng=-48.451393226238935&lat=-1.402774657344807&km_distance=10&page=1&limit=10`
```
http://localhost:3003/containing -> Retorna listagem de regiƵes contendo um ponto especĆfico dentro de um raio definido em quilĆ“metros
```
- **Parâmetros da rota**
- `lng` -> longitude
- `lat` -> latitude
- `km_distance` -> distância em quilÓmetros do ponto
- `filter_user` -> `true` para filtragem regiƵes por usuƔrio
- `page` -> pƔgina atual da busca
- `limit` -> limitar a quantidade por pƔgina