Kinvey Datasource and datalink mapping - node.js

If any one worked on Kinvey (Mbaas) Please help in setting up datalink project using nodeJS
I am new to nodeJS, I created an nodejs project based on kinvey sample.
Below is nodejs code sample
var configTools = require("./config");
var util = require("util");
var querystring = require('querystring');
var ServiceLink = require('./service_link');
var restify = require('restify');
var server = restify.createServer();
//Configure the server to parse the request body into req.body
server.use(restify.bodyParser({ mapParams: false }));
//insert into call chain when debugging
var debug = function(req, res, next) {
if (config.debug){
var method = req.method;
var params = req.params;
var query = req.query;
var body = req.body;
console.log("Method: " + method +
"\nParams: " + util.inspect(params, false, null, true) +
"\nQuery: " + util.inspect(query, false, null, true) +
"\nBody: " + util.inspect(body, false, null, true) + "\n");
}
if (config.debugFullRequest){
console.log(util.inspect(req));
}
return next();
}
// Verify key matches the header
var keyauth = function(req,res,next) {
var key = req.headers['x-auth-key'];
if (key != config.key) {
return next(new restify.InvalidCredentialsError("Invalid API Key"));
} else {
next();
}
}
//Router functions
var extractReq = function(req, next){
if (!req){ return new restify.InternalError("ServiceLink is having problems..."); }
var params = req.params;
var query = req.query;
var body = req.body;
var output = {query: null, params: null, body: null, route: null};
// Extract query
if (query && query !== undefined){
try {
var parsedString = querystring.parse(query);
output["query"] = JSON.parse(parsedString.query);
} catch (e){
return new restify.InvalidContentError("JSON query exception: " + e);
}
}
// Extract route
if (params && params !== undefined){
try {
var s = "";
s = params.collection;
if (params.id){
s = s + "/" + params.id;
}
output["route"] = s;
} catch (e){
return new restify.InvalidContentError("Invalid Params: " + e);
}
}
// Extract body
if (body && body !== undefined){
try {
output["body"] = body;
} catch (e){
return new restify.InvalidContentError("JSON body exception: " + e);
}
}
return output;
};
var preGet = function(req, res, next){
var data = extractReq(req, next);
if (data instanceof Error){
return next(data);
}
ServiceLink.get(data["route"], data["query"], data["body"], res, next);
};
server.get(/\/public\/?.*/, restify.serveStatic({
directory: './docs',
default: 'index.html'
}));
//For debugging we add in the debug middleware
server.get('/:stateList', keyauth, debug, preGet);
server.listen(3000, function() {
console.log('%s listening at %s', server.name, server.url);
});
if you look at the code, i have created angular front end and supply index page for routing.
my html file is loading fine, in that i will call kinvey datastore i.e stateList
like this
var promise = $kinvey.DataStore.find('stateList');
but it is giving me 500 error, when I mapped collection with datalink it is giving me error saying "_count endpoint to be implemented in the data link connector"
My datalink link is http://localhost:3000/
anyone please guide me on this mapping.
Thanks

Related

Node js Printing info from JSON file using a function from another file V2.0

