Merge pull request #549 from flovilmart/refactors-adapter-controller

Improves Controller and Adapter relationship
This commit is contained in:
Nikita Lutsenko
2016-02-22 11:43:38 -08:00
15 changed files with 562 additions and 327 deletions

View File

@@ -0,0 +1,87 @@
var AdaptableController = require("../src/Controllers/AdaptableController").AdaptableController;
var FilesAdapter = require("../src/Adapters/Files/FilesAdapter").default;
var FilesController = require("../src/Controllers/FilesController").FilesController;
var MockController = function(options) {
AdaptableController.call(this, options);
}
MockController.prototype = Object.create(AdaptableController.prototype);
MockController.prototype.constructor = AdaptableController;
describe("AdaptableController", ()=>{
it("should use the provided adapter", (done) => {
var adapter = new FilesAdapter();
var controller = new FilesController(adapter);
expect(controller.adapter).toBe(adapter);
// make sure _adapter is private
expect(controller._adapter).toBe(undefined);
// Override _adapter is not doing anything
controller._adapter = "Hello";
expect(controller.adapter).toBe(adapter);
done();
});
it("should throw when creating a new mock controller", (done) => {
var adapter = new FilesAdapter();
expect(() => {
new MockController(adapter);
}).toThrow();
done();
});
it("should fail setting the wrong adapter to the controller", (done) => {
function WrongAdapter() {};
var adapter = new FilesAdapter();
var controller = new FilesController(adapter);
var otherAdapter = new WrongAdapter();
expect(() => {
controller.adapter = otherAdapter;
}).toThrow();
done();
});
it("should fail to instantiate a controller with wrong adapter", (done) => {
function WrongAdapter() {};
var adapter = new WrongAdapter();
expect(() => {
new FilesController(adapter);
}).toThrow();
done();
});
it("should fail to instantiate a controller without an adapter", (done) => {
expect(() => {
new FilesController();
}).toThrow();
done();
});
it("should accept an object adapter", (done) => {
var adapter = {
createFile: function(config, filename, data) { },
deleteFile: function(config, filename) { },
getFileData: function(config, filename) { },
getFileLocation: function(config, filename) { },
}
expect(() => {
new FilesController(adapter);
}).not.toThrow();
done();
});
it("should accept an object adapter", (done) => {
function AGoodAdapter() {};
AGoodAdapter.prototype.createFile = function(config, filename, data) { };
AGoodAdapter.prototype.deleteFile = function(config, filename) { };
AGoodAdapter.prototype.getFileData = function(config, filename) { };
AGoodAdapter.prototype.getFileLocation = function(config, filename) { };
var adapter = new AGoodAdapter();
expect(() => {
new FilesController(adapter);
}).not.toThrow();
done();
});
});

View File

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

View File

