sábado, 29 de octubre de 2022

Instalando y ejecutando una aplicación Node.js en IIS de Windows Server

 

https://blog.soluciones-dc.com/2019/06/instalando-y-ejecutando-una-aplicacion.html

Instalando y ejecutando una aplicación Node.js en IIS de Windows Server.


Hola, en este articulo te voy a mostrar que pasos seguí para instalar, configurar y ejecutar una aplicación node.js en mi servidor web IIS de un Windows Server 2008 R2.


Lo que necesitamos:

1.- Instalamos Node.js (Yo instale la versión recomendable), lo puedes descargar de la siguiente url: https://nodejs.org/es/



2.- Descargamos iisnode full de la siguiente url: https://github.com/azure/iisnode/wiki/iisnode-releases 



En mi caso descargue iisnode for iis 7/8 (x64), ya que mi servidor es de 64 bits.

3.- Descargamos e instalamos URL Reweite de la siguiente url: https://www.iis.net/downloads/microsoft/url-rewrite 



Ahora bien, comprobamos las rutas de instalación y comenzamos con la instalación y configuración de un sitio nuevo: 



En caso de no existir el archivo setupsamples.bat y la carpeta www la descargamos de la siguiente url:

Setupsamples.bat: https://github.com/tjanczuk/iisnode/blob/master/src/scripts/setupsamples.bat

Carpeta www: https://github.com/tjanczuk/iisnode/tree/master/src/samples 



Entonces comenzamos con la configuración del nuevo sitio. Abrimos una línea de comandos como administrador en la ruta C:\Program Files (x86)\iisnode y ejecutamos el archivo setupsamples.bat. 



Una vez terminada la configuración abrimos IIS para verificar que realmente se creo la aplicación:

Y por último verificamos que el servidor responsa satisfactoriamente entrando a la ruta: http://localhost/node/ 



No olviden dan permisos de escritura y lectura a los usuarios IIS_IUSRS y IUSR

jueves, 27 de octubre de 2022

Node.js + MS SQL Server - Ejemplo y tutorial de API CRUD

 https://jasonwatmore.es/post/2022/06/18/nodejs-ms-sql-server-ejemplo-y-tutorial-de-api-crud#postman-create-user

Node.js + MS SQL Server - Ejemplo y tutorial de API CRUD

Tutorial creado con Node.jsSequelize y MS SQL Server

Otras versiones disponibles:

En este tutorial, cubriremos cómo crear una API de Node.js simple que admita operaciones CRUD y almacene datos en una base de datos de Microsoft SQL Server. La API de ejemplo incluye rutas para recuperar, actualizar, crear y eliminar registros en una base de datos MSSQL, los registros en el ejemplo son registros de usuario pero el mismo patrón CRUD y estructura de código se podría aplicar a cualquier tipo de datos p.ej. productos, servicios, artículos, etc.

Primera generación de base de datos de código MSSQL con Sequelize

La API de Node.js crea automáticamente la base de datos de SQL Server al inicio (si es necesario) y sincroniza las tablas y columnas de la base de datos con los modelos de JavaScript definidos mediante la biblioteca Sequelize ORM. La creación de la base de datos y la sincronización del modelo se realizan mediante la función initialize() en el envoltorio de la base de datos MSSQL.

Código en GitHub

El proyecto API CRUD está disponible en GitHub en https://github.com/cornflourblue/node-mssql-crud-api.

Herramientas necesarias para este tutorial

Para seguir los pasos de este tutorial, necesitará lo siguiente:

  • Node.js & npm - incluye el tiempo de ejecución de Node.js, las herramientas de línea de comandos y el administrador de paquetes; instálelo desde https://nodejs.org/.
  • MS SQL Server - necesitará acceso a la instancia de SQL Server en ejecución para que la API se conecte, puede ser remota (por ejemplo, Azure, AWS, etc.) o en su máquina local. La edición Express de SQL Server está disponible de forma gratuita en https://www.microsoft.com/sql-server/sql-server-downloads. También puede ejecutarlo en un contenedor Docker, las imágenes oficiales de Docker para SQL Server están disponibles en https://hub.docker.com/_/microsoft-mssql-server.
  • Un editor de código para ver y editar el código API, no importa cuál, personalmente uso Visual Studio Code que es un editor gratuito que se ejecuta en Windows, Mac y Linux , puede descargarlo en https://code.visualstudio.com/.


