Source: mcs.js

Source: mcs.js

/**
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
 * Oracle Mobile Cloud Enterprise JavaScript SDK for Cordova, Release: 18.2.1.0, E95445-01
*/





(function(_module, _exports, _define, _window, _global, _self, _this){

var cxa;
var exportMCS = null, s = (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
 */
/**
 * @classdesc Class that holds an analytics event.
 * This class accessible by [mcs.AnalyticsEvent]{@link mcs.AnalyticsEvent} method.
 * @class
 * @global
 */
var AnalyticsEvent =
/**
 * @classdesc Class that holds an analytics event.
 * This class constructor accessible by [mcs.AnalyticsEvent]{@link mcs.AnalyticsEvent} method.
 * @param {string} name - event name
 * @constructor
 * @class
 * @global
 */
function AnalyticsEvent(name) {
  _classCallCheck(this, AnalyticsEvent);

  /**
   * The name of the event.
   * @type {String}
   * @name AnalyticsEvent#name
   */
  this.name = null;
  /**
   * The timestamp of the event. The system will populate with the current time by default.
   * @type {String}
   * @name AnalyticsEvent#timestamp
   */
  this.timestamp = new Date().toISOString();
  /**
   * The ID of the current session.
   * @type {String}
   * @name AnalyticsEvent#sessionID
   */
  this.sessionID = null;
  /**
   * Custom caller specifiable properties as key/value strings.
   * @type {Object}
   * @name AnalyticsEvent#properties
   */
  this.properties = {};
  this.name = name;
};

exports.AnalyticsEvent = AnalyticsEvent;


},{}],2:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.Analytics = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      */


var _analyticsEvent = require("./analytics-event");

var _logger = require("../logger");

var _networkResponse = require("../responses/network-response");

var _types = require("../types");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
 * @classdesc Class that provides analytics capabilities. Callers should use
 * MobileBackend's [analytics]{@link MobileBackend#analytics} property.
 * @class
 * @global
 * @hideconstructor
 */
var Analytics = function () {
    function Analytics(backend, platform, utils) {
        _classCallCheck(this, Analytics);

        this.backend = backend;
        this.platform = platform;
        this.utils = utils;
        this.events = [];
        this.logger = new _logger.Logger('Analytics');
    }
    /**
     * Returns session ID for current session.
     * @returns {String}
     * @function
     * @name Analytics#getSessionId
     */


    _createClass(Analytics, [{
        key: "getSessionId",
        value: function getSessionId() {
            return this.sessionId;
        }
        /**
         * Starts a new session. If one is in progress, then a new session will not be created.
         * @function
         * @name Analytics#startSession
         */

    }, {
        key: "startSession",
        value: function startSession() {
            if (!this.sessionId) {
                this.sessionId = this.utils.uuid();
                this.logNamedEvent('sessionStart').type = 'system';
            }
        }
        /**
         * Ends a session if one exists.
         * @return {Promise<Undefined|NetworkResponse>}
         * @function
         * @name Analytics#endSession
         */

    }, {
        key: "endSession",
        value: function endSession() {
            if (!!this.sessionId) {
                this.logNamedEvent("sessionEnd").type = "system";
                this.logger.debug('Deactivate a default session');
                return this.flush().then(flushSuccess.bind(this));
            } else {
                return Promise.reject(new _networkResponse.NetworkResponse(500, 'Session ID is null'));
            }
            function flushSuccess(response) {
                this.sessionId = undefined;
                return response;
            }
        }
        /**
         * Creates a new analytics event with the given name.
         * @param name {String} The name of the event.
         * @returns {AnalyticsEvent} The [AnalyticsEvent]{@link AnalyticsEvent} instance that was logged.
         * @function
         * @name Analytics#logNamedEvent
         */

    }, {
        key: "logNamedEvent",
        value: function logNamedEvent(name) {
            var event = new _analyticsEvent.AnalyticsEvent(name);
            this.logEvent(event);
            return event;
        }
        /**
         * Writes out an analytics event. It will implicitly call startSession(),
         * which will add a new event to the list of events for Oracle Mobile Cloud Enterprise to consume
         * @param event {AnalyticsEvent} The event to log.
         * @example event: "GettingStartedJSEvent"
         * @returns {AnalyticsEvent} The [AnalyticsEvent]{@link AnalyticsEvent} instance that was logged.
         * @function
         * @name Analytics#logEvent
         */

    }, {
        key: "logEvent",
        value: function logEvent(event) {
            if (this.events.length === 0) {
                this.events[0] = this._createContextEvent();
            }
            this.startSession();
            this.events[this.events.length] = event;
            event.sessionID = this.sessionId;
            return event;
        }
        /**
         * Uploads all events to the service if the device is online or caches them locally until the device goes online, at
         * which point they will be uploaded. If a session is in progress it will end.
         * @return {Promise<NetworkResponse>}
         * @function
         * @name Analytics#flush
         */

    }, {
        key: "flush",
        value: function flush() {
            for (var i = 0; i < this.events.length; i++) {
                var enableLocation = true; //this.config.analytics ? this.config.analytics.location : true;
                if (enableLocation && this.events[i].name == "context") {
                    var gpsLocation = this.platform.getGPSLocation();
                    if (gpsLocation != null && gpsLocation.latitude != null) {
                        this.events[i].properties.latitude = gpsLocation.latitude;
                    }
                    if (gpsLocation != null && gpsLocation.longitude != null) {
                        this.events[i].properties.longitude = gpsLocation.longitude;
                    }
                }
            }
            var eventsString = JSON.stringify(this.events);
            var headers = this.backend.getHttpHeaders();
            headers.add(_types.HEADERS.CONTENT_TYPE, _types.CONTENT_TYPES.APPLICATION_JSON);
            return this.platform.invokeService({
                method: _types.HTTP_METHODS.POST,
                url: this.backend.getPlatformUrl("analytics/events"),
                headers: headers,
                data: eventsString,
                module: _types.MODULE_NAMES.MCS_ANALYTICS
            }).then(invokeServiceSuccess.bind(this), invokeServiceError.bind(this));
            function invokeServiceSuccess(response) {
                this.logger.debug('Analytics events flushed.');
                this.events = [];
                return response;
            }
            function invokeServiceError(response) {
                this.logger.error('Failed to flush analytics events.');
                return Promise.reject(response);
            }
        }
    }, {
        key: "_createContextEvent",
        value: function _createContextEvent() {
            var contextEvent = new _analyticsEvent.AnalyticsEvent("context");
            contextEvent.type = "system";
            contextEvent.sessionID = this.sessionId;
            contextEvent.properties.timezone = "" + new Date().getTimezoneOffset() * 60;
            var deviceInformation = this.platform.getDeviceInformation();
            contextEvent.properties.model = deviceInformation.model;
            contextEvent.properties.manufacturer = deviceInformation.manufacturer;
            contextEvent.properties.osName = deviceInformation.osName;
            contextEvent.properties.osVersion = deviceInformation.osVersion;
            contextEvent.properties.osBuild = deviceInformation.osBuild;
            contextEvent.properties.carrier = deviceInformation.carrier;
            return contextEvent;
        }
    }, {
        key: "_getEvents",
        value: function _getEvents() {
            return this.events;
        }
    }]);

    return Analytics;
}();

exports.Analytics = Analytics;


},{"../logger":13,"../responses/network-response":21,"../types":41,"./analytics-event":1}],3:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.Authorization = exports.AuthenticationResponse = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _logger = require("../logger");

var _networkResponse = require("../responses/network-response");

var _types = require("../types");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


/**
 * Authentication response
 * @private
 */
var AuthenticationResponse = exports.AuthenticationResponse = function (_NetworkResponse) {
    _inherits(AuthenticationResponse, _NetworkResponse);

    function AuthenticationResponse(response, accessToken) {
        _classCallCheck(this, AuthenticationResponse);

        var _this = _possibleConstructorReturn(this, (AuthenticationResponse.__proto__ || Object.getPrototypeOf(AuthenticationResponse)).call(this, response.statusCode, response.data, response.headers));

        _this.accessToken = accessToken;
        return _this;
    }

    return AuthenticationResponse;
}(_networkResponse.NetworkResponse);
/**
 * @class
 * @global
 * @classdesc Class used to authorize a mobile user against Oracle Mobile Cloud Enterprise.
 * Callers should use MobileBackend's [authorization]{@link MobileBackend#authorization} property.
 * @abstract
 * @hideconstructor
 */


var Authorization = function () {
    function Authorization(utils, platform) {
        _classCallCheck(this, Authorization);

        this.utils = utils;
        this.platform = platform;
        this._onAuthenticationCallbacks = [];
        this.logger = new _logger.Logger('Authorization');
    }
    /**
     * Returns true if a user has been authorized, false otherwise. A user can be authorized by calling authenticate() or authenticateAnonymous().
     * @type {Boolean}
     * @name Authorization#isAuthorized
     */


    _createClass(Authorization, [{
        key: "getAccessToken",

        /**
         * Returns the current access token from user credentials.
         * @returns {String} current access token from user credentials.
         * @function
         * @name Authorization#getAccessToken
         */
        value: function getAccessToken() {
            return this._accessToken;
        }
    }, {
        key: "_setAccessToken",
        value: function _setAccessToken(token) {
            this._accessToken = token;
        }
        /**
         * Get is anonymous
         * @return {boolean}
         * @private
         */

    }, {
        key: "_getIsAnonymous",
        value: function _getIsAnonymous() {
            return this._isAnonymous;
        }
        /**
         * Get is authorized
         * @return {boolean}
         * @private
         */

    }, {
        key: "_getIsAuthorized",
        value: function _getIsAuthorized() {
            return this._isAuthorized;
        }
        /**
         * Get anonymous access token
         * @return {string}
         * @private
         */

    }, {
        key: "_getAnonymousAccessToken",
        value: function _getAnonymousAccessToken() {
            return this._anonymousAccessToken;
        }
        /**
         * Authenticate anonymous
         * @param {IDictionary<Headers, string>} headers
         * @param {string} url
         * @param {HttpMethods} method
         * @param {boolean} withCredentials
         * @param data
         * @return {Promise<AuthenticationResponse>}
         * @private
         */

    }, {
        key: "_authenticateAnonymousInvoke",
        value: function _authenticateAnonymousInvoke(headers, url, method, withCredentials, data) {
            this.logout();
            headers = this._getHeaders(headers);
            headers = this._getAnonymousAuthorizationHeaders(headers);
            return this.platform.invokeService({
                url: url,
                method: method,
                headers: headers,
                withCredentials: withCredentials,
                data: data,
                module: _types.MODULE_NAMES.AUTHORIZATION
            }).then(function (response) {
                return new AuthenticationResponse(response, null);
            }).then(this._anonymousTokenResponseConverter.bind(this)).catch(invokeServiceError.bind(this)).then(this._authenticateAnonymousSuccess.bind(this));
            function invokeServiceError(response) {
                this.logger.error("Login failed with error: " + response.statusCode);
                this._clearState();
                return Promise.reject(response);
            }
        }
    }, {
        key: "_getHeaders",

        /**
         * Get headers
         * @param headers
         * @return {any}
         * @private
         */
        value: function _getHeaders(headers) {
            return headers;
        }
        /**
         * Authenticate anonymous success callback.
         * @param {AuthenticationResponse} response
         * @return {INetworkResponse}
         * @private
         */

    }, {
        key: "_authenticateAnonymousSuccess",
        value: function _authenticateAnonymousSuccess(response) {
            this.logger.info("User logged in anonymously " + response.statusCode);
            this._setAuthenticateAnonymousSuccess(response.accessToken);
            return response;
        }
    }, {
        key: "_setAuthenticateAnonymousSuccess",

        /**
         * Set authentication anonymous success callback.
         * @param {string} token
         * @private
         */
        value: function _setAuthenticateAnonymousSuccess(token) {
            this._isAnonymous = true;
            this._isAuthorized = true;
            this._anonymousAccessToken = token;
            for (var i = 0; i < this._onAuthenticationCallbacks.length; i++) {
                this._onAuthenticationCallbacks[i](token);
            }
        }
        /**
         * Authenticate error callback
         * @param {INetworkResponse} response
         * @private
         */

    }, {
        key: "_authenticateError",
        value: function _authenticateError(response) {
            this.logger.error("Login failed with error: " + response.statusCode);
            this._clearState();
        }
    }, {
        key: "_clearState",

        /**
         * Clear state after logout
         * @private
         */
        value: function _clearState() {
            this._accessToken = null;
            this._isAnonymous = false;
            this._anonymousAccessToken = null;
            this._isAuthorized = false;
        }
    }, {
        key: "onAuthentication",

        /**
         * The authentication callback.
         * This callback called when authentication happen.
         * @callback Authorization~OnAuthenticationCallback
         * @param token {String} The authentication token received from server.
         */
        /**
         * Subscribe for on authentication event
         * @param {Authorization~OnAuthenticationCallback} callback The callback that will be called when authentication happen.
         * @function
         * @name Authorization#onAuthentication
         */
        value: function onAuthentication(callback) {
            this._onAuthenticationCallbacks.push(callback);
        }
    }, {
        key: "isAuthorized",
        get: function get() {
            return this._isAuthorized;
        }
    }]);

    return Authorization;
}();

exports.Authorization = Authorization;


},{"../logger":13,"../responses/network-response":21,"../types":41}],4:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.BasicAuthorization = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _authorization = require("./authorization");

var _logger = require("../logger");

var _networkResponse = require("../responses/network-response");

var _mcsAuthorization = require("./mcs-authorization");

var _types = require("../types");

var _dictionary = require("../dictionary");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


/**
 * @class
 * @global
 * @classdesc Class used to authorize a mobile user against Oracle Mobile Cloud Enterprise with the Basic Authentication security schema. Callers should use
 * MobileBackend's [authorization]{@link MobileBackend#authorization} property.
 * @extends MCSAuthorization
 * @hideconstructor
 */
var BasicAuthorization = function (_MCSAuthorization) {
    _inherits(BasicAuthorization, _MCSAuthorization);

    function BasicAuthorization(config, backend, utils, platform) {
        _classCallCheck(this, BasicAuthorization);

        var _this = _possibleConstructorReturn(this, (BasicAuthorization.__proto__ || Object.getPrototypeOf(BasicAuthorization)).call(this, backend, utils, platform));

        _this._logger = new _logger.Logger('BasicAuthorization');
        _this._backendId = utils.validateConfiguration(config.mobileBackendId);
        _this._anonymousToken = utils.validateConfiguration(config.anonymousKey);
        return _this;
    }
    /**
     * Returns the username of the current authorized user if any, null otherwise.
     * @return {String}
     * @function
     * @name BasicAuthorization#getAuthorizedUserName
     */


    _createClass(BasicAuthorization, [{
        key: "getAuthorizedUserName",
        value: function getAuthorizedUserName() {
            return this._authorizedUserName;
        }
    }, {
        key: "authenticate",

        /**
         * Authenticates a user with the given credentials against the service. The user remains logged in until logout() is called.
         * @param username {String} The username of the credentials.
         * @param password {String} The password of the credentials.
         * @return {Promise<NetworkResponse>}
         * @function
         * @name BasicAuthorization#authenticate
         */
        value: function authenticate() {
            var username = arguments.length <= 0 ? undefined : arguments[0];
            var password = arguments.length <= 1 ? undefined : arguments[1];
            this.logout();
            if (!username || !password) {
                this._logger.error('Wrong username or password parameter');
                return Promise.reject(new _networkResponse.NetworkResponse(400, 'Bad Request'));
            }
            var authorizationToken = "Basic " + this.utils.encodeBase64(username + ":" + password);
            var headers = new _dictionary.Dictionary([]);
            headers.add(_types.HEADERS.AUTHORIZATION, authorizationToken);
            headers.add(_types.HEADERS.ORACLE_MOBILE_BACKEND_ID, this._backendId);
            return this.platform.invokeService({
                url: this.backend.getPlatformUrl("users/login"),
                method: _types.HTTP_METHODS.GET,
                headers: headers,
                module: _types.MODULE_NAMES.AUTHORIZATION
            }).then(invokeServiceSuccess.bind(this)).catch(invokeServiceError.bind(this));
            function invokeServiceSuccess(response) {
                this._authenticateSuccess(response, authorizationToken);
                this._authorizedUserName = username;
                return response;
            }
            function invokeServiceError(response) {
                this._authenticateError(response);
                return Promise.reject(response);
            }
        }
        /**
         * Authenticates an anonymous user against the service. The user remains logged in until logout() is called.
         * @return {Promise<NetworkResponse>}
         * @function
         * @name BasicAuthorization#authenticateAnonymous
         */

    }, {
        key: "authenticateAnonymous",
        value: function authenticateAnonymous() {
            return this._authenticateAnonymousInvoke(new _dictionary.Dictionary([]), this.backend.getPlatformUrl("users/login"), _types.HTTP_METHODS.GET);
        }
        /**
         * Get anonymous authorization headers
         * @param {IDictionary<Headers, string>} headers
         * @return {IDictionary<Headers, string>}
         * @private
         */

    }, {
        key: "_getAnonymousAuthorizationHeaders",
        value: function _getAnonymousAuthorizationHeaders(headers) {
            headers.add(_types.HEADERS.AUTHORIZATION, 'Basic ' + this._anonymousToken);
            headers.add(_types.HEADERS.ORACLE_MOBILE_BACKEND_ID, this._backendId);
            return headers;
        }
        /**
         * Checks to see if the authorization token is null, undefined, NaN,an empty string (""), 0, or false.
         * @returns {Boolean}
         * @function
         * @name BasicAuthorization#isTokenValid
         */

    }, {
        key: "isTokenValid",
        value: function isTokenValid() {
            if (this.getAccessToken() !== null && typeof this.getAccessToken() == 'string') {
                this._logger.info("Authorization token is not null or empty");
                return true;
            } else if (this.getAccessToken() == null && typeof this.getAccessToken() !== 'string') {
                this._logger.info("Authorization token is null and/or empty");
                return false;
            }
        }
    }, {
        key: "refreshToken",

        /**
         * For BasicAuth, there is no need to call this function, because the token never expires.
         * This function only exists here because it inherits from the Authorization object, which is also used for other types of authentication in which the token can expire.
         * @return {Promise<NetworkResponse>}
         * @function
         * @name BasicAuthorization#refreshToken
         */
        value: function refreshToken() {
            if (!this._getIsAuthorized() && !this.isTokenValid()) {
                return Promise.reject(new _networkResponse.NetworkResponse(401, "Please use the authenticate with username/password combination or authenticateAnonymous function before using refreshToken."));
            } else if (this._getIsAuthorized() && this.isTokenValid()) {
                this._logger.debug("Authenticated token is valid, you do not need to refresh.");
                return Promise.resolve(new _networkResponse.NetworkResponse(200, this.getAccessToken()));
            }
        }
    }, {
        key: "logout",

        /**
         * Logs out the current user and clears credentials and tokens.
         * @function
         * @name BasicAuthorization#logout
         */
        value: function logout() {
            this._clearState();
        }
    }, {
        key: "_anonymousTokenResponseConverter",
        value: function _anonymousTokenResponseConverter(response) {
            return new _authorization.AuthenticationResponse(response, 'Basic ' + this._anonymousToken);
        }
    }, {
        key: "_getHttpHeaders",
        value: function _getHttpHeaders(headers) {
            if (this.getAccessToken() !== null && typeof this.getAccessToken() == "string") {
                headers.add(_types.HEADERS.AUTHORIZATION, this.getAccessToken());
            }
            headers.add(_types.HEADERS.ORACLE_MOBILE_BACKEND_ID, this._backendId);
            return headers;
        }
    }, {
        key: "_getAnonymousHttpHeaders",
        value: function _getAnonymousHttpHeaders(headers) {
            if (this._getAnonymousAccessToken() && typeof this._getAnonymousAccessToken() == "string") {
                headers.add(_types.HEADERS.AUTHORIZATION, this._getAnonymousAccessToken());
            }
            headers.add(_types.HEADERS.ORACLE_MOBILE_BACKEND_ID, this._backendId);
            return headers;
        }
    }, {
        key: "_clearState",
        value: function _clearState() {
            _get(BasicAuthorization.prototype.__proto__ || Object.getPrototypeOf(BasicAuthorization.prototype), "_clearState", this).call(this);
            this._authorizedUserName = null;
        }
    }]);

    return BasicAuthorization;
}(_mcsAuthorization.MCSAuthorization);

exports.BasicAuthorization = BasicAuthorization;


},{"../dictionary":12,"../logger":13,"../responses/network-response":21,"../types":41,"./authorization":3,"./mcs-authorization":7}],5:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.ExternalTokenExchangeAuthorization = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _authorization = require("./authorization");

var _logger = require("../logger");

var _networkResponse = require("../responses/network-response");

var _mcsAuthorization = require("./mcs-authorization");

var _types = require("../types");

var _dictionary = require("../dictionary");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


/**
 * @class
 * @global
 * @classdesc Class used to authorize a mobile user against Oracle Mobile Cloud Enterprise with External Token Authentication security schema. Callers should use
 * MobileBackend's [authorization]{@link MobileBackend#authorization} property.
 * @extends MCSAuthorization
 * @hideconstructor
 */
var ExternalTokenExchangeAuthorization = function (_MCSAuthorization) {
    _inherits(ExternalTokenExchangeAuthorization, _MCSAuthorization);

    function ExternalTokenExchangeAuthorization(config, backend, utils, platform) {
        _classCallCheck(this, ExternalTokenExchangeAuthorization);

        var _this = _possibleConstructorReturn(this, (ExternalTokenExchangeAuthorization.__proto__ || Object.getPrototypeOf(ExternalTokenExchangeAuthorization)).call(this, backend, utils, platform));

        _this.logger = new _logger.Logger('ExternalTokenExchangeAuthorization');
        _this._backendId = utils.validateConfiguration(config.mobileBackendId);
        _this._anonymousToken = utils.validateConfiguration(config.anonymousKey);
        return _this;
    }
    /**
     * Authenticates a user with the given external token. The user remains logged in until logout() is called.
     * @param token {String} The third party authentication token.
     * @return {Promise<NetworkResponse>}
     * @function
     * @name ExternalTokenExchangeAuthorization#authenticate
     */


    _createClass(ExternalTokenExchangeAuthorization, [{
        key: "authenticate",
        value: function authenticate() {
            var token = arguments.length <= 0 ? undefined : arguments[0];
            this.logout();
            this._redToken = token;
            if (!token) {
                this.logger.error('Wrong token parameter');
                return Promise.reject(new _networkResponse.NetworkResponse(400, 'Bad Request'));
            }
            var authorizationToken = "Bearer " + token;
            var headers = this.backend.getHttpHeaders();
            headers.add(_types.HEADERS.AUTHORIZATION, authorizationToken);
            headers.add(_types.HEADERS.ORACLE_MOBILE_BACKEND_ID, this._backendId);
            return this.platform.invokeService({
                url: this.backend.getPlatformUrl('sso/exchange-token?format=json'),
                method: _types.HTTP_METHODS.GET,
                headers: headers,
                module: _types.MODULE_NAMES.AUTHORIZATION
            }).then(invokeServiceSuccess.bind(this)).catch(invokeServiceError.bind(this));
            function invokeServiceSuccess(response) {
                this._tokenExpiredTime = Date.now() + response.data.expires_in * 1000;
                this._authenticateSuccess(response, response.data.access_token);
                return new _networkResponse.NetworkResponse(200, response.data);
            }
            function invokeServiceError(response) {
                this._authenticateError(response);
                return Promise.reject(response);
            }
        }
        /**
         * Authenticates an anonymous user against the service. The user remains logged in until logout() is called.
         * @return {Promise<NetworkResponse>}
         * @function
         * @name ExternalTokenExchangeAuthorization#authenticateAnonymous
         */

    }, {
        key: "authenticateAnonymous",
        value: function authenticateAnonymous() {
            return this._authenticateAnonymousInvoke(new _dictionary.Dictionary([]), this.backend.getPlatformUrl("users/login"), _types.HTTP_METHODS.GET);
        }
    }, {
        key: "_getAnonymousAuthorizationHeaders",
        value: function _getAnonymousAuthorizationHeaders(headers) {
            headers.add(_types.HEADERS.AUTHORIZATION, 'Basic ' + this._anonymousToken);
            headers.add(_types.HEADERS.ORACLE_MOBILE_BACKEND_ID, this._backendId);
            return headers;
        }
        /**
         * Checks to see if the OAuth token is null,undefined,NaN,empty string (''),0,false and also checks the timestamp
         * of when the token was first retrieved to see if it was still valid.
         * @returns {Boolean}
         * @function
         * @name ExternalTokenExchangeAuthorization#isTokenValid
         */

    }, {
        key: "isTokenValid",
        value: function isTokenValid() {
            if (this.getAccessToken() || this._getAnonymousAccessToken()) {
                this.logger.debug('Token is not null or empty');
                var currentTime = Date.now();
                if (currentTime >= this._tokenExpiredTime) {
                    this.logger.info('Token has expired or user has not been authenticate with the service');
                    return false;
                } else {
                    this.logger.debug('Token is still valid');
                    return true;
                }
            } else {
                return false;
            }
        }
        /**
         * Logs out the current user and clears credentials and tokens and cookies.
         * @function
         * @name ExternalTokenExchangeAuthorization#logout
         */

    }, {
        key: "logout",
        value: function logout() {
            this._redToken = null;
            this._clearState();
        }
        /**
         * Refreshes the authentication token if it has expired. The authentication scheme should support refresh.
         * @return {Promise<String>}
         * @function
         * @name ExternalTokenExchangeAuthorization#refreshToken
         */

    }, {
        key: "refreshToken",
        value: function refreshToken() {
            var boolean = this.isTokenValid();
            if (boolean !== false) {
                if (this._accessToken == null && this._isAnonymous) {
                    this.logger.error('Anonymous token is valid, you do not need to refresh.');
                    return Promise.resolve(this._anonymousAccessToken);
                }
                if (!this._anonymousAccessToken && !this._isAnonymous) {
                    this.logger.error('Authenticated token is valid, you do not need to refresh.');
                    return Promise.resolve(this._accessToken);
                }
            } else {
                this.logger.error('Token is not valid and has expired, refreshing token from service.', this._redToken);
                return this.authenticate(this._redToken).then(function () {
                    return this._accessToken;
                });
            }
        }
    }, {
        key: "_getHttpHeaders",
        value: function _getHttpHeaders(headers) {
            if (this.getAccessToken() !== null && typeof this.getAccessToken() == 'string') {
                headers.add(_types.HEADERS.AUTHORIZATION, 'Bearer ' + this.getAccessToken());
            }
            return headers;
        }
    }, {
        key: "_getAnonymousHttpHeaders",
        value: function _getAnonymousHttpHeaders(headers) {
            if (this._getAnonymousAccessToken() && typeof this._getAnonymousAccessToken() == 'string') {
                headers.add(_types.HEADERS.AUTHORIZATION, 'Bearer ' + this._getAnonymousAccessToken());
            }
            return headers;
        }
    }, {
        key: "_anonymousTokenResponseConverter",
        value: function _anonymousTokenResponseConverter(response) {
            return new _authorization.AuthenticationResponse(response, response.data.access_token);
        }
    }]);

    return ExternalTokenExchangeAuthorization;
}(_mcsAuthorization.MCSAuthorization);