This is a continuation from another question I asked earlier Node.js Printing info from JSON file using a function from another JS file
In my previous question I had problems in calling a function from my data-service.js file that printed all the items in my JSON array, and had it resolved, but now I'm struggling in doing something similar in printing only the employees from my JSON array that I specify through the url. For example http://localhost:8080/employeesstatus=5 would print only the employee with a status of 5 however nothing is getting printed
SERVER.JS
var HTTP_PORT = process.env.PORT || 8080;
var express = require('express');
var data = require('./data-service');
var fs = require('fs');
var app = express();
var object = require('./data-service');
console.log("Express http server listening on 8080");
//app.get('/employees', function(req,res){
// return object.getAllEmployees()
// .then((response) => res.send(response))
//}); //QUESION FROM PREVIOUS POST WHICH WAS RESOLVED
app.get('/employees:?status=:value', function(req,res){
return object.getEmployeesByStatus(req.params.value)
.then((response) => res.send(response));
});
DATA SERVICE.JS
var employees = [];
var departments = [];
var error = 0;
var fs = require("fs");
function initialize(){
employees = fs.readFileSync("./data/employees.json", 'utf8', function(err, data){
if(err){
error = 1;
}
employees = JSON.parse(data);
});
departments = fs.readFileSync("./data/department.json", 'utf8',
function(err, data){
if(err){
error = 1;
}
departments = JSON.parse(data);
});
}
function check() {
return new Promise(function(resolve,reject){
if (error === 0){
resolve("Success");
}
else if(error === 1){
reject("unable to read file");
}
})
};
var getAllEmployees = function(){
return check().then(function(x){
console.log(x);
console.log(employees);
return employees;
}).catch(function(x){
console.log("No results returned");
});
}
var getEmployeesByStatus = function (status){
return check().then(function(x){
var employees2 = JSON.parse(employees);
for (var i = 0; i<employees2.length; i++){
if (employees2[i].status == status){
return console.log(employees2[i]);
}
}
}).catch(function(){
console.log("no results returned");
})
}
module.exports.getAllEmployees = getAllEmployees;
module.exports.getEmployeesByStatus = getEmployeesByStatus;
The 2 functions in question
app.get('/employees:?status=:value', function(req,res){
return object.getEmployeesByStatus(req.params.value)
.then((response) => res.send(response));
});
var getEmployeesByStatus = function (status){
return check().then(function(x){
var employees2 = JSON.parse(employees);
for (var i = 0; i<employees2.length; i++){
if (employees2[i].status == status){
return employees2[i];
}
}
}).catch(function(){
console.log("no results returned");
})
}
1) You should replace /employees route with the following
app.get('/employees/status=:value', function(req,res){
return object.getEmployeesByStatus(req.params.value)
.then((response) => res.send(response));
});
You are able to access using http://localhost:8080/employees/status=5
2) Return employees2[i] instead of console.log(employees2[i]).

Web Digits Fabric Authentication