Ejecute la API CRUD de Node + MSSQL localmente

  1. Descargue o clone el código fuente del proyecto desde https://github.com/cornflourblue/node-mssql-crud-api
  2. Instale todos los paquetes npm necesarios ejecutando npm install o npm i desde la línea de comando en la carpeta raíz del proyecto (donde se encuentra el package.json).
  3. Actualice las credenciales de la base de datos en /config.json para conectarse a su instancia de MS SQL Server y asegúrese de que el servidor MSSQL se está ejecutando.
  4. Inicie la API ejecutando npm start (o npm run dev para comenzar con nodemon) desde la línea de comando en la carpeta raíz del proyecto, debería ver el mensaje Servidor escuchando en el puerto 4000.
  5. Siga las instrucciones a continuación para probar con Postman o conectarse con una de las aplicaciones de ejemplo de una sola página disponibles (React o Angular).

Sincronización de modelos con Sequelize

Al iniciar, también debería ver un resultado como el siguiente de la sincronización del modelo Sequelize que se ejecuta en el contenedor de la base de datos MSSQL, muestra la creación y sincronización de la tabla Users basada en el modelo de usuario Sequelize.

Executing (default): SELECT TABLE_NAME, TABLE_SCHEMA FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = N'Users' AND TABLE_SCHEMA = N'dbo'
Executing (default): SELECT c.COLUMN_NAME AS 'Name', c.DATA_TYPE AS 'Type', c.CHARACTER_MAXIMUM_LENGTH AS 'Length', c.IS_NULLABLE as 'IsNull', COLUMN_DEFAULT AS 'Default', pk.CONSTRAINT_TYPE AS 'Constraint', COLUMNPROPERTY(OBJECT_ID(c.TABLE_SCHEMA+'.'+c.TABLE_NAME), c.COLUMN_NAME, 'IsIdentity') as 'IsIdentity', CAST(prop.value AS NVARCHAR) AS 'Comment' FROM INFORMATION_SCHEMA.TABLES t INNER JOIN INFORMATION_SCHEMA.COLUMNS c ON t.TABLE_NAME = c.TABLE_NAME AND t.TABLE_SCHEMA = c.TABLE_SCHEMA LEFT JOIN (SELECT tc.table_schema, tc.table_name,  cu.column_name, tc.CONSTRAINT_TYPE  FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc  JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE  cu  ON tc.table_schema=cu.table_schema and tc.table_name=cu.table_name  and tc.constraint_name=cu.constraint_name  and tc.CONSTRAINT_TYPE='PRIMARY KEY') pk  ON pk.table_schema=c.table_schema  AND pk.table_name=c.table_name  AND pk.column_name=c.column_name  INNER JOIN sys.columns AS sc ON sc.object_id = object_id(t.table_schema + '.' + t.table_name) AND sc.name = c.column_name LEFT JOIN sys.extended_properties prop ON prop.major_id = sc.object_id AND prop.minor_id = sc.column_id AND prop.name = 'MS_Description' WHERE t.TABLE_NAME = 'Users'
Executing (default): SELECT constraint_name = OBJ.NAME, constraintName = OBJ.NAME, constraintCatalog = 'node-mssql-crud-api', constraintSchema = SCHEMA_NAME(OBJ.SCHEMA_ID), tableName = TB.NAME, tableSchema = SCHEMA_NAME(TB.SCHEMA_ID), tableCatalog = 'node-mssql-crud-api', columnName = COL.NAME, referencedTableSchema = SCHEMA_NAME(RTB.SCHEMA_ID), referencedCatalog = 'node-mssql-crud-api', referencedTableName = RTB.NAME, referencedColumnName = RCOL.NAME FROM sys.foreign_key_columns FKC INNER JOIN sys.objects OBJ ON OBJ.OBJECT_ID = FKC.CONSTRAINT_OBJECT_ID INNER JOIN sys.tables TB ON TB.OBJECT_ID = FKC.PARENT_OBJECT_ID INNER JOIN sys.columns COL ON COL.COLUMN_ID = PARENT_COLUMN_ID AND COL.OBJECT_ID = TB.OBJECT_ID INNER JOIN sys.tables RTB ON RTB.OBJECT_ID = FKC.REFERENCED_OBJECT_ID INNER JOIN sys.columns RCOL ON RCOL.COLUMN_ID = REFERENCED_COLUMN_ID AND RCOL.OBJECT_ID = RTB.OBJECT_ID WHERE TB.NAME ='Users'
Executing (default): ALTER TABLE [Users] ALTER COLUMN [email] NVARCHAR(255) NOT NULL;
Executing (default): ALTER TABLE [Users] ALTER COLUMN [passwordHash] NVARCHAR(255) NOT NULL;
Executing (default): ALTER TABLE [Users] ALTER COLUMN [title] NVARCHAR(255) NOT NULL;
Executing (default): ALTER TABLE [Users] ALTER COLUMN [firstName] NVARCHAR(255) NOT NULL;
Executing (default): ALTER TABLE [Users] ALTER COLUMN [lastName] NVARCHAR(255) NOT NULL;
Executing (default): ALTER TABLE [Users] ALTER COLUMN [role] NVARCHAR(255) NOT NULL;
Executing (default): ALTER TABLE [Users] ALTER COLUMN [createdAt] DATETIMEOFFSET NOT NULL;
Executing (default): ALTER TABLE [Users] ALTER COLUMN [updatedAt] DATETIMEOFFSET NOT NULL;
Executing (default): EXEC sys.sp_helpindex @objname = N'[Users]';