exports.ExternalTokenExchangeAuthorization = ExternalTokenExchangeAuthorization;


},{"../dictionary":12,"../logger":13,"../responses/network-response":21,"../types":41,"./authorization":3,"./mcs-authorization":7}],6:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.FacebookAuthorization = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _authorization = require("./authorization");

var _logger = require("../logger");

var _networkResponse = require("../responses/network-response");

var _mcsAuthorization = require("./mcs-authorization");

var _dictionary = require("../dictionary");

var _types = require("../types");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


/**
 * @classdesc Class used to authorize a user against Facebook and use the OAuth token from Facebook
 * to authenicate against Oracle Mobile Cloud Enterprise. Callers should use
 * MobileBackend's [authorization]{@link MobileBackend#authorization} property.
 * @class
 * @global
 * @extends MCSAuthorization
 * @hideconstructor
 */
var FacebookAuthorization = function (_MCSAuthorization) {
    _inherits(FacebookAuthorization, _MCSAuthorization);

    function FacebookAuthorization(config, backend, utils, platform) {
        _classCallCheck(this, FacebookAuthorization);

        var _this = _possibleConstructorReturn(this, (FacebookAuthorization.__proto__ || Object.getPrototypeOf(FacebookAuthorization)).call(this, backend, utils, platform));

        _this.expiredTime = null;
        _this.logger = new _logger.Logger('FacebookAuthorization');
        _this._backendId = utils.validateConfiguration(config.mobileBackendId);
        _this._anonymousToken = utils.validateConfiguration(config.anonymousKey);
        _this._facebookAppId = utils.validateConfiguration(config.appId);
        _this._scopes = utils.validateConfiguration(config.scopes);
        return _this;
    }
    /**
     * Returns the Facebook Application Id token for the current backend.
     * @return {String}
     * @function
     * @name FacebookAuthorization#getFacebookAppId
     */


    _createClass(FacebookAuthorization, [{
        key: "getFacebookAppId",
        value: function getFacebookAppId() {
            return this._facebookAppId;
        }
        /**
         * Authenticates a user against Facebook. The user remains logged in until logout() is called.
         * In the Facebook Developer console you must define the domain that the application will use.
         * in the Facebook Developer UI, When you add a platform for the application, you choose Website and set the site URL to http://localhost/.
         * @return {Promise<NetworkResponse>}
         * @function
         * @name FacebookAuthorization#authenticate
         */

    }, {
        key: "authenticate",
        value: function authenticate() {
            this.logout();
            if (typeof cordova !== 'undefined') {
                var metadata = cordova.require('cordova/plugin_list').metadata;
                if (this.isInAppBrowserInstalled(metadata) !== true) {
                    return Promise.reject(new _networkResponse.NetworkResponse(100, 'Could not find InAppBrowser plugin, use command "cordova plugin add cordova-plugin-inappbrowser"'));
                } else {
                    return this.authenticateInvoke();
                }
            } else {
                return Promise.reject(new _networkResponse.NetworkResponse(400, 'Bad Request - This method require Cordova framework'));
            }
        }
    }, {
        key: "authenticateInvoke",
        value: function authenticateInvoke() {
            return new Promise(invoke.bind(this)).then(invokeSuccess.bind(this)).catch(invokeError.bind(this));
            function invoke(resolve, reject) {
                var _this2 = this;

                var clientId = this.getFacebookAppId();
                var redirect_uri = 'http://localhost/callback';
                var flowUrl = 'https://www.facebook.com/dialog/oauth?client_id=' + clientId + '&redirect_uri=' + redirect_uri + '&response_type=token&scope=' + this._scopes ? this.scopes : 'public_profile';
                var browserRef = window.open(flowUrl, '_blank', 'location=no,clearsessioncache=yes,clearcache=yes');
                browserRef.show();
                this.logger.info('Opening InAppBrowser to url: ' + flowUrl);
                browserRef.addEventListener('loadstart', function (event) {
                    if (event.url.indexOf(redirect_uri) === 0) {
                        browserRef.close();
                        var callbackResponse = event.url.split('#')[1];
                        var responseParameters = callbackResponse.split('&');
                        var social_token = {};
                        for (var i = 0; i < responseParameters.length; i++) {
                            social_token[responseParameters[i].split('=')[0]] = responseParameters[i].split('=')[1];
                        }
                        if (social_token.access_token) {
                            _this2.expiredTime = Date.now() + social_token.expires_in * 1000;
                            resolve(new _networkResponse.NetworkResponse(200, social_token));
                        } else {
                            if (event.url.indexOf('error_code=100') !== 0 && !_this2.isAuthorized) {
                                reject(new _networkResponse.NetworkResponse(100, 'Cannot authenticate via a web browser'));
                            }
                        }
                    }
                });
                browserRef.addEventListener('exit', function () {
                    if (!_this2._getIsAuthorized()) {
                        reject(new _networkResponse.NetworkResponse(100, 'Cannot authenticate via a web browser'));
                    }
                });
            }
            function invokeSuccess(response) {
                this._authenticateSuccess(response, response.data.access_token);
                this.expiredTime = Date.now() + response.data.expires_in * 1000;
                return response;
            }
            function invokeError(response) {
                this._authenticateError(response);
                return Promise.reject(response);
            }
        }
        /**
         * Authenticates an anonymous user against the service. The user remains logged in until logout() is called.
         * @return {Promise<NetworkResponse>}
         * @function
         * @name FacebookAuthorization#authenticateAnonymous
         */

    }, {
        key: "authenticateAnonymous",
        value: function authenticateAnonymous() {
            return this._authenticateAnonymousInvoke(new _dictionary.Dictionary([]), this.backend.getPlatformUrl("users/login"), _types.HTTP_METHODS.GET);
        }
    }, {
        key: "_getAnonymousAuthorizationHeaders",
        value: function _getAnonymousAuthorizationHeaders(headers) {
            headers.add(_types.HEADERS.AUTHORIZATION, 'Basic ' + this._anonymousToken);
            headers.add(_types.HEADERS.ORACLE_MOBILE_BACKEND_ID, this._backendId);
            return headers;
        }
    }, {
        key: "_anonymousTokenResponseConverter",
        value: function _anonymousTokenResponseConverter(response) {
            return new _authorization.AuthenticationResponse(response, 'Basic ' + this._anonymousToken);
        }
        /**
         * Checks to see if the OAuth token is null, undefined, NaN, AN empty string (''), 0, or false. It also checks the timestamp
         * for when the token was first retrieved to see if it was still valid.
         * @returns {Boolean}
         * @function
         * @name FacebookAuthorization#isTokenValid
         */

    }, {
        key: "isTokenValid",
        value: function isTokenValid() {
            if (this.getAccessToken() || this._getAnonymousAccessToken()) {
                this.logger.debug('Token is not null or empty');
                var currentTime = Date.now();
                if (currentTime >= this.expiredTime) {
                    this.logger.info('Token has expired or user has not been authenticate with the service/Facebook');
                    return false;
                } else {
                    this.logger.debug('Token is still valid');
                    return true;
                }
            } else {
                return false;
            }
        }
        /**
         * Refreshes the authentication token if it has expired from Facebook. The authentication scheme should support refresh.
         * @return {Promise<NetworkResponse>}
         * @function
         * @name FacebookAuthorization#refreshToken
         */

    }, {
        key: "refreshToken",
        value: function refreshToken() {
            var isTokenValid = this.isTokenValid();
            if (isTokenValid && this.getAccessToken() == null && this._getIsAnonymous()) {
                return Promise.resolve(new _networkResponse.NetworkResponse(200, this._getAnonymousAccessToken()));
            } else if (isTokenValid && this._getAnonymousAccessToken() && !this._getIsAnonymous()) {
                return Promise.resolve(new _networkResponse.NetworkResponse(200, this._getAnonymousAccessToken()));
            } else {
                this.logger.error('Token is not valid and has expired, refreshing token from Facebook.');
                return this.authenticate();
            }
        }
    }, {
        key: "logout",

        /**
         * Logs out the current user and clears credentials and tokens.
         * @function
         * @name FacebookAuthorization#logout
         */
        value: function logout() {
            this._clearState();
            this.expiredTime = Date.now() * 1000;
        }
    }, {
        key: "_getHttpHeaders",
        value: function _getHttpHeaders(headers) {
            if (this.getAccessToken() != null && typeof this.getAccessToken() == 'string') {
                headers.add(_types.HEADERS.AUTHORIZATION, 'Basic ' + this._anonymousToken);
                headers.add(_types.HEADERS.ORACLE_MOBILE_SOCIAL_ACCESS_TOKEN, this.getAccessToken());
                headers.add(_types.HEADERS.ORACLE_MOBILE_SOCIAL_IDENTITY_PROVIDER, 'facebook');
            }
            headers.add(_types.HEADERS.ORACLE_MOBILE_BACKEND_ID, this._backendId);
            return headers;
        }
    }, {
        key: "_getAnonymousHttpHeaders",
        value: function _getAnonymousHttpHeaders(headers) {
            if (this._getAnonymousAccessToken() && typeof this._getAnonymousAccessToken() == 'string') {
                headers.add(_types.HEADERS.AUTHORIZATION, this._getAnonymousAccessToken());
            }
            headers.add(_types.HEADERS.ORACLE_MOBILE_BACKEND_ID, this._backendId);
            return headers;
        }
        /**
         * Checks to see if the correct plugin is installed into the application.
         * @return {boolean}
         * @private
         */

    }, {
        key: "isInAppBrowserInstalled",
        value: function isInAppBrowserInstalled(metadata) {
            var inAppBrowserNames = ['cordova-plugin-inappbrowser', 'org.apache.cordova.inappbrowser'];
            return inAppBrowserNames.some(function (name) {
                return metadata.hasOwnProperty(name);
            });
        }
    }]);

    return FacebookAuthorization;
}(_mcsAuthorization.MCSAuthorization);

exports.FacebookAuthorization = FacebookAuthorization;


},{"../dictionary":12,"../logger":13,"../responses/network-response":21,"../types":41,"./authorization":3,"./mcs-authorization":7}],7:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.MCSAuthorization = exports.AuthenticationResponse = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _logger = require("../logger");

var _user = require("./user");

var _networkResponse = require("../responses/network-response");

var _authorization = require("./authorization");

var _types = require("../types");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


var AuthenticationResponse = exports.AuthenticationResponse = function (_NetworkResponse) {
    _inherits(AuthenticationResponse, _NetworkResponse);

    function AuthenticationResponse(response, anonymousAccessToken) {
        _classCallCheck(this, AuthenticationResponse);

        var _this = _possibleConstructorReturn(this, (AuthenticationResponse.__proto__ || Object.getPrototypeOf(AuthenticationResponse)).call(this, response.statusCode, response.data, response.headers));

        _this.accessToken = anonymousAccessToken;
        return _this;
    }

    return AuthenticationResponse;
}(_networkResponse.NetworkResponse);
/**
 * @class
 * @global
 * @classdesc Class used to authorize a mobile user against Oracle Mobile Cloud Enterprise.
 * Callers should use MobileBackend's [authorization]{@link MobileBackend#authorization} property.
 * @abstract
 * @extends Authorization
 * @hideconstructor
 */


var MCSAuthorization = function (_Authorization) {
    _inherits(MCSAuthorization, _Authorization);

    function MCSAuthorization(backend, utils, platform) {
        _classCallCheck(this, MCSAuthorization);

        var _this2 = _possibleConstructorReturn(this, (MCSAuthorization.__proto__ || Object.getPrototypeOf(MCSAuthorization)).call(this, utils, platform));

        _this2.backend = backend;
        _this2.utils = utils;
        _this2.platform = platform;
        _this2.logger = new _logger.Logger('MCSAuthorization');
        return _this2;
    }
    /**
     * Object returned from getCurrentUser().
     * @typedef MCSAuthorization~CurrentUserData
     * @property statusCode {Number} Any HTTP status code returned from the server, if available.
     * @property user {User} The user resource returned by the service.
     */
    /**
     * Returns the user resource associated with the logged in user.
     * @return {Promise<MCSAuthorization~CurrentUserData|NetworkResponse>}
     * @function
     * @name MCSAuthorization#getCurrentUser
     * @example <caption>Example usage of mcs.mobileBackend.authorization.getCurrentUser()</caption>
     * mcs.mobileBackend.authorization.getCurrentUser().then(
     * function(data){
     * },
     * function(exception){
     * });
     * @example // Response example
     * {
     *     "id": "c9a5fdc5-737d-4e93-b292-d258ba334149",
     *     "username": "DwainDRob",
     *     "email": "js_sdk@mcs.com",
     *     "firstName": "Mobile",
     *     "lastName": "User",
     *     "properties": {}
     * }
     */


    _createClass(MCSAuthorization, [{
        key: "getCurrentUser",
        value: function getCurrentUser() {
            return this.platform.invokeService({
                method: 'GET',
                url: this.backend.getPlatformUrl("users/~"),
                headers: this.backend.getHttpHeaders(),
                module: _types.MODULE_NAMES.AUTHORIZATION
            }).then(invokeServiceSuccess.bind(this), invokeServiceError.bind(this));
            function invokeServiceSuccess(response) {
                var user = !!response.data ? new _user.User(response.data) : null;
                return { statusCode: response.statusCode, user: user };
            }
            function invokeServiceError(response) {
                return Promise.reject(response);
            }
        }
    }, {
        key: "_authenticateSuccess",

        /**
         * Authenticate success callback
         * @param {INetworkResponse} response
         * @param {string} accessToken
         * @private
         */
        value: function _authenticateSuccess(response, accessToken) {
            this.logger.info("User logged in " + response.statusCode);
            this._isAnonymous = false;
            this._isAuthorized = true;
            this._accessToken = accessToken;
            for (var i = 0; i < this._onAuthenticationCallbacks.length; i++) {
                this._onAuthenticationCallbacks[i](accessToken);
            }
        }
    }, {
        key: "getAuthorizedUserName",

        /**
         * Returns the username of the current authorized user if any, null otherwise.
         * @function
         * @name MCSAuthorization#getAuthorizedUserName
         * @return {String}
         */
        value: function getAuthorizedUserName() {
            throw Error('THis method is not supported by this authorization method.');
        }
    }]);

    return MCSAuthorization;
}(_authorization.Authorization);

exports.MCSAuthorization = MCSAuthorization;


},{"../logger":13,"../responses/network-response":21,"../types":41,"./authorization":3,"./user":9}],8:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.OAuthAuthorization = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _authorization = require("./authorization");

var _logger = require("../logger");

var _networkResponse = require("../responses/network-response");

var _mcsAuthorization = require("./mcs-authorization");

var _types = require("../types");

var _dictionary = require("../dictionary");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Created by ddrobins on 7/28/15.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


/**
 * @class
 * @global
 * @classdesc Class used to authorize a mobile user against Oracle Mobile Cloud Enterprise. Callers should use
 * MobileBackend's [authorization]{@link MobileBackend#authorization} property.
 * @extends MCSAuthorization
 * @hideconstructor
 */
var OAuthAuthorization = function (_MCSAuthorization) {
    _inherits(OAuthAuthorization, _MCSAuthorization);

    function OAuthAuthorization(oAuthTokenEndPoint, config, backend, tenantName, utils, platform) {
        _classCallCheck(this, OAuthAuthorization);

        var _this = _possibleConstructorReturn(this, (OAuthAuthorization.__proto__ || Object.getPrototypeOf(OAuthAuthorization)).call(this, backend, utils, platform));

        _this.oAuthTokenEndPoint = oAuthTokenEndPoint;
        _this.config = config;
        _this.logger = new _logger.Logger('OAuthAuthorization');
        _this._clientId = utils.validateConfiguration(config.clientId);
        _this._clientSecret = utils.validateConfiguration(config.clientSecret);
        _this._tenantName = utils.validateConfiguration(tenantName);
        return _this;
    }
    /**
     * Returns the username of the current authorized user if any, null otherwise.
     * @return {String}
     * @function
     * @name OAuthAuthorization#getAuthorizedUserName
     */


    _createClass(OAuthAuthorization, [{
        key: "getAuthorizedUserName",
        value: function getAuthorizedUserName() {
            return this._authorizedUserName;
        }
    }, {
        key: "getClientId",

        /**
         * Returns the client ID for the current backend.
         * @return {String}
         * @function
         * @name OAuthAuthorization#getClientId
         */
        value: function getClientId() {
            return this._clientId;
        }
    }, {
        key: "getTenantName",

        /**
         * Returns the tenant name for the current backend.
         * @private
         */
        value: function getTenantName() {
            return this._tenantName;
        }
    }, {
        key: "getClientSecret",

        /**
         * Returns the client secret for the current backend.
         * @return {String}
         * @function
         * @name OAuthAuthorization#getClientSecret
         */
        value: function getClientSecret() {
            return this._clientSecret;
        }
    }, {
        key: "authenticate",

        /**
         * Authenticates a user with the given credentials against the service.
         * The user remains logged in until logout() is called.
         * @param username {String} The username of the credentials.
         * @param password {String} The password of the credentials.
         * @return {Promise<NetworkResponse>}
         * @function
         * @name OAuthAuthorization#authenticate
         */
        value: function authenticate() {
            var username = arguments.length <= 0 ? undefined : arguments[0];
            var password = arguments.length <= 1 ? undefined : arguments[1];
            this.logout();
            if (!username || !password) {
                this.logger.error("Wrong username or password parameter");
                return Promise.reject(new _networkResponse.NetworkResponse(400, 'Bad Request'));
            }
            var authorizationToken = "Basic " + this.utils.encodeBase64(this._clientId + ":" + this._clientSecret);
            var scope = this.config.scope || this.backend._baseUrl + 'urn:opc:resource:consumer::all';
            var requestBody = OAuthAuthorization.urlEncodeComponent(username, password, scope);
            var headers = new _dictionary.Dictionary([]);
            headers.add(_types.HEADERS.CONTENT_TYPE, _types.CONTENT_TYPES.X_WWW_FORM_FORM_URLENCODED);
            headers.add(_types.HEADERS.AUTHORIZATION, authorizationToken);
            if (typeof this._tenantName !== 'undefined') {
                headers.add(_types.HEADERS.X_RESOURCE_IDENTITY_DOMAIN_NAME, this._tenantName);
            }
            return this.platform.invokeService({
                url: this.getOAuthTokenUrl(),
                method: _types.HTTP_METHODS.POST,
                headers: headers,
                data: requestBody,
                withCredentials: false,
                module: _types.MODULE_NAMES.AUTHORIZATION
            }).then(invokeServiceSuccess.bind(this)).catch(invokeServiceError.bind(this));
            function invokeServiceSuccess(response) {
                this._authenticateSuccess(response, response.data.access_token);
                this._authorizedUserName = username;
                return response;
            }
            function invokeServiceError(response) {
                this._authenticateError(response);
                return Promise.reject(response);
            }
        }
    }, {
        key: "authenticateAnonymous",

        /**
         * Authenticates an anonymous user against the service. The user remains logged in until logout() is called.
         * @return {Promise<NetworkResponse>}
         * @function
         * @name OAuthAuthorization#authenticateAnonymous
         */
        value: function authenticateAnonymous() {
            var headers = new _dictionary.Dictionary([]);
            headers.add(_types.HEADERS.CONTENT_TYPE, _types.CONTENT_TYPES.X_WWW_FORM_FORM_URLENCODED);
            if (typeof this._tenantName !== 'undefined') {
                headers.add(_types.HEADERS.X_USER_IDENTITY_DOMAIN_NAME, this._tenantName);
            }
            var scope = this.config.scope || this.backend._baseUrl + 'urn:opc:resource:consumer::all';
            var body = 'grant_type=client_credentials&scope=' + encodeURIComponent(scope);
            return this._authenticateAnonymousInvoke(headers, this.getOAuthTokenUrl(), _types.HTTP_METHODS.POST, false, body).then(invokeServiceSuccess.bind(this));
            function invokeServiceSuccess(response) {
                this._tokenExpiredTime = Date.now() + response.data.expires_in * 1000;
                return response;
            }
        }
    }, {
        key: "_getAnonymousAuthorizationHeaders",
        value: function _getAnonymousAuthorizationHeaders(headers) {
            headers.add(_types.HEADERS.AUTHORIZATION, 'Basic ' + this.utils.encodeBase64(this.getClientId() + ":" + this.getClientSecret()));
            return headers;
        }
        /**
         * Checks to see if the OAuth token is null, undefined, NaN,an empty string (""), 0,or false. It also checks the timestamp
         * for when the token was first retrieved to see if it was still valid.
         * @returns {Boolean}
         * @function
         * @name OAuthAuthorization#isTokenValid
         */

    }, {
        key: "isTokenValid",
        value: function isTokenValid() {
            if (this.getAccessToken() || this._getAnonymousAccessToken()) {
                this.logger.debug("Token is not null or empty");
                var currentTime = Date.now();
                if (currentTime >= this._tokenExpiredTime) {
                    this.logger.info("Token has expired");
                    return false;
                } else {
                    this.logger.debug("Token is still valid");
                    return true;
                }
            } else {
                return false;
            }
        }
    }, {
        key: "logout",

        /**
         * Logs out the current user and clears credentials and tokens.
         * @function
         * @name OAuthAuthorization#logout
         */
        value: function logout() {
            this._clearState();
        }
    }, {
        key: "refreshToken",

        /**
         * For OAuth, the SDK can not refresh because it does not persist client credentials.
         * This function only exists here because it inherits from the Authorization object, which is also used for other types of authentication in which the token can expire.
         * @return {Promise<NetworkResponse>}
         * @function
         * @name OAuthAuthorization#refreshToken
         */
        value: function refreshToken() {
            var isTokenValid = this.isTokenValid();
            if (isTokenValid && !this.getAccessToken() && this._getIsAnonymous()) {
                return Promise.resolve(new _networkResponse.NetworkResponse(200, this._getAnonymousAccessToken()));
            } else if (isTokenValid && !this._getAnonymousAccessToken() && !this._getIsAnonymous()) {
                return Promise.resolve(new _networkResponse.NetworkResponse(200, this._getAnonymousAccessToken()));
            } else {
                this.logger.error("Token has expired or user has not been authenticate with the service.");
                return Promise.resolve(new _networkResponse.NetworkResponse(401, "Please use the authenticate with username/password combination or authenticateAnonymous function before using refreshToken."));
            }
        }
    }, {
        key: "_anonymousTokenResponseConverter",
        value: function _anonymousTokenResponseConverter(response) {
            return new _authorization.AuthenticationResponse(response, response.data.access_token);
        }
    }, {
        key: "_clearState",
        value: function _clearState() {
            _get(OAuthAuthorization.prototype.__proto__ || Object.getPrototypeOf(OAuthAuthorization.prototype), "_clearState", this).call(this);
            this._authorizedUserName = null;
            this._tokenExpiredTime = Date.now() * 1000;
        }
    }, {
        key: "_getHttpHeaders",
        value: function _getHttpHeaders(headers) {
            if (this.getAccessToken() !== null && typeof this.getAccessToken() == "string") {
                headers.add(_types.HEADERS.AUTHORIZATION, "Bearer " + this.getAccessToken());
            }
            return headers;
        }
    }, {
        key: "_getAnonymousHttpHeaders",
        value: function _getAnonymousHttpHeaders(headers) {
            if (this._getAnonymousAccessToken() && typeof this._getAnonymousAccessToken() == "string") {
                headers.add(_types.HEADERS.AUTHORIZATION, "Bearer " + this._getAnonymousAccessToken());
            }
            return headers;
        }
    }, {
        key: "getOAuthTokenUrl",

        /**
         * Constructs a full URL, including the prefix, for the OAuth token endpoint.
         * @returns {String} The full URL for the OAuth token endpoint.
         * @function
         * @name OAuthAuthorization#getOAuthTokenUrl
         */
        value: function getOAuthTokenUrl() {
            var tokenUri = this.utils.validateConfiguration(this.oAuthTokenEndPoint);
            if (!this.utils.strEndsWith(tokenUri, "/")) {
                tokenUri += "/";
            }
            return tokenUri + 'oauth2/v1/token';
        }
    }], [{
        key: "urlEncodeComponent",
        value: function urlEncodeComponent(username, password, scope) {
            if (username.indexOf("@") > -1) {
                username = encodeURIComponent(username).replace(/%20/g, '+');
            } else {
                username = encodeURIComponent(username).replace(/%5B/g, '[').replace(/%5D/g, ']');
            }
            if (password.indexOf("&") > -1) {
                password = encodeURIComponent(password).replace(/%20/g, '+');
            } else {
                password = encodeURIComponent(password).replace(/%5B/g, '[').replace(/%5D/g, ']');
            }
            scope = encodeURIComponent(scope);
            return 'grant_type=password&username=' + username + '&password=' + password + '&scope=' + scope;
        }
    }]);

    return OAuthAuthorization;
}(_mcsAuthorization.MCSAuthorization);

exports.OAuthAuthorization = OAuthAuthorization;


},{"../dictionary":12,"../logger":13,"../responses/network-response":21,"../types":41,"./authorization":3,"./mcs-authorization":7}],9:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
 * Created by ddrobins on 7/28/15.
 */
/**
 * @classdesc Class that enables you to retrieve information on the current user and manage its properties. Callers should use
 * Authorization's [getCurrentUser()]{@link MobileBackend#authorization.getCurrentUser} property.
 * @class
 * @global
 */
var User = function () {
  function User(user) {
    _classCallCheck(this, User);

    this._id = user.id;
    this._userName = user.username;
    this._firstName = user._firstName;
    this._lastName = user._lastName;
    this._email = user.email;
  }
  /**
   * Returns the current user's name.
   *
   * @function
   * @name User#getId
   * @return {string} Current user's name
   */


  _createClass(User, [{
    key: "getId",
    value: function getId() {
      return this._id;
    }
    /**
     * Returns first name for current user.
     * @function
     * @name User#getFirstName
     * @return {string}
     */

  }, {
    key: "getFirstName",
    value: function getFirstName() {
      return this._firstName;
    }
  }, {
    key: "getLastName",

    /**
     * Returns last name for current user.
     * @function
     * @name User#getLastName
     * @return {string}
     */
    value: function getLastName() {
      return this._lastName;
    }
  }, {
    key: "getEmail",

    /**
     * Returns email address for current user.
     * @function
     * @name User#getEmail
     * @return {string}
     */
    value: function getEmail() {
      return this._email;
    }
  }]);

  return User;
}();

exports.User = User;


},{}],10:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.CustomCode = undefined;

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Created by ddrobins on 7/28/15.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      */


var _networkResponse = require("../responses/network-response");

var _types = require("../types");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @classdesc This class provides a way to invoke custom API endpoints for the
 * currently active mobile backend. Callers should use
 * MobileBackend's [customCode]{@link MobileBackend#customCode} property.
 * @class
 * @global
 * @hideconstructor
 */