I am using digits web. I am using the cannonball example. I am running the below code on my local comptuter.
Heres my code of client side
<script>document.getElementById('digits-sdk').onload = function() {
Digits.init({ consumerKey: 'my consumer key' });
Digits.embed({
container: '#my-digits-container',
theme: {
/* Input fields borders */
},
phoneNumber: '+91',
})
.done(onLogin) /*handle the response*/
.fail(onLoginFailure);
};
function onLoginFailure(loginResponse) {
console.log('Digits login failed.');
//setDigitsButton('Verify again');
}
/* Validate and log use in. */
function onLogin(loginResponse){
// Send headers to your server and validate user by calling Digits’ API
//var oAuthHeaders = loginResponse.oauth_echo_headers;
var oAuthHeaders = parseOAuthHeaders(loginResponse.oauth_echo_headers);
$.ajax({
type: 'POST',
url: '/digits',
data: oAuthHeaders,
success: onDigitsSuccess
});
// setDigitsButton('Step 2.....');
}
function parseOAuthHeaders(oAuthEchoHeaders) {
var credentials = oAuthEchoHeaders['X-Verify-Credentials-Authorization'];
var apiUrl = oAuthEchoHeaders['X-Auth-Service-Provider'];
console.log(apiUrl);
return {
apiUrl: apiUrl,
credentials: credentials
};
}
function onDigitsSuccess(response) {
console.log(response.phoneNumber);
setDigitsNumber(response.phoneNumber);
}
function setDigitsNumber(phoneNumber) {
document.getElementById('notr').value = phoneNumber;
console.log('Digits phone number retrieved.');
}
</script>
In the above code I have changed the consumer key only. So ignore that.
And heres my server code
var express = require("express");
var app = express();
var router = express.Router();
var path = __dirname + '/static/';
app.use(express.static(__dirname + '/static'));
router.use(function (req,res,next) {
console.log("/" + req.method);
next();
});
router.get("/",function(req,res){
res.sendFile(path + "homepage9.html");
});
router.get("/about",function(req,res){
res.sendFile(path + "about.html");
});
router.get("/contact",function(req,res){
res.sendFile(path + "contact.html");
});
app.use("/",router);
app.use("*",function(req,res){
res.sendFile(path + "404.html");
});
app.listen(3000,function(){
console.log("Live at Port 3000");
});
var fs = require('fs');
var nconf = require('nconf');
var url = require('url');
var request = require('request');
router.post('/digits', function (req, res) {
console.log("digits entered")
var apiUrl = req.body['apiUrl']
var credentials = req.body['credentials']
var verified = true;
var messages = [];
if (credentials.indexOf('oauth_consumer_key="' + 'my consumer key' + '"') == -1) {
verified = false;
messages.push('The Digits API key does not match.');
}
var hostname = url.parse(req.body.apiUrl).hostname;
if (hostname != 'api.digits.com' && hostname != 'api.twitter.com') {
verified = false;
messages.push('Invalid API hostname.');
}
// Do not perform the request if the API key or hostname are not verified.
if (!verified) {
return res.send({
phoneNumber: "",
userID: "",
error: messages.join(' ')
});
}
// Prepare the request to the Digits API.
var options = {
url: apiUrl,
headers: {
'Authorization': credentials
}
};
// Perform the request to the Digits API.
request.get(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
// Send the verified phone number and Digits user ID.
var digits = JSON.parse(body)
return res.send({
phoneNumber: digits.phone_number,
userID: digits.id_str,
error: ''
});
} else {
// Send the error.
return res.send({
phoneNumber: '',
userID: '',
error: error.message
});
}
});
});
But on the node console i am getting
cannot read property 'apiUrl' of undefined.
on google chrome console i am getting
Failed to load resource: the server responded with a status of 500 (Internal Server Error)
Can any one help of what I am doing wrong.
Also in the cannon ball example i found that it nowhere uses the consumer secret key. Why is that?

Hijack response before sent to client

I have follow codes to be used as middlewares
module.exports=function(callback) {
callbacks.push(callback);
return function(req,res,next) {
if (!res.hijacked) {
res.hijacked=true;
} else {
return next();
}
var send=res.send;
res.send=function(data) {
var body=data instanceof Buffer ? data.toString() : data;
var requests=[];
requests.push(function(next) {
callbacks[0](req,res)(body,doneWrapper(body,next));
});
for (var i=1;i<callbacks.length;i++) {
var hijackCallback=callbacks[i];
requests.push(function(result,next) {
hijackCallback(req,res)(result,doneWrapper(result,next));
});
}
var that=this;
async.waterfall(requests,function(err,result) {
send.call(that,result);
requests=null;
body=null;
that=null;
});
};
next();
};
};
An example of usage is as following:
module.exports=function() {
return hijack(function() {
return function(result,done) {
var json={};
try {
json=JSON.parse(result);
} catch(e) {
return done();
}
if (!_.isArray(json)) {
return done();
}
var sorted=_(json).sortBy(function(item) {
if (_.isObject(item.information)) {
return item.information.rangeIndex1 || 999;
} else {
return 1001;
}
});
done(sorted);
}
});
};
It worked fine initially as middlewares in routes.
However,When i try to make it as app.use(hijackMiddleware()). Something went wrong, I got this Can't set headers after they are sent error.
There is no problem when used as middlewares in routes,though.
Have you consider using express-interceptor? Is really easy to use:
var express = require('express');
var cheerio = require('cheerio');
var interceptor = require('express-interceptor');
var app = express();
var finalParagraphInterceptor = interceptor(function(req, res){
return {
// Only HTML responses will be intercepted
isInterceptable: function(){
return /text\/html/.test(res.get('Content-Type'));
},
// Appends a paragraph at the end of the response body
intercept: function(body, send) {
var $document = cheerio.load(body);
$document('body').append('<p>From interceptor!</p>');
send($document.html());
}
};
})
// Add the interceptor middleware
app.use(finalParagraphInterceptor);
app.use(express.static(__dirname + '/public/'));
app.listen(3000);

