Hapi.js + Vue.js accediendo a mongodb

Como ya dije, esta aplicación estará basada en Mongodb, y usaremos mongoose como ODM.

El primer paso es instalar mongoose:

npm i mongoose

Una vez instalado crearemos un controlador que nos permita usar la BD en toda la aplicación Hapi.js. Para ello haremos uso de los decorate del servidor. Los decorations permite extender objectos ofrecidos por Hapi.js, en nuestro caso server y request. Usando un plugin nos conectaremos a mongodb usando mongoose y añadiremos ese objecto con los decorate.

Creamos el fichero /plugins/db.js con el siguiente código:

/**
 * DB controller
 *
 * It uses Mongoose and "stores" it in the server and the request using `decorate`
 */
const mongoose = require( 'mongoose' );

exports.plugin = {
	name: 'db',
	register: async function( server, options ) {
		mongoose.connect( options.url, { useNewUrlParser: true } );
		const db = mongoose.connection;
		// eslint-disable-next-line
		db.on( 'error', console.error.bind( console, 'connection error:' ) );
		db.once( 'open', function() {
			server.decorate( 'server', 'db', mongoose );
			server.decorate( 'request', 'db', mongoose );
			// eslint-disable-next-line
			console.log( 'DB connected' );
		} );
	},
};

Para configurar la conectividad a mongodb tendremos que añadir los datos a la /config/index.js

const config = {
	server: {
		port: 3001,
	},
	website: {
		name: `WP Desk`,
	},
	db: {
		url: 'mongodb://localhost/wpdesk',
	},
};

Y en el manifiest usado por glue, tendremos que añadir el nuevo plugin y las nuevas opciones de conexión:

const manifest = {
	server: {
		port: Config.get( '/server/port' ),
	},
	register: {
		plugins: [
			{
				plugin: './api/home',
			},
			{
				plugin: './plugins/db',
				options: Config.get( '/db' ),
			},
		],
	},
};

Ya tenemos casi todo configurado, ahora vamos a empezar con un ejemplo creando un esquema de moongose que nos permite acceder a colecciones de mongodb.

Lo más común es tener una colección de usuarios, que tendrá los siguientes campos:

  • userName: de tipo String,
  • firstName: de tipo String,
  • lastName: de tipo String,
  • email: de tipo String,
  • role: que referencia a otro elemento de otra colección,
  • isEnabled: de tipo Boolean,
  • password: de tipo String,
  • resetPassword: un objeto representado por:
    • hash: de tipo String,
    • active: de tipo Boolean,

También crearemos un método estático que devuelva todos los elementos de la colección users para realizar pruebas:

/**
 * User model based on Mongoose
 */
const mongoose = require( 'mongoose' );
const Schema = mongoose.Schema;

// Mongoose schema
const userSchema = new mongoose.Schema( {
	userName: String,
	firstName: String,
	lastName: String,
	email: String,
	role: Schema.Types.ObjectId,
	isEnabled: Boolean,
	password: String,
	resetPassword: {
		hash: String,
		active: Boolean,
	},
} );

/**
 * User static model findAll
 *
 * @returns {array}
 */
userSchema.static( 'findAll', async function() {
	const result = await new Promise( ( resolve, reject ) => {
		this.model( 'User' ).find( {} ).exec( ( error, data ) => {
			if ( error ) {
				reject( error );
			}
			resolve( data );
		} );
	} );
	return result;
} );

const User = mongoose.model( 'User', userSchema );

module.exports = User;

Ya está todo, ahora solo modificamos el handler de la ruta home.js para mostrar los valores de findAll:

/**
 * Route handler
 *
 * @param {object} request
 * @param {object} h Hapi object
 * @returns {object}
 */
handler: async( request, h ) => { // eslint-disable-line
	try {
		const result = await User.findAll();
		return result;
	} catch ( error ) {
		return { error: 500 };
	}
},

Puedes bajarte el código aquí

Hapi.js+Vue.js Crear servidor backend

El primer paso va a ser crear el entorno del servidor, para ello creamos un directorio e inicializamos el proyecto ejecutando:

npm init

Rellenamos todos los datos que nos van pidiendo para configurar el proyecto.

Ya tenemos el proyecto creado, ahora iremos instalando las librerías que necesitamos, en este caso hapi y glue.

npm i @hapi/hapi
npm i @hapi/glue

¿Qué es glue? Glue es un plugin que permite configurar el servidor de forma fácil.

Ahora creamos el fichero index.js e insertamos el siguiente código:

const Glue = require( '@hapi/glue' );

const manifest = {
	server: {
		port: 3001,
	},
};

const options = {
	relativeTo: __dirname,
};

const startServer = async function() {
	try {
		const server = await Glue.compose( manifest, options );
		await server.start();
		console.log( 'hapi days!' ); // eslint-disable-line
	} catch ( err ) {
		console.error( err ); // eslint-disable-line
		process.exit( 1 );
	}
};

startServer();

Fácil de entender, ¿no? Creamos el servidor usando Glue con el manifest y las opciones, y arrancamos el servidor.

Listo, accedemos a http://localhost:3001 para comprobar que funciona. Nos devolverá error 404 porque por ahora no hay definidas routes.

¿Cómo se arranca el servidor? podríamos usar directamente node, pero mejor usaremos nodemon. Primero lo instalamos:

npm i --save-dev nodemon

Y ejecutaremos lo siguiente para arrancar el servidor:

npm run start

Puedes obtener el código en GitHub hapi-vue-demo 0.1.0

Crear aplicación web con Hapi.js, Vue y MongoDB

Estoy aprendiendo Hapi.js y Vue.js y qué mejor que ir anotando aquí lo que voy aprendiendo, y si a alguien le sirve, mejor que mejor.

Pretendo crear una aplicación web e ir explicando en diferentes posts, que iré añadiendo aquí, lo que estoy aprendiendo.

He estado viendo distintos boilerplates y el que más me ha gustado ha sido appy. Podría usarlo, pero prefiero aprender poco a poco que pegarme con algo ya hecho e indagar qué hace cada cosa.

Lo que más me gusta de appy es que diferencia entre el backend y el frontend de forma bastante clara, distintos directorios y aplicaciones para cada cosa. Es por ello que voy a seguir esta estructura. Aquí hay un artículo bastante majo que explica más o menos lo mismo.

Pues nada más, iré subiendo posts sobre lo que voy aprendiendo. Eso sí, porfa, si meto la pata en algo, no me lo tengas muy en cuenta, estoy aprendiendo.

  1. Hapi.js+Vue.js Crear servidor backend (código v0.1.0)
  2. Reorganización de la configuración (código v0.2.0)
  3. Empezar añadiendo routes (código v0.3.0)
  4. Conectando a mongodb (código v0.4.0)
  5. Modelos mejorados y controladores (código v0.5.0)
  6. Inicializando el frontend (código v0.6.0)
  7. Vue router y login form “tonto” (código v0.7.0)
  8. Comunicación entre frontend y el servidor usando JWT (login) (código v0.8.0)
  9. i18n (código v0.9.0)
  10. Activación de usuario, recordar contraseña, … (código v0.10.0)

Enlaces rápidos (15-03-2010)

Más enlaces rápidos, sobre todo basados en NoSQL (por favor, que no lo conviertan en un término que usen los guays y los gurús…)

Me hizo gracia esta frase: “NoSQL is for very smart people who need a very sharp knife.” espero un día cumplir ambas condiciones 🙂

Enlaces rápidos (05-03-2010)

Voy a tener que cambiar el título de estos posts por “Enlaces rápidos sobre NoSQL”, porque al final es sobre lo que más enlazo.