var CustomCode = function () {
    function CustomCode(backend, utils, platform) {
        _classCallCheck(this, CustomCode);

        this.backend = backend;
        this.utils = utils;
        this.platform = platform;
    }

    _createClass(CustomCode, [{
        key: "checkParameters",
        value: function checkParameters(params, comparison) {
            return this.isJSON(params) && params && params != undefined && (typeof params === "undefined" ? "undefined" : _typeof(params)) == comparison;
        }
    }, {
        key: "isJSON",
        value: function isJSON(params) {
            if (typeof params != 'string') params = JSON.stringify(params);
            try {
                JSON.parse(params);
                return true;
            } catch (e) {
                return false;
            }
        }
        /**
         * Invoke custom code JSON request.
         * Allows the user to call custom Code defined on the UI and assigned to the backend defined by the user
         * This custom endpoint should return data only in JSON format.
         * @function
         * @name CustomCode#invokeCustomCodeJSONRequest
         * @param path {String} The path of the endpoint without platform prefix.
         * @param method {String} HTTP method that is invoked, this method accepts: GET, POST, PUT, DELETE, PATCH.
         * @param data {Object} Data that is inserted into the call on the server for POST and PUT methods. Only accepts a JSON object and/or JavaScript array.
         * @return {Promise<NetworkResponse>}
         * @example <caption>These methods must be defined in the custom API for these methods to work.<br/>
         * Example usage of CustomCode.invokeCustomCodeJSONRequest()</caption>
         * mcs.mobileBackend.customCode
         * .invokeCustomCodeJSONRequest('TaskApi1/tasks/100', 'GET', null)
         * .then(invokeSuccess, invokeError);
            * function invokeSuccess(response) {
         *  console.log(response.data);// returns object in JSON format
         * }
         * function invokeError(response) {
         *  console.error(response);
         * }
         */

    }, {
        key: "invokeCustomCodeJSONRequest",
        value: function invokeCustomCodeJSONRequest(path, method, data) {
            if (method in CustomCode.httpMethods) {
                if (method === CustomCode.httpMethods.DELETE && data) {
                    return Promise.reject(new _networkResponse.NetworkResponse(500, 'DELETE method content body'));
                }
                var headers = this.backend.getHttpHeaders();
                headers.add(_types.HEADERS.CONTENT_TYPE, _types.CONTENT_TYPES.APPLICATION_JSON);
                var customData = data ? JSON.stringify(data) : null;
                return this.platform.invokeService({
                    method: method,
                    url: this.backend.getCustomCodeUrl(path),
                    headers: headers,
                    data: customData,
                    module: _types.MODULE_NAMES.CUSTOM_CODE
                });
            } else {
                return Promise.reject(new _networkResponse.NetworkResponse(501, 'Method Not Implemented'));
            }
        }
    }]);

    return CustomCode;
}();
/**
 * @ignore
 * @type {{GET: string, POST: string, PUT: string, DELETE: string}}
 */


CustomCode.httpMethods = { GET: 'GET', POST: 'POST', PUT: 'PUT', DELETE: 'DELETE' };
exports.CustomCode = CustomCode;


},{"../responses/network-response":21,"../types":41}],11:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.Diagnostics = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      */


var _logger = require("../logger");

var _dictionary = require("../dictionary");

var _types = require("../types");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @classdesc Class that provides diagnostics capabilities. Callers should use
 * MobileBackend's [diagnostics]{@link MobileBackend#diagnostics} property.
 * @class
 * @global
 * @hideconstructor
 */
var Diagnostics = function () {
    function Diagnostics(platform, utils) {
        _classCallCheck(this, Diagnostics);

        this.platform = platform;
        this.logger = new _logger.Logger('Diagnostics');
        this._sessionId = utils.uuid();
    }

    _createClass(Diagnostics, [{
        key: "_getHttpHeaders",
        value: function _getHttpHeaders() {
            var headers = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new _dictionary.Dictionary([]);

            headers.add(_types.HEADERS.ORACLE_MOBILE_DIAGNOSTIC_SESSION_ID, this.getSessionId());
            headers.add(_types.HEADERS.ORACLE_MOBILE_DEVICE_ID, this.platform.getDeviceId());
            headers.add(_types.HEADERS.ORACLE_MOBILE_CLIENT_REQUEST_TIME, new Date().toISOString());
            return headers;
        }
        /**
         * Returns the session ID or process ID of the Diagnostics event.
         * @function
         * @name Diagnostics#getSessionId
         * @return {String} process id for the Diagnostics session.
         */

    }, {
        key: "getSessionId",
        value: function getSessionId() {
            return this._sessionId;
        }
    }]);

    return Diagnostics;
}();

exports.Diagnostics = Diagnostics;


},{"../dictionary":12,"../logger":13,"../types":41}],12:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
 *
 * @author Yuri Panshin
 */
var Dictionary = exports.Dictionary = function () {
    function Dictionary(init) {
        _classCallCheck(this, Dictionary);

        this._keys = [];
        this._values = [];
        for (var x = 0; x < init.length; x++) {
            this[init[x].key.toString()] = init[x].value;
            this._keys.push(init[x].key);
            this._values.push(init[x].value);
        }
    }

    _createClass(Dictionary, [{
        key: "add",
        value: function add(key, value) {
            this[key.toString()] = value;
            this._keys.push(key);
            this._values.push(value);
        }
    }, {
        key: "remove",
        value: function remove(key) {
            var index = this._keys.indexOf(key, 0);
            this._keys.splice(index, 1);
            this._values.splice(index, 1);
            delete this[key.toString()];
        }
    }, {
        key: "keys",
        value: function keys() {
            return this._keys;
        }
    }, {
        key: "values",
        value: function values() {
            return this._values;
        }
    }, {
        key: "containsKey",
        value: function containsKey(key) {
            return typeof this[key.toString()] !== "undefined";
        }
    }, {
        key: "toLookup",
        value: function toLookup() {
            return this;
        }
    }]);

    return Dictionary;
}();


},{}],13:[function(require,module,exports){
'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
 * @ignore
 */
var Logger = exports.Logger = function () {
    function Logger(module) {
        _classCallCheck(this, Logger);

        this.module = module;
    }

    _createClass(Logger, [{
        key: 'debug',
        value: function debug() {
            for (var _len = arguments.length, params = Array(_len), _key = 0; _key < _len; _key++) {
                params[_key] = arguments[_key];
            }

            this.log(Logger.LOG_LEVEL.DEBUG, params);
        }
    }, {
        key: 'error',
        value: function error() {
            for (var _len2 = arguments.length, params = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
                params[_key2] = arguments[_key2];
            }

            this.log(Logger.LOG_LEVEL.ERROR, params);
        }
    }, {
        key: 'info',
        value: function info() {
            for (var _len3 = arguments.length, params = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
                params[_key3] = arguments[_key3];
            }

            this.log(Logger.LOG_LEVEL.INFO, params);
        }
    }, {
        key: 'warn',
        value: function warn() {
            for (var _len4 = arguments.length, params = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
                params[_key4] = arguments[_key4];
            }

            this.log(Logger.LOG_LEVEL.WARN, params);
        }
    }, {
        key: 'log',
        value: function log(level, params) {
            if (Logger.logLevel >= level) {
                params.unshift('[mcs.' + this.module + ']');
                var method = void 0;
                switch (Logger.logLevel) {
                    case Logger.LOG_LEVEL.ERROR:
                        method = console.error;
                        break;
                    case Logger.LOG_LEVEL.WARN:
                        method = console.warn;
                        break;
                    case Logger.LOG_LEVEL.INFO:
                        method = console.info;
                        break;
                    case Logger.LOG_LEVEL.DEBUG:
                        method = console.debug;
                        break;
                }
                if (Logger.historyEnabled) {
                    Logger.history.push(Object.assign({}, params, { level: level }));
                    if (Logger.historySize <= Logger.history.length) {
                        Logger.history.shift();
                    }
                }
                method.apply(console, params);
            }
        }
    }]);

    return Logger;
}();

Logger.LOG_LEVEL = {
    NONE: 0,
    ERROR: 1,
    WARN: 2,
    INFO: 3,
    DEBUG: 4
};
Logger.logLevel = Logger.LOG_LEVEL.ERROR;
Logger.historyEnabled = false;
Logger.historySize = 100;
Logger.history = [];


},{}],14:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.MCS = undefined;

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @author Yuri Panshin
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      */


var _utils = require("./utils");

var _logger = require("./logger");

var _analyticsEvent = require("./analytics/analytics-event");

var _storageObject = require("./storage/storage-object");

var _mobileBackend = require("./mobile-backend/mobile-backend");

var _policesMap = require("./polices-map");

var _browserPlatform = require("./platform/browser-platform");

var _cordovaPlatform = require("./platform/cordova-platform");

var _types = require("./types");

var types = _interopRequireWildcard(_types);

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Headers dictionary.
 * The dictionary has lowercase header as a key and a header value as a value.
 * @typedef {Object<string, string>} NetworkResponseHeaders
 */
/**
 * Headers dictionary.
 * The dictionary has header as a key and a header value as a value.
 * @typedef {Object<string, string>} Headers
 */
/**
 * Oracle mobile configuration.
 * @typedef {object} OracleMobileCloudConfig
 * @property [logLevel] {number} Log level for mcs logger. 0 NONE, 1 ERROR, 2 WARN, 3 INFO, 4 DEBUG
 * @property [logHTTP] {boolean} Include http headers and requests in log
 * @property oAuthTokenEndPoint {string} OAuth token endpoint for OAth authentication
 * @property [mobileBackend] {MobileBackendConfig} OAuth token endpoint for OAth authentication
 * @property [sync] {SyncConfig} Configuration for mcs synchronization
 * Can't be combined with syncExpress configuration
 * @property [syncExpress] {SyncExpressConfig} Configuration for sync express
 * Can't be combined with sync configuration
 * @property [disableAnalyticsLocation] {boolean} Disable logging location by legacy analytics
 */
/**
 * Oracle sync configuration.
 * @typedef {object} SyncConfig
 * @property periodicRefreshPolicy {string} Synchronization periodic refresh policy
 * 'PERIODIC_REFRESH_POLICY_REFRESH_NONE'
 * 'PERIODIC_REFRESH_POLICY_REFRESH_EXPIRED_ITEM_ON_STARTUP'
 * 'PERIODIC_REFRESH_POLICY_PERIODICALLY_REFRESH_EXPIRED_ITEMS'
 * @property policies {PolicesConfig[]} Polices per endpoint
 */
/**
 * Oracle sync express configuration.
 * @typedef {object} SyncExpressConfig
 * @property [handler] {string} Handler type to process requests
 * OracleRestHandler - for oracle rest endpoints
 * GenericRequestHandler - for simple rest endpoints, default value
 * @property policies {PolicesConfig[]} Polices per endpoint
 */
/**
 * Oracle sync policies configuration.
 * @typedef {object} PolicesConfig
 * @property path {string} Path for the endpoint
 * @property fetchPolicy {string} Fetch policy for current path
 * 'FETCH_FROM_CACHE_SCHEDULE_REFRESH'
 * 'FETCH_FROM_SERVICE_IF_ONLINE'
 * 'FETCH_FROM_SERVICE'
 */
/**
 * Oracle mobile backend configuration.
 * @typedef {object} MobileBackendConfig
 * @property baseUrl {string} Base url for the backend and analytics
 * @property name {string} Mobile backend name
 * @property authentication {AuthenticationConfig} Backend authorization's configuration
 */
/**
 * Oracle mobile authentication configuration.
 * @typedef {object} AuthenticationConfig
 * @property [type] {string} Authentication default type: basic, oath, facebook, token
 * @property [basic] {BasicAuthConfig} Basic authentication configuration
 * @property [oauth] {OAuthConfig} OAuth authentication configuration
 * @mcs:web
 */
/**
 * Oracle mobile basic authentication configuration.
 * @typedef {object} BasicAuthConfig
 * @property mobileBackendId {string} Mobile backend identifier
 * @property anonymousKey {string} Anonymous key for anonymous authentication
 */
/**
 * Oracle mobile oauth authentication configuration.
 * @typedef {object} OAuthConfig
 * @property clientId {string} OAuth client identifier
 * @property clientSecret {string} OAuth client secret key
 */
/**
 * Oracle mobile facebook authentication configuration.
 * @typedef {object} FacebookAuthConfig
 * @property appId {string} Facebook application identifier
 * @property anonymousKey {string} Anonymous key for anonymous authentication
 * @property mobileBackendId {string} Mobile backend identifier
 * @property scopes {string} Facebook authentication access types:
 * public_profile,user_friends,email,user_location,user_birthday
 * @mcs:cordova
 */
/**
 * Oracle mobile token exchange authentication configuration.
 * @typedef {object} TokenExchangeAuthConfig
 * @property mobileBackendId {string} Mobile backend identifier
 * @property anonymousKey {string} Anonymous key for anonymous authentication
 * @property clientId {string} OAuth client identifier
 * @property clientSecret {string} OAuth client secret key
 * @mcs:cordova
 */
/**
 * MCS module.
 * @global
 * @namespace mcs
 */
var MCS = function () {
    function MCS(cxa, _global) {
        _classCallCheck(this, MCS);

        this.cxa = cxa;
        this._global = _global;
        this._logger = new _logger.Logger('MCS');
        this._utils = new _utils.Utils();
        /**
         * Get list of latest log entries.
         * @return {Array} - last log entries
         * @private
         * @ignore
         */
        this._getLogHistory = function () {
            return _logger.Logger.history;
        };
        /**
         * Represents a mobile backend in Oracle Mobile Cloud Enterprise and provides access to all capabilities of the backend.
         * @name mobileBackend
         * @readonly
         * @type {MobileBackend}
         * @instance
         * @memberOf mcs
         */
        this.mobileBackend = null;
        /**
         * Storage object constructor.
         * Access point to class that represents a storage object resource that can be used to store data.
         * @function
         * @name mcs.StorageObject
         * @memberOf mcs
         * @param storageCollection {StorageCollection}
         * @param [json] {Object} Json storage object representation
         * @returns {StorageObject}
         */
        this.StorageObject = _storageObject.StorageObject;
        /**
         * Log levels enum.
         * @name LOG_LEVEL
         * @enum {number}
         * @memberof mcs
         * @readonly
         * @property {number} NONE 0
         * @property {number} ERROR 1
         * @property {number} WARN 2
         * @property {number} INFO 3
         * @property {number} DEBUG 4
         */
        this.LOG_LEVEL = _logger.Logger.LOG_LEVEL;
        /**
         * Authentication types enum.
         * @name AUTHENTICATION_TYPES
         * @enum {string}
         * @memberof mcs
         * @readonly
         * @instance
         * @property {string} basic 'basic'
         * @property {string} oauth 'oauth'
         * @property {string} facebook 'facebook'
         * @property {string} token 'token'
         */
        this.AUTHENTICATION_TYPES = types.AUTHENTICATION_TYPES;
        /**
         * Analytics event constructor.
         * Creates analytics event.
         * @function
         * @name mcs.AnalyticsEvent
         * @memberOf mcs
         * @param {string} name - event name
         * @type {AnalyticsEvent}
         */
        this.AnalyticsEvent = _analyticsEvent.AnalyticsEvent;
        this._syncExpress = typeof _global.mcs !== 'undefined' ? _global.mcs.sync : null;
    }
    /**
     * Init MCS with configuration
     * @param {IOracleMobileCloudConfig} config - MCS configuration
     * @alias init
     * @memberOf mcs
     */


    _createClass(MCS, [{
        key: "init",
        value: function init(config /*, notificationsCallback?: (data: INotificationData) => void, cxaAnalyticsTrackerParams?: ITrackerParams*/) {
            this._config = Object.assign({
                mcsVersion: '18.2.1.0' // This value replaced by grunt with version from project file
            }, config);
            if (typeof config.logLevel !== 'undefined') {
                _logger.Logger.logLevel = config.logLevel;
            } else {
                _logger.Logger.logLevel = this.LOG_LEVEL.NONE;
            }
            var internalConfig = config;
            this._logger.debug('MCS initialization, version', internalConfig.mcsVersion);
            if (typeof internalConfig.logHistoryEnabled !== 'undefined') {
                _logger.Logger.historyEnabled = internalConfig.logHistoryEnabled;
            }
            if (typeof internalConfig.logHistorySize !== 'undefined') {
                _logger.Logger.historySize = internalConfig.logHistorySize;
            }
            if (typeof internalConfig.mcsGlobal !== 'undefined' && internalConfig.mcsGlobal) {
                this._global.mcs = Object.assign({}, this._global.mcs, this);
            }
            if (!!this._syncExpress) {
                this._initPersistenceConfiguration(config);
            } else if (config.sync || config.syncExpress) {
                this._logger.warn('Sync script was not included on page, switch caching off');
            }
            this._logger.debug(this._utils.isCordova() ? 'Create Cordova platform' : 'Create Browser platform');
            this._platform = this._utils.isCordova() ? new _cordovaPlatform.CordovaPlatform(this._config, this._utils, config.logHTTP) : new _browserPlatform.BrowserPlatform(this._config, this._utils, config.logHTTP);
            if (!!config.mobileBackend) {
                this.mobileBackend = new _mobileBackend.MobileBackend(this._config, this._platform, this._utils, this._syncExpress);
            }
        }
    }, {
        key: "_initPersistenceConfiguration",
        value: function _initPersistenceConfiguration(config) {
            var syncExpress = this._syncExpress;
            syncExpress._setLogLevel(config.logLevel);
            var syncConfig = null;
            if (config.sync && config.syncExpress) {
                throw Error('Configuration contains two types synchronisation, please choose one of those types, switch caching off');
            } else if (config.sync) {
                syncConfig = config.sync;
                syncExpress.options.setModule(syncExpress.McsRequestHandler());
            } else if (config.syncExpress) {
                syncConfig = config.syncExpress;
                var isOracleRestHandler = config.syncExpress.handler && config.syncExpress.handler === 'OracleRestHandler';
                syncExpress.options.setModule(isOracleRestHandler ? syncExpress.OracleRestRequestHandler() : syncExpress.GenericRequestHandler());
            } else {
                this._logger.warn('Missing synchronization configuration, switch caching off');
                syncExpress.options.switchOff();
                return;
            }
            syncExpress.options.switchOff(false);
            var persistenceConfig = {
                default: {
                    conflictResolutionPolicy: 'CLIENT_WINS',
                    expirationPolicy: 'NEVER_EXPIRE',
                    expireAfter: 600,
                    evictionPolicy: 'MANUAL_EVICTION',
                    fetchPolicy: 'FETCH_FROM_SERVICE_IF_ONLINE',
                    updatePolicy: 'QUEUE_IF_OFFLINE',
                    noCache: false
                },
                periodicRefreshInterval: syncConfig.backgroundRefreshPolicy || 120,
                policies: [],
                periodicRefreshPolicy: null
            };
            var mcsPolicies = syncConfig.policies;
            for (var idx in mcsPolicies) {
                if (mcsPolicies.hasOwnProperty(idx)) {
                    var policy = mcsPolicies[idx];
                    if (policy) {
                        persistenceConfig.policies.push(this._getPersistencePolicy(policy));
                    } else {
                        this._logger.error('The ' + policy + 'policy was not found in accepted policies.');
                    }
                }
            }
            syncExpress.options.setPolicies(persistenceConfig);
            syncExpress.options.dbFirst = false;
            syncExpress.options.setMaxSyncAttempts(1);
            syncExpress.options.setAutoRemoveAfterReachMaxAttempts(true);
        }
    }, {
        key: "_getPersistencePolicy",
        value: function _getPersistencePolicy(mcsPolicy) {
            var policy = { path: mcsPolicy.path };
            for (var prop in mcsPolicy) {
                if (mcsPolicy.hasOwnProperty(prop) && prop !== 'path') {
                    var persMap = _policesMap.POLICIES_MAP[prop];
                    if (!persMap) {
                        this._logger.error('The ' + prop + ' policy was not found in accepted policies.');
                    } else if (persMap[mcsPolicy[prop]] === undefined) {
                        this._logger.error('The ' + prop + ' policy value ' + mcsPolicy[prop] + ' was not found in accepted policy values.');
                    } else {
                        policy[persMap.persistencePropertyName] = persMap[mcsPolicy[prop]];
                    }
                }
            }
            return policy;
        }
    }]);

    return MCS;
}();

if (typeof exportMCS !== 'undefined') {
    exportMCS = function exportMCS(_module, _exports, _define, _window, _global, _self, _this, cxa) {
        var glob = void 0;
        if (typeof _window !== "undefined") {
            glob = _window;
        } else if (typeof _global !== "undefined") {
            glob = _global;
        } else if (typeof _self !== "undefined") {
            glob = _self;
        } else {
            glob = _this;
        }
        var mcs = new MCS(cxa, glob);
        if ((typeof _exports === "undefined" ? "undefined" : _typeof(_exports)) === "object" && typeof _module !== "undefined") {
            _module.exports = mcs;
        } else if (typeof _define === "function" && _define.amd) {
            _define([], mcs);
        } else {
            glob.mcs = mcs;
        }
    };
}
exports.MCS = MCS;


},{"./analytics/analytics-event":1,"./logger":13,"./mobile-backend/mobile-backend":15,"./platform/browser-platform":17,"./platform/cordova-platform":18,"./polices-map":20,"./storage/storage-object":24,"./types":41,"./utils":42}],15:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.MobileBackend = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      */


var _logger = require("../logger");

var _diagnostics = require("../diagnostics/diagnostics");

var _customCode = require("../custom-code/custom-code");

var _analytics = require("../analytics/analytics");

var _notifications = require("../notifications/notifications");

var _basicAuthorization = require("../authorization/basic-authorization");

var _oauthAuthorization = require("../authorization/oauth-authorization");

var _facebookAuthorization = require("../authorization/facebook-authorization");

var _externalTokenExchangeAuthorization = require("../authorization/external-token-exchange-authorization");

var _synchronization = require("../sync/synchronization");

var _storage = require("../storage/storage");

var _types = require("../types");

