Skip to content

Commit

Permalink
feat(push): initial fcm transport implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
lykmapipo committed May 27, 2019
1 parent 5cdfce8 commit d030f32
Show file tree
Hide file tree
Showing 2 changed files with 238 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,9 @@ SMTP_PASSWORD=
SMTP_SECURE=
SMTP_FROM=
SMTP_TEST_RECEIVER=


# GOOGLE FCM(GCM) TRANSPORT
PUSH_FCM_API_KEY=
PUSH_FCM_DEFAULT_SENDER_ID=
PUSH_FCM_TEST_REGISTRATION_TOKEN=
232 changes: 232 additions & 0 deletions lib/transports/push.fcm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
'use strict';


/**
* @name push
* @module push
* @description fcm(gcm) push notification transport
* @see {@link https://github.com/ToothlessGear/node-gcm}
* @license MIT
* @author lally elias <lallyelias87@gmail.com>
* @since 0.1.0
* @version 0.1.0
* @public
*/


/* dependencies */
const _ = require('lodash');
const { getString } = require('@lykmapipo/env');
const gcm = require('node-gcm');


/**
* @name defaults
* @description default configuration options
* @type {Object}
* @author lally elias <lallyelias87@gmail.com>
* @since 0.1.0
* @version 0.1.0
* @private
*/
exports.defaults = {
//Google FCM API Key
apiKey: getString('PUSH_FCM_API_KEY'),
};


/**
* @name countryCode
* @description transport country code
* @type {String}
* @author lally elias <lallyelias87@gmail.com>
* @since 0.1.0
* @version 0.1.0
* @public
*/
exports.countryCode = undefined;


/**
* @name countryName
* @description transport country name
* @type {String}
* @author lally elias <lallyelias87@gmail.com>
* @since 0.1.0
* @version 0.1.0
* @public
*/
exports.countryCode = undefined;


/**
* @name name
* @description name of the transport
* @type {String}
* @author lally elias <lallyelias87@gmail.com>
* @since 0.1.0
* @version 0.1.0
* @public
*/
exports.name = 'fcm-push';


/**
* @name toObject
* @function toObject
* @description convert transport details into object
* @author lally elias <lallyelias87@gmail.com>
* @since 0.1.0
* @version 0.1.0
* @public
*/
exports.toObject = function toObject() {
const object = {
name: exports.name,
countryCode: exports.countryCode,
countryName: exports.countryName
};
return object;
};


/**
* @name init
* @function init
* @description initialize transport
* @author lally elias <lallyelias87@gmail.com>
* @since 0.1.0
* @version 0.1.0
* @private
*/
exports.init = function (options) {

//initialize transport if not exist
if (!exports.transport) {

//merge options
exports.options =
_.merge({}, exports.defaults, exports.options, options);

//ensure Google FCM API Key
const { apiKey } = exports.options;

//create transport
//initiate node GCM(FCM) sender
//@see {@link https://github.com/ToothlessGear/node-gcm#example-application}
exports.transport = new gcm.Sender(apiKey);

}

};


/**
* @name _send
* @function _send
* @description send push notification message using fcm(gcm) transport
*
* Note!: message options may contain push message data & notification
*
* @param {Message} message valid message instance
* @param {Function} done a callback to invoke on success or failure
* @author lally elias <lallyelias87@gmail.com>
* @since 0.1.0
* @version 0.1.0
* @private
*/
exports._send = function (message, done) {

//ensure transport is initialized
exports.init();

//prepare FCM push notification compliant payload
let payload =
_.merge({}, message.options, {
notification: {
title: message.subject,
body: message.body
}
});

//prepare push notification recipients
const to = message.to && message.to.length > 1 ? message.to : message.to[0];

//instantiate node-gcm message
payload = new gcm.Message(payload);

//perform actual send
exports.transport.send(payload, to, function (error, response) {

//check for reachability
//@see {@link https://github.com/ToothlessGear/node-gcm/blob/master/lib/sender.js#L153}
if (error && _.isNumber(error) && error >= 500) {
error = new Error('GCM(FCM) Server Unavailable');
error.status = 'Internal Server Error';
error.code = error;
}

//check for authorization
//@see {@link https://github.com/ToothlessGear/node-gcm/blob/master/lib/sender.js#L157}
if (error && _.isNumber(error) && error === 401) {
error = new Error(
'Unauthorized (401). Check that your API token is correct.'
);
error.status = 'Unauthorized';
error.code = error;
}

//check failure response
//@see {@link https://github.com/ToothlessGear/node-gcm/blob/master/lib/sender.js#L161}
if (error && _.isNumber(error) &&
error !== 200 && error !== 401 && error <= 500) {
error = new Error('Invalid Request');
error.status = 'Invalid Request';
error.code = error;
}

//respond with error
if (error) {
done(error);
}

//respond with success result
else {
//merge default response details
response = _.merge({}, { success: true }, response);

//process push results if available
if (response.results) {
response.results = _.map(message.to, function (val, index) {
return _.merge({}, { to: val }, response.results[index]);
});
}
done(null, response);
}

});

};


/**
* @name send
* @function send
* @description send push notification via transaport
* @param {Message} message valid message instance
* @param {Function} done callback to invoke on success or failure
* @return {Object|Error} send result or error
* @since 0.1.0
* @version 0.1.0
* @public
*/
exports.send = function (message, done) {

//ensure email sender
message.sender =
(message.sender || getString('PUSH_FCM_SENDER_ID', exports.name));

//perform actual push notification sending
exports._send(message, done);

};

0 comments on commit d030f32

Please sign in to comment.