Merge pull request #584 from flovilmart/hotfix-pushadapters

hotfix for #549
This commit is contained in:
Drew
2016-02-22 16:45:52 -08:00
9 changed files with 97 additions and 84 deletions

View File

@@ -1,5 +1,5 @@
var AdapterLoader = require("../src/Adapters/AdapterLoader").AdapterLoader; var loadAdapter = require("../src/Adapters/AdapterLoader").loadAdapter;
var FilesAdapter = require("../src/Adapters/Files/FilesAdapter").default; var FilesAdapter = require("../src/Adapters/Files/FilesAdapter").default;
describe("AdaptableController", ()=>{ describe("AdaptableController", ()=>{
@@ -7,7 +7,7 @@ describe("AdaptableController", ()=>{
it("should instantiate an adapter from string in object", (done) => { it("should instantiate an adapter from string in object", (done) => {
var adapterPath = require('path').resolve("./spec/MockAdapter"); var adapterPath = require('path').resolve("./spec/MockAdapter");
var adapter = AdapterLoader.load({ var adapter = loadAdapter({
adapter: adapterPath, adapter: adapterPath,
key: "value", key: "value",
foo: "bar" foo: "bar"
@@ -21,7 +21,7 @@ describe("AdaptableController", ()=>{
it("should instantiate an adapter from string", (done) => { it("should instantiate an adapter from string", (done) => {
var adapterPath = require('path').resolve("./spec/MockAdapter"); var adapterPath = require('path').resolve("./spec/MockAdapter");
var adapter = AdapterLoader.load(adapterPath); var adapter = loadAdapter(adapterPath);
expect(adapter instanceof Object).toBe(true); expect(adapter instanceof Object).toBe(true);
expect(adapter.options).toBe(adapterPath); expect(adapter.options).toBe(adapterPath);
@@ -30,7 +30,7 @@ describe("AdaptableController", ()=>{
it("should instantiate an adapter from string that is module", (done) => { it("should instantiate an adapter from string that is module", (done) => {
var adapterPath = require('path').resolve("./src/Adapters/Files/FilesAdapter"); var adapterPath = require('path').resolve("./src/Adapters/Files/FilesAdapter");
var adapter = AdapterLoader.load({ var adapter = loadAdapter({
adapter: adapterPath adapter: adapterPath
}); });
@@ -39,7 +39,7 @@ describe("AdaptableController", ()=>{
}); });
it("should instantiate an adapter from function/Class", (done) => { it("should instantiate an adapter from function/Class", (done) => {
var adapter = AdapterLoader.load({ var adapter = loadAdapter({
adapter: FilesAdapter adapter: FilesAdapter
}); });
expect(adapter instanceof FilesAdapter).toBe(true); expect(adapter instanceof FilesAdapter).toBe(true);
@@ -47,22 +47,22 @@ describe("AdaptableController", ()=>{
}); });
it("should instantiate the default adapter from Class", (done) => { it("should instantiate the default adapter from Class", (done) => {
var adapter = AdapterLoader.load(null, FilesAdapter); var adapter = loadAdapter(null, FilesAdapter);
expect(adapter instanceof FilesAdapter).toBe(true); expect(adapter instanceof FilesAdapter).toBe(true);
done(); done();
}); });
it("should use the default adapter", (done) => { it("should use the default adapter", (done) => {
var defaultAdapter = new FilesAdapter(); var defaultAdapter = new FilesAdapter();
var adapter = AdapterLoader.load(null, defaultAdapter); var adapter = loadAdapter(null, defaultAdapter);
expect(adapter instanceof FilesAdapter).toBe(true); expect(adapter instanceof FilesAdapter).toBe(true);
done(); done();
}); });
it("should use the provided adapter", (done) => { it("should use the provided adapter", (done) => {
var originalAdapter = new FilesAdapter(); var originalAdapter = new FilesAdapter();
var adapter = AdapterLoader.load(originalAdapter); var adapter = loadAdapter(originalAdapter);
expect(adapter).toBe(originalAdapter); expect(adapter).toBe(originalAdapter);
done(); done();
}); });
}); });

View File

@@ -1,6 +1,6 @@
var OneSignalPushAdapter = require('../src/Adapters/Push/OneSignalPushAdapter'); var OneSignalPushAdapter = require('../src/Adapters/Push/OneSignalPushAdapter');
var classifyInstallations = require('../src/Adapters/Push/PushAdapterUtils').classifyInstallations;
describe('OneSignalPushAdapter', () => { describe('OneSignalPushAdapter', () => {
it('can be initialized', (done) => { it('can be initialized', (done) => {
// Make mock config // Make mock config
@@ -47,7 +47,7 @@ describe('OneSignalPushAdapter', () => {
} }
]; ];
var deviceMap = OneSignalPushAdapter.classifyInstallation(installations, validPushTypes); var deviceMap = OneSignalPushAdapter.classifyInstallations(installations, validPushTypes);
expect(deviceMap['android']).toEqual([makeDevice('androidToken')]); expect(deviceMap['android']).toEqual([makeDevice('androidToken')]);
expect(deviceMap['ios']).toEqual([makeDevice('iosToken')]); expect(deviceMap['ios']).toEqual([makeDevice('iosToken')]);
expect(deviceMap['win']).toBe(undefined); expect(deviceMap['win']).toBe(undefined);

View File

@@ -80,7 +80,7 @@ describe('ParsePushAdapter', () => {
} }
]; ];
var deviceMap = ParsePushAdapter.classifyInstallation(installations, validPushTypes); var deviceMap = ParsePushAdapter.classifyInstallations(installations, validPushTypes);
expect(deviceMap['android']).toEqual([makeDevice('androidToken')]); expect(deviceMap['android']).toEqual([makeDevice('androidToken')]);
expect(deviceMap['ios']).toEqual([makeDevice('iosToken')]); expect(deviceMap['ios']).toEqual([makeDevice('iosToken')]);
expect(deviceMap['win']).toBe(undefined); expect(deviceMap['win']).toBe(undefined);

View File

@@ -1,39 +1,35 @@
export class AdapterLoader { export function loadAdapter(options, defaultAdapter) {
static load(options, defaultAdapter) { let adapter;
let adapter;
// We have options and options have adapter key // We have options and options have adapter key
if (options) { if (options) {
// Pass an adapter as a module name, a function or an instance // Pass an adapter as a module name, a function or an instance
if (typeof options == "string" || typeof options == "function" || options.constructor != Object) { if (typeof options == "string" || typeof options == "function" || options.constructor != Object) {
adapter = options; adapter = options;
}
if (options.adapter) {
adapter = options.adapter;
}
} }
if (options.adapter) {
if (!adapter) { adapter = options.adapter;
adapter = defaultAdapter;
} }
// This is a string, require the module
if (typeof adapter === "string") {
adapter = require(adapter);
// If it's define as a module, get the default
if (adapter.default) {
adapter = adapter.default;
}
}
// From there it's either a function or an object
// if it's an function, instanciate and pass the options
if (typeof adapter === "function") {
var Adapter = adapter;
adapter = new Adapter(options);
}
return adapter;
} }
}
if (!adapter) {
adapter = defaultAdapter;
}
export default AdapterLoader; // This is a string, require the module
if (typeof adapter === "string") {
adapter = require(adapter);
// If it's define as a module, get the default
if (adapter.default) {
adapter = adapter.default;
}
}
// From there it's either a function or an object
// if it's an function, instanciate and pass the options
if (typeof adapter === "function") {
var Adapter = adapter;
adapter = new Adapter(options);
}
return adapter;
}

View File

@@ -3,6 +3,8 @@
// PushAdapter, it uses GCM for android push and APNS // PushAdapter, it uses GCM for android push and APNS
// for ios push. // for ios push.
import { classifyInstallations } from './PushAdapterUtils';
const Parse = require('parse/node').Parse; const Parse = require('parse/node').Parse;
var deepcopy = require('deepcopy'); var deepcopy = require('deepcopy');
import PushAdapter from './PushAdapter'; import PushAdapter from './PushAdapter';
@@ -25,7 +27,7 @@ export class OneSignalPushAdapter extends PushAdapter {
send(data, installations) { send(data, installations) {
console.log("Sending notification to "+installations.length+" devices.") console.log("Sending notification to "+installations.length+" devices.")
let deviceMap = PushAdapter.classifyInstallation(installations, this.validPushTypes); let deviceMap = classifyInstallations(installations, this.validPushTypes);
let sendPromises = []; let sendPromises = [];
for (let pushType in deviceMap) { for (let pushType in deviceMap) {
@@ -43,6 +45,14 @@ export class OneSignalPushAdapter extends PushAdapter {
return Parse.Promise.when(sendPromises); return Parse.Promise.when(sendPromises);
} }
static classifyInstallations(installations, validTypes) {
return classifyInstallations(installations, validTypes)
}
getValidPushTypes() {
return this.validPushTypes;
}
sendToAPNS(data,tokens) { sendToAPNS(data,tokens) {
data= deepcopy(data['data']); data= deepcopy(data['data']);

View File

@@ -7,6 +7,7 @@ const Parse = require('parse/node').Parse;
const GCM = require('../../GCM'); const GCM = require('../../GCM');
const APNS = require('../../APNS'); const APNS = require('../../APNS');
import PushAdapter from './PushAdapter'; import PushAdapter from './PushAdapter';
import { classifyInstallations } from './PushAdapterUtils';
export class ParsePushAdapter extends PushAdapter { export class ParsePushAdapter extends PushAdapter {
constructor(pushConfig = {}) { constructor(pushConfig = {}) {
@@ -31,8 +32,16 @@ export class ParsePushAdapter extends PushAdapter {
} }
} }
getValidPushTypes() {
return this.validPushTypes;
}
static classifyInstallations(installations, validTypes) {
return classifyInstallations(installations, validTypes)
}
send(data, installations) { send(data, installations) {
let deviceMap = PushAdapter.classifyInstallation(installations, this.validPushTypes); let deviceMap = classifyInstallations(installations, this.validPushTypes);
let sendPromises = []; let sendPromises = [];
for (let pushType in deviceMap) { for (let pushType in deviceMap) {
let sender = this.senderMap[pushType]; let sender = this.senderMap[pushType];

View File

@@ -16,39 +16,7 @@ export class PushAdapter {
* Get an array of valid push types. * Get an array of valid push types.
* @returns {Array} An array of valid push types * @returns {Array} An array of valid push types
*/ */
getValidPushTypes() { getValidPushTypes() {}
return this.validPushTypes;
}
/**g
* Classify the device token of installations based on its device type.
* @param {Object} installations An array of installations
* @param {Array} validPushTypes An array of valid push types(string)
* @returns {Object} A map whose key is device type and value is an array of device
*/
static classifyInstallation(installations, validPushTypes) {
// Init deviceTokenMap, create a empty array for each valid pushType
let deviceMap = {};
for (let validPushType of validPushTypes) {
deviceMap[validPushType] = [];
}
for (let installation of installations) {
// No deviceToken, ignore
if (!installation.deviceToken) {
continue;
}
let pushType = installation.deviceType;
if (deviceMap[pushType]) {
deviceMap[pushType].push({
deviceToken: installation.deviceToken,
appIdentifier: installation.appIdentifier
});
} else {
console.log('Unknown push type from installation %j', installation);
}
}
return deviceMap;
}
} }
export default PushAdapter; export default PushAdapter;

View File

@@ -0,0 +1,30 @@
/**g
* Classify the device token of installations based on its device type.
* @param {Object} installations An array of installations
* @param {Array} validPushTypes An array of valid push types(string)
* @returns {Object} A map whose key is device type and value is an array of device
*/
export function classifyInstallations(installations, validPushTypes) {
// Init deviceTokenMap, create a empty array for each valid pushType
let deviceMap = {};
for (let validPushType of validPushTypes) {
deviceMap[validPushType] = [];
}
for (let installation of installations) {
// No deviceToken, ignore
if (!installation.deviceToken) {
continue;
}
let pushType = installation.deviceType;
if (deviceMap[pushType]) {
deviceMap[pushType].push({
deviceToken: installation.deviceToken,
appIdentifier: installation.appIdentifier
});
} else {
console.log('Unknown push type from installation %j', installation);
}
}
return deviceMap;
}

View File

@@ -33,7 +33,7 @@ import { PushRouter } from './Routers/PushRouter';
import { FilesRouter } from './Routers/FilesRouter'; import { FilesRouter } from './Routers/FilesRouter';
import { LogsRouter } from './Routers/LogsRouter'; import { LogsRouter } from './Routers/LogsRouter';
import { AdapterLoader } from './Adapters/AdapterLoader'; import { loadAdapter } from './Adapters/AdapterLoader';
import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter'; import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter';
import { LoggerController } from './Controllers/LoggerController'; import { LoggerController } from './Controllers/LoggerController';
@@ -107,9 +107,9 @@ function ParseServer({
} }
const filesControllerAdapter = AdapterLoader.load(filesAdapter, GridStoreAdapter); const filesControllerAdapter = loadAdapter(filesAdapter, GridStoreAdapter);
const pushControllerAdapter = AdapterLoader.load(push, ParsePushAdapter); const pushControllerAdapter = loadAdapter(push, ParsePushAdapter);
const loggerControllerAdapter = AdapterLoader.load(loggerAdapter, FileLoggerAdapter); const loggerControllerAdapter = loadAdapter(loggerAdapter, FileLoggerAdapter);
// We pass the options and the base class for the adatper, // We pass the options and the base class for the adatper,
// Note that passing an instance would work too // Note that passing an instance would work too