var _dictionary = require("../dictionary");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @classdesc Represents a mobile backend in Oracle Mobile Cloud Enterprise
 * and provides access to all capabilities of the backend.
 * Callers should use [mcs's mobileBackend]{@link mcs#mobileBackend} property...
 * @class
 * @global
 * @hideconstructor
 * @mcs:web
 */
var MobileBackend = function () {
    /**
     * Creates mobile backend object.
     * @protected
     * @param config {IOracleMobileCloudConfigInternal}
     * @param platform {IPlatform}
     * @param utils {IUtils}
     * @param syncExpress {ISyncExpressInternal}
     * @private
     */
    function MobileBackend(config, platform, utils, syncExpress) {
        _classCallCheck(this, MobileBackend);

        this.config = config;
        this.platform = platform;
        this.utils = utils;
        this.syncExpress = syncExpress;
        this.PLATFORM_PATH = 'mobile/platform';
        this.CUSTOM_CODE_PATH = 'mobile/custom';
        this.authenticationType = null;
        this.logger = new _logger.Logger('MobileBackend');
        /**
         * The name of the MobileBackend as read from the configuration.
         * @type {string}
         * @name MobileBackend#name
         * @readonly
         */
        this.name = null;
        /**
         * Returns the Authorization object used to authorize a mobile user
         * against Oracle Mobile Cloud Enterprise.
         * Please use {@link mcs#mobileBackend#setAuthenticationType} to initialize this property.<br/>
         * @readonly
         * @type {Authorization}
         * @name MobileBackend#authorization
         */
        this.authorization = null;
        /**
         * Returns the Diagnostics object that enables end-end debugging across application and cloud.
         * @readonly
         * @type {Diagnostics}
         * @name MobileBackend#diagnostics
         */
        this.diagnostics = null;
        /**
         * Returns the CustomCode object that enables calls to custom APIs.
         * @readonly
         * @type {CustomCode}
         * @name MobileBackend#customCode
         */
        this.customCode = null;
        /**
         * Returns the Analytics object that enables capture of mobile analytics events.
         * @readonly
         * @type {Analytics}
         * @name MobileBackend#analytics
         */
        this.analytics = null;
        /**
         * Returns the Storage object that provides cloud-based object storage capabilities.
         * @readonly
         * @type {Storage}
         * @name MobileBackend#storage
         */
        this.storage = null;
        /**
         * Returns the Synchronization object that provides caching and synchronization capabilities.
         * @readonly
         * @type {Synchronization}
         * @name MobileBackend#synchronization
         */
        this.synchronization = null;
        /**
         * Returns an instance of the application configuration object.
         * Callers can download the configuration from the service by invoking loadAppConfig().
         * @readonly
         * @type {object}
         * @name MobileBackend#appConfig
         */
        this.appConfig = {};
        /**
         * Returns the Notifications object that provides notification capabilities.
         * @readonly
         * @type {Notifications}
         * @name MobileBackend#notifications
         * @mcs:cordova
         */
        this.notifications = null;
        this._mbeConfig = config.mobileBackend;
        this.name = this._mbeConfig.name;
        this.diagnostics = new _diagnostics.Diagnostics(platform, utils);
        this.customCode = new _customCode.CustomCode(this, utils, platform);
        this.analytics = new _analytics.Analytics(this, platform, utils);
        this.storage = new _storage.Storage(this, utils, platform);
        this._baseUrl = utils.validateConfiguration(this._mbeConfig.baseUrl);
        if (syncExpress) {
            this.synchronization = new _synchronization.Synchronization(this, config.sync, utils, platform, syncExpress.common, syncExpress.options, syncExpress.process);
        }
        if (typeof cordova !== 'undefined') {
            this.notifications = new _notifications.Notifications(this, platform, navigator);
        }
        if (this._mbeConfig.authentication.type) {
            this.setAuthenticationType(this._mbeConfig.authentication.type);
        }
    }
    /**
     * Constructs a full URL by pre-pending the prefix for platform API REST endpoints
     * to the given endpoint path.
     * @function
     * @name MobileBackend#getPlatformUrl
     * @param path {string} The relative path of the endpoint following the platform prefix,
     * i.e. /mobile/platform.
     * @returns {string} The full URL.
     */


    _createClass(MobileBackend, [{
        key: "getPlatformUrl",
        value: function getPlatformUrl(path) {
            var url = this._baseUrl;
            if (this.authenticationType == 'ssoAuth' && this.utils.strEndsWith(this._baseUrl, '1')) {
                url = url.substring(0, url.length - 4) + '7777';
            }
            url = this.utils.validateConfiguration(url) + '/' + this.PLATFORM_PATH;
            if (!this.utils.strEndsWith(url, '/')) {
                url += '/';
            }
            return url + path;
        }
    }, {
        key: "getCustomCodeUrl",

        /**
         * Constructs a full URL by prepending the prefix for custom API REST endpoints
         * to the given endpoint path.
         * @function
         * @name MobileBackend#getCustomCodeUrl
         * @param path {string} The relative path of the endpoint following the platform prefix,
         * i.e. {BaseUrl}/mobile/custom.
         * @returns {string} The full URL.
         */
        value: function getCustomCodeUrl(path) {
            return this.utils.validateConfiguration(this._baseUrl) + this._getCustomCodeUri(path);
        }
    }, {
        key: "getHttpHeaders",

        /**
         * Populates auth and diagnostics HTTP headers for making REST calls to a mobile backend.
         * @function
         * @name MobileBackend#getHttpHeaders
         * @param [headers] {Headers} An optional object with which to populate with the headers.
         * @returns {Headers} The headers parameter that is passed in.
         * If not provided, a new object with the populated headers
         * as properties of that object is created.
         */
        value: function getHttpHeaders() {
            var headers = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new _dictionary.Dictionary([]);

            var authorization = this.authorization;
            headers = this.diagnostics._getHttpHeaders(headers);
            if (authorization) {
                if (authorization._getIsAuthorized() && authorization._getIsAnonymous()) {
                    headers = authorization._getAnonymousHttpHeaders(headers);
                } else {
                    headers = authorization._getHttpHeaders(headers);
                }
            }
            return headers;
        }
        /**
         * Use this method to retrieve current authentication type.
         * @function
         * @name MobileBackend#getAuthenticationType
         * @return {string} Authentication type
         */

    }, {
        key: "getAuthenticationType",
        value: function getAuthenticationType() {
            return this.authenticationType;
        }
    }, {
        key: "setAuthenticationType",

        /**
         * Initialize and returns the Authorization object
         * that provides authorization capabilities and access to user properties.
         * @function
         * @name MobileBackend#setAuthenticationType
         * @param {string} type
         * For [Basic authentication]{@link BasicAuthorization},
         * you would specify "basic" to use the Basic Authentication security schema.<br/>
         * For [OAuth authentication]{@link OAuthAuthorization},
         * you would specify "oauth" to use OAuth Authentication security schema.<br/>
         * @return {Authorization}
         * @throws When unrecognized authentication type provided,
         * this method will throw an Exception stating that the type of Authentication that you provided
         * is not supported at this time.
         * @example <caption>Example usage of mobileBackend.setAuthenticationType()</caption>
         * // Basic Authorization schema
         * mcs.mobileBackend.setAuthenticationType('basic');
         * @example // OAuth Authorization schema
         * mcs.mobileBackend.setAuthenticationType('oauth');
         */
        value: function setAuthenticationType(type) {
            var authType = this.utils.validateConfiguration(type);
            this.authorization = null;
            if (!_types.AUTHENTICATION_TYPES.hasOwnProperty(authType)) {
                throw Error('Wrong Authentication type: ' + type + ', please use one of: \n' + _types.AUTHENTICATION_TYPES.basic + '\n' + _types.AUTHENTICATION_TYPES.oauth + '\n' + _types.AUTHENTICATION_TYPES.facebook + '\n' + _types.AUTHENTICATION_TYPES.token);
            }
            if (!this._mbeConfig.authentication.hasOwnProperty(authType)) {
                throw Error('No Authentication Type called ' + type + ' is defined in configuration \n' + 'check configuration in authorization object for the following objects:\n' + _types.AUTHENTICATION_TYPES.basic + '\n' + _types.AUTHENTICATION_TYPES.oauth + '\n' + _types.AUTHENTICATION_TYPES.facebook + '\n' + _types.AUTHENTICATION_TYPES.token);
            }
            if (this.authorization && this.authorization._getIsAuthorized()) {
                this.authorization.logout();
            }
            if (authType === _types.AUTHENTICATION_TYPES.basic) {
                this.authorization = new _basicAuthorization.BasicAuthorization(this._mbeConfig.authentication.basic, this, this.utils, this.platform);
                this.logger.info('Your Authentication type: ' + authType);
                this.authenticationType = authType;
            } else if (authType === _types.AUTHENTICATION_TYPES.oauth) {
                this.authorization = new _oauthAuthorization.OAuthAuthorization(this.config.oAuthTokenEndPoint, this._mbeConfig.authentication.oauth, this, this._mbeConfig.tenantId, this.utils, this.platform);
                this.logger.info('Your Authentication type: ' + authType);
                this.authenticationType = authType;
            } else if (authType === _types.AUTHENTICATION_TYPES.facebook) {
                this.authorization = new _facebookAuthorization.FacebookAuthorization(this._mbeConfig.authentication.facebook, this, this.utils, this.platform);
                this.logger.info('Your Authentication type: ' + authType);
                this.authenticationType = authType;
            } else if (authType === _types.AUTHENTICATION_TYPES.token) {
                this.authorization = new _externalTokenExchangeAuthorization.ExternalTokenExchangeAuthorization(this._mbeConfig.authentication.token, this, this.utils, this.platform);
                this.logger.info('Your Authentication type: ' + authType);
                this.authenticationType = authType;
            }
            return this.authorization;
        }
    }, {
        key: "loadAppConfig",

        /**
         * Downloads the configuration from the service.
         * The AppConfig property will contain the downloaded configuration.
         * @function
         * @memberOf MobileBackend
         * @name MobileBackend#loadAppConfig
         * @return {Promise<NetworkResponse>}
         */
        value: function loadAppConfig() {
            var headers = this.getHttpHeaders();
            headers.add(_types.HEADERS.CONTENT_TYPE, _types.CONTENT_TYPES.APPLICATION_JSON);
            if (!this.authorization._getIsAuthorized()) {
                headers = this.authorization._getAnonymousAuthorizationHeaders(headers);
            }
            return this.platform.invokeService({
                method: _types.HTTP_METHODS.GET,
                url: this.getPlatformUrl('appconfig/client'),
                headers: headers,
                module: _types.MODULE_NAMES.APP_CONFIG
            }).catch(invokeServiceFail.bind(this));
            function invokeServiceFail(response) {
                this.logger.error('App config download failed! with status code: ' + response.statusCode);
                return Promise.reject(response);
            }
        }
    }, {
        key: "_getCustomCodeUri",
        value: function _getCustomCodeUri(path) {
            var url = '/' + this.CUSTOM_CODE_PATH;
            if (this.utils.strEndsWith(path, '/')) {
                path = path.slice(0, -1);
            }
            return url + '/' + path;
        }
    }]);

    return MobileBackend;
}();

exports.MobileBackend = MobileBackend;


},{"../analytics/analytics":2,"../authorization/basic-authorization":4,"../authorization/external-token-exchange-authorization":5,"../authorization/facebook-authorization":6,"../authorization/oauth-authorization":8,"../custom-code/custom-code":10,"../diagnostics/diagnostics":11,"../dictionary":12,"../logger":13,"../notifications/notifications":16,"../storage/storage":25,"../sync/synchronization":40,"../types":41}],16:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.Notifications = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      */


var _logger = require("../logger");

var _types = require("../types");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @classdesc Class that provides notification capabilities. Callers should use
 * MobileBackend's [notifications]{@link MobileBackend#notifications} property.
 * @class
 * @hideconstructor
 * @global
 */
var Notifications = function () {
    function Notifications(backend, platform, navigator) {
        _classCallCheck(this, Notifications);

        this.backend = backend;
        this.platform = platform;
        this.navigator = navigator;
        this.logger = new _logger.Logger('Notifications');
    }
    /**
     * Get device platform.
     * Returns a string with device information used by [Notifications]{@link Notifications}
     * @function
     * @name Notifications#getDevicePlatform
     * @returns {String} The device specific information for platform.
     * @example : 'IOS', 'ANDROID'
     */


    _createClass(Notifications, [{
        key: "getDevicePlatform",
        value: function getDevicePlatform() {
            var platform = void 0;
            if (this.navigator.userAgent.match(/Android/i)) {
                platform = _types.PLATFORM_ID.ANDROID;
            } else if (this.navigator.userAgent.match(/iPad/i) || this.navigator.userAgent.match(/iPod/i) || this.navigator.userAgent.match(/iPhone/i)) {
                platform = _types.PLATFORM_ID.IOS;
            }
            return platform.toUpperCase();
        }
    }, {
        key: "registerForNotifications",

        /**
         * Register for notifications.
         * Registers the current Cordova app running on the device for receiving push notifications.
         * @function
         * @name Notifications#registerForNotifications
         * @param deviceToken {String} Platform-specific device token.
         * @param packageName {String} Platform-specific application reverse domain identifier.
         * @param appVersion {String} Platform-specific application version.
         * @param notificationProvider {String} The provider to register, posible values: 'APNS', 'FCM', 'WNS', 'SYNIVERSE'.
         * @return {Promise<NetworkResponse>}
         *
         * @example <caption>Example usage of mcs.mobileBackend.notifications.registerForNotifications()</caption>
         * mcs.mobileBackend
         *    .notifications
         *    .registerForNotifications('YOUR_DEVICE_TOKEN', 'com.yourcompany.project', '1.0.0', 'GCM')
         *    .then(registerSuccess)
         *    .catch(registerError);
         *
         * function registerSuccess(response){
         *    console.log(response);
         * }
         *
         * function registerError(response){
         *    console.error(response);
         * }
         */
        value: function registerForNotifications(deviceToken, packageName, appVersion, notificationProvider) {
            if (!(notificationProvider in _types.NOTIFICATION_PROVIDER)) {
                throw Error('No Notification Provider Type called ' + notificationProvider + '\n' + 'please use one of those types\n' + _types.NOTIFICATION_PROVIDER.APNS + '\n' + _types.NOTIFICATION_PROVIDER.FCM + '\n' + _types.NOTIFICATION_PROVIDER.WNS + '\n' + _types.NOTIFICATION_PROVIDER.SYNIVERSE);
            }
            var headers = this.backend.getHttpHeaders();
            headers.add(_types.HEADERS.CONTENT_TYPE, _types.CONTENT_TYPES.APPLICATION_JSON);
            var platform = typeof device === "undefined" ? this.getDevicePlatform() : device.platform.toUpperCase();
            var payload = {
                notificationToken: deviceToken,
                notificationProvider: notificationProvider,
                mobileClient: {
                    id: packageName,
                    version: appVersion,
                    platform: platform
                }
            };
            return this.platform.invokeService({
                method: _types.HTTP_METHODS.POST,
                url: this.backend.getPlatformUrl('devices/register'),
                headers: headers,
                data: JSON.stringify(payload),
                module: _types.MODULE_NAMES.NOTIFICATIONS
            }).then(invokeServiceSuccess.bind(this)).catch(invokeServiceError.bind(this));
            function invokeServiceSuccess(response) {
                this.logger.info('Device registered for push notifications.', response.statusCode);
                return response;
            }
            function invokeServiceError(response) {
                this.logger.error('Device registration for push notifications failed!', response);
                return Promise.reject(response);
            }
        }
    }, {
        key: "deregisterForNotifications",

        /**
         * Deregister from notifications.
         * Deregisters the current Cordova app running on the device for receiving push notifications.
         * @function
         * @name Notifications#deregisterForNotifications
         * @param deviceToken {String} Platform-specific success callback token.
         * @param packageName {String} Platform-specific application reverse domain identifier.
         * @return {Promise<NetworkResponse>}
         *
         * @example <caption>Example usage of mcs.mobileBackend.notifications.deregisterForNotifications()</caption>
         * mcs.mobileBackend
         *   .notifications
         *    .deregisterForNotifications('YOUR_DEVICE_TOKEN', 'com.yourcompany.project', '1.0.0')
         *    .then(deregisterSuccess)
         *    .catch(deregisterError);
         *
         * function deregisterSuccess(response){
         *   console.log(response);
         * }
         *
         * function deregisterError(response){
         *    console.log(response);
         * }
         */
        value: function deregisterForNotifications(deviceToken, packageName) {
            var headers = this.backend.getHttpHeaders();
            headers.add(_types.HEADERS.CONTENT_TYPE, _types.CONTENT_TYPES.APPLICATION_JSON);
            var payload = {
                notificationToken: deviceToken,
                mobileClient: {
                    id: packageName,
                    platform: typeof device == 'undefined' ? this.getDevicePlatform() : device.platform.toUpperCase()
                }
            };
            return this.platform.invokeService({
                method: _types.HTTP_METHODS.POST,
                url: this.backend.getPlatformUrl('devices/deregister'),
                headers: headers,
                data: JSON.stringify(payload),
                module: _types.MODULE_NAMES.NOTIFICATIONS
            }).then(invokeServiceSuccess.bind(this)).catch(invokeServiceError.bind(this));
            function invokeServiceSuccess(response) {
                this.logger.info('Device deregistered for push notifications succeeded.', response.statusCode);
                return response;
            }
            function invokeServiceError(response) {
                this.logger.error('Device deregistration for push notifications failed!', response);
                return Promise.reject(response);
            }
        }
    }]);

    return Notifications;
}();

exports.Notifications = Notifications;


},{"../logger":13,"../types":41}],17:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.BrowserPlatform = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _platform = require("./platform");

var _logger = require("../logger");

var _networkResponse = require("../responses/network-response");

var _types = require("../types");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


/**
 * Platform class for browser applications.
 * @private
 * @extends Platform
 * @global
 */
var BrowserPlatform = function (_Platform) {
    _inherits(BrowserPlatform, _Platform);

    function BrowserPlatform(config, utils) {
        var logHTTP = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

        _classCallCheck(this, BrowserPlatform);

        var _this = _possibleConstructorReturn(this, (BrowserPlatform.__proto__ || Object.getPrototypeOf(BrowserPlatform)).call(this, utils));

        _this.config = config;
        _this.logHTTP = logHTTP;
        _this.queryRegex = /\?/;
        _this.logger = new _logger.Logger('BrowserPlatform');
        _this.isBrowser = true;
        _this.isCordova = false;
        return _this;
    }

    _createClass(BrowserPlatform, [{
        key: "invokeService",
        value: function invokeService(request) {
            var url = request.url;
            if (this.isBrowser) {
                url = url + (this.queryRegex.test(url) ? "&" : "?") + "_=" + new Date().getTime();
            }
            return new Promise(invoke.bind(this));
            function invoke(resolve, reject) {
                var _this2 = this;

                var xhr = new XMLHttpRequest();
                xhr.open(request.method, url);
                for (var key in request.headers) {
                    if (request.headers.hasOwnProperty(key)) {
                        xhr.setRequestHeader(key, request.headers[key]);
                    }
                }
                xhr.setRequestHeader(_types.HEADERS.ORACLE_MOBILE_CLIENT_SDK_INFO, this._getClientSDKInfoHeader(request.module));
                xhr.withCredentials = request.hasOwnProperty('withCredentials') && typeof request.withCredentials === 'boolean' ? request.withCredentials : true;
                xhr.responseType = request.responseType || _types.XML_HTTP_REQUEST_RESPONSE_TYPE.JSON;
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        var response = xhr.responseType == '' || xhr.responseType == 'text' ? xhr.responseText : xhr.response;
                        var headers = xhr['responseHeaders'] ? _this2.utils.normalizeHeaderKeys(xhr['responseHeaders']) : _this2.utils.parseHeaders(xhr.getAllResponseHeaders());
                        var netResponse = new _networkResponse.NetworkResponse(xhr.status, response, headers);
                        if (_this2.logHTTP) {
                            var object = {
                                headers: headers,
                                body: response
                            };
                            _this2.logger.debug('Received ' + request.method + ' response from ' + request.url, object);
                        }
                        if (xhr.status >= 200 && xhr.status <= 299) {
                            resolve(netResponse);
                        } else {
                            reject(netResponse);
                        }
                    }
                };
                xhr.send(request.data);
                if (this.logHTTP) {
                    var object = {
                        headers: request.headers,
                        body: request.data
                    };
                    this.logger.debug('Sent ' + request.method + ' request to ' + request.url, object);
                }
            }
        }
    }, {
        key: "_getClientSDKInfoHeader",
        value: function _getClientSDKInfoHeader(module) {
            var infoHeader = this.isCordova ? _types.PLATFORM_NAMES.CORDOVA : _types.PLATFORM_NAMES.JAVASCRIPT;
            infoHeader += ' ' + (this.config.mcsVersion || 'Unknown');
            infoHeader += ' [' + module + ']';
            return infoHeader;
        }
    }]);

    return BrowserPlatform;
}(_platform.Platform);

exports.BrowserPlatform = BrowserPlatform;


},{"../logger":13,"../responses/network-response":21,"../types":41,"./platform":19}],18:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.CordovaPlatform = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _browserPlatform = require("./browser-platform");

var _logger = require("../logger");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */
/**
 * Platform class for Cordova applications.
 * @private
 * @extends BrowserPlatform
 * @global
 */
var CordovaPlatform = function (_BrowserPlatform) {
    _inherits(CordovaPlatform, _BrowserPlatform);

    function CordovaPlatform(config, utils) {
        var logHTTP = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

        _classCallCheck(this, CordovaPlatform);

        var _this = _possibleConstructorReturn(this, (CordovaPlatform.__proto__ || Object.getPrototypeOf(CordovaPlatform)).call(this, config, utils, logHTTP));

        _this.ANDROID_OS_NAME = 'Android';
        _this.IOS_OS_NAME = 'iOS';
        _this.latitude = null;
        _this.longitude = null;
        _this.logger = new _logger.Logger('CordovaPlatform');
        _this.isBrowser = false;
        _this.isCordova = true;
        var self = _this;
        if (!!navigator && !!navigator.geolocation && navigator.geolocation.watchPosition) {
            navigator.geolocation.watchPosition(function (position) {
                self.latitude = position.coords.latitude + '';
                self.longitude = position.coords.longitude + '';
            });
        }
        return _this;
    }
    /**
     * Overrides [Platform.getGPSLocation()]{@link Platform#getGPSLocation}
     * @override
     * @function
     * @name CordovaPlatform#getGPSLocation
     */


    _createClass(CordovaPlatform, [{
        key: "getGPSLocation",
        value: function getGPSLocation() {
            return {
                latitude: this.latitude,
                longitude: this.longitude
            };
        }
        /**
         * Checks the current state of the device. Platform implementations should call this function
         * when the state changes. The state is inspected before background operations
         * like synchronization are performed.
         * Cordova Network Information Plugin MUST be installed for this function to operate.
         * `cordova plugin add cordova-plugin-network-information`
         * @function
         * @name CordovaPlatform#checkConnection
         */

    }, {
        key: "checkConnection",
        value: function checkConnection() {
            var networkState = navigator['connection'].type;
            var states = {};
            states[Connection.UNKNOWN] = 'Unknown connection';
            states[Connection.ETHERNET] = 'Ethernet connection';
            states[Connection.WIFI] = 'WiFi connection';
            states[Connection.CELL_2G] = 'Cell 2G connection';
            states[Connection.CELL_3G] = 'Cell 3G connection';
            states[Connection.CELL_4G] = 'Cell 4G connection';
            states[Connection.CELL] = 'Cell generic connection';
            states[Connection.NONE] = 'No network connection';
            this.logger.info('Connection type: ' + states[networkState]);
            return states[networkState];
        }
    }, {
        key: "getDeviceInformation",

        /**
         * Returns device information.
         *
         * @function
         * @name CordovaPlatform#getDeviceInformation
         @return Returns an object of variables used to return device specific information like:
            @return model: Nexus One returns "Passion", Motorola Droid  returns "voles", etc.
         *
         @return manufacturer: Returns the manufacturer name:
         *
         * Samsung
         * LG
         * Motorola
         * Micosoft
         * Sony
         * Apple
         *
         @return OS Name: Depending on the device, a few examples are:
         * "Android"
         * "BlackBerry 10"
         * Browser:         returns "MacIntel" on Mac
         *                  returns "Win32" on Windows
         * "iOS"
         * "WinCE"
         * "Tizen"
         *
         @return OS Version: Depending on the device, a few examples are:
         * Android:    Froyo OS would return "2.2"
         Eclair OS would return "2.1", "2.0.1", or "2.0"
         Version can also return update level "2.1-update1"
            * BlackBerry: Torch 9800 using OS 6.0 would return "6.0.0.600"
         *
         * Browser:    Returns version number for the browser
            * iPhone:     iOS 3.2 returns "3.2"
         * Windows Phone 7: returns current OS version number, ex. on Mango returns 7.10.7720
         * Tizen: returns "TIZEN_20120425_2"
         *
         @return OS Build: Get the version of Cordova running on the device.
         * Overrides [Platform.getDeviceInformation()]{@link Platform#getDeviceInformation}
         * @override
         */
        value: function getDeviceInformation() {
            if (typeof device === 'undefined') {
                return {
                    'model': '<unknown>',
                    'manufacturer': '<unknown>',
                    'osName': '<unknown>',
                    'osVersion': '<unknown>',
                    'osBuild': '<unknown>',
                    'carrier': '<unknown>'
                };
            } else {
                return {
                    'model': device.model,
                    'manufacturer': device.manufacturer,
                    'osName': device.platform,
                    'osVersion': device.version,
                    'osBuild': 'cordova ' + device.cordova,
                    'carrier': '<unknown>'
                };
            }
        }
    }]);

    return CordovaPlatform;
}(_browserPlatform.BrowserPlatform);

exports.CordovaPlatform = CordovaPlatform;


},{"../logger":13,"./browser-platform":17}],19:[function(require,module,exports){
'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.Platform = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      */


var _logger = require('../logger');

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Base class for platform-specific capabilities. Users may derive from this class to
 * provide implementations specific to their platform.
 * @private
 * @abstract
 * @global
 */
var Platform = function () {
    function Platform(utils) {
        _classCallCheck(this, Platform);

        this.utils = utils;
        this.deviceState = typeof deviceState !== 'undefined' ? deviceState.unrestricted : null;
        this.deviceStateChangedCallbacks = [];
        this.ANDROID_OS_NAME = '';
        this.IOS_OS_NAME = '';
        this.logger = new _logger.Logger('Platform');
        this.deviceId = utils.uuid();
    }
    /**
     * Returns a device ID used by [Diagnostics]{@link Diagnostics}.
     * @returns {String} The device ID.
     */


    _createClass(Platform, [{
        key: 'getDeviceId',
        value: function getDeviceId() {
            return this.deviceId;
        }
        /**
         * Sets the current state of the device. Platform implementations should call this function
         * when the state changes. The state is inspected before background operations
         * like synchronization are performed.
         * @param state {mcs.deviceState} The new state of the device.
         */

    }, {
        key: 'setDeviceState',
        value: function setDeviceState(state) {
            if (this.deviceState != state) {
                this.logger.info("Device state changing from " + this.deviceState + " to " + state);
                this.deviceState = state;
                for (var i = 0; i < this.deviceStateChangedCallbacks.length; i++) {
                    this.deviceStateChangedCallbacks[i](this.deviceState);
                }
            }
        }
        /**
         * Class that provides the current GPS location of the device.
         * @typedef {Object} Platform.GPSLocation
         * @property {String} latitude - The device's current latitude.
         * @property {String} longitude - The device's current longitude.
         */
        /**
         * Returns an object that has the current GPS location of the device or null.
         * @returns {Platform~GPSLocation} The GPS location is available.
         */

    }, {
        key: 'getGPSLocation',
        value: function getGPSLocation() {
            return {
                latitude: null,
                longitude: null
            };
        }
        /**
         * Class that provides information about the device.
         * @typedef {Object} Platform.DeviceInformation
         * @property {String} model - The device's model.
         * @property {String} manufacturer - The device's manufacturer.
         * @property {String} osName - The operating system.
         * @property {String} osVersion - The operating system's version.
         * @property {String} osBuild - The operating system's build number.
         * @property {String} carrier - The device's wireless carrier.
         */
        /**
         * Returns an object with device information used by [Analytics]{@link Analytics}
         * @returns {Platform~DeviceInformation} The device specific information.
         */

    }, {
        key: 'getDeviceInformation',
        value: function getDeviceInformation() {
            return {
                "model": "<unknown>",
                "manufacturer": "<unknown>",
                "osName": "<unknown>",
                "osVersion": "<unknown>",
                "osBuild": "<unknown>",
                "carrier": "<unknown>"
            };
        }
    }]);

    return Platform;
}();

exports.Platform = Platform;


},{"../logger":13}],20:[function(require,module,exports){
'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});
/**
 * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
 *
 * @author Yuri Panshin
 * @ignore
 */
var POLICIES_MAP = exports.POLICIES_MAP = {
    fetchPolicy: {
        persistencePropertyName: 'fetchPolicy',
        FETCH_FROM_CACHE_SCHEDULE_REFRESH: 'FETCH_FROM_CACHE_SCHEDULE_REFRESH',
        FETCH_FROM_SERVICE_IF_ONLINE: 'FETCH_FROM_SERVICE_IF_ONLINE',
        FETCH_FROM_CACHE: 'FETCH_FROM_CACHE',
        FETCH_FROM_SERVICE: 'FETCH_FROM_SERVICE',
        FETCH_FROM_SERVICE_ON_CACHE_MISS: 'FETCH_FROM_SERVICE_ON_CACHE_MISS',
        FETCH_FROM_SERVICE_ON_CACHE_MISS_OR_EXPIRY: 'FETCH_FROM_SERVICE_ON_CACHE_MISS_OR_EXPIRY',
        FETCH_WITH_REFRESH: 'FETCH_WITH_REFRESH'
    },
    evictionPolicy: {
        persistencePropertyName: 'evictionPolicy',
        EVICT_ON_EXPIRY_AT_STARTUP: 'EVICT_ON_EXPIRY_AT_STARTUP',
        MANUAL_EVICTION: 'MANUAL_EVICTION'
    },
    expirationPolicy: {
        persistencePropertyName: 'expirationPolicy',
        EXPIRE_ON_RESTART: 'EXPIRE_ON_RESTART',
        EXPIRE_AFTER: 'EXPIRE_AFTER',
        NEVER_EXPIRE: 'NEVER_EXPIRE'
    },
    updatePolicy: {
        persistencePropertyName: 'updatePolicy',
        QUEUE_IF_OFFLINE: 'QUEUE_IF_OFFLINE',
        UPDATE_IF_ONLINE: 'UPDATE_IF_ONLINE'
    },
    refreshPolicy: {
        persistencePropertyName: 'refreshPolicy',
        PeriodicallyRefreshExpiredResource: ''
    },
    conflictResolutionPolicy: {
        persistencePropertyName: 'conflictResolutionPolicy',
        SERVER_WINS: 'SERVER_WINS',
        PRESERVE_CONFLICT: 'PRESERVE_CONFLICT',
        CLIENT_WINS: 'CLIENT_WINS'
    },
    noCache: {
        persistencePropertyName: 'noCache',
        'false': false,
        'true': true
    }
};


},{}],21:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
 * Created by Yuri Panshin on 2016-08-26.
 */
/**
 * @classdesc Class that provides network response details.
 * @class
 * @global
 * @hideconstructor
 */
var NetworkResponse = function NetworkResponse(statusCode, data, headers) {
  _classCallCheck(this, NetworkResponse);

  /**
   * The network status code.
   * @type {Number}
   * @readonly
   * @name NetworkResponse#statusCode
   */
  this.statusCode = 0;
  /**
   * The error data.
   * @type {Object}
   * @readonly
   * @name NetworkResponse#data
   */
  this.data = null;
  this.statusCode = statusCode;
  this.data = data;
  this.headers = headers;
};

exports.NetworkResponse = NetworkResponse;


},{}],22:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
 * Created by Yuri Panshin on 2016-08-26.
 */
/**
 * @classdesc Class that provides network storage object details.
 * @class
 * @global
 * @hideconstructor
 */
var NetworkStorageObject = function NetworkStorageObject(statusCode, storageObject) {
  _classCallCheck(this, NetworkStorageObject);

  /**
   * The network status code.
   * @type {Number}
   * @readonly
   * @name NetworkStorageObject#statusCode
   */
  this.statusCode = 0;
  /**
   * The error data.
   * @type {StorageObject}
   * @readonly
   * @name NetworkStorageObject#storageObject
   */
  this.storageObject = null;
  this.statusCode = statusCode;
  this.storageObject = storageObject;
};

exports.NetworkStorageObject = NetworkStorageObject;


},{}],23:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.StorageCollection = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      */


var _storageObject = require("./storage-object");