Pruebe la API CRUD de Node + SQL Server con Postman

Postman es una gran herramienta para probar API, puede descargarla en https://www.postman.com/downloads.

A continuación, encontrará instrucciones sobre cómo usar Postman para realizar las siguientes acciones:


Cómo crear un nuevo usuario con Postman

Para crear un nuevo usuario con la API CRUD siga estos pasos:

  1. Abra una nueva pestaña de solicitud haciendo clic en el botón más (+) al final de las pestañas.
  2. Cambie el método HTTP a POST con el selector desplegable a la izquierda del campo de entrada de URL.
  3. En el campo URL ingrese la dirección de la ruta de los usuarios de su API local - http://localhost:4000/users
  4. Seleccione la pestaña Body debajo del campo URL, cambie el botón de opción de tipo de cuerpo a raw y cambie el selector desplegable de formato a JSON .
  5. Ingrese un objeto JSON que contenga las propiedades de usuario requeridas en el área de texto Body, por ejemplo:
    {
        "title": "Mr",
        "firstName": "George",
        "lastName": "Costanza",
        "role": "User",
        "email": "george@costanza.com",
        "password": "george-likes-spicy-chicken",
        "confirmPassword": "george-likes-spicy-chicken"
    }
  6. Haga clic en el botón Send, debería recibir un "200 OK" respuesta con el mensaje "User created" en el cuerpo de la respuesta.

Esta es una captura de pantalla de Postman después de enviar la solicitud y crear el usuario:

Volver al principio


Cómo recuperar una lista de todos los usuarios con Postman

Para obtener una lista de todos los usuarios de Node + MSSQL CRUD API, siga estos pasos:

  1. Abra una nueva pestaña de solicitud haciendo clic en el botón más (+) al final de las pestañas.
  2. Cambie el método HTTP a GET con el selector desplegable a la izquierda del campo de entrada de URL.
  3. En el campo URL ingrese la dirección de la ruta de los usuarios de su API local - http://localhost:4000/users
  4. Haga clic en el botón Send, debería recibir "200 OK" respuesta que contiene una matriz JSON con todos los registros de usuario en el sistema.

