Skip to content
This repository was archived by the owner on Nov 7, 2024. It is now read-only.
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
39 changes: 23 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
# Desafio técnico para desenvolvedores
# Ateliware-dev-hiring-challenge

Construa uma nova aplicação, utilizando o framework de sua preferência (Ruby on Rails, Elixir Phoenix, Python Django ou Flask, NodeJS Sails, Java Spring, ASP.NET ou outro), a qual deverá conectar na API do GitHub e disponibilizar as seguintes funcionalidades:
## Especificações

- Botão para buscar e armazenar os repositórios destaques de 5 linguagens à sua escolha;
- Listar os repositórios encontrados;
- Visualizar os detalhes de cada repositório.
Deploy feito no heroku disponivel [aqui](https://frontend-dev-hiring.herokuapp.com/).

Alguns requisitos:
+ Frontend: [React](https://pt-br.reactjs.org).
+ [Axios](https://axios-http.com).
+ Backend: [Node.js](https://nodejs.org).
+ [Sequelize](https://sequelize.org).
+ [Express](https://expressjs.com).
+ Banco de dados: [PostgreSQL](https://www.postgresql.org).
+ Subindo ao ar com [Supabase](https://supabase.com).
+ Testes:
+ [React Testing Library](https://testing-library.com).
+ [Mocha](https://mochajs.org).
+ [Chai](https://www.chaijs.com).
+ [Sinon](https://sinonjs.org).
+ Conteiner: [Docker](https://www.docker.com).

- Deve ser uma aplicação totalmente nova;
- A solução deve estar em um repositório público do GitHub;
- A aplicação deve armazenar as informações encontradas;
- Utilizar PostgreSQL, MySQL ou SQL Server;
- O deploy deve ser realizado, preferencialmente, no Heroku, AWS ou no Azure;
- A aplicação precisa ter testes automatizados;
- Preferenciamente dockerizar a aplicação;
- Por favor atualizar o readme da aplicação com passo a passo com instrução para subir o ambiente.

Quando terminar, faça um Pull Request neste repo e avise-nos por email.

**IMPORTANTE:** se você não conseguir finalizar o teste, por favor nos diga o motivo e descreva quais foram as suas dificuldades. Você pode também sugerir uma outra abordagem para avaliarmos seus skills técnicos, vender seu peixe, mostrar-nos do que é capaz.
## Funcionalidades

### Testes:
`cd backend`\
`npm test`
### Docker:
`docker-compose up -d`
11 changes: 11 additions & 0 deletions backend/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 . .

CMD ["node", "index.js"]
32 changes: 32 additions & 0 deletions backend/config/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require('dotenv/config');

const {
HOST, PASSWORD_POSTGRES, DATABASE, DB_USERNAME, DB_PORT,
} = process.env;

module.exports = {
development: {
username: DB_USERNAME,
password: PASSWORD_POSTGRES,
database: DATABASE,
host: HOST,
port: DB_PORT,
dialect: 'postgres',
},
test: {
username: DB_USERNAME,
password: PASSWORD_POSTGRES,
database: DATABASE,
host: HOST,
port: DB_PORT,
dialect: 'postgres',
},
production: {
username: DB_USERNAME,
password: PASSWORD_POSTGRES,
database: DATABASE,
host: HOST,
port: DB_PORT,
dialect: 'postgres',
},
};
66 changes: 66 additions & 0 deletions backend/controllers/gitControllers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
const { GitRepos } = require('../models');

const postRepos = async (req, res) => {
const {
id,
name,
language,
description,
user,
userImage,
created,
updated,
stars,
watchs,
size,
issues,
url,
} = req.body;
try {
const post = await GitRepos.create({
id,
name,
language,
description,
user,
userImage,
created,
updated,
stars,
watchs,
size,
issues,
url,
});

return res.status(201).json(post);
} catch (error) {
return res.status(500).json({ message: 'Internal error' });
}
};

const getAllRepos = async (_req, res) => {
try {
const repositories = await GitRepos.findAll();

return res.status(200).json(repositories);
} catch (error) {
return res.status(500).json({ message: 'Internal error' });
}
};

const deleteAllRepos = async (_req, res) => {
try {
await GitRepos.destroy({ where: {} });

return res.status(200).json({ message: 'All repositories has been deleted' });
} catch (error) {
return res.status(500).json({ message: 'Internal error' });
}
};

module.exports = {
postRepos,
getAllRepos,
deleteAllRepos,
};
5 changes: 5 additions & 0 deletions backend/heroku.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
build:
docker:
web: Dockerfile
run:
web: node index.js
21 changes: 21 additions & 0 deletions backend/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require('dotenv/config');

const express = require('express');
const cors = require('cors');
const git = require('./controllers/gitControllers');

const app = express();

app.use(express.json());
app.use(cors());

app.route('/repos')
.get(git.getAllRepos)
.post(git.postRepos)
.delete(git.deleteAllRepos);

const port = process.env.PORT;

app.get('/', (req, res) => res.send(`<h1>Executando na porta ${port}</h1>`));

module.exports = app.listen(port);
59 changes: 59 additions & 0 deletions backend/migrations/20220327005431-create-git-repos.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('GitRepos', {
id: {
allowNull: false,
autoIncrement: false,
primaryKey: true,
type: Sequelize.INTEGER,
},
name: {
type: Sequelize.STRING,
},
language: {
type: Sequelize.STRING,
},
description: {
type: Sequelize.STRING,
},
user: {
type: Sequelize.STRING,
},
userImage: {
type: Sequelize.STRING,
},
created: {
type: Sequelize.DATE,
},
updated: {
type: Sequelize.DATE,
},
stars: {
type: Sequelize.INTEGER,
},
watchs: {
type: Sequelize.INTEGER,
},
size: {
type: Sequelize.INTEGER,
},
issues: {
type: Sequelize.INTEGER,
},
url: {
type: Sequelize.STRING,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
});
},
async down(queryInterface) {
await queryInterface.dropTable('GitRepos');
},
};
17 changes: 17 additions & 0 deletions backend/models/gitrepos.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = (sequelize, DataTypes) => {
const GitRepos = sequelize.define('GitRepos', {
name: DataTypes.STRING,
language: DataTypes.STRING,
description: DataTypes.STRING,
user: DataTypes.STRING,
userImage: DataTypes.STRING,
created: DataTypes.DATE,
updated: DataTypes.DATE,
stars: DataTypes.INTEGER,
watchs: DataTypes.INTEGER,
size: DataTypes.INTEGER,
issues: DataTypes.INTEGER,
url: DataTypes.STRING,
});
return GitRepos;
};
41 changes: 41 additions & 0 deletions backend/models/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* eslint-disable prefer-template */
/* eslint-disable no-path-concat */
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');

const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
// eslint-disable-next-line import/no-dynamic-require
const config = require(__dirname + '/../config/config.js')[env];
const db = {};

// eslint-disable-next-line no-console
console.log(config);

let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}

fs
.readdirSync(__dirname)
.filter((file) => (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'))
.forEach((file) => {
// eslint-disable-next-line global-require, import/no-dynamic-require
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});

Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;
Loading