var _networkStorageObject = require("../responses/network-storage-object");

var _types = require("../types");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @classdesc Class that holds the StorageCollection resource. StorageCollections contain Storage objects
 * which can be used to persist data in Oracle Mobile Cloud Enterprise.
 * @class
 * @global
 * @hideconstructor
 */
var StorageCollection = function () {
    function StorageCollection(name, userId, userIsolated, backend, utils, logger, platform) {
        _classCallCheck(this, StorageCollection);

        this.userIsolated = userIsolated;
        this.backend = backend;
        this.utils = utils;
        this.logger = logger;
        this.platform = platform;
        this.storage = backend.storage;
        this.userId = utils.validateConfiguration(userId);
        this.id = utils.validateConfiguration(name);
    }
    /**
     * The description of the StorageCollection.
     * @type {String}
     * @name StorageCollection#description
     * @deprecated Will be deleted in next version. Use {@link StorageCollection#getDescription} instead.
     */


    _createClass(StorageCollection, [{
        key: "getStorage",

        /**
         * Returns storage object for current storage collection.
         *
         * @function
         * @name StorageCollection#getStorage
         * @return storage object data for current storage collection.
         */
        value: function getStorage() {
            return this.storage;
        }
    }, {
        key: "getUserIsolated",
        value: function getUserIsolated() {
            return this.data ? this.data.userIsolated : this.userIsolated;
        }
    }, {
        key: "getUserId",

        /**
         * Get user id.
         * Returns user ID for current storage collection.
         * @return {string} user ID for current storage collection.
         * @function
         * @name StorageCollection#getUserId
         */
        value: function getUserId() {
            return this.userId;
        }
    }, {
        key: "getData",

        /**
         * Get data.
         * Returns data for current storage collection.
         * @return {object} storage object data for current storage collection.
         * @function
         * @name StorageCollection#getData
         */
        value: function getData() {
            return this.data;
        }
    }, {
        key: "getDescription",

        /**
         * Get description.
         * The description of the StorageCollection.
         * @return {String}
         * @function
         * @name StorageCollection#getDescription
         */
        value: function getDescription() {
            if (this.data) {
                return this.data.description;
            } else {
                this.logger.warn('Collection metadata was not loaded yet, please use StorageCollection.loadMetadata to load metadata.');
            }
        }
    }, {
        key: "toJSON",

        /**
         * Convert collection to static object that used by JSON.stringify
         * @ignore
         */
        value: function toJSON() {
            return {
                id: this.id,
                description: this.getDescription(),
                userId: this.getUserId(),
                userIsolated: this.getUserIsolated(),
                data: this.getData()
            };
        }
        /**
         * Load metadata.
         * Load collection metadata
         * @returns {Promise<StorageCollection|NetworkResponse>}
         * @function
         * @name StorageCollection#loadMetadata
         */

    }, {
        key: "loadMetadata",
        value: function loadMetadata() {
            var headers = this.backend.getHttpHeaders();
            headers.add(_types.HEADERS.ACCEPT, _types.CONTENT_TYPES.APPLICATION_JSON);
            return this.platform.invokeService({
                method: _types.HTTP_METHODS.GET,
                url: this.backend.getPlatformUrl("storage/collections/" + this.id),
                headers: headers,
                module: _types.MODULE_NAMES.STORAGE
            }).then(invokeServiceSuccess.bind(this));
            function invokeServiceSuccess(response) {
                this.data = response.data;
                return this;
            }
        }
        /**
         * Returns a list of StorageObjects from the collection starting from the offset and up to the limit. The service may return fewer objects.<br/>
         * 1. If the collection is a shared collection, then it returns all the objects.<br/>
         * 2. If the collection is a user-isolated collection and allObjects is false, then it returns the objects which belong to the current user.<br/>
         * 3. If the collection is user-isolated collection, and allObjects is true, then it returns all the objects in the collection.<br/>
         * The objects might belong to other users. And the current user MUST have READ_ALL or READ_WRITE_ALL permission.
         * @param offset {Number} The offset at which to start. Must be greater than 0.
         * @param limit {Number} The max number of StorageObjects to return. Must be non-negative.
         * @param allObjects {Boolean} whether to return all the objects in the list.
         * @return {Promise<Array<StorageObject>|NetworkResponse>}
         * @function
         * @name StorageCollection#getObjects
         */

    }, {
        key: "getObjects",
        value: function getObjects(offset, limit, allObjects) {
            var headers = this.backend.getHttpHeaders();
            headers.add(_types.HEADERS.ACCEPT, _types.CONTENT_TYPES.APPLICATION_JSON);
            var url = "storage/collections/" + this.id + "/objects";
            if (offset != null) {
                url += url.indexOf("?") == -1 ? "?" : "&";
                url += "offset=" + offset;
            }
            if (limit != null) {
                url += url.indexOf("?") == -1 ? "?" : "&";
                url += "limit=" + limit;
            }
            if (this.getUserIsolated() && allObjects) {
                url += url.indexOf("?") == -1 ? "?" : "&";
                url += "user=*";
            } else if (this.getUserIsolated() && this.getUserId() != null) {
                url += url.indexOf("?") == -1 ? "?" : "&";
                url += "user=" + this.getUserId();
            }
            return this.platform.invokeService({
                method: _types.HTTP_METHODS.GET,
                url: this.backend.getPlatformUrl(url),
                headers: headers,
                module: _types.MODULE_NAMES.STORAGE
            }).then(invokeServiceSuccess.bind(this));
            function invokeServiceSuccess(response) {
                var objects = [];
                var objectsJson = response.data;
                for (var i = 0; i < objectsJson.items.length; i++) {
                    objects[objects.length] = new _storageObject.StorageObject(this, objectsJson.items[i]);
                }
                return objects;
            }
        }
        /**
         * Returns a StorageObject given its ID. The contents of the object will be downloaded lazily.
         * @function
         * @name StorageCollection#getObject
         * @param id {string} The ID of the Storage Object to return.
         * @param objectType {string} responseType for the XMLHttpRequest Object.
         * Default response type if not defined is json.
         * Ths parameter can be one of the types: 'json', 'blob', 'arraybuffer', 'document', 'text'.
         * @return {Promise<StorageObject|NetworkResponse>}
         *
         * @example StorageCollection.getObject('00e39862-9652-458b-9a82-d1a66cf1a0c7', mcs.RESPONSE_TYPES.BLOB).then(
         * function(storageObject){
         * },
         * function(networkResponse){
         * });
         */

    }, {
        key: "getObject",
        value: function getObject(id, objectType) {
            var storageObject = new _storageObject.StorageObject(this, this.backend);
            storageObject.id = id;
            return storageObject.readPayload(objectType).then(readPayloadSuccess);
            function readPayloadSuccess() {
                return storageObject;
            }
        }
    }, {
        key: "loadObjectPayload",
        value: function loadObjectPayload(objectId, objectType) {
            var headers = this.backend.getHttpHeaders();
            var url = "storage/collections/" + this.id + "/objects/" + objectId;
            if (this.userId != null && this.getUserIsolated()) {
                url += "?user=" + this.userId;
            }
            return this.platform.invokeService({
                method: _types.HTTP_METHODS.GET,
                url: this.backend.getPlatformUrl(url),
                headers: headers,
                responseType: objectType || _types.XML_HTTP_REQUEST_RESPONSE_TYPE.BLOB,
                module: _types.MODULE_NAMES.STORAGE
            });
        }
        /**
         * Creates a new StorageObject in the collection.
         * @function
         * @name StorageCollection#postObject
         * @param storageObject {StorageObject} The StorageObject to create.
         * @example storageObject:
         * {
        * "id": " 213ddbac-ccb2-4a53-ad48-b4588244tc4c", // A service generated ID for the StorageObject. The ID is unique in the StorageCollection.
        * "name" : "JSText.txt", // A user provided name for the StorageObject. A StorageCollection may have multiple StorageObjects with the same name.
        * "contentLength": 798", // The length of data content in bytes stored in the StorageObject.
        * "contentType" : "text/plain ", // The media-type associated with the StorageObject.
        * "createdBy" : "DwainDRob", // The name of the user who created the StorageObject
        * "createdOn": "Sat, 17 Oct 2015 10:33:12", // Server generated timestamp when the StorageObject was created.
        * "modifiedBy": "DwainDRob", // The name of the user who last updated the StorageObject.
        * "modifiedOn": "Sat, 17 Oct 2015 10:33:12" //  Server generated timestamp when the StorageObject was last updated.
        * }
         * @return {Promise<NetworkResponse>}
         */

    }, {
        key: "postObject",
        value: function postObject(storageObject) {
            return this._postOrPutStorageObject(storageObject, true);
        }
    }, {
        key: "putObject",

        /**
         * Updates an existing StorageObject in the collection.
         * @function
         * @name StorageCollection#putObject
         * @param storageObject {StorageObject} The StorageObject to update.
         * @return {Promise<NetworkStorageObject|NetworkResponse>}
         */
        value: function putObject(storageObject) {
            return this._postOrPutStorageObject(storageObject, false);
        }
    }, {
        key: "_postOrPutStorageObject",
        value: function _postOrPutStorageObject(storageObject, isPost) {
            var headers = this.backend.getHttpHeaders();
            headers.add(_types.HEADERS.ORACLE_MOBILE_NAME, encodeURI(storageObject.getDisplayName()));
            headers.add(_types.HEADERS.CONTENT_TYPE, storageObject.contentType);
            var url = "storage/collections/" + this.id + "/objects";
            if (!isPost) {
                url += "/" + storageObject.id;
                if (storageObject._eTag != null) {
                    headers.add(_types.HEADERS.IF_MATCH, storageObject._eTag);
                }
            }
            if (this.getUserIsolated() && this.getUserId() != null) {
                url += "?user=" + this.getUserId();
            }
            return this.platform.invokeService({
                method: isPost ? _types.HTTP_METHODS.POST : _types.HTTP_METHODS.PUT,
                url: this.backend.getPlatformUrl(url),
                headers: headers,
                data: storageObject.getPayload(),
                module: _types.MODULE_NAMES.STORAGE
            }).then(invokeServiceSuccess.bind(this));
            function invokeServiceSuccess(response) {
                var object = new _storageObject.StorageObject(this, response.data);
                return new _networkStorageObject.NetworkStorageObject(response.statusCode, object);
            }
        }
    }, {
        key: "contains",

        /**
         * Checks the service if a StorageObject with the given ID exists in the collection.
         * @function
         * @name StorageCollection#contains
         * @param id {String} The ID of the StorageObject to check.
         * @return {Promise<NetworkResponse>}
         */
        value: function contains(id) {
            var headers = this.backend.getHttpHeaders();
            var url = "storage/collections/" + this.id + "/objects/" + id;
            if (this.getUserIsolated() && this.getUserId() != null) {
                url += "?user=" + this.getUserId();
            }
            return this.platform.invokeService({
                method: _types.HTTP_METHODS.HEAD,
                url: this.backend.getPlatformUrl(url),
                headers: headers,
                module: _types.MODULE_NAMES.STORAGE
            });
        }
    }, {
        key: "deleteObject",

        /**
         * Deletes a StorageObject from a collection.
         * @function
         * @name StorageCollection#deleteObject
         * @param id {String} The ID of the StorageObject to delete.
         * @return {Promise<NetworkResponse>}
         */
        value: function deleteObject(id) {
            var headers = this.backend.getHttpHeaders();
            headers.add(_types.HEADERS.IF_MATCH, '*');
            var url = "storage/collections/" + this.id + "/objects/" + id;
            if (this.getUserIsolated() && this.getUserId() != null) {
                url += "?user=" + this.getUserId();
            }
            return this.platform.invokeService({
                method: _types.HTTP_METHODS.DELETE,
                url: this.backend.getPlatformUrl(url),
                headers: headers,
                module: _types.MODULE_NAMES.STORAGE
            });
        }
    }, {
        key: "description",
        get: function get() {
            return this.data ? this.data.description : undefined;
        }
    }]);

    return StorageCollection;
}();

exports.StorageCollection = StorageCollection;


},{"../responses/network-storage-object":22,"../types":41,"./storage-object":24}],24:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.StorageObject = undefined;

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      */


var _types = require("../types");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var StorageObject = function () {
    /**
     * @classdesc Class that represents a storage object resource that can be used to store data.
     * This class constructor accessible by [mcs.StorageObject]{@link mcs.StorageObject} method.
     * @param storageCollection {StorageCollection}
     * @param json {Object}
     * @class
     * @global
     */
    function StorageObject(storageCollection, json) {
        _classCallCheck(this, StorageObject);

        this.storageCollection = storageCollection;
        if (json) {
            this.id = json.id;
            this.name = json.name;
            this.contentLength = json.contentLength;
            this.contentType = json.contentType;
            this._eTag = json.eTag;
            this.createdBy = json.createdBy;
            this.createdOn = json.createdOn;
            this.modifiedBy = json.modifiedBy;
            this.modifiedOn = json.modifiedOn;
        }
    }
    /**
     * Get payload.
     * Returns the current StorageObject payload.
     *
     * @function
     * @name StorageObject#getPayload
     * @return Current Storage object payload.
     */


    _createClass(StorageObject, [{
        key: "getPayload",
        value: function getPayload() {
            return this.payload;
        }
    }, {
        key: "setPayload",

        /**
         * Sets the payload for the StorageObject.
         *
         * @function
         * @name StorageObject#setPayload
         * @param payload The payload to be associated with StorageObject.
         */
        value: function setPayload(payload) {
            this.payload = payload;
        }
    }, {
        key: "getstorageCollection",

        /**
         * Returns the current StorageCollection.
         *
         * @function
         * @name StorageObject#getstorageCollection
         * @return Current StorageCollection.
         */
        value: function getstorageCollection() {
            return this.storageCollection;
        }
    }, {
        key: "getStorage",

        /**
         * Returns the current StorageObject.
         *
         * @function
         * @name StorageObject#getStorage
         * @return Current StorageObject.
         */
        value: function getStorage() {
            return this.storageCollection.getStorage();
        }
    }, {
        key: "loadPayload",

        /**
         * Loads a StorageObject's contents from an object.
         * @function
         * @name StorageObject#loadPayload
         * @param payload {Object} The object to load from.
         * @param contentType {String} The media-type to associate with the content.
         */
        value: function loadPayload(payload, contentType) {
            this.payload = payload;
            this.contentType = contentType;
            if (this.contentType === _types.CONTENT_TYPES.TEXT_PLAIN) {
                if (typeof this.payload === "string") {
                    this.payload = payload;
                }
            } else if (this.contentType === _types.CONTENT_TYPES.APPLICATION_JSON) {
                if (typeof this.payload === "string") {
                    this.payload = payload;
                } else if (_typeof(this.payload) == "object") {
                    this.payload = JSON.stringify(payload);
                }
            }
            this.contentLength = this.payload.length;
        }
    }, {
        key: "setDisplayName",

        /**
         * Sets a StorageObject's display name from an object.
         * @function
         * @name StorageObject#setDisplayName
         * @param name {Object} The object's name to be associated with the object.
         * @returns The object's name in UTC-8 ASCII format.
         */
        value: function setDisplayName(name) {
            this.name = name;
        }
    }, {
        key: "getDisplayName",

        /**
         * Returns a StorageObject's display name from an object.
         *
         * @function
         * @name StorageObject#getDisplayName
         * @returns {String} object's name decoded if encoded into the MobileBackend.
         */
        value: function getDisplayName() {
            return this.name;
        }
        /**
         * Returns the contents of the StorageObject. May result in a download from the service if the contents were not
         * previously downloaded.
         * @function
         * @name StorageObject#readPayload
         * @param {String} objectType responseType for the XMLHttpRequest Object.
         * @return {Promise<StorageObject|NetworkResponse>}
         */

    }, {
        key: "readPayload",
        value: function readPayload(objectType) {
            var payload = this.getPayload();
            if (!payload) {
                return this.storageCollection.loadObjectPayload(this.id, objectType).then(invokeServiceSuccess.bind(this));
            } else {
                return Promise.resolve(this);
            }
            function invokeServiceSuccess(response) {
                this.setPayload(response.data);
                this.name = decodeURI(response.headers[_types.HEADERS.ORACLE_MOBILE_NAME.toLowerCase()]);
                this._eTag = response.headers[_types.HEADERS.E_TAG.toLowerCase()];
                this.contentLength = response.data.size; // TODO: check this property
                this.contentType = response.headers[_types.HEADERS.CONTENT_TYPE.toLowerCase()];
                this.createdBy = response.headers[_types.HEADERS.ORACLE_MOBILE_CREATED_BY.toLowerCase()];
                this.createdOn = response.headers[_types.HEADERS.ORACLE_MOBILE_CREATED_ON.toLowerCase()];
                this.modifiedBy = response.headers[_types.HEADERS.ORACLE_MOBILE_MODIFIED_BY.toLowerCase()];
                this.modifiedOn = response.headers[_types.HEADERS.ORACLE_MOBILE_MODIFIED_ON.toLowerCase()];
                return this;
            }
        }
    }]);

    return StorageObject;
}();

exports.StorageObject = StorageObject;


},{"../types":41}],25:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.Storage = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      */


var _logger = require("../logger");

var _storageCollection = require("./storage-collection");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @classdesc Class that provides cloud-based storage capabilities. Callers should use
 * MobileBackend's [storage]{@link MobileBackend#storage} property.
 * @class
 * @global
 * @hideconstructor
 */
var Storage = function () {
    function Storage(backend, utils, platform) {
        _classCallCheck(this, Storage);

        this.backend = backend;
        this.utils = utils;
        this.platform = platform;
        this.logger = new _logger.Logger('Storage');
    }
    /**
     * Returns a StorageCollection with the given name from the service associated with the user. Subsequent accesses to StorageObjects in the
     * StorageCollection will only return StorageObjects owned by the user.
     * @function
     * @name Storage#getCollection
     * @param name {String} The name of the StorageCollection.
     * @param [userId] {String} Optional, the ID of the user retrieved from the UI.
     * @param [userIsolated] {Boolean} - indicate if collection is in isolated mode, used in combination with lazyLoad and userId.
     * This parameter is not required in case lazyLoad is not provided.
     * @param [lazyLoad] {Boolean} - indicate not to load collection metadata
     * @return {Promise<StorageCollection|NetworkResponse>}
     */


    _createClass(Storage, [{
        key: "getCollection",
        value: function getCollection(name, userId, userIsolated, lazyLoad) {
            var collection = new _storageCollection.StorageCollection(name, this.utils.validateConfiguration(userId), userIsolated, this.backend, this.utils, this.logger, this.platform);
            if (lazyLoad) {
                return Promise.resolve(collection);
            } else {
                return collection.loadMetadata();
            }
        }
    }]);

    return Storage;
}();

exports.Storage = Storage;


},{"../logger":13,"./storage-collection":23}],26:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.FetchCollectionBuilder = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     *
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     * @author Yuri Panshin
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     */


var _dictionary = require("../../dictionary");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @classdesc Class that exposes fluent APIs for fetching objects from an API endpoint.
 * @class
 * @global
 * @hideconstructor
 */
var FetchCollectionBuilder = function () {
    function FetchCollectionBuilder(endpoint, json) {
        _classCallCheck(this, FetchCollectionBuilder);

        this.endpoint = endpoint;
        this.json = json;
        this._fetchFromService = false;
        this._offset = -1;
        this._limit = -1;
        this._fetchAll = false;
        this._withParams = {};
        this._withHeaders = new _dictionary.Dictionary([]);
    }
    /**
     * Executes the fetch and returns the results.
     * @function
     * @name FetchCollectionBuilder#execute
     * @return {Promise<MobileObjectCollection|NetworkResponse>}
     */


    _createClass(FetchCollectionBuilder, [{
        key: "execute",
        value: function execute() {
            return this.endpoint._executeFetchObjects(this._withHeaders, this._withParams, this._fetchAll, this._offset, this._limit, this._fetchFromService);
        }
    }]);

    return FetchCollectionBuilder;
}();

exports.FetchCollectionBuilder = FetchCollectionBuilder;


},{"../../dictionary":12}],27:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.MobileEndpoint = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @author Yuri Panshin
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      */


var _mobileObject = require("./mobile-object");

var _getProcessor = require("../processors/get-processor");

var _postProcessor = require("../processors/post-processor");

var _putProcessor = require("../processors/put-processor");

var _deleteProcessor = require("../processors/delete-processor");

var _mobileObjectCollection = require("./mobile-object-collection");

var _fetchCollectionBuilder = require("./fetch-collection-builder");

var _networkResponse = require("../../responses/network-response");

var _types = require("../../types");

var _dictionary = require("../../dictionary");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @classdesc Class that represents an endpoint in a custom code API. Callers should use
 * [Synchronization.openEndpoint()]{@link Synchronization#openEndpoint} to create a new MobileEndpoint.
 * @class
 * @global
 * @hideconstructor
 */
var MobileEndpoint = function () {
    function MobileEndpoint(synchronization, apiName, endpointPath, backend, utils, platform, common, options) {
        var _this = this;

        _classCallCheck(this, MobileEndpoint);

        this.backend = backend;
        this.utils = utils;
        this.platform = platform;
        this.common = common;
        this.options = options;
        /**
         * Deletes all cached resources.
         * @function
         * @name MobileEndpoint#purge
         */
        this.purge = function () {
            _this.options.module.flush(_this.backend.getCustomCodeUrl(_this.apiName + "/" + _this.endpointPath));
        };
        this.synchronization = synchronization;
        this.apiName = apiName;
        this.endpointPath = endpointPath;
    }
    /**
     * Creates a new MobileObject. The object is not uploaded to the service until [save()]{@link MobileObject#save} is invoked.
     * @function
     * @name MobileEndpoint#purge
     * @returns {MobileObject} A new MobileObject.
     */


    _createClass(MobileEndpoint, [{
        key: "createObject",
        value: function createObject(object) {
            object = object || {};
            object.__proto__ = new _mobileObject.MobileObject(this, null);
            return object;
        }
        /**
         * Resource processor response.
         * @typedef ResourceProcessorResponse
         * @property {string} uri
         * @property {object} data
         */
        /**
         * Fetches an object from the API's endpoint.
         * @function
         * @name MobileEndpoint#fetchObject
         * @param id {String} The ID of the object.
         * @param fetchFromService {Boolean} If true will download from the service; if false will return any pinned object
         * and will trigger a background refresh.
         * @return {Promise<MobileObject|ResourceProcessorResponse>}
         */

    }, {
        key: "fetchObject",
        value: function fetchObject(id, fetchFromService) {
            var url = this.apiName;
            if (this.endpointPath && this.endpointPath.length > 0) {
                url += '/' + this.endpointPath;
            }
            if (id && id != '') {
                url += '/' + id;
            }
            url = this.backend.getCustomCodeUrl(url);
            var processor = new _getProcessor.GetProcessor(this.backend, this.apiName, this.endpointPath, this.platform, this.utils, this.common, this.options);
            var headers = new _dictionary.Dictionary([]);
            headers.add(_types.HEADERS.ACCEPT, _types.CONTENT_TYPES.APPLICATION_JSON);
            return processor.performRequest(url, headers, fetchFromService).then(performRequestSuccess.bind(this));
            function performRequestSuccess(resource) {
                if (!resource.data || resource.data === '') {
                    return Promise.reject(new _networkResponse.NetworkResponse(404, 'Object not found in cache.'));
                } else {
                    var object = resource.data;
                    if (typeof object === 'string') {
                        object = object != '' ? JSON.parse(object) : null;
                    }
                    object.__proto__ = new _mobileObject.MobileObject(this, resource.uri);
                    return object;
                }
            }
        }
    }, {
        key: "_save",
        value: function _save(mobileObject, saveIfOffline) {
            var isPost = !mobileObject._getMcsURI();
            var url = isPost ? this.backend.getCustomCodeUrl(this.apiName + "/" + this.endpointPath) : this.backend._baseUrl + mobileObject._getMcsURI();
            var processor = isPost ? new _postProcessor.PostProcessor(this.backend, this.apiName, this.endpointPath, this.platform, this.utils, this.common, this.options) : new _putProcessor.PutProcessor(this.backend, this.apiName, this.endpointPath, this.platform, this.utils, this.common, this.options);
            var data = JSON.stringify(mobileObject);
            var headers = new _dictionary.Dictionary([]);
            headers.add(_types.HEADERS.ACCEPT, _types.CONTENT_TYPES.APPLICATION_JSON);
            headers.add(_types.HEADERS.CONTENT_TYPE, _types.CONTENT_TYPES.APPLICATION_JSON);
            return processor.performRequest(url, headers, data).then(performRequestSuccess.bind(this));
            function performRequestSuccess(resource) {
                var object = resource.data;
                if (typeof object === 'string') {
                    object = object != '' ? JSON.parse(object) : null;
                }
                this._updateMobileObject(mobileObject, object);
                mobileObject.__proto__ = new _mobileObject.MobileObject(this, resource.uri);
                return mobileObject;
            }
        }
    }, {
        key: "_delete",
        value: function _delete(mobileObject, deleteIfOffline) {
            var processor = new _deleteProcessor.DeleteProcessor(this.backend, this.apiName, this.endpointPath, this.platform, this.utils, this.common, this.options);
            var url = this.backend._baseUrl + mobileObject._getMcsURI();
            return processor.performRequest(url).then(success.bind(this));
            function success() {
                this._updateMobileObject(mobileObject._syncResource);
                mobileObject._syncResource = null;
            }
        }
    }, {
        key: "_updateMobileObject",
        value: function _updateMobileObject(mobileObject) {
            var newObject = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
            for (var property in mobileObject) {
                if (mobileObject.hasOwnProperty(property)) {
                    delete mobileObject[property];
                }
            }
            for (var _property in newObject) {
                if (newObject.hasOwnProperty(_property)) {
                    mobileObject[_property] = newObject[_property];
                }
            }
        }
    }, {
        key: "_executeFetchObjects",
        value: function _executeFetchObjects(withHeaders, withParams, fetchAll, offset, limit, fetchFromService) {
            var endpoint = this;
            var headers = this.backend.getHttpHeaders(withHeaders);
            headers.add(_types.HEADERS.ORACLE_MOBILE_SYNC_AGENT, 'true');
            var request = {
                method: _types.HTTP_METHODS.GET,
                url: this.backend.getCustomCodeUrl(this.apiName + "/" + this.endpointPath),
                headers: headers,
                module: _types.MODULE_NAMES.SYNC
            };
            return this.platform.invokeService(request).then(invokeServiceSuccess.bind(this));
            function invokeServiceSuccess(response) {
                var data = response.data;
                if (typeof data === 'string') {
                    data = data != '' ? JSON.parse(data) : null;
                }
                var objects = [];
                for (var idx in data.items) {
                    if (data.items.hasOwnProperty(idx)) {
                        var object = data.items[idx];
                        var uri = '/' + data.uris[idx];
                        object.__proto__ = new _mobileObject.MobileObject(endpoint, uri);
                        objects.push(object);
                    }
                }
                return new _mobileObjectCollection.MobileObjectCollection(endpoint, /*syncResource*/null).initialize(objects);
            }
        }
        /**
         * Method to fetch a collection of objects from the endpoint. If the collection exists in the cache, the cached copy is returned; otherwise it is downloaded from the service..
         * @return {FetchCollectionBuilder}
         */

    }, {
        key: "fetchObjects",
        value: function fetchObjects() {
            return new _fetchCollectionBuilder.FetchCollectionBuilder(this);
        }
    }]);

    return MobileEndpoint;
}();

exports.MobileEndpoint = MobileEndpoint;


},{"../../dictionary":12,"../../responses/network-response":21,"../../types":41,"../processors/delete-processor":31,"../processors/get-processor":32,"../processors/post-processor":33,"../processors/put-processor":34,"./fetch-collection-builder":26,"./mobile-object":29,"./mobile-object-collection":28}],28:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.MobileObjectCollection = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _mobileResource = require("./mobile-resource");