@@ -1,4 +1,5 @@
var FilesController = require('../src/Controllers/FilesController').FilesController; var FilesController = require('../src/Controllers/FilesController').FilesController;
var GridStoreAdapter = require("../src/Adapters/Files/GridStoreAdapter").GridStoreAdapter;
var Config = require("../src/Config"); var Config = require("../src/Config");
// Small additional tests to improve overall coverage // Small additional tests to improve overall coverage
@@ -6,7 +7,8 @@ describe("FilesController",()=>{
it("should properly expand objects", (done) => { it("should properly expand objects", (done) => {
var config = new Config(Parse.applicationId); var config = new Config(Parse.applicationId);
var filesController = new FilesController(); var adapter = new GridStoreAdapter();
var filesController = new FilesController(adapter);
var result = filesController.expandFilesInObject(config, function(){}); var result = filesController.expandFilesInObject(config, function(){});
expect(result).toBeUndefined(); expect(result).toBeUndefined();

View File

@@ -77,10 +77,9 @@ describe('LoggerController', () => {
it('should throw without an adapter', (done) => { it('should throw without an adapter', (done) => {
var loggerController = new LoggerController();
expect(() => { expect(() => {
loggerController.getLogs(); var loggerController = new LoggerController();
}).toThrow(); }).toThrow();
done(); done();
}); });

3
spec/MockAdapter.js Normal file
View File

@@ -0,0 +1,3 @@
module.exports = function(options) {
this.options = options;
}

View File

@@ -227,7 +227,8 @@ describe('OneSignalPushAdapter', () => {
function makeDevice(deviceToken, appIdentifier) { function makeDevice(deviceToken, appIdentifier) {
return { return {
deviceToken: deviceToken deviceToken: deviceToken,
appIdentifier: appIdentifier
}; };
} }

View File

@@ -0,0 +1,39 @@
export class AdapterLoader {
static load(options, defaultAdapter) {
let adapter;
// We have options and options have adapter key
if (options) {
// Pass an adapter as a module name, a function or an instance
if (typeof options == "string" || typeof options == "function" || options.constructor != Object) {
adapter = options;
}
if (options.adapter) {
adapter = options.adapter;
}
}
if (!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;
}
}
export default AdapterLoader;

View File

@@ -5,14 +5,16 @@
const Parse = require('parse/node').Parse; const Parse = require('parse/node').Parse;
var deepcopy = require('deepcopy'); var deepcopy = require('deepcopy');
import PushAdapter from './PushAdapter';
function OneSignalPushAdapter(pushConfig) { export class OneSignalPushAdapter extends PushAdapter {
constructor(pushConfig = {}) {
super(pushConfig);
this.https = require('https'); this.https = require('https');
this.validPushTypes = ['ios', 'android']; this.validPushTypes = ['ios', 'android'];
this.senderMap = {}; this.senderMap = {};
pushConfig = pushConfig || {};
this.OneSignalConfig = {}; this.OneSignalConfig = {};
this.OneSignalConfig['appId'] = pushConfig['oneSignalAppId']; this.OneSignalConfig['appId'] = pushConfig['oneSignalAppId'];
this.OneSignalConfig['apiKey'] = pushConfig['oneSignalApiKey']; this.OneSignalConfig['apiKey'] = pushConfig['oneSignalApiKey'];
@@ -21,17 +23,9 @@ function OneSignalPushAdapter(pushConfig) {
this.senderMap['android'] = this.sendToGCM.bind(this); this.senderMap['android'] = this.sendToGCM.bind(this);
} }
/** send(data, installations) {
* Get an array of valid push types.
* @returns {Array} An array of valid push types
*/
OneSignalPushAdapter.prototype.getValidPushTypes = function() {
return this.validPushTypes;
}
OneSignalPushAdapter.prototype.send = function(data, installations) {
console.log("Sending notification to "+installations.length+" devices.") console.log("Sending notification to "+installations.length+" devices.")
let deviceMap = classifyInstallation(installations, this.validPushTypes); let deviceMap = PushAdapter.classifyInstallation(installations, this.validPushTypes);
let sendPromises = []; let sendPromises = [];
for (let pushType in deviceMap) { for (let pushType in deviceMap) {
@@ -49,7 +43,7 @@ OneSignalPushAdapter.prototype.send = function(data, installations) {
return Parse.Promise.when(sendPromises); return Parse.Promise.when(sendPromises);
} }
OneSignalPushAdapter.prototype.sendToAPNS = function(data,tokens) { sendToAPNS(data,tokens) {
data= deepcopy(data['data']); data= deepcopy(data['data']);
@@ -110,7 +104,7 @@ OneSignalPushAdapter.prototype.sendToAPNS = function(data,tokens) {
return promise; return promise;
} }
OneSignalPushAdapter.prototype.sendToGCM = function(data,tokens) { sendToGCM(data,tokens) {
data= deepcopy(data['data']); data= deepcopy(data['data']);
var post = {}; var post = {};
@@ -161,8 +155,7 @@ OneSignalPushAdapter.prototype.sendToGCM = function(data,tokens) {
return promise; return promise;
} }
sendToOneSignal(data, cb) {
OneSignalPushAdapter.prototype.sendToOneSignal = function(data, cb) {
let headers = { let headers = {
"Content-Type": "application/json", "Content-Type": "application/json",
"Authorization": "Basic "+this.OneSignalConfig['apiKey'] "Authorization": "Basic "+this.OneSignalConfig['apiKey']
@@ -195,36 +188,8 @@ OneSignalPushAdapter.prototype.sendToOneSignal = function(data, cb) {
request.write(JSON.stringify(data)) request.write(JSON.stringify(data))
request.end(); request.end();
} }
/**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
*/
function 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
});
} else {
console.log('Unknown push type from installation %j', installation);
}
}
return deviceMap;
} }
if (typeof process !== 'undefined' && process.env.NODE_ENV === 'test') {
OneSignalPushAdapter.classifyInstallation = classifyInstallation; export default OneSignalPushAdapter;
}
module.exports = OneSignalPushAdapter; module.exports = OneSignalPushAdapter;

View File

@@ -6,13 +6,15 @@
const Parse = require('parse/node').Parse; 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';
function ParsePushAdapter(pushConfig) { export class ParsePushAdapter extends PushAdapter {
constructor(pushConfig = {}) {
super(pushConfig);
this.validPushTypes = ['ios', 'android']; this.validPushTypes = ['ios', 'android'];
this.senderMap = {}; this.senderMap = {};
pushConfig = pushConfig || {};
let pushTypes = Object.keys(pushConfig); let pushTypes = Object.keys(pushConfig);
for (let pushType of pushTypes) { for (let pushType of pushTypes) {
if (this.validPushTypes.indexOf(pushType) < 0) { if (this.validPushTypes.indexOf(pushType) < 0) {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED, throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
@@ -29,16 +31,8 @@ function ParsePushAdapter(pushConfig) {
} }
} }
/** send(data, installations) {
* Get an array of valid push types. let deviceMap = PushAdapter.classifyInstallation(installations, this.validPushTypes);
* @returns {Array} An array of valid push types
*/
ParsePushAdapter.prototype.getValidPushTypes = function() {
return this.validPushTypes;
}
ParsePushAdapter.prototype.send = function(data, installations) {
let deviceMap = classifyInstallation(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];
@@ -51,38 +45,7 @@ ParsePushAdapter.prototype.send = function(data, installations) {
} }
return Parse.Promise.when(sendPromises); return Parse.Promise.when(sendPromises);
} }
/**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
*/
function 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;
} }
if (typeof process !== 'undefined' && process.env.NODE_ENV === 'test') { export default ParsePushAdapter;
ParsePushAdapter.classifyInstallation = classifyInstallation;
}
module.exports = ParsePushAdapter; module.exports = ParsePushAdapter;

View File

@@ -8,10 +8,47 @@
// //
// Default is ParsePushAdapter, which uses GCM for // Default is ParsePushAdapter, which uses GCM for
// android push and APNS for ios push. // android push and APNS for ios push.
export class PushAdapter { export class PushAdapter {
send(devices, installations) { } send(devices, installations) { }
getValidPushTypes() { } /**
* Get an array of valid push types.
* @returns {Array} An array of valid push types
*/
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,65 @@
/*
AdaptableController.js
AdaptableController is the base class for all controllers
that support adapter,
The super class takes care of creating the right instance for the adapter
based on the parameters passed
*/
// _adapter is private, use Symbol
var _adapter = Symbol();
export class AdaptableController {
constructor(adapter) {
this.adapter = adapter;
}
set adapter(adapter) {
this.validateAdapter(adapter);
this[_adapter] = adapter;
}
get adapter() {
return this[_adapter];
}
expectedAdapterType() {
throw new Error("Subclasses should implement expectedAdapterType()");
}
validateAdapter(adapter) {
if (!adapter) {
throw new Error(this.constructor.name+" requires an adapter");
}
let Type = this.expectedAdapterType();
// Allow skipping for testing
if (!Type) {
return;
}
// Makes sure the prototype matches
let mismatches = Object.getOwnPropertyNames(Type.prototype).reduce( (obj, key) => {
const adapterType = typeof adapter[key];
const expectedType = typeof Type.prototype[key];
if (adapterType !== expectedType) {
obj[key] = {
expected: expectedType,
actual: adapterType
}
}
return obj;
}, {});
if (Object.keys(mismatches).length > 0) {
console.error(adapter, mismatches);
throw new Error("Adapter prototype don't match expected prototype");
}
}
}
export default AdaptableController;

View File

@@ -1,20 +1,19 @@
// FilesController.js // FilesController.js
import { Parse } from 'parse/node'; import { Parse } from 'parse/node';
import { randomHexString } from '../cryptoUtils'; import { randomHexString } from '../cryptoUtils';
import AdaptableController from './AdaptableController';
import { FilesAdapter } from '../Adapters/Files/FilesAdapter';
export class FilesController { export class FilesController extends AdaptableController {
constructor(filesAdapter) {
this._filesAdapter = filesAdapter;
}
getFileData(config, filename) { getFileData(config, filename) {
return this._filesAdapter.getFileData(config, filename); return this.adapter.getFileData(config, filename);
} }
createFile(config, filename, data) { createFile(config, filename, data) {
filename = randomHexString(32) + '_' + filename; filename = randomHexString(32) + '_' + filename;
var location = this._filesAdapter.getFileLocation(config, filename); var location = this.adapter.getFileLocation(config, filename);
return this._filesAdapter.createFile(config, filename, data).then(() => { return this.adapter.createFile(config, filename, data).then(() => {
return Promise.resolve({ return Promise.resolve({
url: location, url: location,
name: filename name: filename
@@ -23,7 +22,7 @@ export class FilesController {
} }
deleteFile(config, filename) { deleteFile(config, filename) {
return this._filesAdapter.deleteFile(config, filename); return this.adapter.deleteFile(config, filename);
} }
/** /**
@@ -49,11 +48,15 @@ export class FilesController {
if (filename.indexOf('tfss-') === 0) { if (filename.indexOf('tfss-') === 0) {
fileObject['url'] = 'http://files.parsetfss.com/' + config.fileKey + '/' + encodeURIComponent(filename); fileObject['url'] = 'http://files.parsetfss.com/' + config.fileKey + '/' + encodeURIComponent(filename);
} else { } else {
fileObject['url'] = this._filesAdapter.getFileLocation(config, filename); fileObject['url'] = this.adapter.getFileLocation(config, filename);
}
} }
} }
} }
} }
expectedAdapterType() {
return FilesAdapter;
}
}
export default FilesController; export default FilesController;

View File

@@ -1,5 +1,7 @@
import { Parse } from 'parse/node'; import { Parse } from 'parse/node';
import PromiseRouter from '../PromiseRouter'; import PromiseRouter from '../PromiseRouter';
import AdaptableController from './AdaptableController';
import { LoggerAdapter } from '../Adapters/Logger/LoggerAdapter';
const Promise = Parse.Promise; const Promise = Parse.Promise;
const MILLISECONDS_IN_A_DAY = 24 * 60 * 60 * 1000; const MILLISECONDS_IN_A_DAY = 24 * 60 * 60 * 1000;
@@ -14,11 +16,7 @@ export const LogOrder = {
ASCENDING: 'asc' ASCENDING: 'asc'
} }
export class LoggerController { export class LoggerController extends AdaptableController {
constructor(loggerAdapter, loggerOptions) {
this._loggerAdapter = loggerAdapter;
}
// check that date input is valid // check that date input is valid
static validDateTime(date) { static validDateTime(date) {
@@ -59,7 +57,7 @@ export class LoggerController {
// order (optional) Direction of results returned, either “asc” or “desc”. Defaults to “desc”. // order (optional) Direction of results returned, either “asc” or “desc”. Defaults to “desc”.
// size (optional) Number of rows returned by search. Defaults to 10 // size (optional) Number of rows returned by search. Defaults to 10
getLogs(options= {}) { getLogs(options= {}) {
if (!this._loggerAdapter) { if (!this.adapter) {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED, throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
'Logger adapter is not availabe'); 'Logger adapter is not availabe');
} }
@@ -68,11 +66,15 @@ export class LoggerController {
options = LoggerController.parseOptions(options); options = LoggerController.parseOptions(options);
this._loggerAdapter.query(options, (result) => { this.adapter.query(options, (result) => {
promise.resolve(result); promise.resolve(result);
}); });
return promise; return promise;
} }
expectedAdapterType() {
return LoggerAdapter;
}
} }
export default LoggerController; export default LoggerController;

View File

@@ -1,12 +1,10 @@
import { Parse } from 'parse/node'; import { Parse } from 'parse/node';
import PromiseRouter from '../PromiseRouter'; import PromiseRouter from '../PromiseRouter';
import rest from '../rest'; import rest from '../rest';
import AdaptableController from './AdaptableController';
import { PushAdapter } from '../Adapters/Push/PushAdapter';
export class PushController { export class PushController extends AdaptableController {
constructor(pushAdapter) {
this._pushAdapter = pushAdapter;
};
/** /**
* Check whether the deviceType parameter in qury condition is valid or not. * Check whether the deviceType parameter in qury condition is valid or not.
@@ -28,7 +26,7 @@ export class PushController {
deviceType + ' is not supported push type.'); deviceType + ' is not supported push type.');
} }
} }
}; }
/** /**
* Check whether the api call has master key or not. * Check whether the api call has master key or not.
@@ -42,13 +40,12 @@ export class PushController {
} }
sendPush(body = {}, where = {}, config, auth) { sendPush(body = {}, where = {}, config, auth) {
var pushAdapter = this._pushAdapter; var pushAdapter = this.adapter;
if (!pushAdapter) { if (!pushAdapter) {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED, throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
'Push adapter is not available'); 'Push adapter is not available');
} }
PushController.validateMasterKey(auth); PushController.validateMasterKey(auth);
PushController.validatePushType(where, pushAdapter.getValidPushTypes()); PushController.validatePushType(where, pushAdapter.getValidPushTypes());
// Replace the expiration_time with a valid Unix epoch milliseconds time // Replace the expiration_time with a valid Unix epoch milliseconds time
body['expiration_time'] = PushController.getExpirationTime(body); body['expiration_time'] = PushController.getExpirationTime(body);
@@ -57,7 +54,8 @@ export class PushController {
rest.find(config, auth, '_Installation', where).then(function(response) { rest.find(config, auth, '_Installation', where).then(function(response) {
return pushAdapter.send(body, response.results); return pushAdapter.send(body, response.results);
}); });
}; }
/** /**
* Get expiration time from the request body. * Get expiration time from the request body.
* @param {Object} request A request object * @param {Object} request A request object
@@ -84,7 +82,11 @@ export class PushController {
body['expiration_time'] + ' is not valid time.'); body['expiration_time'] + ' is not valid time.');
} }
return expirationTime.valueOf(); return expirationTime.valueOf();
}; }
expectedAdapterType() {
return PushAdapter;
}
}; };
export default PushController; export default PushController;

View File

@@ -33,6 +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 { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter'; import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter';
import { LoggerController } from './Controllers/LoggerController'; import { LoggerController } from './Controllers/LoggerController';
@@ -67,9 +68,9 @@ function ParseServer({
appId, appId,
masterKey, masterKey,
databaseAdapter, databaseAdapter,
filesAdapter = new GridStoreAdapter(), filesAdapter,
push, push,
loggerAdapter = new FileLoggerAdapter(), loggerAdapter,
databaseURI, databaseURI,
cloud, cloud,
collectionPrefix = '', collectionPrefix = '',
@@ -91,15 +92,6 @@ function ParseServer({
DatabaseAdapter.setAdapter(databaseAdapter); DatabaseAdapter.setAdapter(databaseAdapter);
} }
// Make push adapter
let pushConfig = push;
let pushAdapter;
if (pushConfig && pushConfig.adapter) {
pushAdapter = pushConfig.adapter;
} else if (pushConfig) {
pushAdapter = new ParsePushAdapter(pushConfig)
}
if (databaseURI) { if (databaseURI) {
DatabaseAdapter.setAppDatabaseURI(appId, databaseURI); DatabaseAdapter.setAppDatabaseURI(appId, databaseURI);
} }
@@ -114,9 +106,16 @@ function ParseServer({
} }
} }
const filesController = new FilesController(filesAdapter);
const pushController = new PushController(pushAdapter); const filesControllerAdapter = AdapterLoader.load(filesAdapter, GridStoreAdapter);
const loggerController = new LoggerController(loggerAdapter); const pushControllerAdapter = AdapterLoader.load(push, ParsePushAdapter);
const loggerControllerAdapter = AdapterLoader.load(loggerAdapter, FileLoggerAdapter);
// We pass the options and the base class for the adatper,
// Note that passing an instance would work too
const filesController = new FilesController(filesControllerAdapter);
const pushController = new PushController(pushControllerAdapter);
const loggerController = new LoggerController(loggerControllerAdapter);
cache.apps[appId] = { cache.apps[appId] = {
masterKey: masterKey, masterKey: masterKey,