ccc

Node.js: Subir a producción

Lo primero en package.json añadir en scripts el comando de start, quedaría: "scripts": {
   "dev": "nodemon src/index.js",
   "start": "node src/index.js"
},
Tener creado un .gitignore con:
node_modules/
.env

Y subir todo al respositorio de github o bitbucket

Node.js: Variables de entorno

npm i dotenv
Creamos el fichero .env en la raiz
PORT=3000
DB_HOST=localhost
DB_PORT=3306 # es el port para mysql
DB_USER=root
DB_PASSWORD=
DB_DATABASE=ejemplo
Creamos el fichero src/config.js
import {config} from "dotenv"
config()
export const PORT = process.env.PORT || 3000
export const DB_HOST = process.env.DB_HOST || localhost
export const DB_PORT = process.env.DB_PORT || 3306
export const DB_USER = process.env.DB_USER || root
export const DB_PASSWORD = process.env.DB_PASSWORD || ""
export const DB_DATABASE = process.env.DB_DATABASE || ejemplo
Y ahora ya en el fichero src/db.js:
import {createPool} from "mysql2/promise"
import {PORT,DB_HOST,DB_PORT,DB_USER,DB_PASSWORD,DB_DATABASE} from "./config.js"

export const pool = createPool({
   host: DB_HOST,
   user: DB_USER,
   password: DB_PASSWORD,
   port: DB_PORT,
   database: DB_DATABASE
})
Una forma más limpia y ordenada es no poner todo el código en index.js sino crear un fichero src/app.js donde meter todas las inicializaciones del index, y en el index dejar solo:
import app from "./app.js"
import {PORT} from "./config.js"
app.listen(PORT)
console.log("server funcionando en: "+PORT)

Node.js: Control de errores

Cuando se produce un error se para la ejecución y no se puede seguir usandolo. Por tanto siempre es aconsejable usar try y catch para todo. try {
   const [rows] = await pool.query("select * from clientes")
   res.json(rows)
}
catch(error) {
   return res.status(500).json({
     message: "algo ha fallado"
   })
}

Así si se produce cualquier error se ejecuta el catch, sale ese mensaje pero la ejecución no se interrumpe y sigue todo OK.
Personalizar el mensaje de error si una url no existe. En el index.js justo antes del app.listen(3000):
// si no encuentra ninguna ruta que saque un error de pag no encontrada
app.use((req,res,next) => {
   res.status(404).json({
     message: "Error: Esa url no existe"
   })
})

Node.js: Actualizar un dato

En el clientesRoutes.js:
router.put("/updateCliente/:id",updateCliente)
En el clientesController:
export const updateCliente = async (req,res) => {
   const id = req.params.id
   const {nombre,edad,profesion} = req.body
   const [result] = await pool.query("update clientes set nombre=IFNULL(?,nombre), edad=IFNULL(?,edad), profesion=IFNULL(?,profesion) where id = ?",[nombre,edad,profesion,id])
   if (result.affectedRows == 0) {
     return res.status(404).json({
        message: "Cliente no se pudo actualizar"
     })
   }
   res.send("Cliente actualizado")
}

A la hora de envíar se pondrá en el Thunder Client (o en el POstman) PUT localhost:3000/updateCliente/2

Por convenio si no se van a actualizar todos los datos entonces se envía con PATCH (aunque hace lo mismo que PUT)

Node.js Controllers: Borrar un dato

En \src\routes\clientesRoutes.js:
router.delete("/deleteCliente/:id",deleteCliente)
En \src\controllers\clientesControllers.js:
export const deleteCliente = async (req,res) => {
   const [result] = await pool.query("deleteeee from clientes where id = ?",[req.params.id])
   if (result.affectedRows <=0) {
     return res.status(404).json({
     "message": "Cliente no encontrado al intentar borrarlo"
     })
   }
   res.sendStatus(204) // que todo OK pero no envia nada
}

Node.js controllers: Obtener datos

En \src\routes\clientesRoutes.js:
router.get("/getCLientes",getClientes)
router.get("/getCLienteById/:id",getClienteById)

En \src\controllers\clientesControllers.js:
export const getClientes = async (req,res) => {
   const [rows] = await pool.query("selectttt * from clientes")
   res.json(rows)
}

export const getClienteById = async (req,res) => {
   const [rows] = await pool.query("selecttttt * from clientes where id = ?", [req.params.id])
   if (rows.length <= 0) {
      return res.status(404).json({
      "message": "Cliente no encontrado"
      })
   }
   res.json(rows[0])
}