Esta es una captura de pantalla de Postman después de realizar una solicitud para obtener todos los usuarios:

Volver al principio


Cómo recuperar un usuario por ID con Postman

Para obtener un usuario específico por id desde Node + MSSQL CRUD API, siga estos pasos:

  1. Abra una nueva pestaña de solicitud haciendo clic en el botón más (+) al final de las pestañas.
  2. Cambie el método HTTP a GET con el selector desplegable a la izquierda del campo de entrada de URL.
  3. En el campo URL, ingrese la dirección de la ruta /users/{id} con la identificación del usuario que desea recuperar, por ejemplo, http://localhost:4000/users/1
  4. Haga clic en el botón Send, debería recibir "200 OK" respuesta que contiene un objeto JSON con los detalles del usuario especificado.

Esta es una captura de pantalla de Postman después de realizar una solicitud para obtener un usuario por ID:

Volver al principio


Cómo actualizar un usuario con Postman

Para actualizar un usuario con la API CRUD, siga estos pasos:

  1. Abra una nueva pestaña de solicitud haciendo clic en el botón más (+) al final de las pestañas.
  2. Cambie el método HTTP a PUT con el selector desplegable a la izquierda del campo de entrada de URL.
  3. En el campo URL ingrese la dirección de la ruta /users/{id} con la identificación del usuario que desea actualizar, por ejemplo, http://localhost:4000/users/1
  4. Seleccione la pestaña Body debajo del campo URL, cambie el botón de opción de tipo de cuerpo a raw y cambie el selector desplegable de formato a JSON .
  5. Ingrese un objeto JSON en el área de texto Body que contenga las propiedades que desea actualizar, por ejemplo, para actualizar el nombre y el apellido:
    {
        "firstName": "Art",
        "lastName": "Vandelay"
    }
  6. Haga clic en el botón Send, debería recibir "200 OK" respuesta con el mensaje "User updated" en el cuerpo de la respuesta.

Esta es una captura de pantalla de Postman después de enviar la solicitud y actualizar el usuario:

Volver al principio


Cómo eliminar un usuario con Postman

Para eliminar un usuario con la API sigue estos pasos:

  1. Abra una nueva pestaña de solicitud haciendo clic en el botón más (+) al final de las pestañas.
  2. Cambie el método HTTP a DELETE con el selector desplegable a la izquierda del campo de entrada de URL.
  3. En el campo URL, ingrese la dirección de la ruta /users/{id} con la identificación del usuario que desea eliminar, por ejemplo, http://localhost:4000/usuarios/1
  4. Haga clic en el botón Send, debería recibir "200 OK" respuesta con el mensaje "User deleted" en el cuerpo de la respuesta.

Esta es una captura de pantalla de Postman después de enviar la solicitud y eliminar al usuario:

Volver al principio


Ejecute una aplicación React con Node + MSSQL CRUD API

Para obtener detalles completos sobre la aplicación React CRUD, consulte la publicación React - CRUD Example with React Hook Form. Pero para ponerse en marcha rápidamente, solo siga los pasos a continuación.

  1. Descargue o clone el código del tutorial de React desde https://github.com/cornflourblue/react-hook-form-crud-example
  2. Instale todos los paquetes npm necesarios ejecutando npm install o npm i desde la línea de comando en la carpeta raíz del proyecto (donde se encuentra el package.json).
  3. Elimine o comente las 2 líneas debajo del comentario // setup fake backend ubicado en el archivo /src/index.jsx.
  4. Inicie la aplicación ejecutando npm start desde la línea de comando en la carpeta raíz del proyecto, esto iniciará un navegador que muestra la aplicación y debe estar conectado con Node + MS SQL Server CRUD API que ya tienes en ejecución.


Ejecute una aplicación Angular con Node + SQL Server CRUD API

