Student User
2019-08-02 e5e3675bebd2a6fbb5b5ffaf4403c4039b25a5ea
add sample for ch10s03 lab
6 files added
349 ■■■■■ changed files
todo-backend/app.js 36 ●●●●● patch | view | raw | blame | history
todo-backend/controllers/items.js 131 ●●●●● patch | view | raw | blame | history
todo-backend/controllers/serverinfo.js 29 ●●●●● patch | view | raw | blame | history
todo-backend/models/db.js 10 ●●●●● patch | view | raw | blame | history
todo-backend/models/items.js 127 ●●●●● patch | view | raw | blame | history
todo-backend/package.json 16 ●●●●● patch | view | raw | blame | history
todo-backend/app.js
New file
@@ -0,0 +1,36 @@
var restify = require('restify');
var controller = require('./controllers/items');
var serverinfo = require('./controllers/serverinfo');
var db = require('./models/db');
var model = require('./models/items');
model.connect(db.params, function(err) {
    if (err) throw err;
});
var server = restify.createServer()
    .use(restify.fullResponse())
    .use(restify.queryParser())
    .use(restify.bodyParser())
    .use(restify.CORS());;
controller.context(server, '/todo/api', model);
serverinfo.context(server, '/todo/api');
var port = process.env.PORT || 8080;
server.listen(port, function (err) {
    if (err)
        console.error(err);
    else
        console.log('App is ready at : ' + port);
});
/*
process.on('uncaughtException', function (err) {
    console.error(JSON.parse(JSON.stringify(err, ['stack', 'message', 'inner'], 2)))
});
*/
todo-backend/controllers/items.js
New file
@@ -0,0 +1,131 @@
var model = undefined;
exports.context = function(server, path, itemsModel) {
    if (!server)
        done('has to provide a restify server object');
    var context = "/items";
    if (path)
        context = path + context;
    server.get(context + '/', this.list);
    server.get(context + '/:id', this.read);
    server.get(context + '-count', this.count);
    server.post(context + '/', this.save);
    server.del(context + '/:id', this.destroy);
    model = itemsModel;
};
exports.list = function(req, res, next) {
    var page_no = req.query.page || 1;
    var sortField = req.query.sortFields || "id";
    var sortDirection = req.query.sortDirections || "asc";
    model.listAll(page_no, sortField, sortDirection, function(err, items) {
        if (err) {
            res.send(err);
        }
        else {
            if (items) {
                model.countAll(function(err, n) {
                    if (err) {
                        res.send(err);
                    }
                    else {
                        if (n) {
                            var page = {
                                "currentPage" : page_no,
                                "list" : items,
                                "pageSize" : 10,
                                "sortDirections" : sortDirection,
                                "sortFields" : sortField,
                                "totalResults" : n
                            };
                            res.json(page);
                            next();
                        }
                    }
                });
            }
            else {
                res.send(err);
            }
        }
    })
};
exports.read = function(req, res, next) {
    var key = req.params.id;
    model.read(key, function(err, item) {
        if (err) {
            res.send(err);
        }
        else {
            if (item) {
                res.json(item);
                next();
            }
            else {
                res.send(err);
            }
        }
    })
};
exports.count = function(req, res, next) {
    model.countAll(function(err, n) {
        if (err) {
            res.send(err);
        }
        else {
            var page = {
              count: n
            };
            res.json(page)
            next();
        }
    })
};
exports.save = function(req, res, next) {
    if (req.params.id) {
        model.update(req.params.id, req.params.description, req.params.done, function(err, item) {
            if (err) {
                res.send(err);
            }
            else {
                res.json(item);
                next();
            }
        });
    }
    else {
        model.create(req.params.description, req.params.done, function(err, item) {
            if (err) {
                res.send(err);
            }
            else {
                res.json(item);
                next();
            }
        });
    }
};
exports.destroy = function(req, res, next) {
    if (req.params.id) {
        model.destroy(req.params.id, function(err, item) {
            if (err) {
                res.send(err);
            }
            else {
                res.json(item);
            }
        });
    }
}
todo-backend/controllers/serverinfo.js
New file
@@ -0,0 +1,29 @@
var os = require('os');
exports.context = function(server, path) {
    if (!server)
        done('has to provide a restify server object');
    server.get(path + '/host', this.serverInfo);
};
exports.serverInfo = function(req, res, next) {
    var address;
    var ifaces = os.networkInterfaces();
    for (var dev in ifaces) {
        var iface = ifaces[dev].filter(function(details) {
            return details.family === 'IPv4' && details.internal === false;
        });
        if (iface.length > 0)
            address = iface[0].address;
    }
    var reply = {
        ip: address,
        hostname: os.hostname()
    };
    res.json(reply);
    next();
};
todo-backend/models/db.js
New file
@@ -0,0 +1,10 @@
module.exports.params = {
  dbname: process.env.DATABASE_NAME,
  username: process.env.DATABASE_USER,
  password: process.env.DATABASE_PASSWORD,
  params: {
      host: process.env.DATABASE_SVC,
      dialect: 'mysql',
  }
};
todo-backend/models/items.js
New file
@@ -0,0 +1,127 @@
var Sequelize = require("sequelize");
var Item = undefined;
module.exports.connect = function(params, callback) {
    var sequlz = new Sequelize(
        params.dbname, params.username, params.password,
        params.params);
    Item = sequlz.define('Item', {
        id: { type: Sequelize.BIGINT,
            primaryKey: true, unique: true, allowNull: false,
            autoIncrement: true },
        description: { type: Sequelize.STRING,
            allowNull: true },
        done: { type: Sequelize.BOOLEAN,
            allowNull: true }
    }, {
        timestamps: false,
        freezeTableName: true
    });
    if (process.env.DATABASE_INIT == 'true') {
        Item.sync({ force: true }).then(function() {
            callback();
        }).catch(function(err) {
            callback(err);
        });
    }
}
exports.disconnect = function(callback) {
    //XXX shouln'd to something to close or release the db connection?
    callback();
}
exports.create = function(description, done, callback) {
    Item.create({
        //id: id,
        description: description,
        done: (done) ? true : false
    }).then(function(item) {
        callback(null, item);
    }).catch(function(err) {
        callback(err);
    });
}
exports.update = function(key, description, done, callback) {
    Item.find({ where:{ id: key } }).then(function(item) {
        if (!item) {
            callback(new Error("Nothing found for key " + key));
        }
        else {
            item.updateAttributes({
                description: description,
                done: (done) ? true : false
            }).then(function() {
                callback(null, item);
            }).error(function(err) {
                callback(err);
            });
        }
    }).catch(function(err) {
        callback(err);
    });
}
exports.read = function(key, callback) {
    Item.find({ where:{ id: key } }).then(function(item) {
        if (!item) {
            callback(new Error("Nothing found for key " + key));
        }
        else {
            //XXX why recreating the item object?
            callback(null, {
                id: item.id,
                description: item.description,
                done: item.done
            });
        }
    }).catch(function(err) {
        callback(err);
    });
}
exports.destroy = function(key, callback) {
    Item.find({ where:{ id: key } }).then(function(item) {
        if (!item) {
            callback(new Error("Nothing found for " + key));
        }
        else {
            item.destroy().then(function() {
                callback(null, item);
            }).error(function(err) {
                callback(err);
            });
        }
    }).catch(function(err) {
        callback(err);
    });
}
exports.countAll = function(callback) {
    Item.findAll({
        attributes: [[Sequelize.fn('COUNT', Sequelize.col('id')), 'no_items']]
    }).then(function(n) {
        callback(null, n[0].get('no_items'));
    }).catch(function(err) {
        callback(err);
    });
}
exports.listAll = function(page, sortField, sortDirection, callback) {
    Item.findAll({ offset: 10 * (page - 1), limit: 10,  order: [[sortField, sortDirection]] }).then(function(items) {
        var theitems = [];
        items.forEach(function(item) {
            //XXX why recreating the item objects for theitems?
            theitems.push({
                id: item.id, description: item.description, done: item.done });
        });
        callback(null, theitems);
    }).catch(function(err) {
        callback(err);
    });
}
todo-backend/package.json
New file
@@ -0,0 +1,16 @@
{
  "name": "todo-single",
  "description": "single container version of the todoapp",
  "version": "0.0.2",
  "private": true,
  "author": "Red Hat Training",
  "license": "ASL",
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "restify": "4.0.3",
    "sequelize": "3.14.2",
    "mysql": "2.9.0"
  }
}