var _syncResourceType = require("../sync-resource-type");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                *
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @author Yuri Panshin
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


/**
 * @classdesc Class that represents a collection of MobileObjects returned by a custom code API.
 * @class
 * @global
 * @hideconstructor
 */
var MobileObjectCollection = function (_MobileResource) {
    _inherits(MobileObjectCollection, _MobileResource);

    function MobileObjectCollection(endpoint, uri) {
        _classCallCheck(this, MobileObjectCollection);

        var _this = _possibleConstructorReturn(this, (MobileObjectCollection.__proto__ || Object.getPrototypeOf(MobileObjectCollection)).call(this, endpoint, uri));

        _this._type = _syncResourceType.SyncResourceType.item;
        _this._objects = [];
        return _this;
    }

    _createClass(MobileObjectCollection, [{
        key: "initialize",
        value: function initialize(objects) {
            for (var idx in objects) {
                if (objects.hasOwnProperty(idx)) {
                    var object = objects[idx];
                    this._objects.push(object);
                }
            }
            return this;
        }
    }, {
        key: "getLength",

        /**
         * The count of items in the collection
         * @function
         * @name MobileObjectCollection#getLength
         * @returns {number}
         */
        value: function getLength() {
            return this._objects.length;
        }
    }, {
        key: "getItem",

        /**
         * Return specific object from collection.
         * @function
         * @name MobileObjectCollection#getItem
         * @param idx {number} item position in collection.
         * @return {MobileObject}
         */
        value: function getItem(idx) {
            return this._objects[idx];
        }
    }, {
        key: "all",

        /**
         * Return all objects from collection.
         * @function
         * @name MobileObjectCollection#all
         * @return {MobileObject[]}
         */
        value: function all() {
            return this._objects;
        }
    }, {
        key: "forEach",

        /**
         * Run this method on every object.
         * @callback MobileObjectCollection#forEachCallback
         * @param object {MobileObject} the mobile object.
         */
        /**
         * For each.
         * Run method per item
         * @function
         * @name MobileObjectCollection#forEach
         * @param method {MobileObjectCollection#forEachCallback} method to run on item.
         */
        value: function forEach(method) {
            this._objects.forEach(method);
        }
    }]);

    return MobileObjectCollection;
}(_mobileResource.MobileResource);

exports.MobileObjectCollection = MobileObjectCollection;


},{"../sync-resource-type":39,"./mobile-resource":30}],29:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.MobileObject = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _mobileResource = require("./mobile-resource");

var _syncResourceType = require("../sync-resource-type");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                *
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @author Yuri Panshin
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


/**
 * @classdesc Class that represents an object returned by a custom code API.
 * @class
 * @global
 * @hideconstructor
 */
var MobileObject = function (_MobileResource) {
  _inherits(MobileObject, _MobileResource);

  function MobileObject(endpoint, uri) {
    _classCallCheck(this, MobileObject);
    var _this = _possibleConstructorReturn(this, (MobileObject.__proto__ || Object.getPrototypeOf(MobileObject)).call(this, endpoint, uri));

    _this._type = _syncResourceType.SyncResourceType.item;
    return _this;
  }
  /**
   * Save the object.
   * Saves any changes to the object back to the service.
   * @function
   * @name MobileObject#save
   * @param saveIfOffline {Boolean} If true will cache updates locally and sync them back to the service if the device is offline; if false will fail if the device is offline.
   * @return {Promise<NetworkResponse>}
   */


  _createClass(MobileObject, [{
    key: "save",
    value: function save(saveIfOffline) {
      return this._getEndpoint()._save(this, saveIfOffline);
    }
    /**
     * Saves any changes to the object back to the service.
     * @function
     * @name MobileObject#delete
     * @param deleteIfOffline {Boolean} If true will cache the delete locally and sync back to the service if the device is offline; if false will fail if the device is offline.
     * @return {Promise<NetworkResponse>}
     */

  }, {
    key: "delete",
    value: function _delete(deleteIfOffline) {
      return this._getEndpoint()._delete(this, deleteIfOffline);
    }
  }]);

  return MobileObject;
}(_mobileResource.MobileResource);

exports.MobileObject = MobileObject;


},{"../sync-resource-type":39,"./mobile-resource":30}],30:[function(require,module,exports){
'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
 *
 * @author Yuri Panshin
 */
/**
 * Base class for MobileObject, MobileCollection and MobileFile.
 * @abstract
 * @private
 */
var MobileResource = function () {
    function MobileResource(endpoint, uri) {
        _classCallCheck(this, MobileResource);

        this.endpoint = endpoint;
        this.uri = uri;
    }

    _createClass(MobileResource, [{
        key: '_getEndpoint',
        value: function _getEndpoint() {
            return this.endpoint;
        }
    }, {
        key: '_getMcsId',
        value: function _getMcsId() {
            return this.uri ? this.uri.substring(this.uri.lastIndexOf('/') + 1, this.uri.length) : null;
        }
    }, {
        key: '_getMcsURI',
        value: function _getMcsURI() {
            return this.uri;
        }
    }]);

    return MobileResource;
}();

exports.MobileResource = MobileResource;


},{}],31:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.DeleteProcessor = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _syncProcessor = require("./sync-processor");

var _types = require("../../types");

var _dictionary = require("../../dictionary");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                *
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @author Yuri Panshin
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


var DeleteProcessor = function (_SyncProcessor) {
    _inherits(DeleteProcessor, _SyncProcessor);

    function DeleteProcessor(backend, apiName, endpointPath, platform, utils, common, options) {
        _classCallCheck(this, DeleteProcessor);

        return _possibleConstructorReturn(this, (DeleteProcessor.__proto__ || Object.getPrototypeOf(DeleteProcessor)).call(this, backend, apiName, endpointPath, false, utils, platform, options, common));
    }

    _createClass(DeleteProcessor, [{
        key: "performRequest",
        value: function performRequest(url) {
            var headers = this.getHttpHeaders(new _dictionary.Dictionary([]));
            return this.platform.invokeService({
                method: _types.HTTP_METHODS.DELETE,
                url: url,
                module: _types.MODULE_NAMES.SYNC,
                headers: headers
            });
        }
    }]);

    return DeleteProcessor;
}(_syncProcessor.SyncProcessor);

exports.DeleteProcessor = DeleteProcessor;


},{"../../dictionary":12,"../../types":41,"./sync-processor":35}],32:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.GetProcessor = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _syncProcessor = require("./sync-processor");

var _types = require("../../types");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                *
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @author Yuri Panshin
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


var GetProcessor = function (_SyncProcessor) {
    _inherits(GetProcessor, _SyncProcessor);

    function GetProcessor(backend, apiName, endpointPath, platform, utils, common, options) {
        _classCallCheck(this, GetProcessor);

        return _possibleConstructorReturn(this, (GetProcessor.__proto__ || Object.getPrototypeOf(GetProcessor)).call(this, backend, apiName, endpointPath, false, utils, platform, options, common));
    }

    _createClass(GetProcessor, [{
        key: "performRequest",
        value: function performRequest(url, requestHeaders, fetchFromService) {
            var headers = this.getHttpHeaders(requestHeaders);
            return this.platform.invokeService({
                method: _types.HTTP_METHODS.GET,
                url: url,
                headers: headers,
                module: _types.MODULE_NAMES.SYNC
            }).then(success.bind(this));
            function success(response) {
                return {
                    uri: this.getUri(response, url),
                    data: response.data
                };
            }
        }
    }]);

    return GetProcessor;
}(_syncProcessor.SyncProcessor);

exports.GetProcessor = GetProcessor;


},{"../../types":41,"./sync-processor":35}],33:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.PostProcessor = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _syncProcessor = require("./sync-processor");

var _types = require("../../types");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                *
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @author Yuri Panshin
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


var PostProcessor = exports.PostProcessor = function (_SyncProcessor) {
    _inherits(PostProcessor, _SyncProcessor);

    function PostProcessor(backend, apiName, endpointPath, platform, utils, common, options) {
        _classCallCheck(this, PostProcessor);

        return _possibleConstructorReturn(this, (PostProcessor.__proto__ || Object.getPrototypeOf(PostProcessor)).call(this, backend, apiName, endpointPath, false, utils, platform, options, common));
    }

    _createClass(PostProcessor, [{
        key: "performRequest",
        value: function performRequest(url, requestHeaders, requestData) {
            var headers = this.getHttpHeaders(requestHeaders);
            return this.platform.invokeService({
                method: _types.HTTP_METHODS.POST,
                url: url,
                headers: headers,
                data: requestData,
                module: _types.MODULE_NAMES.SYNC
            }).then(success.bind(this));
            function success(response) {
                return {
                    uri: this.getUri(response, url),
                    data: response.data
                };
            }
        }
    }]);

    return PostProcessor;
}(_syncProcessor.SyncProcessor);


},{"../../types":41,"./sync-processor":35}],34:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.PutProcessor = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _syncProcessor = require("./sync-processor");

var _types = require("../../types");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                *
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @author Yuri Panshin
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


var PutProcessor = exports.PutProcessor = function (_SyncProcessor) {
    _inherits(PutProcessor, _SyncProcessor);

    function PutProcessor(backend, apiName, endpointPath, platform, utils, common, options) {
        _classCallCheck(this, PutProcessor);

        return _possibleConstructorReturn(this, (PutProcessor.__proto__ || Object.getPrototypeOf(PutProcessor)).call(this, backend, apiName, endpointPath, false, utils, platform, options, common));
    }

    _createClass(PutProcessor, [{
        key: "performRequest",
        value: function performRequest(url, requestHeaders, requestData) {
            var headers = this.getHttpHeaders(requestHeaders);
            return this.platform.invokeService({
                method: _types.HTTP_METHODS.PUT,
                url: url,
                headers: headers,
                data: requestData,
                module: _types.MODULE_NAMES.SYNC
            }).then(success.bind(this));
            function success(response) {
                return {
                    uri: this.getUri(response, url),
                    data: response.data
                };
            }
        }
    }]);

    return PutProcessor;
}(_syncProcessor.SyncProcessor);


},{"../../types":41,"./sync-processor":35}],35:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.SyncProcessor = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _syncResourceType = require("../sync-resource-type");

var _mcsRequestHandler = require("../sync-express/mcs-request-handler");

var _types = require("../../types");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var SyncProcessor = exports.SyncProcessor = function () {
    function SyncProcessor(backend, apiName, endpointPath, resolvingOfflineUpdate, utils, platform, options, common) {
        _classCallCheck(this, SyncProcessor);

        this.backend = backend;
        this.apiName = apiName;
        this.endpointPath = endpointPath;
        this.resolvingOfflineUpdate = resolvingOfflineUpdate;
        this.utils = utils;
        this.platform = platform;
        this.options = options;
        this.common = common;
    }

    _createClass(SyncProcessor, [{
        key: "getHttpHeaders",
        value: function getHttpHeaders(requestHeaders) {
            var headers = this.backend.getHttpHeaders(requestHeaders);
            headers.add(_types.HEADERS.ORACLE_MOBILE_SYNC_AGENT, 'true');
            return headers;
        }
    }, {
        key: "getType",
        value: function getType(responseHeaders, responseData) {
            var type = _syncResourceType.SyncResourceType.file;
            var resourceType = responseHeaders[_types.HEADERS.ORACLE_MOBILE_SYNC_RESOURCE_TYPE.toLowerCase()];
            if (resourceType != null) {
                if (resourceType === _types.RESOURCE_TYPES.ITEM) {
                    type = _syncResourceType.SyncResourceType.item;
                } else if (resourceType === _types.RESOURCE_TYPES.COLLECTION) {
                    type = _syncResourceType.SyncResourceType.collection;
                }
            } else {
                if (this.common.isString(responseData)) {
                    try {
                        var json = JSON.parse(responseData);
                        if (this.common.isArray(json)) {
                            type = _syncResourceType.SyncResourceType.collection;
                        } else {
                            type = _syncResourceType.SyncResourceType.item;
                        }
                    } catch (e) {
                        type = _syncResourceType.SyncResourceType.file;
                    }
                }
            }
            return type;
        }
    }, {
        key: "getUri",
        value: function getUri(response, url) {
            var location = response && response.headers ? response.headers[_types.HEADERS.LOCATION.toLowerCase()] : null;
            if (location != null) {
                return '/' + location;
            } else {
                var obj = null;
                if (response.data) {
                    if (typeof response.data === 'string') {
                        obj = response.data != '' ? JSON.parse(response.data) : null;
                    } else {
                        obj = response.data;
                    }
                }
                if (obj && obj[_mcsRequestHandler.McsRequestHandler.URI_KEY]) {
                    var uri = obj[_mcsRequestHandler.McsRequestHandler.URI_KEY];
                    delete obj[_mcsRequestHandler.McsRequestHandler.URI_KEY];
                    return uri;
                } else {
                    return this.options.parseURL(url).path;
                }
            }
        }
    }, {
        key: "createResource",
        value: function createResource(method, url, statusCode, requestHeaders, responseHeaders, requestData, responseData, response) {
            var location = response.headers[_types.HEADERS.LOCATION.toLowerCase()];
            if (location != null) {
                location = '/' + location;
            } else {
                location = url;
            }
            var type = _syncResourceType.SyncResourceType.file;
            var resourceType = responseHeaders[_types.HEADERS.ORACLE_MOBILE_SYNC_RESOURCE_TYPE.toLowerCase()];
            if (resourceType != null) {
                if (resourceType == _types.RESOURCE_TYPES.ITEM) {
                    type = _syncResourceType.SyncResourceType.item;
                } else if (resourceType == _types.RESOURCE_TYPES.COLLECTION) {
                    type = _syncResourceType.SyncResourceType.collection;
                }
            } else {
                if (this.common.isString(responseData)) {
                    try {
                        var json = JSON.parse(responseData);
                        if (this.common.isArray(json)) {
                            type = _syncResourceType.SyncResourceType.collection;
                        } else {
                            type = _syncResourceType.SyncResourceType.item;
                        }
                    } catch (e) {
                        type = _syncResourceType.SyncResourceType.file;
                    }
                }
            }
            return null;
        }
    }]);

    return SyncProcessor;
}();


},{"../../types":41,"../sync-express/mcs-request-handler":37,"../sync-resource-type":39}],36:[function(require,module,exports){
'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.DB = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _logger = require('../../logger');

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Creates the offline database and return base API for external usage.
 * @ignore
 * @type {{getDB, getCollection, getCollectionByName, getCollections, save, close, flush}}
 */
var DB = exports.DB = function () {
    function DB(name, $options) {
        var _this = this;

        _classCallCheck(this, DB);

        this.name = name;
        this.$options = $options;
        /**
         * Create internal JS offline persistence db.
         */
        this._db = null;
        this.options = {
            autosave: true,
            autosaveInterval: 500,
            autoload: true,
            adapter: null
        };
        this.logger = new _logger.Logger('DB');
        if ($options.isCordova) {
            if (typeof LokiCordovaFSAdapter === 'function') {
                this.options.adapter = new LokiCordovaFSAdapter({ "prefix": "loki" });
            } else {
                this.logger.warn('LokiCordovaFSAdapter is not installed');
            }
        }
        if ($options.isCordova) {
            $options.deviceReady(function () {
                _this.init();
            });
        } else {
            $options.ready(this.init.bind(this));
        }
    }


    _createClass(DB, [{
        key: 'init',
        value: function init(name) {
            if (this.$options.off === true || this.$options.isTest === true) {
                this.options = {
                    autosave: false,
                    autosaveInterval: 60 * 1000 * 60 * 24 * 30 * 12,
                    autoload: false,
                    adapter: null
                };
            }
            var dbName = this.name || name || this.$options.offlineDBName || 'offline';
            this._db = new loki(dbName, this.options);
            this._db.loadDatabase();
        }
        /**
         * Wraps the way collection should be taken from the database. If given collection name does not exist
         * it will create it.
         *
         * @param name - the name of the collection to get, create
         * @returns {*}
         */

    }, {
        key: 'getCollectionByName',
        value: function getCollectionByName(name) {
            var col = this._db.getCollection(name);
            if (!col) {
                var options = {
                    clone: true,
                    disableChangesApi: true,
                    transactional: true // make sure that operations are transactional
                };
                col = this._db.addCollection(name, options);
            }
            return col;
        }
        /**
         * Return collection directly with promise. If collection does not exist it will be created.
         *
         * @param name - the name of the database collection
         * @returns {*}
         * @deprecated
         */

    }, {
        key: 'getCollection',
        value: function getCollection(name) {
            var _this2 = this;

            return new Promise(function (resolve) {
                _this2._db.loadDatabase({}, function () {
                    var col = _this2._db.getCollection(name);
                    if (!col) {
                        var options = {
                            clone: true,
                            disableChangesApi: true,
                            transactional: true // make sure that operations are transactional
                        };
                        col = _this2._db.addCollection(name /*, options*/);
                    }
                    resolve(col);
                });
            });
        }
        /**
         * In case developer explicitly wants to save the database, after db operation.
         */

    }, {
        key: 'saveDatabase',
        value: function saveDatabase() {
            this._db.save();
        }
        /**
         * Returns all registered collections from the offline database.
         */

    }, {
        key: 'getCollections',
        value: function getCollections() {
            return this._db.listCollections();
        }
        /**
         * Return the object to the internal created database
         * @returns {*}
         */

    }, {
        key: 'internalDB',
        value: function internalDB() {
            return this._db;
        }
        /**
         * Emits a close event with an optional callback. Note that this does not destroy the db or collections,
         * it's a utility method that can be called before closing the process or 'onbeforeunload' in a browser.
         *
         * @param callback - optional
         */

    }, {
        key: 'close',
        value: function close(callback) {
            this._db.close(callback);
        }
        /**
         * This will go through all database collections and remove the data from them.
         */

    }, {
        key: 'flush',
        value: function flush() {
            var self = this;
            return new Promise(function (resolve) {
                var collections = self.getCollections();
                for (var i = 0; i < collections.length; i++) {
                    self.getCollectionByName(collections[i].name).removeDataOnly();
                }
                resolve(true);
            });
        }
    }]);

    return DB;
}();


},{"../../logger":13}],37:[function(require,module,exports){
'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.McsRequestHandler = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _requestHandler = require('./request-handler');

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               *
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               * @authors Lyudmil Pelov
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               */


/**
 * This module provide the MCS Persistent capabilities
 * @ignore
 * @type {{}}
 */
var McsRequestHandler = exports.McsRequestHandler = function (_RequestHandler) {
    _inherits(McsRequestHandler, _RequestHandler);

    function McsRequestHandler(options, common, utils) {
        _classCallCheck(this, McsRequestHandler);

        return _possibleConstructorReturn(this, (McsRequestHandler.__proto__ || Object.getPrototypeOf(McsRequestHandler)).call(this, 'mcs-request', options, common, utils));
    }

    _createClass(McsRequestHandler, [{
        key: 'buildResponseObject',
        value: function buildResponseObject(obj) {
            return obj;
        }
    }, {
        key: 'getResponsePayload',
        value: function getResponsePayload(response) {
            return response.data;
        }
    }, {
        key: 'getModuleName',
        value: function getModuleName() {
            return 'MCS';
        }
        /**
         * Check to see if this was also MCS payload!
         *
         * @param request
         * @returns {boolean}
         */

    }, {
        key: 'isPersistentGetRequest',
        value: function isPersistentGetRequest(request) {
            _get(McsRequestHandler.prototype.__proto__ || Object.getPrototypeOf(McsRequestHandler.prototype), 'isPersistentGetRequest', this).call(this, request);
            var resourceTypeHeader = McsRequestHandler.HEADER_RESOURCE_TYPE in request || request.headers[McsRequestHandler.HEADER_RESOURCE_TYPE];
            if (resourceTypeHeader === 'collection') {
                if (this.$common.isEmpty(request.data)) {
                    throw new Error('cannot proceed with empty payload');
                }
                if (!('items' in request.data)) {
                    throw new Error('items is not in the payload returned from MCS, probably not Sync Custom Code');
                }
                if (!('uris' in request.data)) {
                    throw new Error('url is not in the payload returned from MCS, probably not Sync Custom Code');
                }
                if (!('etags' in request.data)) {
                    throw new Error('etags is not in the payload returned from MCS, probably not Sync Custom Code');
                }
            } else if (resourceTypeHeader !== 'item') {
                throw new Error('oracle-mobile-sync-resource-type is not in the headers returned from MCS, probably not Sync Custom Code');
            }
            return true;
        }
        /**
         * Transform the payload and add it into the $db!
         *
         * NOTE: Such a transformations could hold a lot of resources!
         *
         * @param collection
         * @param payload
         * @returns {*}
         */

    }, {
        key: 'handleMcsGetCollectionPayload',
        value: function handleMcsGetCollectionPayload(payload, collection) {
            var size = payload.items.length;
            var now = Date.now();
            for (var i = 0; i < size; i++) {
                var item = payload.items[i];
                item[McsRequestHandler.URI_KEY] = parseUri((this.$common.stringStartsWith(payload.uris[i], '/') ? '' : '/') + payload.uris[i]).path;
                item[McsRequestHandler.ETAG_KEY] = payload.etags[i];
                var query = {};
                query[McsRequestHandler.URI_KEY] = item[McsRequestHandler.URI_KEY];
                var result = collection.findOne(query);
                if (result) {
                    this.$common.extendOwn(result, item);
                    collection.update(result);
                } else {
                    collection.insert(item);
                }
            }
            collection.removeWhere(function (dbObj) {
                return dbObj.meta.updated < now;
            });
            return collection.find();
        }
        /**
         * Handle item payload from the MCS
         *
         * @param collection
         * @param payload
         * @param path
         * @returns {*}
         */

    }, {
        key: 'handleMcsGetItemPayload',
        value: function handleMcsGetItemPayload(collection, payload, path) {
            var query = {};
            query[McsRequestHandler.URI_KEY] = path;
            var result = collection.findOne(query);
            if (result) {
                var item = payload;
                this.$common.extendOwn(result, item);
                return collection.update(result);
            } else {
                var item = payload;
                item[McsRequestHandler.URI_KEY] = path;
                return collection.insert(item);
            }
        }
        /**
         * If nothing in the payload check get what is in the offline $db!
         * @param response - response is always array of objects!
         */

    }, {
        key: 'handleGet',
        value: function handleGet(response) {
            var persistentPath = this.$options.isPersistentUrl(response.url);
            if (persistentPath === false) {
                throw new Error('Persistence.handleMcsGet()-> URI was not configured for persistence:' + response.url);
            }
            var collection = this.$db.getCollectionByName(persistentPath.root);
            if (this.$common.isEmpty(persistentPath.params)) {
                var result = collection.find();
                var data = {
                    items: [],
                    uris: [],
                    etags: []
                };
                for (var idx in result) {
                    if (result[idx].hasOwnProperty(McsRequestHandler.URI_KEY)) {
                        data.uris.push(result[idx][McsRequestHandler.URI_KEY]);
                        delete result[idx][McsRequestHandler.URI_KEY];
                    }
                    if (result[idx].hasOwnProperty(McsRequestHandler.ETAG_KEY)) {
                        data.etags.push(result[idx][McsRequestHandler.ETAG_KEY]);
                        delete result[idx][McsRequestHandler.ETAG_KEY];
                    }
                    var cleanObject = this.$common.cleanObject(result[idx]);
                    data.items.push(cleanObject);
                }
                return data;
            }
            var query = {};
            query[McsRequestHandler.URI_KEY] = persistentPath.path;
            return this.$common.cleanObject(collection.findOne(query));
        }

    }, {
        key: 'handleGetStore',
        value: function handleGetStore(response) {
            var persistentPath = this.$options.isPersistentUrl(response.url);
            if (persistentPath === false) {
                throw new Error('Persistence.handleMcsGetStore()-> URI was not configured for persistence:' + response.url);
            }
            var collection = this.$db.getCollectionByName(persistentPath.root);
            var payload = response.data;
            var resourceTypeHeader = McsRequestHandler.HEADER_RESOURCE_TYPE in response || response.headers[McsRequestHandler.HEADER_RESOURCE_TYPE];
            if (resourceTypeHeader === 'collection') {
                return this.handleMcsGetCollectionPayload(payload, collection);
            } else if (resourceTypeHeader === 'item') {
                return this.handleMcsGetItemPayload(collection, payload, persistentPath.path);
            } else if (resourceTypeHeader) {
                this.logger.error('unknown Oracle-Mobile-Sync-Resource-Type (%s)', resourceTypeHeader);
                throw new Error('unknown Oracle-Mobile-Sync-Resource-Type');
            } else {
                this.logger.error('this is not MCS response, unable to handle the payload, no MCS header was specified: ', response);
                throw new Error('this is not MCS response, unable to handle the payload, no MCS header was specified');
            }
        }
        /**
         * Currently posts supports only adding new objects into the root!
         *
         * @param response
         * @param force
         */

    }, {
        key: 'handlePost',
        value: function handlePost(response, force) {
            var persistentPath = this.$options.isPersistentUrl(response.url);
            if (persistentPath === false) {
                throw new Error('Persistence.handleMcsPost()-> URI was not configured for persistence:' + response.url);
            }
            var collection = this.$db.getCollectionByName(persistentPath.root);
            var payload = response.data;
            if (!this.$common.isEmpty(persistentPath.params)) {
                throw new Error('you can add new objects only against the root REST resource endpoint');
            }
            if (this.$common.isArray(payload)) {
                throw new Error("the payload cannot be array");
            }
            else if (this.$common.isObject(payload) && !this.$common.isNull(payload) && !this.$common.isFunction(payload)) {
                    if (response.data && response.data[McsRequestHandler.URI_KEY]) {
                        return this.updatePayloadWithNewUri(collection, response);
                    } else {
                        var uri = null;
                        if (response && response.headers && response.headers[McsRequestHandler.HEADER_LOCATION]) {
                            uri = this.$common.stringStartsWith(response.headers[McsRequestHandler.HEADER_LOCATION], '/') ? response.headers[McsRequestHandler.HEADER_LOCATION] : '/' + response.headers[McsRequestHandler.HEADER_LOCATION];
                        }
                        var result = null;
                        if (uri) {
                            var query = {};
                            query[McsRequestHandler.URI_KEY] = uri;
                            result = collection.findOne(query);
                        }
                        if (!result) {
                            payload[McsRequestHandler.ETAG_KEY] = '"0-1B2M2Y8AsgTpgAmY7PhCfg"'; // empty e-tag
                            result = collection.insert(payload);
                            this.markObjAsOfflineIfForced(result, force);
                        } else {
                            this.$common.extendOwn(result, response.data);
                        }
                        if (!uri) {
                            var key = persistentPath.tokens.length > 0 && /^\w+$/.test(persistentPath.tokens[0].name) ? persistentPath.tokens[0].name : null;
                            var value = null;
                            if (key) {
                                value = response.data.hasOwnProperty(key) ? response.data[key] : this.$common.getUID();
                            }
                            uri = value === null ? persistentPath.root + '/' + this.$common.getUID() : persistentPath.root + '/' + value;
                        }
                        result[McsRequestHandler.URI_KEY] = uri;
                        return collection.update(result);
                    }
                }
            throw new Error("don't know what to do with the payload");
        }
    }, {
        key: 'updatePayloadWithNewUri',
        value: function updatePayloadWithNewUri(collection, response) {
            var query = {};
            query[McsRequestHandler.URI_KEY] = response.data[McsRequestHandler.URI_KEY];
            var result = collection.findOne(query);
            if (result) {
                this.$common.extendOwn(result, response.data);
                result[McsRequestHandler.URI_KEY] = this.$common.stringStartsWith(response.headers[McsRequestHandler.HEADER_LOCATION], '/') ? response.headers[McsRequestHandler.HEADER_LOCATION] : '/' + response.headers[McsRequestHandler.HEADER_LOCATION];
                return collection.update(result);
            } else {
                throw new Error("the payload was not found in collection:" + query[McsRequestHandler.URI_KEY]);
            }
        }
        /**
         * Currently posts supports only adding new objects into the root!
         *
         * @param response
         * @param force
         */

    }, {
        key: 'handlePut',
        value: function handlePut(response, force) {
            var persistentPath = this.$options.isPersistentUrl(response.url);
            if (persistentPath === false) {
                throw new Error('Persistence.handleMcsPut()-> URI was not configured for persistence:' + response.url);
            }
            var collection = this.$db.getCollectionByName(persistentPath.root);
            var payload = response.data;
            if (!this.$common.isEmpty(persistentPath.params)) {
                if (this.$common.isArray(payload)) {
                    throw new Error("the payload cannot be array");
                }
                else if (this.$common.isObject(payload) && !this.$common.isNull(payload) && !this.$common.isFunction(payload)) {
                        var query = {};
                        query[McsRequestHandler.URI_KEY] = persistentPath.path;
                        var result = collection.findOne(query);
                        if (result) {
                            this.$common.extendOwn(result, payload);
                            this.markObjAsOfflineIfForced(result, force);
                            return collection.update(result);
                        }
                    }
            }
            throw new Error("you can execute update operations only against existing items in the offline database!");
        }
        /**
         *
         * @param response
         * @returns {*}
         */

    }, {
        key: 'handleDelete',
        value: function handleDelete(response) {
            var persistentPath = this.$options.isPersistentUrl(response.url);
            if (persistentPath === false) {
                throw new Error('Persistence.handleMcsDelete()-> URI was not configured for persistence:' + response.url);
            }
            var collection = this.$db.getCollectionByName(persistentPath.root);
            var payload = response.data;
            if (!this.$common.isEmpty(persistentPath.params)) {
                var query = {};
                query[McsRequestHandler.URI_KEY] = persistentPath.path;
                var findOne = collection.findOne(query);
                if (findOne) {
                    return collection.remove(findOne);
                }
                throw new Error('unable to find object with the given ID(%s) in the database' /*, response.url*/);
            }
        }
    }, {
        key: 'data',
        value: function data(path) {
            function doData(path) {
                var persistentPath = this.$options.isPersistentUrl(path);
                if (!persistentPath) {
                    throw new Error('Persistence.BaseModule.data() given URI not configured for persistence: ' + path);
                }
                return this.$db.getCollectionByName(persistentPath.root);
            }
            return new Promise(function (resolve) {
                return resolve(doData(path));
            });
        }

    }, {
        key: 'router',
        value: function router(request) {
            var _this2 = this;

            var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

            return new Promise(function (resolve) {
                if (!_this2.$common.isObject(request)) {
                    console.error('Passed object is not defined request!', request);
                    throw new Error('Passed object is not defined request!');
                }
                if (!request.hasOwnProperty('method')) {
                    _this2.logger.error('request.method was not provided!', request);
                    throw new Error('request.method was not provided!');
                }
                var _request = _this2.$common.clone(request);
                _request.method = _this2.$utils._normalizeMethod(_request.method);
                if (!_this2[_request.method]) {
                    _this2.logger.error('specified router is not implemented!');
                    throw new Error('specified router is not implemented!');
                }
                var result = _this2[_request.method](_request, force);
                resolve(result);
            });
        }

    }, {
        key: 'get',
        value: function get(request) {
            var _this3 = this;

            var doGet = function doGet(request) {
                _this3.logger.info('get()');
                _this3.isPersistentRequest(request);
                var _request = _this3.$common.clone(request);
                if (!_request.hasOwnProperty('data') || _this3.$common.isEmpty(_request.data)) {
                    return _this3.$common.clone(_this3.handleGet(_request));
                }
                _this3.isPersistentGetRequest(request);
                return _this3.$common.clone(_this3.handleGetStore(_request));
            };
            return new Promise(function (resolve) {
                resolve(doGet(request));
            });
        }
    }]);

    return McsRequestHandler;
}(_requestHandler.RequestHandler);

McsRequestHandler.URI_KEY = '$mcs$mcsPersistenceURI';
McsRequestHandler.ETAG_KEY = '$mcs$etag';
McsRequestHandler.HEADER_LOCATION = "location";
McsRequestHandler.HEADER_RESOURCE_TYPE = "oracle-mobile-sync-resource-type";


},{"./request-handler":38}],38:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.RequestHandler = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     *
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     * @authors Lyudmil Pelov
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     */