Para obtener detalles completos sobre la aplicación Angular CRUD, consulte la publicación Angular 11 - CRUD Example with Reactive Forms. Pero para ponerse en marcha rápidamente, solo siga los pasos a continuación.

  1. Descargue o clone el código del tutorial de Angular desde https://github.com/cornflourblue/angular-11-crud-example
  2. Instale todos los paquetes npm necesarios ejecutando npm install desde la línea de comando en la carpeta raíz del proyecto (donde se encuentra el package.json).
  3. Elimine o comente la línea debajo del comentario // provider used to create fake backend ubicado en el archivo /src/app/app.module.ts.
  4. Inicie la aplicación ejecutando npm start desde la línea de comando en la carpeta raíz del proyecto, esto iniciará un navegador que muestra la aplicación y debe estar conectado con Node.js + MSSQL CRUD API que ya tienes en ejecución.


Estructura del proyecto API CRUD de Node.js + MSSQL

El proyecto del tutorial está estructurado en carpetas de funciones (users) y carpetas de componentes compartidos/sin funciones (_helpers, _middleware). Las carpetas de componentes compartidos contienen código que se puede usar en varias funciones u otras partes de la aplicación, y tienen el prefijo _ de subrayado para agruparlos y facilitar la diferenciación entre el código compartido y el específico de la función.

El ejemplo de CRUD solo contiene una sola función (users) en este momento, pero podría ampliarse fácilmente con otras funciones copiando la carpeta de usuarios y siguiendo el mismo patrón.

Haga clic en cualquiera de los enlaces a continuación para saltar a una descripción de cada archivo junto con su código:

 

Carpeta de ayudantes

Ruta: /_helpers

La carpeta de ayudantes contiene todos los elementos que no encajan en otras carpetas pero que no justifican tener una carpeta propia.

 

Contenedor de base de datos del servidor MSSQL

Ruta: /_helpers/db.js

El envoltorio de la base de datos MSSQL se conecta a MSSQL mediante Sequelize & el cliente tedious y exporta un objeto que expone todos los modelos de base de datos para la aplicación (actualmente solo User). Proporciona una manera fácil de acceder a cualquier parte de la base de datos desde un solo punto.

La función initialize() se ejecuta una vez en el inicio de la API y realiza las siguientes acciones:

  • Se conecta a MS SQL Server utilizando el cliente db tedious y ejecuta una consulta para crear la base de datos API si aún no existe.
  • Se conecta a la base de datos API con Sequelize ORM.
  • Inicializa el modelo User y lo adjunta al objeto db exportado.
  • Crea/actualiza automáticamente tablas en la base de datos de SQL Server para que coincidan con el modelo de Sequelize (si es necesario) llamando a await sequelize.sync({ alter: true }). Para obtener más información sobre las opciones de sincronización de modelos de Sequelize, consulte https://sequelize.org/master/manual/model-basics.html#model-synchronization.
const tedious = require('tedious');
const { Sequelize } = require('sequelize');

const { dbName, dbConfig } = require('config.json');

module.exports = db = {};

initialize();

async function initialize() {
    const dialect = 'mssql';
    const host = dbConfig.server;
    const { userName, password } = dbConfig.authentication.options;

    // create db if it doesn't already exist
    await ensureDbExists(dbName);

    // connect to db
    const sequelize = new Sequelize(dbName, userName, password, { host, dialect });

    // init models and add them to the exported db object
    db.User = require('../users/user.model')(sequelize);

    // sync all models with database
    await sequelize.sync({ alter: true });
}

async function ensureDbExists(dbName) {
    return new Promise((resolve, reject) => {
        const connection = new tedious.Connection(dbConfig);
        connection.connect((err) => {
            if (err) {
                console.error(err);
                reject(`Connection Failed: ${err.message}`);
            }

            const createDbQuery = `IF NOT EXISTS(SELECT * FROM sys.databases WHERE name = '${dbName}') CREATE DATABASE [${dbName}];`;
            const request = new tedious.Request(createDbQuery, (err) => {
                if (err) {
                    console.error(err);
                    reject(`Create DB Query Failed: ${err.message}`);
                }

                // query executed successfully
                resolve();
            });

            connection.execSql(request);
        });
    });
}
 

Objeto/Enumeración de rol

