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
5 changes: 5 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"presets": [
"@babel/preset-env"
]
}
15 changes: 15 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "pwa-chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}"
}
]
}
44 changes: 26 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,65 +1,73 @@
# Prueba de Backend NodeJS

Crear un CRUD para crear productos conectado a MongoDB.

## Presentación

Soy Yonathan Gutiérrez Rodríguez, me interesa entrar al programa y formarme como un buen desarrollador además de demostrar lo que puedo aportar a la región en cuanto a talento se trata, me siento emocionado por esta oportunidad ya que creo en la premisa de Platzi y una región con mayores estándares de vida para sus pobladores…

## Despliegue

```
http://40.76.68.35:3000
```

ali esta con las especificaciones de las 11 rutas solicitadas para el reto.

## Arquitectura

<img src="https://live.staticflickr.com/65535/51184362209_51b82f629e_k.jpg" alt="nodeplatzi">

### Instalación

```
npm install
```

### Ejecución

```
npm run start
```

## Modelos

### Product

Un Producto debe tener los siguientes atributos:

- name
- price
- description
- categoryId
- image

### Category

Una Categoría debe tener los siguientes atributos:

- name
- image

## Requerimientos

### CRUD de productos

- [ ] GET `/api/products/` Endpoint para retornar la lista de productos.
- [ ] GET `/api/products/{id}/` Endpoint para retornar un producto.
- [ ] POST `/api/products/` Endpoint para crear un producto.
- [ ] PUT `/api/products/{id}/` Endpoint para modificar un producto.
- [ ] DELETE `/api/products/{id}/` Endpoint para eliminar un producto.

### CRUD de categorías

- [ ] GET `/api/categories/` Endpoint para retornar la lista de categorías.
- [ ] GET `/api/categories/{id}/` Endpoint para retornar un categoría.
- [ ] POST `/api/categories/` Endpoint para crear un categoría.
- [ ] PUT `/api/categories/{id}/` Endpoint para modificar un categoría.
- [ ] DELETE `/api/categories/{id}/` Endpoint para eliminar un categoría.
- [ ] GET `/api/categories/{id}/products` Endpoint para retornar la lista de productos que pertenecen a una categoría.

## Instrucciones

1. Utilizando el archivo `.env-example` realiza la configuración para tu archivo `.env`.
2. Proponer una arquitectura la aplicación.
3. Verificar que la conexión de tu aplicación a MongoDBAtlas funcione.
4. Realizar el deploy de tu aplicación.

### Correr pruebas en local
```
npm run test:e2e
```
1. Debes tener mongoDB en local corriendo para hacer las pruebas.
2. Y poner las variables de ambiente en el archivo `.env`.


## Enviar solución de reto
Debes de crear un "Fork" de este proyecto, revolverlo desde tu cuenta personal.

### Licencia

La licencia [MIT](https://opensource.org/licenses/MIT).
63 changes: 63 additions & 0 deletions dist/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createApp = createApp;

var _express = _interopRequireWildcard(require("express"));

var _cors = _interopRequireDefault(require("cors"));

var _index = _interopRequireDefault(require("./routes/index.routes"));

var _categories = _interopRequireDefault(require("./routes/categories.routes"));

var _products = _interopRequireDefault(require("./routes/products.routes"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

function createApp() {
return _createApp.apply(this, arguments);
}

function _createApp() {
_createApp = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
var app;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
// SETTINGS
app = (0, _express["default"])();
app.use((0, _cors["default"])());
app.use(_express["default"].json()); //MIDDLEWARES

app.use((0, _express.json)()); // ROUTES

app.use(_index["default"]);
app.use('/api/categories', _categories["default"]);
app.use('/api/products', _products["default"]);
return _context.abrupt("return", app);

case 8:
case "end":
return _context.stop();
}
}
}, _callee);
}));
return _createApp.apply(this, arguments);
}

module.exports = createApp;
15 changes: 15 additions & 0 deletions dist/config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require("dotenv").config();

const config = {
dev: process.env.NODE_ENV !== "production",
port: process.env.PORT || 3000,
dbUser: process.env.MONGO_USER,
dbPassword: process.env.MONGO_PASSWORD,
dbHost: process.env.MONGO_HOST,
dbName: process.env.MONGO_DB_NAME,
dbPort: process.env.MONGO_PORT,
dbConnection: process.env.MONGO_CONNECTION,
};
module.exports = {
config: config,
};
54 changes: 54 additions & 0 deletions dist/controllers/category.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"use strict";

var _category = _interopRequireDefault(require("../models/category.model"));

var _mongoose = _interopRequireDefault(require("mongoose"));

var _database = require("../database");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

exports.newCategory = /*#__PURE__*/function () {
var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(req, res, next) {
var category;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
category = new _category["default"](req.body);
(0, _database.connect)();
_context.prev = 2;
_context.next = 5;
return category.db.save().then(function (result) {
res.status(200).json({
message: 'Category save correctly'
});

_mongoose["default"].connection.close();
});

case 5:
return _context.abrupt("return", result);

case 8:
_context.prev = 8;
_context.t0 = _context["catch"](2);
console.log("Error de: ".concat(_context.t0));
next();

case 12:
case "end":
return _context.stop();
}
}
}, _callee, null, [[2, 8]]);
}));

return function (_x, _x2, _x3) {
return _ref.apply(this, arguments);
};
}();
1 change: 1 addition & 0 deletions dist/controllers/product.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"use strict";
55 changes: 55 additions & 0 deletions dist/database.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"use strict";

Object.defineProperty(exports, "__esModule", {
value: true
});
exports.connect = connect;

var _mongoose = _interopRequireDefault(require("mongoose"));

var _config = require("./config");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

function connect() {
return _connect.apply(this, arguments);
}

function _connect() {
_connect = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
var db;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.prev = 0;
_context.next = 3;
return _mongoose["default"].createConnection(_config.config.dbHost, {
useUnifiedTopology: true,
useNewUrlParser: true,
useFindAndModify: false
});

case 3:
db = _context.sent;
console.log("Database is connected in MongoAtlas!");
return _context.abrupt("return", db);

case 8:
_context.prev = 8;
_context.t0 = _context["catch"](0);
console.log(_context.t0);

case 11:
case "end":
return _context.stop();
}
}
}, _callee, null, [[0, 8]]);
}));
return _connect.apply(this, arguments);
}
53 changes: 53 additions & 0 deletions dist/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"use strict";

require("@babel/polyfill");

var _config = require("./config");

var _app = _interopRequireDefault(require("./app"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

var app = (0, _app["default"])();

function main() {
return _main.apply(this, arguments);
}

function _main() {
_main = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.prev = 0;
_context.next = 3;
return app;

case 3:
_context.sent.listen(_config.config.port);

console.log("Is connected in port ".concat(_config.config.port));
_context.next = 10;
break;

case 7:
_context.prev = 7;
_context.t0 = _context["catch"](0);
console.error("Error es: ", _context.t0);

case 10:
case "end":
return _context.stop();
}
}
}, _callee, null, [[0, 7]]);
}));
return _main.apply(this, arguments);
}

main();
29 changes: 29 additions & 0 deletions dist/models/category.model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;

var _mongoose = _interopRequireWildcard(require("mongoose"));

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

var categoriesSchema = new _mongoose.Schema({
name: {
type: String,
trim: true
},
image: {
type: String,
trim: true
}
});

var _default = _mongoose["default"].model('categories', categoriesSchema);

exports["default"] = _default;
Loading