var _db = require("./db");

var _logger = require("../../logger");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var RequestHandler = exports.RequestHandler = function () {
    function RequestHandler(dbname, $options, $common, $utils) {
        var _this = this;

        _classCallCheck(this, RequestHandler);

        this.dbname = dbname;
        this.$options = $options;
        this.$common = $common;
        this.$utils = $utils;
        this.logger = new _logger.Logger('RequestHandler');
        this.prefix = $options.dbPrefix;
        this.$db = new _db.DB(this.prefix + '.' + this.dbname, $options);
        $options.onDbPrefixChange = function (oldVal, newVal) {
            _this.$db = new _db.DB(newVal + '.' + _this.dbname, $options);
        };
    }

    _createClass(RequestHandler, [{
        key: "isPersistentRequest",
        value: function isPersistentRequest(request) {
            if (!request) {
                throw new Error('request cannot be undefined or null value');
            }
            if (!this.$common.isObject(request)) {
                throw new Error('request has to be defined object with properties like: url, data etc.');
            }
            if (this.$common.isEmpty(request)) {
                throw new Error('request cannot be empty object, it request properties like: url, data etc.');
            }
            if (this.$common.isArray(request) || this.$common.isFunction(request)) {
                throw new Error('request cannot be array or function');
            }
            if (!('url' in request)) {
                throw new Error('request.url was not specified');
            }
            return true;
        }
    }, {
        key: "isPersistentGetRequest",
        value: function isPersistentGetRequest(request) {
            this.isPersistentRequest(request);
            return true;
        }
    }, {
        key: "isPostRequest",
        value: function isPostRequest(request) {
            this.isPersistentRequest(request);
            if (!('data' in request)) {
                throw new Error('request.data was not defined!');
            }
            if (!this.$common.isObject(request.data)) {
                throw new Error('request.data is not a object or array!');
            }
            if (this.$common.isFunction(request.data)) {
                throw new Error('request.data cannot be function');
            }
            return true;
        }
    }, {
        key: "isOfflinePersistObj",
        value: function isOfflinePersistObj(obj) {
            return !!('meta' in obj && obj.meta.hasOwnProperty('offline-persist'));
        }
    }, {
        key: "isLokiDbObj",
        value: function isLokiDbObj(obj) {
            return !!('$loki' in obj && typeof obj.$loki === 'number' && !isNaN(obj.$loki));
        }
    }, {
        key: "buildFindQueryBasedOnUrlParams",
        value: function buildFindQueryBasedOnUrlParams(urlQueryParams) {
            var dbQuery = {};
            if (urlQueryParams.attr.length > 0) {
                var key = urlQueryParams.attr[0].name;
                dbQuery[key] = urlQueryParams.attr[0].pattern.indexOf('\d') >= 0 ? parseInt(urlQueryParams.attr[0].value) : urlQueryParams.attr[0].value + "";
            }
            return dbQuery;
        }
    }, {
        key: "buildUniqueIDValue",
        value: function buildUniqueIDValue(isPersistentUrl, value) {
            var isInt = function isInt() {
                if (isPersistentUrl.uri.tokens.length > 1) {
                    return isPersistentUrl.uri.tokens[isPersistentUrl.uri.tokens.length - 1].pattern.indexOf('\d') >= 0;
                } else {
                    return false;
                }
            };
            var parse = function parse(value) {
                return isInt() ? parseInt(value) : value + "";
            };
            if (this.$common.isEmpty(value)) {
                return parse(this.$common.getUID());
            }
            if (typeof value === 'number' && isInt()) {
                return value;
            }
            return parse(value);
        }
        /**
         * Transform the payload and add it into the $db!
         *
         * NOTE: Such a transformations could hold a lot of resources!
         *
         * @param collection
         * @param isPersistentUrl
         * @param payload
         * @returns {*}
         */

    }, {
        key: "handleGetRootArrayPayload",
        value: function handleGetRootArrayPayload(payload, isPersistentUrl, collection) {
            var _this2 = this;
            if (isPersistentUrl.uri.tokens.length > 1) {
                var dbArray = collection.find();
                if (dbArray.length > 0) {
                    var keyNameToCompare = isPersistentUrl.uri.tokens[1].name;
                    collection.removeWhere(function (dbObj) {
                        var foundObjectIndex = payload.findIndex(function (payloadObj) {
                            return payloadObj[keyNameToCompare] === dbObj[keyNameToCompare];
                        });
                        if (foundObjectIndex > -1) {
                            try {
                                if (_this2.isOfflinePersistObj(dbObj)) {
                                    dbObj = _this2.$common.deepExtend(payload[foundObjectIndex], dbObj);
                                } else {
                                    _this2.$common.extendOwn(dbObj, payload[foundObjectIndex]);
                                }
                                collection.update(dbObj);
                                payload.splice(foundObjectIndex, 1);
                            } catch (e) {
                                _this2.logger.error(e);
                            } finally {
                                return false;
                            }
                        } else {
                            if (_this2.isOfflinePersistObj(dbObj)) {
                                return false;
                            }
                            return true;
                        }
                    });
                    payload.forEach(function (obj) {
                        if (_this2.isLokiDbObj(obj)) {
                            collection.update(obj);
                        } else {
                            collection.insert(obj);
                        }
                    });
                    return collection.find();
                }
                return collection.insert(payload);
            }
            collection.removeWhere(function (obj) {
                return !_this2.isOfflinePersistObj(obj);
            });
            return collection.insert(payload);
        }
    }, {
        key: "handleGetRootObjectPayload",
        value: function handleGetRootObjectPayload(payload, isPersistentUrl, collection) {
            var _this3 = this;
            if (isPersistentUrl.uri.tokens.length > 1) {
                var keyNameToCompare = isPersistentUrl.uri.tokens[1].name;
                if (!payload.hasOwnProperty(keyNameToCompare)) {
                    this.logger.error('payload does not contain unique key specified in the URL settings');
                    throw new Error('payload does not contain unique key specified in the URL settings');
                }
                var findObjByKeyQuery = {};
                findObjByKeyQuery[keyNameToCompare] = payload[keyNameToCompare];
                var result = collection.findOne(findObjByKeyQuery);
                if (result) {
                    if (this.isOfflinePersistObj(result)) {
                        result = this.$common.deepExtend(payload, result);
                    } else {
                        this.$common.extendOwn(result, payload);
                    }
                    return collection.update(result);
                }
                return collection.insert(payload);
            }
            collection.removeWhere(function (obj) {
                return !_this3.isOfflinePersistObj(obj);
            });
            return collection.insert(payload);
        }
        /**
         * Build nested property structure to be used in GET calls to setup or edit existing objects!
         *
         * @param queryParams  query parameters properties!
         * @returns {string}  prop1.prop2[value].prop3....
         * @deprecated  use buildNestedPropertyArrayParams
         */

    }, {
        key: "buildNestedPropertySearchString",
        value: function buildNestedPropertySearchString(queryParams) {
            var nestedProperty = "";
            if (queryParams.attr.length > 1) {
                for (var i = 1; i < queryParams.attr.length; i++) {
                    if (queryParams.attr[i].is) {
                        if (nestedProperty.length > 0) nestedProperty += "." + queryParams.attr[i].name;else nestedProperty += queryParams.attr[i].name;
                    }
                    else {
                            if (nestedProperty.length > 0) {
                                nestedProperty += "." + queryParams.attr[i].name + "[" + queryParams.attr[i].value + "]";
                            } else {
                                nestedProperty += queryParams.attr[i].value;
                            }
                        }
                }
            }
            return nestedProperty;
        }
        /**
         * Has to be build a string of properties which can be used when adding new elements!
         *
         * @param queryParams
         * @param isPersistentUrl
         * @param isNotGet
         *
         * @return {Array<persistenceUtils~Property>} - array of properties with parameters and values
         */

    }, {
        key: "buildNestedPropertyArrayParams",
        value: function buildNestedPropertyArrayParams(isPersistentUrl, queryParams) {
            var isNotGet = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
            var nestedProperty = [];
            var params = queryParams.attr;
            if (Array.isArray(params) && params.length > 0) {
                var tokens = isPersistentUrl.uri.tokens.length > 1 ? isPersistentUrl.uri.tokens.slice(1) : [];
                for (var i = 0; i < params.length; i++) {
                    var isLast = params.length - 1 == i;
                    if (params[i].is) {
                        nestedProperty.push({
                            name: params[i].name,
                            value: null,
                            isProperty: true,
                            isInteger: false
                        });
                        if (isLast && tokens[i + 1] && isNotGet) {
                            var isInt = this.$utils.isUrlRegexInteger(tokens[i + 1].pattern);
                            nestedProperty.push({
                                name: tokens[i + 1].name,
                                value: isInt ? this.$common.getUID() : this.$common.getUID() + "",
                                isProperty: false,
                                isInteger: isInt
                            });
                        }
                    }
                    else {
                            var proValue = params[i].value || this.$common.getUID();
                            nestedProperty.push({
                                name: params[i].name,
                                value: proValue,
                                isProperty: false,
                                isInteger: this.$utils.isUrlRegexInteger(tokens[i].pattern)
                            });
                        }
                }
            }
            return nestedProperty;
        }
        /**
         * Search for that nested object and add the new payload to it, if any!
         *
         * @param obj
         * @param persistentUrlObj
         * @param queryParams
         * @param payload
         * @param dbPayload {Object} - payload that exists in local database
         * @returns {{obj: *, result: *}}
         */

    }, {
        key: "createObjFromUrlParamsForExistingForPost",
        value: function createObjFromUrlParamsForExistingForPost(obj, persistentUrlObj, queryParams, payload, dbPayload) {
            var nestedProperty = this.buildNestedPropertyArrayParams(persistentUrlObj, queryParams);
            var result = obj;
            if (Array.isArray(nestedProperty) && nestedProperty.length > 0) {
                var nestedQuery;
                if (dbPayload) {
                    var key = this.getKeyForCurrentObject(persistentUrlObj, queryParams);
                    nestedQuery = {
                        key: key,
                        value: dbPayload[key.name]
                    };
                }
                result = this.$utils.setNestedProperty2(obj, nestedProperty, payload, nestedQuery);
            } else {
                this.$common.extendOwn(obj, payload);
            }
            return {
                obj: obj,
                result: result
            };
        }
        /**
         * Returns current nested item key token
         * @param persistentUrlObj
         * @param queryParams
         * @returns {*}
         */

    }, {
        key: "getKeyForCurrentObject",
        value: function getKeyForCurrentObject(persistentUrlObj, queryParams) {
            var length = queryParams.attr.length;
            return persistentUrlObj.uri.tokens[length + 1];
        }
        /**
         * In case of given DB object but we have URL with sub parameters, we have to check if those nested obj exist,
         * and create them if not and add the payload inside.
         *
         * @param obj - object form the offline DB
         * @param queryParams - URL parameters, usually what is returned from $utils.extractKeyValuesFromUrl2
         * @param payload - from the REST API call
         * @return {{obj: *, result: *}}
         * @param persistentUrlObj
         */

    }, {
        key: "createObjFromUrlParamsForGETAction",
        value: function createObjFromUrlParamsForGETAction(obj, persistentUrlObj, queryParams, payload) {
            var nestedProperty = this.buildNestedPropertyArrayParams(persistentUrlObj, queryParams, false);
            var result = obj;
            if (Array.isArray(nestedProperty) && nestedProperty.length > 0) {
                result = this.$utils.setNestedProperty2(obj, nestedProperty, payload);
            }
            return {
                obj: obj,
                result: result
            };
        }
        /**
         * Try to find that nested object when offline or when no payload in GET
         * @param obj
         * @param persistentUrlObj
         * @param queryParams
         * @returns {*}
         */

    }, {
        key: "getNestedPropertyFromUrlParamsForExisting",
        value: function getNestedPropertyFromUrlParamsForExisting(obj, persistentUrlObj, queryParams) {
            var nestedProperty = this.buildNestedPropertyArrayParams(persistentUrlObj, queryParams, false);
            if (Array.isArray(nestedProperty) && nestedProperty.length > 0) {
                return this.$utils.getNestedProperty(obj, nestedProperty);
            }
            return obj;
        }
        /**
         * If forces, you could mark the object to be stored in the DB only and not synced!
         *
         * @param obj
         * @param force
         * @returns {*}
         */

    }, {
        key: "markObjAsOfflineIfForced",
        value: function markObjAsOfflineIfForced(obj, force) {
            if (force) {
                if (this.isOfflinePersistObj(obj)) {
                    delete obj.meta['offline-persist'];
                }
                return obj;
            }
            if ('meta' in obj) {
                obj.meta['offline-persist'] = true;
                return obj;
            }
            obj['meta'] = {};
            obj.meta['offline-persist'] = true;
            return obj;
        }
        /**
         * Use only if you have no new data, empty payload, and you want to return everything from the db,
         * depending on the GET URL
         *
         * TODO: should be extended to be able to query sub element!
         * @param response{url}
         * @returns {*}
         */

    }, {
        key: "handleGet",
        value: function handleGet(response) {
            var parsed = this.$options.parseURL(response.url);
            var isPersistentUrl = this.$utils.isPersistUrl(parsed.path);
            if (!isPersistentUrl) {
                throw new Error('Persistence.RequestHandler.get() given URI was not configured for persistence:' + parsed.path);
            }
            var queryParams = this.$utils.extractKeyValuesFromUrl2(isPersistentUrl);
            var collection = this.$db.getCollectionByName(queryParams.root);
            var keyValueObj = this.buildFindQueryBasedOnUrlParams(queryParams);
            if (!this.$common.isEmpty(keyValueObj)) {
                var result = collection.findOne(keyValueObj);
                if (result) {
                    var nestedObject = this.getNestedPropertyFromUrlParamsForExisting(result, isPersistentUrl, queryParams);
                    var cleanObject = this.$common.cleanObject(nestedObject);
                    return this.buildResponseObject(cleanObject);
                } else {
                    return null; // TODO: check if generic handler fine with this response (from generic handler: return [];)
                }
            } else {
                this.logger.debug('return all from db');
                var cleanObjects = this.$common.cleanObjects(collection.find());
                return this.buildResponseObject(cleanObjects);
            }
        }
        /**
         * Response property
         * @typedef persistenceRequestHandler~Response
         * @property url {String}
         * @property data {Object}
         */
        /**
         * Stores/merges given payload into the offline db!
         *
         * @param response {persistenceRequestHandler~Response}
         * @returns {*}
         */

    }, {
        key: "handleGetStore",
        value: function handleGetStore(response) {
            var parsed = this.$options.parseURL(response.url);
            var isPersistentUrl = this.$utils.isPersistUrl(parsed.path);
            if (!isPersistentUrl) {
                throw new Error('Persistence.RequestHandler.get() given URI was not configured for persistence:' + parsed.path);
            }
            var queryParams = this.$utils.extractKeyValuesFromUrl2(isPersistentUrl);
            var collection = this.$db.getCollectionByName(queryParams.root);
            var payload = this.getResponsePayload(response);
            var keyValueObj = this.buildFindQueryBasedOnUrlParams(queryParams);
            if (!this.$common.isEmpty(keyValueObj)) {
                var result = collection.findOne(keyValueObj);
                var newObj = void 0;
                if (result) {
                    newObj = this.createObjFromUrlParamsForGETAction(result, isPersistentUrl, queryParams, payload);
                    collection.update(newObj.obj);
                } else {
                    newObj = this.createObjFromUrlParamsForGETAction(keyValueObj, isPersistentUrl, queryParams, payload);
                    collection.insert(newObj.obj);
                }
                return this.buildResponseObject(newObj.result);
            } else {
                if (this.$common.isArray(payload) && !this.$common.isFunction(payload) && !this.$common.isEmpty(payload)) {
                    var items = this.handleGetRootArrayPayload(payload, isPersistentUrl, collection);
                    return this.buildResponseObject(items);
                }
                else if (this.$common.isObject(payload) && !this.$common.isArray(payload) && !this.$common.isFunction(payload) && !this.$common.isEmpty(payload)) {
                        return this.handleGetRootObjectPayload(payload, isPersistentUrl, collection);
                    } else {
                        this.logger.error('handleGetStore', 'unknown or empty object passed for the operation');
                        throw new Error('RequestHandler.handleGetStore -> unknown or empty object passed for the operation');
                    }
            }
        }
        /**
         * Handle post array payload.
         *
         * @param payload
         * @param isPersistentUrl
         * @param collection
         * @param force
         * @returns {*}
         */

    }, {
        key: "handlePostRootArrayPayload",
        value: function handlePostRootArrayPayload(payload, isPersistentUrl, collection, force) {
            var _this4 = this;

            var keyNameToCompare = isPersistentUrl.uri.tokens.length > 1 ? isPersistentUrl.uri.tokens[1].name : null;
            payload.forEach(function (obj) {
                if (_this4.isLokiDbObj(obj)) {
                    _this4.markObjAsOfflineIfForced(obj, force);
                    collection.update(obj);
                }
                else if (keyNameToCompare && obj.hasOwnProperty(keyNameToCompare)) {
                        var result = collection.findOne({ keyNameToCompare: obj[keyNameToCompare] });
                        if (result) {
                            _this4.$common.extendOwn(result, obj);
                            _this4.markObjAsOfflineIfForced(result, force);
                            collection.update(result);
                        } else {
                            _this4.markObjAsOfflineIfForced(obj, force);
                            collection.insert(obj);
                        }
                    } else {
                        var objInsertResult = collection.insert(obj);
                        objInsertResult[keyNameToCompare] = _this4.buildUniqueIDValue(isPersistentUrl); //objInsertResult.$loki + "";
                        _this4.markObjAsOfflineIfForced(objInsertResult, force);
                        return _this4.$common.cleanObject(collection.update(objInsertResult));
                    }
            });
            return this.$common.cleanObjects(collection.find());
        }
        /**
         * Handle post create object from only simple json object
         * @param payload
         * @param isPersistentUrl
         * @param collection
         * @param force {Boolean} mark the object as offline
         * @returns {*}
         */

    }, {
        key: "handlePostRootObjectPayload",
        value: function handlePostRootObjectPayload(payload, isPersistentUrl, collection, force) {
            var keyNameToCompare = isPersistentUrl.uri.tokens.length > 1 ? isPersistentUrl.uri.tokens[1].name : '';
            if (keyNameToCompare && !payload.hasOwnProperty(keyNameToCompare)) {
                this.logger.info('get payload', "does not have the key specified in the URL settings");
                payload[keyNameToCompare] = '';
                var insertResult = collection.insert(payload);
                if (insertResult) {
                    insertResult[keyNameToCompare] = this.buildUniqueIDValue(isPersistentUrl); //insertResult.$loki + "";
                    this.markObjAsOfflineIfForced(insertResult, force);
                    return this.$common.cleanObject(collection.update(insertResult));
                }
                throw new Error('unable to store the payload object');
            }
            else if (keyNameToCompare && payload.hasOwnProperty(keyNameToCompare)) {
                    var queryForObject = {};
                    queryForObject[keyNameToCompare] = payload[keyNameToCompare];
                    var result = collection.findOne(queryForObject);
                    if (result) {
                        this.$common.extendOwn(result, payload);
                        this.markObjAsOfflineIfForced(result, force);
                        return this.$common.cleanObject(collection.update(result));
                    }
                    payload[keyNameToCompare] = this.buildUniqueIDValue(isPersistentUrl, payload[keyNameToCompare]);
                }
            this.markObjAsOfflineIfForced(payload, force);
            return this.$common.cleanObject(collection.insert(payload));
        }
        /**
         * Handle Post HTTP request!
         *
         * @param response {persistenceRequestHandler~Response}
         * @param force - it means that the meta['offline-persist'] property will be deleted to force update on next GET
         * @returns {*}
         */

    }, {
        key: "handlePost",
        value: function handlePost(response, force) {
            var parsed = this.$options.parseURL(response.url);
            var isPersistentUrl = this.$utils.isPersistUrl(parsed.path);
            if (!isPersistentUrl) {
                throw new Error('Persistence.RequestHandler.post() given URI not configured for persistence: ' + parsed.path);
            }
            var queryParams = this.$utils.extractKeyValuesFromUrl2(isPersistentUrl);
            var collection = this.$db.getCollectionByName(queryParams.root);
            var payload = response.data;
            var keyValueObj = this.buildFindQueryBasedOnUrlParams(queryParams);
            if (!this.$common.isEmpty(keyValueObj)) {
                var result = collection.findOne(keyValueObj);
                if (result) {
                    var newObj = this.createObjFromUrlParamsForExistingForPost(result, isPersistentUrl, queryParams, payload);
                    var propertyName = isPersistentUrl.uri.tokens[isPersistentUrl.uri.tokens.length - 1].name;
                    newObj.result[propertyName] = this.buildUniqueIDValue(isPersistentUrl, newObj.result[propertyName]);
                    this.markObjAsOfflineIfForced(newObj.obj, force);
                    collection.update(newObj.obj);
                    return this.$common.cleanObject(newObj.result);
                } else {
                    var newObj = this.createObjFromUrlParamsForExistingForPost(keyValueObj, isPersistentUrl, queryParams, payload);
                    this.markObjAsOfflineIfForced(newObj.obj, force);
                    collection.insert(newObj.obj);
                    return this.$common.cleanObject(newObj.result);
                }
            }
            if (this.$common.isArray(payload)) {
                return this.handlePostRootArrayPayload(payload, isPersistentUrl, collection, force);
            }
            else if (this.$common.isObject(payload) && !this.$common.isArray(payload) && !this.$common.isNull(payload)) {
                    return this.handlePostRootObjectPayload(payload, isPersistentUrl, collection, force);
                }
            throw new Error("don't know what to do with the payload");
        }
        /**
         * Works like HTTP post
         * https://gist.github.com/wookiehangover/877067
         *
         * @param response
         * @param force
         * @returns {*}
         */

    }, {
        key: "handlePut",
        value: function handlePut(response, force) {
            var parsed = this.$options.parseURL(response.url);
            var isPersistentUrl = this.$utils.isPersistUrl(parsed.path);
            if (!isPersistentUrl) {
                throw new Error('Persistence.RequestHandler.post() given URI not configured for persistence: ' + parsed.path);
            }
            var queryParams = this.$utils.extractKeyValuesFromUrl2(isPersistentUrl);
            var collection = this.$db.getCollectionByName(queryParams.root);
            var payload = response.data;
            var keyValueObj = this.buildFindQueryBasedOnUrlParams(queryParams);
            if (!this.$common.isEmpty(keyValueObj)) {
                var result = collection.findOne(keyValueObj);
                if (result) {
                    var newObj = this.createObjFromUrlParamsForExistingForPost(result, isPersistentUrl, queryParams, payload);
                    this.markObjAsOfflineIfForced(newObj.obj, force);
                    collection.update(newObj.obj);
                    return newObj.result;
                } else {
                    var newObj = this.createObjFromUrlParamsForExistingForPost(keyValueObj, isPersistentUrl, queryParams, payload);
                    this.markObjAsOfflineIfForced(newObj.obj, force);
                    collection.insert(newObj.obj);
                    return newObj.result;
                }
            }
            if (this.$common.isArray(payload)) {
                return this.handlePostRootArrayPayload(payload, isPersistentUrl, collection, force);
            }
            else if (this.$common.isObject(payload) && !this.$common.isArray(payload) && !this.$common.isNull(payload)) {
                    return this.handlePostRootObjectPayload(payload, isPersistentUrl, collection, force);
                }
            throw new Error('no key specified to recognise obj in the database for editing!');
        }
        /**
         * Works like HTTP post
         * https://gist.github.com/wookiehangover/877067
         *
         * @param response
         * @param force
         * @returns {*}
         */

    }, {
        key: "handlePatch",
        value: function handlePatch(response, force) {
            var parsed = this.$options.parseURL(response.url);
            var isPersistentUrl = this.$utils.isPersistUrl(parsed.path);
            if (!isPersistentUrl) {
                throw new Error('Persistence.RequestHandler.post() given URI not configured for persistence: ' + parsed.path);
            }
            var queryParams = this.$utils.extractKeyValuesFromUrl2(isPersistentUrl);
            var collection = this.$db.getCollectionByName(queryParams.root);
            var payload = response.data;
            var keyValueObj = this.buildFindQueryBasedOnUrlParams(queryParams);
            if (!this.$common.isEmpty(keyValueObj)) {
                var result = collection.findOne(keyValueObj);
                if (result) {
                    var newObj = this.createObjFromUrlParamsForExistingForPost(result, isPersistentUrl, queryParams, payload);
                    this.markObjAsOfflineIfForced(newObj.obj, force);
                    collection.update(newObj.obj);
                    return newObj.result;
                } else {
                    var newObj = this.createObjFromUrlParamsForExistingForPost(keyValueObj, isPersistentUrl, queryParams, payload);
                    this.markObjAsOfflineIfForced(newObj.obj, force);
                    collection.insert(newObj.obj);
                    return newObj.result;
                }
            }
            if (this.$common.isArray(payload)) {
                return this.handlePostRootArrayPayload(payload, isPersistentUrl, collection, force);
            }
            else if (this.$common.isObject(payload) && !this.$common.isArray(payload) && !this.$common.isNull(payload)) {
                    return this.handlePostRootObjectPayload(payload, isPersistentUrl, collection, force);
                }
            throw new Error('no key specified to recognise obj in the database for editing!');
        }
        /**
         * Delete specific element from the offline db
         *
         * @param request
         * @returns {*}
         */

    }, {
        key: "handleDelete",
        value: function handleDelete(request) {
            var parsed = this.$options.parseURL(request.url);
            var isPersistentUrl = this.$utils.isPersistUrl(parsed.path);
            if (!isPersistentUrl) {
                throw new Error('Persistence.RequestHandler.post() given URI not configured for persistence: ' + parsed.path);
            }
            var queryParams = this.$utils.extractKeyValuesFromUrl2(isPersistentUrl);
            var collection = this.$db.getCollectionByName(queryParams.root);
            var keyValueObj = this.buildFindQueryBasedOnUrlParams(queryParams);
            if (!this.$common.isEmpty(keyValueObj)) {
                var findOne = collection.findOne(keyValueObj);
                if (findOne) {
                    return this.$common.cleanObject(collection.remove(findOne));
                }
                throw new Error('unable to find object with the given ID(%s) in the database' /*, keyValueObj*/);
            }
            if (request.hasOwnProperty('data')) {
                var payload = request.data;
                if (!this.$common.isEmpty(payload) && this.$common.isObject(payload) && !this.$common.isArray(payload)) {
                    var keyNameToCompare = isPersistentUrl.uri.tokens.length > 1 ? isPersistentUrl.uri.tokens[1].name : null;
                    if (keyNameToCompare && !request.data.hasOwnProperty(keyNameToCompare)) {
                        throw new Error('payload does not have the key required to delete the object');
                    }
                    var findOne = collection.findOne({ keyNameToCompare: request.data[keyNameToCompare] });
                    if (findOne) {
                        return this.$common.cleanObject(collection.remove(findOne));
                    }
                }
            }
            this.logger.error('payload does not have the key required to delete the object in the payload');
            throw new Error('payload does not have the key required to delete the object in the payload');
        }
    }, {
        key: "postSuccessOperations",
        value: function postSuccessOperations(obj) {
            if (obj.syncObj.method === 'POST') {
                var cpObj = this.$common.clone(obj);
                var parsed = this.$options.parseURL(cpObj.syncObj.url);
                var isPersistentUrl = this.$utils.isPersistUrl(parsed.path);
                if (!isPersistentUrl) {
                    this.logger.debug('sync post success operation exist');
                    return obj;
                }
                var queryParams = this.$utils.extractKeyValuesFromUrl2(isPersistentUrl);
                var collection = this.$db.getCollectionByName(queryParams.root);
                var beforeSyncPayload = cpObj.syncObj.data;
                var response = cpObj.response;
                var keyValueObj = this.buildFindQueryBasedOnUrlParams(queryParams);
                if (!this.$common.isEmpty(keyValueObj)) {
                    var parent = collection.findOne(keyValueObj);
                    if (parent) {
                        var result = this.createObjFromUrlParamsForExistingForPost(parent, isPersistentUrl, queryParams, response, beforeSyncPayload);
                        var propertyName = isPersistentUrl.uri.tokens[isPersistentUrl.uri.tokens.length - 1].name;
                        result.result[propertyName] = this.buildUniqueIDValue(isPersistentUrl, result.result[propertyName]);
                        collection.update(result.obj);
                        return this.$common.cleanObject(result.result);
                    }
                    else {
                            var newObj = this.createObjFromUrlParamsForExistingForPost(keyValueObj, isPersistentUrl, queryParams, response);
                            collection.insert(newObj.obj);
                            return this.$common.cleanObject(newObj.result);
                        }
                }
                else {
                        var keyNameToCompare = isPersistentUrl.uri.tokens.length > 1 ? isPersistentUrl.uri.tokens[1].name : '';
                        if (keyNameToCompare && !beforeSyncPayload.hasOwnProperty(keyNameToCompare)) {
                            response = this.$common.extendOwn(beforeSyncPayload, response);
                            return this.$common.cleanObject(collection.insert(response));
                        } else {
                            var queryForObject = {};
                            queryForObject[keyNameToCompare] = beforeSyncPayload[keyNameToCompare];
                            var _result = collection.findOne(queryForObject);
                            this.$common.extendOwn(_result, response);
                            return this.$common.cleanObject(collection.update(_result));
                        }
                    }
            }
            return obj;
        }
    }, {
        key: "flush",
        value: function flush(path) {
            var _this5 = this;

            this.logger.info('Persistence.RequestHandler.flush()', path);
            if (this.$common.isEmpty(path)) {
                return this.$db.flush();
            } else {
                var parsed = this.$options.parseURL(path);
                var isPersistentUrl = this.$utils.isPersistUrl(parsed.path);
                return new Promise(function (resolve, reject) {
                    if (!isPersistentUrl) {
                        reject(new Error('Persistence.RequestHandler.flush() given URI not configured for persistence: ' + parsed.path));
                    } else {
                        var queryParams = _this5.$utils.extractKeyValuesFromUrl2(isPersistentUrl);
                        resolve(_this5.$db.getCollectionByName(queryParams.root).removeDataOnly());
                    }
                });
            }
        }

    }, {
        key: "getDB",
        value: function getDB() {
            return this.$db;
        }
    }, {
        key: "get",
        value: function get(request) {
            var _this6 = this;

            var doGet = function doGet(request) {
                _this6.logger.info('get()');
                _this6.isPersistentGetRequest(request);
                var _request = _this6.$common.clone(request);
                if (!_request.hasOwnProperty('data') || _this6.$common.isEmpty(_request.data)) {
                    return _this6.$common.clone(_this6.handleGet(_request));
                }
                return _this6.$common.clone(_this6.handleGetStore(_request));
            };
            return new Promise(function (resolve) {
                resolve(doGet(request));
            });
        }

    }, {
        key: "post",
        value: function post(request, force) {
            var _this7 = this;

            var doPost = function doPost(request, force) {
                _this7.logger.info('post()');
                _this7.isPostRequest(request);
                var _request = _this7.$common.clone(request);
                return _this7.$common.clone(_this7.handlePost(_request, force));
            };
            return new Promise(function (resolve) {
                resolve(doPost(request, force));
            });
        }
    }, {
        key: "put",
        value: function put(request, force) {
            var _this8 = this;

            var doPut = function doPut(request, force) {
                _this8.logger.info('put()');
                _this8.isPostRequest(request);
                var _request = _this8.$common.clone(request);
                return _this8.$common.clone(_this8.handlePut(_request, force));
            };
            return new Promise(function (resolve) {
                resolve(doPut(request, force));
            });
        }
    }, {
        key: "patch",
        value: function patch(request, force) {
            var _this9 = this;

            var doPatch = function doPatch(request, force) {
                _this9.logger.info('patch()');
                _this9.isPostRequest(request);
                var _request = _this9.$common.clone(request);
                return _this9.$common.clone(_this9.handlePatch(_request, force));
            };
            return new Promise(function (resolve) {
                resolve(doPatch(request, force));
            });
        }
    }, {
        key: "delete",
        value: function _delete(request) {
            var _this10 = this;

            var doDelete = function doDelete(request) {
                _this10.logger.info('delete()');
                _this10.isPersistentRequest(request);
                var _request = _this10.$common.clone(request);
                return _this10.$common.clone(_this10.handleDelete(_request));
            };
            return new Promise(function (resolve) {
                resolve(doDelete(request));
            });
        }

    }, {
        key: "data",
        value: function data(path) {
            var _this11 = this;

            var doData = function doData(path) {
                _this11.logger.info('data()');
                if (path == null) {
                    throw new Error('Path cannot be empty!');
                }
                var parsed = _this11.$options.parseURL(path);
                var isPersistentUrl = _this11.$utils.isPersistUrl(parsed.path);
                if (!isPersistentUrl) {
                    throw new Error('post() given URI not configured for persistence: ' + parsed.path);
                }
                var queryParams = _this11.$utils.extractKeyValuesFromUrl2(isPersistentUrl);
                return _this11.$db.getCollectionByName(queryParams.root);
            };
            return new Promise(function (resolve) {
                resolve(doData(path));
            });
        }
    }, {
        key: "router",
        value: function router(request) {
            var _this12 = this;

            var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

            return new Promise(function (resolve) {
                if (!_this12.isPersistentGetRequest(request)) {
                    _this12.logger.error('Passed object is not defined request for GET!', request.url);
                    throw new Error('Passed object is not defined request for GET!');
                }
                if (!request.hasOwnProperty('method')) {
                    _this12.logger.error('request.method was not provided!', request);
                    throw new Error('request.method was not provided!');
                }
                var _request = _this12.$common.clone(request);
                _request.method = _this12.$utils._normalizeMethod(_request.method);
                if (!_this12[_request.method]) {
                    _this12.logger.error('specified router is not implemented!');
                    throw new Error('specified router is not implemented!');
                }
                var result = _this12[_request.method](_request, force);
                resolve(result);
            });
        }
    }]);

    return RequestHandler;
}();


},{"../../logger":13,"./db":36}],39:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
/**
 * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
 *
 * @author Yuri Panshin
 * @ignore
 */
