En este artÃculo estaremos creando una REST API usando Node js con TypeScript y MongoDB Atlas
Primeramente dejame contarte que ya tengo un tiempo programando en javascript(en el frontend) y hace un par de meses he venido probando javascript para el backend(Node.js) pero como en mi trabajo actual(también en mis trabajos anteriores) programó en C# y mi mayor experiencia se centra en este lenguaje, por esta razón he querido usar en mi aprendizaje de Node.js TypeScript ya que la sintaxis es muy parecida a c#(también se parece a java) y me siento más cómodo que usando solo javascript(de hecho usar ts te trae muchas ventajas que lo veremos en artÃculos posteriores)
Lo primero que tienes que hacer es instalar Node.js
Una vez instalado node procedemos a instalar TypeScript de manera global
Iniciamos un nuevo proyecto de node
Creamos el archivo configuración para TypeScript
npm install -g typescript
npm init -y
tsc --init
En el archivo de configuración de TypeScript realizaremos las siguientes modificaciones
"target": "es6", //usamos ECMAScript 6
"outDir": "./dist", //especificamos la carpeta donde se generara el codigo js cuando compilemos el codigo ts
Instalamos los módulos que estaremos usando en este proyecto
npm i express mongoose morgan cors helmet
Instalar dependencias para desarrollo
npm install @types/node @types/mongoose @types/express @types/morgan nodemon typescript -D
La ultima configuracion que haremos será dentro del archivo package.json para no estar compilando nuestro código TypeScript y luego ejecutar el código js generado con node siempre que hagamos cambios haremos la siguiente configuración
"scripts": {
"ts": "tsc -w",
"dev": "nodemon ./dist/server.js",
"start": "tsc && node ./dist/server.js"
},
Ahora bastará con que ejecutemos npm run ts para que nuestro código ts se compile automáticamente y npm run dev para que nuestra aplicación se reinicie automáticamente al detectar cambios en el códigoLa estructura del proyecto que crearemos será la siguiente
Te explico rápidamente la estructura del proyecto
- src carpeta donde estará todo nuestro desarrollo.
- controller tendremos los controladores que son los encargados de procesar las peticiones y retornar la información.
- models contendrá los modelos que usaremos para manejar los datos de nuestra db.
- routes es donde armaremos las rutas que tendrás nuestras peticiones.
- services es donde realizaremos las consultas a la db.
- server.ts es la clase de inicio de nuestra aplicación.
Como te lo mencione anteriormente estaremos usando MongoDB Atlas que prácticamente es un servicio que te permite tener tu servidor de mongodb en la nube(te permite poder probarlo gratis) asà que deberás crear una cuenta MongoDB Atlas una vez registrado lo único que debes hacer es crear un cluster y con esto podrás obtener los datos para poder conectarte al servidor de mongodb, para este ejemplo yo cree el cluster con el nombre por defecto que es Cluster0 y cree una base de datos llamada api-db
Empezaremos primero en la carpeta models crearemos un archivo llamado Products.ts que representara la collection de nuestra db
import {Schema, model, Document} from 'mongoose';
export interface IProduct extends Document {
name: string;
category: string;
price: Number;
};
const ProductSchema = new Schema(
{
name: {type: String, required: true},
category: {type: String, required: true},
price: {type: Number, required: true},
createdAt: {type: Date, default: Date.now}
}
);
export default model<IProduct>('Product', ProductSchema);
Una vez tenemos creado nuestro modelo que representa nuestra collection crearemos el servicio para poder hacer las consultas a la db, dentro de la carpeta services creamos el archivo productServices.ts
import Product, { IProduct } from "../models/Products";
import { ObjectID } from "mongodb";
export async function getProductsServices() {
try {
return await Product.find();
} catch (error) {
// Log Errors
throw Error(error);
}
}
export async function getProductServices(id: ObjectID) {
try {
return await Product.findOne({ _id: id });
} catch (error) {
// Log Errors
throw Error(error);
}
}
export async function createProductServices(product: IProduct) {
try {
await product.save();
return product;
} catch (error) {
// Log Errors
throw Error(error);
}
}
export async function updateProductServices(id: ObjectID, product: IProduct) {
try {
await Product.findOneAndUpdate({ _id: id}, product);
return product;
} catch (error) {
// Log Errors
throw Error(error);
}
}
export async function deleteProductServices(id: ObjectID) {
try {
return await Product.findOneAndRemove({_id: id});
} catch (error) {
// Log Errors
throw Error(error);
}
}
Ahora crearemos el controlador que será el encargado de procesar las solicitudes y retornar la información correspondiente en la carpeta controller creamos el archivo productController.ts
import { Request, Response } from "express";
import Product, { IProduct } from "../models/Products";
import { ObjectID } from "mongodb";
import {
getProductServices,
getProductsServices,
createProductServices,
updateProductServices,
deleteProductServices
} from "../services/productServices";
export async function getProductsController(req: Request, res: Response) {
try {
const products = await getProductsServices();
console.log(products);
res.json(products);
} catch (error) {
res.status(500).json({ status: 500, message: error.message });
}
}
export async function getProductController(req: Request, res: Response) {
try {
const { id } = req.params;
const product = await getProductServices(new ObjectID(id));
console.log(product);
res.json(product);
} catch (error) {
res.status(500).json({ status: 500, message: error.message });
}
}
export async function createProductController(req: Request, res: Response) {
try {
const { name, category, price } = req.body;
const newproduct: IProduct = new Product({ name, category, price });
await createProductServices(newproduct);
res.json(newproduct);
} catch (error) {
res.status(500).json({ status: 500, message: error.message });
}
}
export async function updateProductController(req: Request, res: Response) {
try {
const { id } = req.params;
const product = await updateProductServices(new ObjectID(id), req.body);
console.log(product);
res.json(product);
} catch (error) {
res.status(500).json({ status: 500, message: error.message });
}
}
export async function deleteProductController(req: Request, res: Response) {
try {
const { id } = req.params;
const product = await deleteProductServices(new ObjectID(id));
console.log(product);
res.json(product);
} catch (error) {
res.status(500).json({ status: 500, message: error.message });
}
}
Ahora definiremos las diferentes rutas que tendrá nuestra rest api en la carpeta routes creamos el archivo productRoutes.ts
import { Router } from "express";
import {
getProductController,
getProductsController,
createProductController,
updateProductController,
deleteProductController
} from "../controller/productController";
class Product {
public router: Router;
constructor() {
this.router = Router();
this.routes();
}
routes() {
this.router.get("/", getProductsController);
this.router.get("/:id", getProductController);
this.router.post("/", createProductController);
this.router.put('/:id', updateProductController);
this.router.delete('/:id', deleteProductController);
}
}
const product = new Product();
export default product.router;
Por último nos falta crear nuestra clase principal en donde configuramos nuestra servidor express asà que dentro de la carpeta src creamos el archivo server.ts
import express from "express";
import morgan from "morgan";
import routes from "./routes/index";
import productsRoutes from "./routes/productRoute";
import mongoose from "mongoose";
import cors from "cors";
class Server {
public app: express.Application;
constructor() {
this.app = express();
this.config();
this.routes();
}
config() {
//connection mongodb atlas
const mongodb_atlas =
"mongodb+srv://<user>:<password>@cluster0.fvcxm.mongodb.net/api-db?retryWrites=true&w=majority";
mongoose.set("useFindAndModify", true);
mongoose
.connect(mongodb_atlas || process.env.MONGODB_URL, {
useNewUrlParser: true,
useCreateIndex: true,
})
.then((db) => console.log("Connected to database"))
.catch((err) => {
console.error(`Error connecting to the database. \n${err}`);
});
//Settings
this.app.set("port", process.env.PORT || 3000);
//Middlewares
this.app.use(express.json());
this.app.use(express.urlencoded({ extended: false }));
this.app.use(morgan("dev"));
this.app.use(cors());
}
routes() {
this.app.use("/api/products", productsRoutes);
}
start() {
this.app.listen(this.app.get("port"), () => {
console.log("Server on port:", this.app.get("port"));
});
}
}
const server = new Server();
server.start();
Ejecutamos nuestra aplicación
npm run ts
npm run dev
Ahora tenemos nuestra rest api lista, empecemos haciendo un post para crear un nuevo producto
Ahora probemos la petición get para devolver todos los productos
Consultemos un producto por su id
Actualicemos un producto put
Y por último eliminemos un producto delete
Nuestra REST API está funcionando perfectamente. Esta estructura te puede servir como partida inicial de tu próximo proyecto
puedes descargar el código desde este repositorio
Hasta la próxima.
Saludos desde El Salvador...
0 Comentarios