simple social network using node.js and mongodb

I am trying to build simple social network and I am following this book(Building Node Applications with MongoDB and Backbone)(https://github.com/Swiftam/book-node-mongodb-backbone/tree/master/ch10). However, I just realized that the node.js version has been updated.
I tied to solve some the issue however I got problem in chat.js that states this is the error:
ch10/routes/chat.js:27
data.sessionStore.load(data.sessionID, function(err, session) {
TypeError: Cannot read property 'load' of undefined
module.exports = function(app, models) {
var io = require('socket.io');
var utils = require('connect').utils;
var cookie = require('cookie');
this.io = io;
//var Session = require('connect').middleware.session.Session;
var sio = io.listen(app.server);
sio.configure(function() {
// Utility methods to see if the account is online
app.isAccountOnline = function(accountId) {
var clients = sio.sockets.clients(accountId);
return (clients.length > 0);
};
sio.set('authorization', function(data, accept) {
var signedCookies = cookie.parse(data.headers.cookie);
// var cookies = utils.parseSignedCookies(signedCookies, app.sessionSecret);
// data.sessionID = cookies['express.sid'];
data.sessionStore = app.sessionStore;
data.sessionStore.load(data.sessionID, function(err, session) {
if (err || !session) {
accept("Error", false);
} else {
data.session = session;
accept(null, true);
}
});
});
sio.sockets.on('connection', function(socket) {
var session = socket.handshake.session;
var accountId = session.accountId;
var sAccount = null;
socket.join(accountId);
io.use(function (socket, next) { next(); });
// Immediately trigger the login event
// of this account
app.triggerEvent('event:' + accountId, {
from: accountId,
action: 'login'
});
var handleContactEvent = function(eventMessage) {
socket.emit('contactEvent', eventMessage);
};
var subscribeToAccount = function(accountId) {
var eventName = 'event:' + accountId;
app.addEventListener(eventName, handleContactEvent);
console.log('Subscribing to ' + eventName);
};
// Find the account contacts and subscribe
models.Account.findById(accountId, function subscribeToFriendFeed(account) {
var subscribedAccounts = {};
sAccount = account;
account.contacts.forEach(function(contact) {
if (!subscribedAccounts[contact.accountId]) {
subscribeToAccount(contact.accountId);
subscribedAccounts[contact.accountId] = true;
}
});
// Subscribed to my feed as well
if (!subscribedAccounts[accountId]) {
subscribeToAccount(accountId);
}
});
// Remove listeners if socket disconnects
socket.on('disconnect', function() {
sAccount.contacts.forEach(function(contact) {
var eventName = 'event:' + contact.accountId;
app.removeEventListener(eventName, handleContactEvent);
console.log('Unsubscribing from ' + eventName);
});
app.triggerEvent('event:' + accountId, {
from: accountId,
action: 'logout'
});
});
var cookieParser = require('cookie-parser')(SESSION_SECRET);
// ### Cookie parser
// Wrapper arround Express cookie parser, so we can use the same cookie parser for socket.io.
// Parse Cookie header and populate `socket.request.cookies` with an object keyed by the cookie names.
// Uses signed cookies by passing a secret string, which assigns `socket.request.secret` so it may be used by other middleware.
function cookieParserWrapper (socket, next) {
// request, response and callback
cookieParser(socket.request, {}, next);
}
// Handle incoming chats from client
socket.on('chatclient', function(data) {
sio.sockets.in(data.to).emit('chatserver', {
from: accountId,
text: data.text
});
});
});
});
}
Without testing the code myself or anything.
"TypeError: Cannot read property 'load' of undefined"
That particular error means that data.sessionStore is undefined and that "load" does not exists as a property, since there is literally nothing defined in data.sessionStore.
So the problem in my opinion is that your session system is not working properly. Hope that helps a bit!

Proper way of using mongodb connection or express.js across multiple node.js file

I want to split my node.js file into multiple file like:
user.js for dealing with user database CRUD
group.js for dealing with group database CRUD
database.js for initializing database
restful.js for initializing express.js
What my concern is whether this is a common or good practice.
So the following files are after splitting:
app.js
require('./restful');
require('./database');
config.js
module.exports = function(){
database :{
username: "mark",
password: "pass",
host: "127.0.0.1",
port: "27017",
name: "mydb"
};
database.js
var config = require('./config');
var mongodb = require('mongodb');
var url = 'mongodb://'+ config.database.username+ ':' + config.database.password + '#' + config.database.host + ':' + config.database.port + '/' + config.database.name;
var Database = function() {
var db;
// always return the singleton instance, if it has been initialised once already.
if (Database.prototype._singletonInstance) {
return Database.prototype._singletonInstance;
}
this.getDatabase = function() {
return db;
}
this.get = this.getDatabase;
mongodb.MongoClient.connect(url, function(err, result) {
if(err || result === undefined || result === null) {
throw err;
} else {
db = result;
}
});
Database.prototype._singletonInstance = this;
};
new Database();
console.log('MongoDb set up OK!');
exports.Database = Database;
};
restful.js
var express = require('express');
var bodyParser = require('body-parser');
var restful_express = express();
restful_express.use(bodyParser());
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST');
res.header('Access-Control-Expose-Headers', 'token');
res.header('Access-Control-Allow-Headers', 'Content-Type, X-XSRF-TOKEN, Last-Event-ID, Content-Language, Accept-Language, Accept');
res.header('X-XSS-Protection', 0);
next();
}
restful_express.use(allowCrossDomain);
restful_express.listen(process.env.PORT || 7272, function(err) {
winlog.info('ExpressJs listening at 7272');
});
var Restful = function() {
// always return the singleton instance, if it has been initialised once already.
if (Restful.prototype._singletonInstance) {
return Restful.prototype._singletonInstance;
}
this.getRestful = function() {
return restful_express;
}
Restful.prototype._singletonInstance = this;
};
new Restful();
console.log('Express.js Restful set up OK!');
exports.Restful = Restful;
user.js
var config = require('./config');
var database = require('./database');
var db = database.Database();
var restful = require('./restful').Restful().getRestful();
module.exports = function(){
restful.get('/getUser/:email', function(req, res) {
db.get().collection("user").findOne({email:req.param('email')}, function(err, result) {
if(result) {
res.send({name:result.name});
} else {
res.statusCode = 400;
res.send({msg:'Email not found'});
}
});
});
});
group.js
var config = require('./config');
var database = require('./database');
var db = database.Database();
var restful = require('./restful').Restful().getRestful();
module.exports = function(){
restful.get('/getGroup/:name', function(req, res) {
db.get().collection("group").findOne({name:req.param('name')}, function(err, result) {
if(result) {
res.send({name:result.name});
} else {
res.statusCode = 400;
res.send({msg:'Group not found'});
}
});
});
});
So database.js can be simplified to:
var config = require('./config');
var mongodb = require('mongodb');
var db;
var url = 'mongodb://'+ config.database.username+ ':' + config.database.password + '#' + config.database.host + ':' + config.database.port + '/' + config.database.name;
module.exports = function(){
initDb : function () {
mongodb.MongoClient.connect(url, function(err, result) {
if(err || result === undefined || result === null) {
throw err;
} else {
db = result;
}
});
},
getDb : function () {
if(db === null || db === undefined) {
this.initDb();
}
return db;
}
};
It's just an absolutely legal way. But quite over complicated one.
module is a singleton by default. Regardless how many times you call require('some_module'); it's scaffolding code is executed only once. Try the following code in REPL
//index.js
var i = 0;
i ++;
exports.show = function(){
return i;
};
exports.increment = function(){
return i++;
};
then in REPL
> var one = require('./index.js');
> one.show();
1
> var two = require('./index.js');
> two.show();
1
> one.increment();
2
> two.show();
2

Resources