|
n |
n
nThis article shows you how to build an portfolio mobile app using Nodejs, Cloudinary, MongoDB and Ionicframework. I assumed that readers of the this series already have basic knowledge in NodeJS,MongoDB and Ionicframework.
nnnn
n
nElements of the App
n
nNodeJS
nThe API will be written with NodeJS.
n
n
n
nCloudinary
nCloudinary is the media management platform for web and mobile developers, so all the portfolio images will be stored here
n
n
n
nMongoDB
nThe application database will be mongodb
n
n
n
nIonicframework
nThe mobile app itself will be built using Ionicframework
n
nLet’s begin with the API.
n
nCreate a folder named mobile-portfolio-nodejs-api and cd into the directory from your favourite command line tool. Run npm init and follow the instructions to generate package.js file.
n
nModify your package.json file to look like this:
n
n
{n "name": "mobile-portfolio-nodejs-api",n "version": "1.0.0",n "description": "A NodeJS API for mobile portfolio app",n "main": "index.js",n "scripts": {n "start": "node index.js"n },n "keywords": [n "nodejs",n "api",n "express"n ],n "author": "Adesina Mark Omoniyi",n "license": "MIT",n "dependencies": {n "bcrypt-nodejs": "0.0.3",n "body-parser": "^1.15.2",n "cloudinary": "^1.4.4",n "connect-multiparty": "^2.0.0",n "cors": "^2.8.1",n "express": "^4.14.0",n "mongoose": "^5.1.4"n },n "engines": {n "node": "8.11.2"n }n}n
n
nAll the dependencies needed for the project has been included in the package.json file. The next thing is to run npm install to bring in all the dependencies from the package repositories online.
n
n
nThe App Server
nCreate a file named index.js in the root of the project folder and bring in the basic modules required to run our simple server. Modify the index.js to reflect the following:
n
n
var express = require('express'),n app = express(),n bodyParser = require('body-parser'),n cors = require('cors');nnnapp.set('port', (process.env.PORT || 5000));nnapp.use(bodyParser.urlencoded({ extended: true }));napp.use(bodyParser.json());napp.use(cors());nnserver.listen(app.get('port'), function () {n console.log('Node app is running on port', app.get('port'));n});nn
n
nThe code is pretty simple, we created our server using express and we asked the server to listen on port 5000. As it is the app isn’t doing anything cool currently.n
n
n
nThe MongoDB Database
nLet’s create the database where all the portfolio app data will be stored. We are going to be using MLab. This is a Database-as-a-Service for MongoDB, I wont be covering how database can be created in MLab there are lots of articles online that can be of help.
n
nCreate the database and name it mobile-portfolio. The next thing is to find a way of connection to the database from within our express app.
n
nCreate a folder called configuration in the root of the project folder and add a file named app.config.js, add the code below to the file created.
n
n
module.exports = {n 'serverPort':8000,n 'dbUrl':'mongodb://:@ds237409.mlab.com:37409/food-delivery' n }n
n
nReplace the dbUrl with your own url as copied from MLab dashboard.
n
nCreate another folder in the root of the project folder named db-connection and add file named db.connection.js, modify the file like so:
n
var mongoose = require('mongoose');nvar config = require('../configuration/app.config');nnmongoose.connect(config.dbUrl);nnmongoose.connection.on('connected', function () {n console.log('Mongoose connected to ' + config.dbUrl);n});nmongoose.connection.on('error',function (err) {n console.log('Mongoose connection error: ' + err);n});nmongoose.connection.on('disconnected', function () {n console.log('Mongoose disconnected');n});nprocess.on('SIGINT', function() {n mongoose.connection.close(function () {n console.log('Mongoose disconnected through app termination');n process.exit(0);n });n});n
n
n
nCloudinary Setup
nI wont also be covering how to register and setup a free cloudinary account in the article. That can be found on their blog.
n
nAfter setting up a free account, there three essential information that are needed to enable our app communicate with cloudinary which are api_key, cloud_name and api_secret.
n
nModify the app.config.js file to reflect the cloudinary settings like so:
n
n
module.exports = {n 'serverPort':8000,n 'dbUrl':'mongodb://:@ds237409.mlab.com:37409/food-delivery',n 'cloud_name': 'YOUR_CLOUD_NAME',n 'api_key': 'API_KEY',n 'api_secret': 'YOUR_SECRET' n }n
n
nNow let’s add our configuration to the index.js file like so:
n
config = require('./configuration/app.config'),n dbConnection = require('./db-connection/db.connection')n
n
nThe full code in the index.js now look like this:
n
var express = require('express'),n app = express(),n bodyParser = require('body-parser'),n config = require('./configuration/app.config'),n dbConnection = require('./db-connection/db.connection')n cors = require('cors');nnnapp.set('port', (process.env.PORT || config.serverPort));nnapp.use(bodyParser.urlencoded({ extended: true }));napp.use(bodyParser.json());napp.use(cors());nnserver.listen(app.get('port'), function () {n console.log('Node app is running on port', app.get('port'));n});n
n
nnnn
n
nTher Server Route
nCurrently, if we run the app using node index.js and we try to check our browser via http://localhost:8000 you will see that the app isn’t coming up. That is because no route has been defined.
n
nAdd a folder called routes and add a file named app.routes.js, add the following code:
n
module.exports = function (express, app) {nn var router = express.Router();nn router.get('/', function (req, res) {n res.json("API Home Page");n })nn app.use('/', router);nn}n
n
nThen add the this line of code to the index.js file ti fire up the route we just created:
n
require('./routes/app-routes')(express, app);n
n
nIf we run node index now our app should be running on port 8000.
n
nThe App Models
nWe are going to create three models namely user, category and portfolio. Add a folder named interface and add three files user.js,category.js and portfolio.js, modify the files like so:
n
var mongoose = require('mongoose');nvar Schema = mongoose.Schema;nvar bcrypt = require('bcrypt-nodejs');nnnvar userSchema = new Schema({n email: { type: String, required: true },n password: { type: String, required: true },n firstName: { type: String, default: '' },n lastName: { type: String, default: '' },n phone: { type: String, required: true },n role:{type:String,required:true},n avatar_url:{type:String,default:''},n created_at: { type: Date, default: Date.now }n});nnuserSchema.pre('save', function (next) {n var user = this;n if (!user.isModified('password')) return next();n bcrypt.genSalt(10, function (err, salt) {n if (err) return next(err);n bcrypt.hash(user.password, salt, null, function (err, hash) {n if (err) return next(err);n user.password = hash;n next();n })n })n})nnuserSchema.methods.comparePassword = function (password) {n return bcrypt.compareSync(password, this.password)n}nnmodule.exports = mongoose.model('User', userSchema);n
n
n
var mongoose = require('mongoose');nvar Schema = mongoose.Schema;nnvar categorySchema = new Schema({n title: { type: String,required:true },n created_at: { type: Date, default: Date.now }n});nnmodule.exports = mongoose.model('Category', categorySchema);n
n
n
var mongoose = require('mongoose');nvar Schema = mongoose.Schema;nnvar portfolioSchema = new Schema({n author: { type: Schema.Types.ObjectId, ref: 'User' },n category:{ type: Schema.Types.ObjectId,ref:'Category'},n title: { type: String },n image_url: { type: String, default: '' },n description: { type: String },n web_url: { type: String, default: '' },n created_at: { type: Date, default: Date.now }n});nnmodule.exports = mongoose.model('Portfolio', portfolioSchema);n
n
nNext, let’s add the controllers where the real code will live. We are going to need three controllers, add a folder named controllers and create three files – category.controller.js, portfolio.controller.js and user.controller.js and add the following code:
n
var Category = require('../interfaces/category'),n config = require('../configuration/app.config');nn module.exports = {nn add:(req, res, next)=>{n var category =new Category({n title:req.body.titlen }).save((err, response) => {n if (err) {n res.status(400).json({ status: 0, message: JSON.stringify(err) });n } else {n res.status(201).json({n status: 1,n message: 'Category has been created successfully',n data: responsen });n }n });n },nn get:(req,res,next)=>{n Category.find({}, (err, result)=> {n if (err) return next(err);n res.status(200).json({ status: 1, message: null, count: result.length, data: result });n });n }nn }n
n
n
var User = require('../interfaces/user');nnmodule.exports = {nn register: (req, res, next) => {nn var user = new User({nn email: req.body.email,n password: req.body.password,n firstName: req.body.firstName,n lastName: req.body.lastName,n phone: req.body.phone,n role:req.body.role,n avatar_url:req.body.avatar_urlnn }).save((err, response) => {n if (err) {n res.status(400).json({ status: 0, message: JSON.stringify(err) });n } else {n res.status(201).json({n status: 1,n message: 'User has been created successfully',n data: responsen });n }n });n },nn update: (req, res, next) =>{n User.findByIdAndUpdate({ _id: req.params.id }, (err, res, next)=> {n if (err) return next(err);n });n },n login: (req, res, next) => {n User.findOne({ email: req.body.email }, (err, result)=> {n if (err) return next(err);n res.status(200).json({ status: 1, message: null, count: result.length, data: result });n });n },n get: (req, res, next)=> {n User.find({}, (err, result)=> {n if (err) return next(err);n res.status(200).json({ status: 1, message: null, count: result.length, data: result });n });n },n delete: (req, res, next)=> {n User.find({}).remove().exec( (err, result) => {n res.json({ result });n })n }nnnn}n
n
n
var Portfolio = require('../interfaces/portfolio'),n config = require('../configuration/app.config'),n cloudinary = require('cloudinary'),n multipart = require('connect-multiparty')();nncloudinary.config({n cloud_name: config.cloud_name,n api_key: config.api_key,n api_secret: config.api_secretn});nnmodule.exports = {nn add: (req, res, next) => {nn if(!req.files){n var portfolio = new Portfolio({n author: req.body.author_id,n category: req.body.category_id,n title: req.body.title,n image_url: '',n description: req.body.description,n web_url: req.body.web_urln }).save((err, response) => {n if (err) {n res.status(400).json({ status: 0, message: JSON.stringify(err) });n } else {n res.status(201).json({n status: 1,n message: 'Portfolio has been created successfully',n data: responsen });n }n });n }else{nn cloudinary.uploader.upload(req.files.file.path, (resp) => {nn var portfolio = new Portfolio({n author: req.body.author_id,n category: req.body.category_id,n title: req.body.title,n image_url: resp.url,n description: req.body.description,n web_url: req.body.web_urln }).save((err, response) => {n if (err) {n res.status(400).json({ status: 0, message: JSON.stringify(err) });n } else {n res.status(201).json({n status: 1,n message: 'Portfolio has been created successfully',n data: responsen });n }n });nn });n }n },n getAll: (req, res, next) => {n Portfolio.find({}, 'category title image_url description web_url')n .populate('author', 'firstName lastName avatar_url role')n .sort('-created_at')n .exec(function (err, result) {n if (err) return next(err);n res.status(httpCodes.OK).json({ status: 1, message: null, count: result.length, data: result });n })n },n get: (req, res, next) => {nn }nnnn}n
n
nThen modify the app.route.js file like so
n
var userCtrl = require('../controllers/user.controller'),n catCtrl = require('../controllers/category.controller'),n portfolioCtrl =require('../controllers/portfolio.controller');nvar multipart = require('connect-multiparty')();nnmodule.exports = function (express, app) {nn var router = express.Router();nn router.get('/', function (req, res) {n res.json("API Home Page");n })nn //Users API Routesn router.post('/api/v1/users', multipart, userCtrl.register);n router.get('/api/v1/users', userCtrl.get);n router.post('/api/v1/categories',catCtrl.add);n router.get('/api/v1/categories',catCtrl.get);nn router.post('/api/v1/portfolios',portfolioCtrl.add);n app.use('/', router);nn}n
n
n
n
nThat is it! Our API is ready. In the next article I will walk you through on building the mobile app. Till then happy coding.
n
n
n
n