Node.js: Controllers: Insertar datos

Para probarlo desde el postman o desde el Thunder Client enviamos la prueba en json a:
POST: localhost:3000/crearCliente:
{
   "nombre": "nom3",
   "edad": 33,
   "profesion": "prof3"
}

Para poder recibir en json en el index.js tenemos q tener:
app.use(express.json());
Y luego en clientesController:
export const crearCliente = async (req,res) => {
   const {nombre,edad,profesion} = req.body
   const [rows] = await pool.query("insert into clientes(nombre,edad,profesion) values (?,?,?)", [nombre,edad,profesion])
   res.send(rows)
}

Node.js: Controllers

Creas un fichero \src\controllers\clientesControllers.js:
export const getClientes = (req,res) => {
   res.send("Aquí obtendremos todos los clientes")
}
export const crearCliente = (req,res) => {
   res.send("Crear cliente nuevo")
}
export const updateCliente = (req,res) => {
   res.send("Actualizar cliente")
}
export const deleteCliente = (req,res) => {
   res.send("Borrar cliente")
}

Y en \src\routes\clientesRoutes.js:
import {Router} from "express"
import {getClientes,crearCliente,updateCliente,deleteCliente} from "../controllers/clientesControllers.js"

const router = Router()

router.get("/getCLientes",getClientes)
router.post("/crearCliente",crearCliente)
router.put("/updateCliente",updateCliente)
router.delete("/deleteCliente",deleteCliente)

export default router;

Node.js: Crear rutas

Por ejemplo crear rutas para usar en nuestro index.js: routes/index_routes.js:
import {Router} from "express"
import {pool} from "../src/db.js"
const router = Router()

router.get("/probarCnn", async (req,res) => {
   const result = await pool.query("select * from clientes")
   res.json(result)
})
export default router;
Y luego para usarlo en nuestro index.js:
import indexRoute from "../routes/index_routes.js"
...
app.use(indexRoute)

Otro ejemplo: routes/clientes_routes.js:
import {Router} from "express"
const router = Router()

router.get("/getCLientes",(req,res) => {
   res.send("Aquí obtendremos todos los clientes")
})
export default router;
Y para usarlo en el index (o en el fichero q queramos):
import clientRoute from "../routes/clientes_routes.js"
...
app.use(clientRoute)

Visual Studio Code: Extensión Thunder Client para simular peticiones GET, POST, PUT y DELETE

Instalar la extensión de "Thunder Client" Para hacerlo todo desde el Visual Studio Code y así no tener que usar Postman y otros programas similares.

Para ejecutarlo sale una vez instalado un icono de un trueno.

Node.js: enlazar con Mysql

Lo primero crear el package.js con: npm init -y
Y luego hay que instalar todos estos módulos:
npm i express nodemon Para probar nodemon en el script del package.js:
"scripts": {
   "dev": "nodemon src/index.js"
},
Y así para ejecutarlo:
npm run dev

También es util en package poner:
"type": "module", Para así poder import/export módulos más fácilmente de un archivo a otro
Para q funcione las variables globales de .env:
npm i dotenv -D Y luego para usarlo en cualquier fichero js:
require("dotenv").config();
...
console.log(process.env.PORT);

Para instalar el módulo de mysql:
npm install --save mysql2
Para usarlo crear un fichero db.js:
import {createPool} from "mysql2/promise"

export const pool = createPool({
   host:'localhost',
   user:'root',
   password:'',
   port:3306,
   database: 'ejemplo'
})

Y desde otro fichero llamarlo:
import {pool} from "./db.js"
...
app.get("/probarCnn", async (req,res) => {
   const result = await pool.query("select * from clientes")
   res.json(result)
})

Node: Hacer un deploy para subir una app a Internet

El único cloud gratuito que he encontrado es render.com.

Primero hay que subir el proyecto a github
Luego registrarse en render (seguramente te pida autentificación con la App del móvil de "salesforce authenticator" (deberás instalarla previamente)

Una vez dentro de render.com crea "new web service" y te identificas con tu github.
Select solo el repositorio que quieres q se ejecute
En los datos a rellenar:
root directory: .
Build command: npm install
start command: node src/index.js

Si tarda más de 5 minutos en ejecutarse el deploy es pq hay un error, abortarlo y en el log saldrá los errores encontrados

Más información en: https://www.youtube.com/watch?v=yln_CffenYw