Ruta: /_helpers/role.js

El objeto de rol define todos los roles en la aplicación de ejemplo, lo creé para usarlo como un enumeración para evitar pasar roles como cadenas, así que en lugar de 'Admin' y 'User' podemos usar Role.Admin y Role.User.

module.exports = {
    Admin: 'Admin',
    User: 'User'
}
 

Carpeta de Middleware Express.js

Ruta: /_middleware

La carpeta de middleware contiene funciones de middleware de Express.js que pueden ser utilizadas por rutas/características dentro de la API CRUD de Node.js.

 

Middleware del controlador de errores global

Ruta: /_middleware/error-handler.js

El controlador de errores global se usa para capturar todos los errores y eliminar la necesidad de un código de manejo de errores duplicado en toda la aplicación CRUD. Está configurado como middleware en el archivo principal server.js.

Por convención, los errores de tipo 'string' se tratan como errores personalizados (específicos de la aplicación), esto simplifica el código para generar errores personalizados, ya que solo se debe generar una cadena ( por ejemplo, lanzar 'Mensaje de error'). Además de esto, si un error personalizado termina con las palabras 'not found', se devuelve un código de respuesta 404; de lo contrario, se devuelve una respuesta estándar 400. Consulte el servicio de usuario para ver algunos ejemplos de errores personalizados generados por la API, los errores se detectan en el controlador de usuarios para cada ruta y se pasa a la función next que los pasa a este controlador de errores global.

module.exports = errorHandler;

function errorHandler(err, req, res, next) {
    switch (true) {
        case typeof err === 'string':
            // custom application error
            const is404 = err.toLowerCase().endsWith('not found');
            const statusCode = is404 ? 404 : 400;
            return res.status(statusCode).json({ message: err });
        default:
            return res.status(500).json({ message: err.message });
    }
}
 

Middleware de validación de solicitudes

Ruta: /_middleware/validate-request.js

La función de middleware de solicitud de validación valida el cuerpo de una solicitud contra un objeto de esquema Joi.

Lo utilizan las funciones de middleware de esquema en los controladores para validar solicitudes con un esquema para una ruta específica (por ejemplo, createSchema para la ruta de creación de usuario en controlador de usuarios). Para obtener más información sobre la validación del esquema Joi, consulte https://www.npmjs.com/package/joi.

module.exports = validateRequest;

function validateRequest(req, next, schema) {
    const options = {
        abortEarly: false, // include all errors
        allowUnknown: true, // ignore unknown props
        stripUnknown: true // remove unknown props
    };
    const { error, value } = schema.validate(req.body, options);
    if (error) {
        next(`Validation error: ${error.details.map(x => x.message).join(', ')}`);
    } else {
        req.body = value;
        next();
    }
}
 

Carpeta de funciones de usuarios

Ruta: /users

La carpeta de usuarios contiene todo el código que es específico de la función de usuarios de la API CRUD de Node.js + MSSQL.

 

Modelo de usuario Sequelize

Ruta: /users/user.model.js

El modelo de usuario utiliza Sequelize para definir el esquema de la tabla users en la base de datos de SQL Server. El objeto del modelo Sequelize exportado brinda acceso completo para realizar operaciones CRUD (create, read, update, delete) en usuarios en MSSQL; consulte el servicio de usuario a continuación para ver ejemplos de su uso (a través del ayudante db).

El defaultScope configura el modelo para excluir el hash de la contraseña de los resultados de la consulta de forma predeterminada. El ámbito withHash se puede utilizar para consultar a los usuarios e incluir el hash de la contraseña en los resultados. Para obtener más información sobre los ámbitos de Sequelize, consulte https://sequelize.org/master/manual/scopes.html.

const { DataTypes } = require('sequelize');

module.exports = model;