var SyncResourceType = {
  item: 0,
  collection: 1,
  file: 2
};
exports.SyncResourceType = SyncResourceType;


},{}],40:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.Synchronization = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @author Yuri Panshin
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      */


var _mobileEndpoint = require("./endpoint/mobile-endpoint");

var _logger = require("../logger");

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @classdesc Class that provides caching and synchronization capabilities. Callers should use
 * MobileBackend's [synchronization]{@link MobileBackend#synchronization} property.
 * @class
 * @global
 * @hideconstructor
 */
var Synchronization = function () {
    function Synchronization(backend, config, utils, platform, common, options, process) {
        _classCallCheck(this, Synchronization);

        this.config = config;
        this.utils = utils;
        this.platform = platform;
        this.common = common;
        this.options = options;
        this.process = process;
        this._endpoints = {};
        this.logger = new _logger.Logger('Synchronization');
        this.backend = backend;
        if (!options['_originalIsOnline']) {
            options['_originalIsOnline'] = options.isOnline.bind(options);
        }
        var _isOffline = false;
        options.isOnline = function () {
            return _isOffline === false ? options['_originalIsOnline']() : !_isOffline;
        };
        this.setOfflineMode = function (isOffline) {
            _isOffline = typeof isOffline === 'boolean' ? isOffline : true;
        };
    }
    /**
     * Gets device network status which is currently being used by Synchronization.
     * @function
     * @name Synchronization#isOnline
     * @returns {Boolean}
     */


    _createClass(Synchronization, [{
        key: "isOnline",
        value: function isOnline() {
            return this.options.isOnline();
        }
        /**
         * Deletes all cached resources.
         * @function
         * @name Synchronization#purge
         */

    }, {
        key: "purge",
        value: function purge() {
            for (var apiName in this._endpoints) {
                if (this._endpoints.hasOwnProperty(apiName)) {
                    var api = this._endpoints[apiName];
                    for (var path in api) {
                        if (api.hasOwnProperty(path)) {
                            api[path].purge();
                        }
                    }
                }
            }
        }
    }, {
        key: "openEndpoint",

        /**
         * Open endpoint.
         * Returns a [MobileEndpoint]{@link MobileEndpoint} that provides access
         * to an endpoint in a custom code API.
         * @function
         * @name Synchronization#openEndpoint
         * @param {string} apiName The name of the custom code API
         * @param {string} endpointPath The endpoint in the custom code API
         * @returns {MobileEndpoint} A MobileEndpoint object.
         */
        value: function openEndpoint(apiName, endpointPath) {
            this._endpoints[apiName] = this._endpoints[apiName] || {};
            this._endpoints[apiName][endpointPath] = this._endpoints[apiName][endpointPath] || new _mobileEndpoint.MobileEndpoint(this, apiName, endpointPath, this.backend, this.utils, this.platform, this.common, this.options);
            return this._endpoints[apiName][endpointPath];
        }

    }, {
        key: "_run",
        value: function _run(callback) {
            return this.process.run(callback);
        }
    }, {
        key: "_runWithoutReadInBackground",
        value: function _runWithoutReadInBackground(callback) {
            return this.process.runWithoutReadInBackground(callback);
        }
    }]);

    return Synchronization;
}();

exports.Synchronization = Synchronization;


},{"../logger":13,"./endpoint/mobile-endpoint":27}],41:[function(require,module,exports){
'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});
/**
 * Copyright© 2017, Oracle and/or its affiliates. All rights reserved.
 *
 * @author Yuri Panshin
 */
var HEADERS = exports.HEADERS = {
    ORACLE_MOBILE_DIAGNOSTIC_SESSION_ID: 'Oracle-Mobile-DIAGNOSTIC-SESSION-ID',
    ORACLE_MOBILE_DEVICE_ID: 'Oracle-Mobile-DEVICE-ID',
    ORACLE_MOBILE_CLIENT_REQUEST_TIME: 'Oracle-Mobile-CLIENT-REQUEST-TIME',
    ORACLE_MOBILE_ANALYTICS_APPLICATION_ID: 'Oracle-Mobile-Analytics-Application-Id',
    ORACLE_MOBILE_NAME: 'Oracle-Mobile-Name',
    ORACLE_MOBILE_CREATED_BY: 'Oracle-Mobile-Created-By',
    ORACLE_MOBILE_CREATED_ON: 'Oracle-Mobile-Created-On',
    ORACLE_MOBILE_MODIFIED_BY: 'Oracle-Mobile-Modified-By',
    ORACLE_MOBILE_MODIFIED_ON: 'Oracle-Mobile-Modified-On',
    ORACLE_MOBILE_SYNC_RESOURCE_TYPE: 'Oracle-Mobile-Sync-Resource-Type',
    ORACLE_MOBILE_SYNC_AGENT: 'Oracle-Mobile-Sync-Agent',
    LOCATION: 'Location',
    ORACLE_MOBILE_BACKEND_ID: 'Oracle-Mobile-Backend-Id',
    ORACLE_MOBILE_SOCIAL_IDENTITY_PROVIDER: 'Oracle-Mobile-Social-Identity-Provider',
    ORACLE_MOBILE_SOCIAL_ACCESS_TOKEN: 'Oracle-Mobile-Social-Access-Token',
    ORACLE_MOBILE_CLIENT_SDK_INFO: 'Oracle-Mobile-Client-SDK-Info',
    ACCEPT: 'Accept',
    CONTENT_TYPE: 'Content-Type',
    E_TAG: 'ETag',
    IF_MATCH: 'If-Match',
    AUTHORIZATION: 'Authorization',
    X_USER_IDENTITY_DOMAIN_NAME: 'X-USER-IDENTITY-DOMAIN-NAME',
    X_RESOURCE_IDENTITY_DOMAIN_NAME: 'X-RESOURCE-IDENTITY-DOMAIN-NAME',
    ACCEPT_ENCODING: 'Accept-Encoding'
};
var CONTENT_TYPES = exports.CONTENT_TYPES = {
    APPLICATION_JSON: 'application/json',
    TEXT_PLAIN: 'text/plain',
    X_WWW_FORM_FORM_URLENCODED: 'application/x-www-form-urlencoded; charset=utf-8'
};
var HTTP_METHODS = exports.HTTP_METHODS = {
    GET: 'GET',
    PUT: 'PUT',
    PATCH: 'PATCH',
    POST: 'POST',
    DELETE: 'DELETE',
    HEAD: 'HEAD'
};
var RESOURCE_TYPES = exports.RESOURCE_TYPES = {
    ITEM: 'item',
    COLLECTION: 'collection',
    FILE: 'file'
};
var AUTHENTICATION_TYPES = exports.AUTHENTICATION_TYPES = {
    basic: 'basic',
    oauth: 'oauth',
    facebook: 'facebook',
    token: 'token'
};
var MODULE_NAMES = exports.MODULE_NAMES = {
    STORAGE: 'Storage',
    AUTHORIZATION: 'Authorization',
    USER_MANAGEMENT: 'UserManagement',
    APP_POLICES: 'AppPolicies',
    LOCATION: 'Location',
    SYNC: 'Sync',
    SYNC_EXPRESS: 'SyncExpress',
    NOTIFICATIONS: 'Notifications',
    MCS_ANALYTICS: 'MCSAnalytics',
    ANALYTICS: 'Analytics',
    CUSTOM_CODE: 'CustomCode',
    APP_CONFIG: 'AppConfig'
};
var PLATFORM_NAMES = exports.PLATFORM_NAMES = {
    JAVASCRIPT: 'Javascript',
    CORDOVA: 'Cordova'
};
var PLATFORM_ID = exports.PLATFORM_ID = {
    ANDROID: 'android',
    IOS: 'ios'
};
var NOTIFICATION_PROVIDER = exports.NOTIFICATION_PROVIDER = {
    FCM: 'FCM',
    APNS: 'APNS',
    WNS: 'WNS',
    SYNIVERSE: 'SYNIVERSE'
};
var XML_HTTP_REQUEST_RESPONSE_TYPE = exports.XML_HTTP_REQUEST_RESPONSE_TYPE = {
    JSON: 'json',
    BLOB: 'blob'
};


},{}],42:[function(require,module,exports){
'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
 * @ignore
 */
var Utils = exports.Utils = function () {
    function Utils() {
        _classCallCheck(this, Utils);
    }

    _createClass(Utils, [{
        key: 'removeSpace',
        value: function removeSpace(input) {
            return input.replace(/ /g, '');
        }
    }, {
        key: 'uuid',
        value: function uuid() {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                var r = Math.random() * 16 | 0,
                    v = c == 'x' ? r : r & 0x3 | 0x8;
                return v.toString(16);
            });
        }
    }, {
        key: 'validateConfiguration',
        value: function validateConfiguration(input) {
            var prop = input;
            if (/\s/.test(prop) && prop) {
                prop = this.removeSpace(input);
            }
            return prop;
        }
    }, {
        key: 'encodeBase64',
        value: function encodeBase64(input) {
            var output = "";
            var chr1,
                chr2,
                chr3 = "";
            var enc1,
                enc2,
                enc3,
                enc4 = "";
            var i = 0;
            do {
                chr1 = input.charCodeAt(i++);
                chr2 = input.charCodeAt(i++);
                chr3 = input.charCodeAt(i++);
                enc1 = chr1 >> 2;
                enc2 = (chr1 & 3) << 4 | chr2 >> 4;
                enc3 = (chr2 & 15) << 2 | chr3 >> 6;
                enc4 = chr3 & 63;
                if (isNaN(chr2)) {
                    enc3 = enc4 = 64;
                } else if (isNaN(chr3)) {
                    enc4 = 64;
                }
                output = output + Utils.KEY_STR.charAt(enc1) + Utils.KEY_STR.charAt(enc2) + Utils.KEY_STR.charAt(enc3) + Utils.KEY_STR.charAt(enc4);
                chr1 = chr2 = chr3 = "";
                enc1 = enc2 = enc3 = enc4 = "";
            } while (i < input.length);
            return output;
        }
    }, {
        key: 'decodeBase64',
        value: function decodeBase64(input) {
            var output = "";
            var chr1,
                chr2,
                chr3 = "";
            var enc1,
                enc2,
                enc3,
                enc4 = "";
            var i = 0;
            var base64test = /[^A-Za-z0-9\+\/\=]/g;
            if (base64test.exec(input)) {
                return null;
            }
            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
            do {
                enc1 = Utils.KEY_STR.indexOf(input.charAt(i++));
                enc2 = Utils.KEY_STR.indexOf(input.charAt(i++));
                enc3 = Utils.KEY_STR.indexOf(input.charAt(i++));
                enc4 = Utils.KEY_STR.indexOf(input.charAt(i++));
                chr1 = enc1 << 2 | enc2 >> 4;
                chr2 = (enc2 & 15) << 4 | enc3 >> 2;
                chr3 = (enc3 & 3) << 6 | enc4;
                output = output + String.fromCharCode(chr1);
                if (enc3 != 64) {
                    output = output + String.fromCharCode(chr2);
                }
                if (enc4 != 64) {
                    output = output + String.fromCharCode(chr3);
                }
                chr1 = chr2 = chr3 = "";
                enc1 = enc2 = enc3 = enc4 = "";
            } while (i < input.length);
            return output;
        }
    }, {
        key: 'hasValue',
        value: function hasValue(obj, key, value) {
            return obj.hasOwnProperty(key) && obj[key] === value;
        }
    }, {
        key: 'isEquivalentURL',
        value: function isEquivalentURL(url1, url2) {
            if (url1.indexOf("https") === 0 && url2.indexOf("https") === 0) {
                url1 = this.getPort(url1) === 443 ? url1.replace(':443', '') : url1;
                url2 = this.getPort(url2) === 443 ? url2.replace(':443', '') : url2;
            } else if (url1.indexOf("https") === -1 && url2.indexOf("https") === -1) {
                url1 = this.getPort(url1) === 80 ? url1.replace(':80', '') : url1;
                url2 = this.getPort(url2) === 80 ? url2.replace(':80', '') : url2;
            }
            return url1.indexOf(url2) === 0;
        }
    }, {
        key: 'getPort',
        value: function getPort(url) {
            var colonIdx = url.indexOf(':', 7);
            var slashIdx = url.indexOf('/', colonIdx);
            if (colonIdx > 0 && slashIdx == -1) {
                slashIdx = url.length;
            }
            var port = url.substr(colonIdx + 1, slashIdx - colonIdx - 1);
            if (port && !isNaN(port * 1)) {
                return port * 1;
            } else {
                return -1;
            }
        }
        /**
         * Convert headers string to dictionary with lowercase keys.
         * @param {string} headerStr
         * @return {object}
         */

    }, {
        key: 'parseHeaders',
        value: function parseHeaders(headerStr) {
            var headers = {};
            if (!headerStr) {
                return headers;
            }
            var headerPairs = headerStr.split('\r\n');
            for (var i = 0, ilen = headerPairs.length; i < ilen; i++) {
                var headerPair = headerPairs[i];
                var index = headerPair.indexOf(': ');
                if (index > 0) {
                    headers[headerPair.substring(0, index).toLowerCase()] = headerPair.substring(index + 2);
                }
            }
            return headers;
        }
    }, {
        key: 'normalizeHeaderKeys',
        value: function normalizeHeaderKeys(responseHeaders) {
            var headers = {};
            if (this.isArray(responseHeaders)) {
                var array = responseHeaders;
                for (var i = 0; i < array.length; i++) {
                    headers[array[i].name.toLowerCase()] = array[i].value;
                }
            } else {
                for (var key in responseHeaders) {
                    if (responseHeaders.hasOwnProperty(key)) {
                        headers[key.toLowerCase()] = responseHeaders[key];
                    }
                }
            }
            return headers;
        }
    }, {
        key: 'isArray',
        value: function isArray(arg) {
            return Object.prototype.toString.call(arg) === '[object Array]';
        }
    }, {
        key: 'isCordova',
        value: function isCordova() {
            return typeof window['cordova'] != 'undefined';
        }
        /**
         * Checks to see if the string ends with a suffix.
         * @return {boolean}
         */

    }, {
        key: 'strEndsWith',
        value: function strEndsWith(str, suffix) {
            return str.match(suffix + '$') == suffix;
        }
    }, {
        key: 'hashCode',
        value: function hashCode(input) {
            return input.split('').reduce(function (acc, char) {
                acc = (acc << 5) - acc + char.charCodeAt(0);
                return acc & acc;
            }, 0);
        }
    }]);

    return Utils;
}();

Utils.KEY_STR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";


},{}]},{},[14]);
exportMCS(_module, _exports, _define, _window, _global, _self, _this, cxa);
})(typeof module === "undefined" ? undefined : module, typeof exports === "undefined" ? undefined : exports, typeof define === "undefined" ? undefined : define, typeof window === "undefined" ? undefined : window, typeof global === "undefined" ? undefined : global, typeof self === "undefined" ? undefined : self, this);