Hapi.js + Vue.js accediendo a mongodb

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í