function model(sequelize) {
    const attributes = {
        email: { type: DataTypes.STRING, allowNull: false },
        passwordHash: { type: DataTypes.STRING, allowNull: false },
        title: { type: DataTypes.STRING, allowNull: false },
        firstName: { type: DataTypes.STRING, allowNull: false },
        lastName: { type: DataTypes.STRING, allowNull: false },
        role: { type: DataTypes.STRING, allowNull: false }
    };

    const options = {
        defaultScope: {
            // exclude password hash by default
            attributes: { exclude: ['passwordHash'] }
        },
        scopes: {
            // include hash with this scope
            withHash: { attributes: {}, }
        }
    };

    return sequelize.define('User', attributes, options);
}
 

Servicio de usuario

Ruta: /users/user.service.js

El servicio de usuario es responsable de toda la interacción de la base de datos y la lógica comercial central relacionada con las operaciones CRUD del usuario, encapsula toda la interacción con el modelo de usuario Sequelize y expone un conjunto simple de métodos que utilizan los controlador de usuarios.

La parte superior del archivo contiene el objeto de servicio exportado con solo los nombres de los métodos para que sea fácil ver todos los métodos de un vistazo, el resto del archivo contiene las funciones de implementación para cada método de servicio, seguidas de las funciones auxiliares locales.

const bcrypt = require('bcryptjs');

const db = require('_helpers/db');

module.exports = {
    getAll,
    getById,
    create,
    update,
    delete: _delete
};

async function getAll() {
    return await db.User.findAll();
}

async function getById(id) {
    return await getUser(id);
}

async function create(params) {
    // validate
    if (await db.User.findOne({ where: { email: params.email } })) {
        throw 'Email "' + params.email + '" is already registered';
    }

    const user = new db.User(params);
    
    // hash password
    user.passwordHash = await bcrypt.hash(params.password, 10);

    // save user
    await user.save();
}

async function update(id, params) {
    const user = await getUser(id);

    // validate
    const usernameChanged = params.username && user.username !== params.username;
    if (usernameChanged && await db.User.findOne({ where: { username: params.username } })) {
        throw 'Username "' + params.username + '" is already taken';
    }

    // hash password if it was entered
    if (params.password) {
        params.passwordHash = await bcrypt.hash(params.password, 10);
    }

    // copy params to user and save
    Object.assign(user, params);
    await user.save();
}

async function _delete(id) {
    const user = await getUser(id);
    await user.destroy();
}

// helper functions

async function getUser(id) {
    const user = await db.User.findByPk(id);
    if (!user) throw 'User not found';
    return user;
}
 

Controlador de usuarios de Express.js

Ruta: /users/users.controller.js

El controlador de usuarios define todas las rutas /users para Node.js + MSSQL CRUD API, las definiciones de ruta se agrupan en la parte superior del archivo y las funciones de implementación se encuentran debajo, seguidas de la ruta funciones de validación de esquemas. El controlador está vinculado a la ruta /users en el archivo principal server.js.

Las rutas que requieren validación de esquema incluyen una función de middleware con la convención de nomenclatura <ruta>Schema (por ejemplo, createSchema). Cada función de validación de esquema define un esquema para el cuerpo de la solicitud utilizando la biblioteca Joi y llama a validateRequest(req, next, schema) para garantizar que el cuerpo de la solicitud sea válido. Si la validación tiene éxito, la solicitud continúa con la siguiente función de middleware (la función de ruta); de lo contrario, se devuelve un error con los detalles de por qué falló la validación. Para obtener más información sobre la validación del esquema Joi, consulte https://www.npmjs.com/package/joi.

Express es el servidor web utilizado por la API CRUD, es uno de los marcos de aplicaciones web más populares para Node.js. Para obtener más información, consulte https://expressjs.com/.

const express = require('express');
const router = express.Router();
const Joi = require('joi');

const validateRequest = require('_middleware/validate-request');
const Role = require('_helpers/role');
const userService = require('./user.service');

// routes

router.get('/', getAll);
router.get('/:id', getById);
router.post('/', createSchema, create);
router.put('/:id', updateSchema, update);
router.delete('/:id', _delete);

module.exports = router;

// route functions

function getAll(req, res, next) {
    userService.getAll()
        .then(users => res.json(users))
        .catch(next);
}

