Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .commitlintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
extends: ['@commitlint/config-conventional'],
};
12 changes: 12 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
]
}
66 changes: 66 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# next.js build output
.next

# typescript compiled code
dist/

db
6 changes: 6 additions & 0 deletions .huskyrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"hooks": {
"pre-commit": "npm run style:check && npm run lint:check && npm run test:unit",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
}
26 changes: 26 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"arrowParens": "avoid",
"bracketSpacing": true,
"embeddedLanguageFormatting": "auto",
"htmlWhitespaceSensitivity": "css",
"insertPragma": false,
"jsxBracketSameLine": false,
"jsxSingleQuote": false,
"printWidth": 80,
"proseWrap": "preserve",
"quoteProps": "as-needed",
"requirePragma": false,
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all",
"useTabs": false,
"vueIndentScriptAndStyle": false,
"rangeStart": 0,
"overrides": [
{
"files": ".prettierrc",
"options": { "parser": "json" }
}
]
}
11 changes: 11 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM node:alpine

WORKDIR /app
COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 8000
CMD [ "npm", "run","start" ]
75 changes: 13 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,18 @@
# Raks Back-end Developer Test
### Requisitos
- docker
- docker-compose
- NodeJS `LTS`

Be sure to read **all** of this document carefully, and follow the guidelines within.
### Iniciar o projeto
- Execute `docker-compose up -d` para subir o ambiente do banco de dados (MYSQL).
- Execute `npm run start` para iniciar o servidor NodeJS (porta 8000).
- Acesse a collection do Postman: https://www.getpostman.com/collections/74a6186e30475cbe75bc
- Para acessar os docs da API: http://localhost:8000/docs

## Context
## Arquitetura

Build a RESTful API that can `create/read/update/delete` user data from a persistence store.
A API foi implementada em cima de clean architecture. Essa abordagem possibilita que o código seja menos acoplado, permitindo alta extensibilidade.

### User Model
Segue o diagrama da arquitetura do projeto:

```
{
"id": "xxx", // user ID (must be unique)
"name": "backend test", // user name
"dob": "", // date of birth
"address": "", // user address
"description": "", // user description
"createdAt": "" // user created date
"updatedAt": "" // user updated date
}
```

### Functionality

- The API should follow typical RESTful API design pattern.
- The data should be saved in the DB.
- Provide proper API documentation.
- Proper error handling should be used.

## What We Care About

Use any libraries that you would normally use if this were a real production App. Please note: we're interested in your code & the way you solve the problem, not how well you can use a particular library or feature.

_We're interested in your method and how you approach the problem just as much as we're interested in the end result._

Here's what you should strive for:

- Good use of current Node.js & Express.js
- Good use of API design best practices.
- Solid testing approach.
- Extensible code.

## Implementation Path:

### Basic Requirements

- Use Node.js `LTS` and any framework of your choice.
- Use any SQL DB. MySQL DB is preferred.
- Write concise and clear commit messages.
- Write clear **documentation** on how it has been designed and how to run the code.

### Bonus
- **Use typescript.**
- Use of Sequelize ORM (https://sequelize.org/)
- Provide proper unit tests.
- Add a read only endpoint to fetch location information based off the user's address (use [NASA](https://api.nasa.gov/api.html) or [Mapbox](https://www.mapbox.com/api-documentation/) APIs)
- Providing an online demo is welcomed, but not required.

## Q&A

> Where should I send back the result when I'm done?

Fork this repo and send us a pull request when you think you are done. Or send me the link of the forked repo.

> What if I have a question?

Create a new issue in this repo or send me an email.
![Arquitetura](https://i.imgur.com/jTW4Q13.png)
18 changes: 18 additions & 0 deletions config/custom.environment-variables.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"App": {
"port": "APP_PORT",
"database": {
"mongoUrl": "MONGODB_URL"
},
"resources": {
"StormGlass": {
"apiUrl": "STORM_GLASS_API_URL",
"apiToken": "STORM_GLASS_API_TOKEN",
"cacheApiTtl": "STORM_GLASS_API_CACHE_TTL"
}
},
"auth": {
"key": "JWT_SECRET_KEY"
}
}
}
28 changes: 28 additions & 0 deletions config/default.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"App": {
"port": 8000,
"database": {
"port": 3306,
"type": "mysql",
"host": "localhost",
"username": "root",
"password": "123456",
"database": "app"
},
"auth": {
"key": "some-key",
"tokenExpiresIn": "20000000"
},
"resources": {
"StormGlass": {
"apiUrl": "https://api.stormglass.io/v2",
"apiToken": "do-not-hard-code",
"cacheTtl": 3600
}
},
"logger": {
"enabled": true,
"level": "info"
}
}
}
15 changes: 15 additions & 0 deletions config/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"App": {
"resources": {
"StormGlass": {
"apiToken": "test-token"
}
},
"database": {
"mongoUrl": "mongodb://localhost:27017/surf-forecast-test"
},
"logger": {
"enabled": false
}
}
}
15 changes: 15 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: '3'

services:
mysql:
image: mysql:5.7
container_name: mysql
ports:
- 3306:3306
volumes:
- ./db:/var/lib/mysql
environment:
MYSQL_DATABASE: app
MYSQL_ROOT_PASSWORD: 123456
MYSQL_USER: app
MYSQL_PASSWORD: 098765
10 changes: 10 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const { resolve } = require('path');
const root = resolve(__dirname);
module.exports = {
rootDir: root,
displayName: 'root-tests',
testMatch: ['<rootDir>/tests/**/*.test.ts'],
testEnvironment: 'node',
clearMocks: true,
preset: 'ts-jest',
};
15 changes: 15 additions & 0 deletions ormconfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const config = require('config');

module.exports = {
"type": config.get('App.database.type'),
"host": config.get('App.database.host'),
"port": config.get('App.database.port'),
"username": config.get('App.database.username'),
"password": config.get('App.database.password'),
"database": config.get('App.database.database'),
"synchronize": true,
"logging": false,
"entities": [
"dist/domain/entities/**/*.entity.js"
]
}
Loading