function getById(req, res, next) {
    userService.getById(req.params.id)
        .then(user => res.json(user))
        .catch(next);
}

function create(req, res, next) {
    userService.create(req.body)
        .then(() => res.json({ message: 'User created' }))
        .catch(next);
}

function update(req, res, next) {
    userService.update(req.params.id, req.body)
        .then(() => res.json({ message: 'User updated' }))
        .catch(next);
}

function _delete(req, res, next) {
    userService.delete(req.params.id)
        .then(() => res.json({ message: 'User deleted' }))
        .catch(next);
}

// schema functions

function createSchema(req, res, next) {
    const schema = Joi.object({
        title: Joi.string().required(),
        firstName: Joi.string().required(),
        lastName: Joi.string().required(),
        role: Joi.string().valid(Role.Admin, Role.User).required(),
        email: Joi.string().email().required(),
        password: Joi.string().min(6).required(),
        confirmPassword: Joi.string().valid(Joi.ref('password')).required()
    });
    validateRequest(req, next, schema);
}

function updateSchema(req, res, next) {
    const schema = Joi.object({
        title: Joi.string().empty(''),
        firstName: Joi.string().empty(''),
        lastName: Joi.string().empty(''),
        role: Joi.string().valid(Role.Admin, Role.User).empty(''),
        email: Joi.string().email().empty(''),
        password: Joi.string().min(6).empty(''),
        confirmPassword: Joi.string().valid(Joi.ref('password')).empty('')
    }).with('password', 'confirmPassword');
    validateRequest(req, next, schema);
}
 

Configuración API

Ruta: /config.json

El archivo de configuración de la API contiene datos de configuración para la API CRUD, incluye las opciones de conexión dbConfig para el servidor MSSQL. La propiedad dbName es el nombre de la base de datos que la API crea automáticamente al iniciarse en el contenedor de base de datos.

{
    "dbName": "node-mssql-crud-api",
    "dbConfig": {
        "server": "localhost",
        "options": {
            "port": 1433,
            "trustServerCertificate": true
        },
        "authentication": {
            "type": "default",
            "options": {
                "userName": "sa",
                "password": ""
            }
        }
    }
}
 

Package.json

Ruta: /package.json

El archivo package.json contiene información de configuración del proyecto, incluidas las dependencias del paquete Node.js que se instalan cuando ejecuta npm install.

La sección scripts contiene scripts que se ejecutan al ejecutar el comando npm run <script name>, el script start también se puede ejecutar con el comando de acceso directo npm start.

La secuencia de comandos start inicia la API CRUD normalmente usando node, y la secuencia de comandos dev inicia la API en modo de desarrollo usando nodemon que reinicia automáticamente la API de Node.js cuando se cambia un archivo.

Para obtener más información, consulte https://docs.npmjs.com/files/package.json.

{
    "name": "node-mssql-crud-api",
    "version": "1.0.0",
    "license": "MIT",
    "scripts": {
        "start": "node ./server.js",
        "dev": "nodemon ./server.js"
    },
    "dependencies": {
        "bcryptjs": "^2.4.3",
        "cors": "^2.8.5",
        "express": "^4.18.1",
        "joi": "^17.6.0",
        "rootpath": "^0.1.2",
        "sequelize": "^6.21.0",
        "tedious": "^14.6.0"
    },
    "devDependencies": {
        "nodemon": "^2.0.16"
    }
}
 

Archivo de inicio del servidor

Ruta: /server.js

El archivo server.js es el punto de entrada a la API CRUD de Node.js, configura el middleware de la aplicación, vincula los controladores a las rutas e inicia el servidor web Express para la API.

require('rootpath')();
const express = require('express');
const app = express();
const cors = require('cors');

const errorHandler = require('_middleware/error-handler');

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());

// api routes
app.use('/users', require('./users/users.controller'));

// global error handler
app.use(errorHandler);

// start server
const port = process.env.NODE_ENV === 'production' ? (process.env.PORT || 80) : 4000;
app.listen(port, () => console.log('Server listening on port ' + port));