parse
Version:
Parse JavaScript SDK
1,379 lines (1,352 loc) • 1.01 MB
JavaScript
/**
* Parse JavaScript SDK v6.1.1
*
* The source tree of this library can be found at
* https://github.com/ParsePlatform/Parse-SDK-JS
*/
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Parse = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(_dereq_,module,exports){
"use strict";
var _Object$defineProperty = _dereq_("@babel/runtime-corejs3/core-js-stable/object/define-property");
var _interopRequireDefault = _dereq_("@babel/runtime-corejs3/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
value: true
});
exports.track = track;
var _CoreManager = _interopRequireDefault(_dereq_("./CoreManager"));
/**
* Parse.Analytics provides an interface to Parse's logging and analytics
* backend.
*
* @class Parse.Analytics
* @static
* @hideconstructor
*/
/**
* Tracks the occurrence of a custom event with additional dimensions.
* Parse will store a data point at the time of invocation with the given
* event name.
*
* Dimensions will allow segmentation of the occurrences of this custom
* event. Keys and values should be {@code String}s, and will throw
* otherwise.
*
* To track a user signup along with additional metadata, consider the
* following:
* <pre>
* var dimensions = {
* gender: 'm',
* source: 'web',
* dayType: 'weekend'
* };
* Parse.Analytics.track('signup', dimensions);
* </pre>
*
* There is a default limit of 8 dimensions per event tracked.
*
* @function track
* @name Parse.Analytics.track
* @param {string} name The name of the custom event to report to Parse as
* having happened.
* @param {object} dimensions The dictionary of information by which to
* segment this event.
* @returns {Promise} A promise that is resolved when the round-trip
* to the server completes.
*/
function track(name, dimensions) {
name = name || '';
name = name.replace(/^\s*/, '');
name = name.replace(/\s*$/, '');
if (name.length === 0) {
throw new TypeError('A name for the custom event must be provided');
}
for (const key in dimensions) {
if (typeof key !== 'string' || typeof dimensions[key] !== 'string') {
throw new TypeError('track() dimensions expects keys and values of type "string".');
}
}
return _CoreManager.default.getAnalyticsController().track(name, dimensions);
}
const DefaultController = {
track(name, dimensions) {
const RESTController = _CoreManager.default.getRESTController();
return RESTController.request('POST', 'events/' + name, {
dimensions
});
}
};
_CoreManager.default.setAnalyticsController(DefaultController);
},{"./CoreManager":4,"@babel/runtime-corejs3/core-js-stable/object/define-property":91,"@babel/runtime-corejs3/helpers/interopRequireDefault":104}],2:[function(_dereq_,module,exports){
"use strict";
var _Object$defineProperty = _dereq_("@babel/runtime-corejs3/core-js-stable/object/define-property");
var _interopRequireDefault = _dereq_("@babel/runtime-corejs3/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _ParseUser = _interopRequireDefault(_dereq_("./ParseUser"));
var _uuid = _interopRequireDefault(_dereq_("./uuid"));
let registered = false;
/**
* Provides utility functions for working with Anonymously logged-in users. <br />
* Anonymous users have some unique characteristics:
* <ul>
* <li>Anonymous users don't need a user name or password.</li>
* <ul>
* <li>Once logged out, an anonymous user cannot be recovered.</li>
* </ul>
* <li>signUp converts an anonymous user to a standard user with the given username and password.</li>
* <ul>
* <li>Data associated with the anonymous user is retained.</li>
* </ul>
* <li>logIn switches users without converting the anonymous user.</li>
* <ul>
* <li>Data associated with the anonymous user will be lost.</li>
* </ul>
* <li>Service logIn (e.g. Facebook, Twitter) will attempt to convert
* the anonymous user into a standard user by linking it to the service.</li>
* <ul>
* <li>If a user already exists that is linked to the service, it will instead switch to the existing user.</li>
* </ul>
* <li>Service linking (e.g. Facebook, Twitter) will convert the anonymous user
* into a standard user by linking it to the service.</li>
* </ul>
*
* @class Parse.AnonymousUtils
* @static
*/
const AnonymousUtils = {
/**
* Gets whether the user has their account linked to anonymous user.
*
* @function isLinked
* @name Parse.AnonymousUtils.isLinked
* @param {Parse.User} user User to check for.
* The user must be logged in on this device.
* @returns {boolean} <code>true</code> if the user has their account
* linked to an anonymous user.
* @static
*/
isLinked(user) {
const provider = this._getAuthProvider();
return user._isLinked(provider.getAuthType());
},
/**
* Logs in a user Anonymously.
*
* @function logIn
* @name Parse.AnonymousUtils.logIn
* @param {object} options MasterKey / SessionToken.
* @returns {Promise} Logged in user
* @static
*/
logIn(options) {
const provider = this._getAuthProvider();
return _ParseUser.default.logInWith(provider.getAuthType(), provider.getAuthData(), options);
},
/**
* Links Anonymous User to an existing PFUser.
*
* @function link
* @name Parse.AnonymousUtils.link
* @param {Parse.User} user User to link. This must be the current user.
* @param {object} options MasterKey / SessionToken.
* @returns {Promise} Linked with User
* @static
*/
link(user, options) {
const provider = this._getAuthProvider();
return user.linkWith(provider.getAuthType(), provider.getAuthData(), options);
},
/**
* Returns true if Authentication Provider has been registered for use.
*
* @function isRegistered
* @name Parse.AnonymousUtils.isRegistered
* @returns {boolean}
* @static
*/
isRegistered() {
return registered;
},
_getAuthProvider() {
const provider = {
restoreAuthentication() {
return true;
},
getAuthType() {
return 'anonymous';
},
getAuthData() {
return {
authData: {
id: (0, _uuid.default)()
}
};
}
};
if (!registered) {
_ParseUser.default._registerAuthenticationProvider(provider);
registered = true;
}
return provider;
}
};
var _default = exports.default = AnonymousUtils;
},{"./ParseUser":38,"./uuid":64,"@babel/runtime-corejs3/core-js-stable/object/define-property":91,"@babel/runtime-corejs3/helpers/interopRequireDefault":104}],3:[function(_dereq_,module,exports){
"use strict";
var _Object$defineProperty = _dereq_("@babel/runtime-corejs3/core-js-stable/object/define-property");
var _interopRequireDefault = _dereq_("@babel/runtime-corejs3/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
value: true
});
exports.getJobStatus = getJobStatus;
exports.getJobsData = getJobsData;
exports.run = run;
exports.startJob = startJob;
var _keys = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/object/keys"));
var _promise = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/promise"));
var _CoreManager = _interopRequireDefault(_dereq_("./CoreManager"));
var _decode = _interopRequireDefault(_dereq_("./decode"));
var _encode = _interopRequireDefault(_dereq_("./encode"));
var _ParseError = _interopRequireDefault(_dereq_("./ParseError"));
var _ParseQuery = _interopRequireDefault(_dereq_("./ParseQuery"));
var _ParseObject = _interopRequireDefault(_dereq_("./ParseObject"));
/**
* Contains functions for calling and declaring
* <a href="/docs/cloud_code_guide#functions">cloud functions</a>.
* <p><strong><em>
* Some functions are only available from Cloud Code.
* </em></strong></p>
*
* @class Parse.Cloud
* @static
* @hideconstructor
*/
/**
* Makes a call to a cloud function.
*
* @function run
* @name Parse.Cloud.run
* @param {string} name The function name.
* @param {object} data The parameters to send to the cloud function.
* @param {object} options
* Valid options are:<ul>
* <li>useMasterKey: In Cloud Code and Node only, causes the Master Key to
* be used for this request.
* <li>sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
* <li>installationId: the installationId which made the request
* <li>context: A dictionary that is accessible in Cloud Code triggers.
* </ul>
* @returns {Promise} A promise that will be resolved with the result
* of the function.
*/
function run(name, data, options) {
if (typeof name !== 'string' || name.length === 0) {
throw new TypeError('Cloud function name must be a string.');
}
const requestOptions = _ParseObject.default._getRequestOptions(options);
return _CoreManager.default.getCloudController().run(name, data, requestOptions);
}
/**
* Gets data for the current set of cloud jobs.
*
* @function getJobsData
* @name Parse.Cloud.getJobsData
* @returns {Promise} A promise that will be resolved with the result
* of the function.
*/
function getJobsData() {
return _CoreManager.default.getCloudController().getJobsData({
useMasterKey: true
});
}
/**
* Starts a given cloud job, which will process asynchronously.
*
* @function startJob
* @name Parse.Cloud.startJob
* @param {string} name The function name.
* @param {object} data The parameters to send to the cloud function.
* @returns {Promise} A promise that will be resolved with the jobStatusId
* of the job.
*/
function startJob(name, data) {
if (typeof name !== 'string' || name.length === 0) {
throw new TypeError('Cloud job name must be a string.');
}
return _CoreManager.default.getCloudController().startJob(name, data, {
useMasterKey: true
});
}
/**
* Gets job status by Id
*
* @function getJobStatus
* @name Parse.Cloud.getJobStatus
* @param {string} jobStatusId The Id of Job Status.
* @returns {Parse.Object} Status of Job.
*/
function getJobStatus(jobStatusId) {
const query = new _ParseQuery.default('_JobStatus');
return query.get(jobStatusId, {
useMasterKey: true
});
}
const DefaultController = {
run(name, data, options) {
const RESTController = _CoreManager.default.getRESTController();
const payload = (0, _encode.default)(data, true);
const request = RESTController.request('POST', 'functions/' + name, payload, options);
return request.then(res => {
if (typeof res === 'object' && (0, _keys.default)(res).length > 0 && !Object.hasOwn(res, 'result')) {
throw new _ParseError.default(_ParseError.default.INVALID_JSON, 'The server returned an invalid response.');
}
const decoded = (0, _decode.default)(res);
if (decoded && Object.hasOwn(decoded, 'result')) {
return _promise.default.resolve(decoded.result);
}
return _promise.default.resolve(undefined);
});
},
getJobsData(options) {
const RESTController = _CoreManager.default.getRESTController();
return RESTController.request('GET', 'cloud_code/jobs/data', null, options);
},
async startJob(name, data, options) {
const RESTController = _CoreManager.default.getRESTController();
const payload = (0, _encode.default)(data, true);
options.returnStatus = true;
const response = await RESTController.request('POST', 'jobs/' + name, payload, options);
return response._headers?.['X-Parse-Job-Status-Id'];
}
};
_CoreManager.default.setCloudController(DefaultController);
},{"./CoreManager":4,"./ParseError":24,"./ParseObject":30,"./ParseQuery":33,"./decode":55,"./encode":56,"@babel/runtime-corejs3/core-js-stable/object/define-property":91,"@babel/runtime-corejs3/core-js-stable/object/keys":96,"@babel/runtime-corejs3/core-js-stable/promise":98,"@babel/runtime-corejs3/helpers/interopRequireDefault":104}],4:[function(_dereq_,module,exports){
(function (process){(function (){
"use strict";
var _Object$defineProperty = _dereq_("@babel/runtime-corejs3/core-js-stable/object/define-property");
var _interopRequireDefault = _dereq_("@babel/runtime-corejs3/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _forEach = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/instance/for-each"));
/** Based on https://github.com/react-native-async-storage/async-storage/blob/main/packages/default-storage-backend/src/types.ts */
const config = {
IS_NODE: typeof process !== 'undefined' && !!process.versions && !!process.versions.node && !process.versions.electron,
REQUEST_ATTEMPT_LIMIT: 5,
REQUEST_BATCH_SIZE: 20,
REQUEST_HEADERS: {},
SERVER_URL: 'https://api.parse.com/1',
SERVER_AUTH_TYPE: null,
SERVER_AUTH_TOKEN: null,
LIVEQUERY_SERVER_URL: null,
ENCRYPTED_KEY: null,
VERSION: 'js' + "6.1.1",
APPLICATION_ID: null,
JAVASCRIPT_KEY: null,
MAINTENANCE_KEY: null,
MASTER_KEY: null,
USE_MASTER_KEY: false,
PERFORM_USER_REWRITE: true,
FORCE_REVOCABLE_SESSION: false,
ENCRYPTED_USER: false,
IDEMPOTENCY: false,
ALLOW_CUSTOM_OBJECT_ID: false,
PARSE_ERRORS: []
};
function requireMethods(name, methods, controller) {
(0, _forEach.default)(methods).call(methods, func => {
if (typeof controller[func] !== 'function') {
throw new Error(`${name} must implement ${func}()`);
}
});
}
const CoreManager = {
get: function (key) {
if (Object.hasOwn(config, key)) {
return config[key];
}
throw new Error('Configuration key not found: ' + key);
},
set: function (key, value) {
config[key] = value;
},
setIfNeeded: function (key, value) {
if (!Object.hasOwn(config, key)) {
config[key] = value;
}
return config[key];
},
/* Specialized Controller Setters/Getters */
setAnalyticsController(controller) {
requireMethods('AnalyticsController', ['track'], controller);
config['AnalyticsController'] = controller;
},
getAnalyticsController() {
return config['AnalyticsController'];
},
setCloudController(controller) {
requireMethods('CloudController', ['run', 'getJobsData', 'startJob'], controller);
config['CloudController'] = controller;
},
getCloudController() {
return config['CloudController'];
},
setConfigController(controller) {
requireMethods('ConfigController', ['current', 'get', 'save'], controller);
config['ConfigController'] = controller;
},
getConfigController() {
return config['ConfigController'];
},
setCryptoController(controller) {
requireMethods('CryptoController', ['encrypt', 'decrypt'], controller);
config['CryptoController'] = controller;
},
getCryptoController() {
return config['CryptoController'];
},
setEventEmitter(eventEmitter) {
config['EventEmitter'] = eventEmitter;
},
getEventEmitter() {
return config['EventEmitter'];
},
setFileController(controller) {
requireMethods('FileController', ['saveFile', 'saveBase64'], controller);
config['FileController'] = controller;
},
setEventuallyQueue(controller) {
requireMethods('EventuallyQueue', ['poll', 'save', 'destroy'], controller);
config['EventuallyQueue'] = controller;
},
getEventuallyQueue() {
return config['EventuallyQueue'];
},
getFileController() {
return config['FileController'];
},
setInstallationController(controller) {
requireMethods('InstallationController', ['currentInstallationId', 'currentInstallation', 'updateInstallationOnDisk'], controller);
config['InstallationController'] = controller;
},
getInstallationController() {
return config['InstallationController'];
},
setLiveQuery(liveQuery) {
config['LiveQuery'] = liveQuery;
},
getLiveQuery() {
return config['LiveQuery'];
},
setObjectController(controller) {
requireMethods('ObjectController', ['save', 'fetch', 'destroy'], controller);
config['ObjectController'] = controller;
},
getObjectController() {
return config['ObjectController'];
},
setObjectStateController(controller) {
requireMethods('ObjectStateController', ['getState', 'initializeState', 'removeState', 'getServerData', 'setServerData', 'getPendingOps', 'setPendingOp', 'pushPendingState', 'popPendingState', 'mergeFirstPendingState', 'getObjectCache', 'estimateAttribute', 'estimateAttributes', 'commitServerChanges', 'enqueueTask', 'clearAllState'], controller);
config['ObjectStateController'] = controller;
},
getObjectStateController() {
return config['ObjectStateController'];
},
setPushController(controller) {
requireMethods('PushController', ['send'], controller);
config['PushController'] = controller;
},
getPushController() {
return config['PushController'];
},
setQueryController(controller) {
requireMethods('QueryController', ['find', 'aggregate'], controller);
config['QueryController'] = controller;
},
getQueryController() {
return config['QueryController'];
},
setRESTController(controller) {
requireMethods('RESTController', ['request', 'ajax'], controller);
config['RESTController'] = controller;
},
getRESTController() {
return config['RESTController'];
},
setSchemaController(controller) {
requireMethods('SchemaController', ['get', 'create', 'update', 'delete', 'send', 'purge'], controller);
config['SchemaController'] = controller;
},
getSchemaController() {
return config['SchemaController'];
},
setSessionController(controller) {
requireMethods('SessionController', ['getSession'], controller);
config['SessionController'] = controller;
},
getSessionController() {
return config['SessionController'];
},
setStorageController(controller) {
if (controller.async) {
requireMethods('An async StorageController', ['getItemAsync', 'setItemAsync', 'removeItemAsync', 'getAllKeysAsync'], controller);
} else {
requireMethods('A synchronous StorageController', ['getItem', 'setItem', 'removeItem', 'getAllKeys'], controller);
}
config['StorageController'] = controller;
},
setLocalDatastoreController(controller) {
requireMethods('LocalDatastoreController', ['pinWithName', 'fromPinWithName', 'unPinWithName', 'getAllContents', 'clear'], controller);
config['LocalDatastoreController'] = controller;
},
getLocalDatastoreController() {
return config['LocalDatastoreController'];
},
setLocalDatastore(store) {
config['LocalDatastore'] = store;
},
getLocalDatastore() {
return config['LocalDatastore'];
},
getStorageController() {
return config['StorageController'];
},
setAsyncStorage(storage) {
config['AsyncStorage'] = storage;
},
getAsyncStorage() {
return config['AsyncStorage'];
},
setWebSocketController(controller) {
config['WebSocketController'] = controller;
},
getWebSocketController() {
return config['WebSocketController'];
},
setUserController(controller) {
requireMethods('UserController', ['setCurrentUser', 'currentUser', 'currentUserAsync', 'signUp', 'logIn', 'become', 'logOut', 'me', 'requestPasswordReset', 'upgradeToRevocableSession', 'requestEmailVerification', 'verifyPassword', 'linkWith'], controller);
config['UserController'] = controller;
},
getUserController() {
return config['UserController'];
},
setLiveQueryController(controller) {
requireMethods('LiveQueryController', ['setDefaultLiveQueryClient', 'getDefaultLiveQueryClient', '_clearCachedDefaultClient'], controller);
config['LiveQueryController'] = controller;
},
getLiveQueryController() {
return config['LiveQueryController'];
},
setHooksController(controller) {
requireMethods('HooksController', ['create', 'get', 'update', 'remove'], controller);
config['HooksController'] = controller;
},
getHooksController() {
return config['HooksController'];
},
setParseOp(op) {
config['ParseOp'] = op;
},
getParseOp() {
return config['ParseOp'];
},
setParseObject(object) {
config['ParseObject'] = object;
},
getParseObject() {
return config['ParseObject'];
},
setParseQuery(query) {
config['ParseQuery'] = query;
},
getParseQuery() {
return config['ParseQuery'];
},
setParseRole(role) {
config['ParseRole'] = role;
},
getParseRole() {
return config['ParseRole'];
},
setParseUser(user) {
config['ParseUser'] = user;
},
getParseUser() {
return config['ParseUser'];
}
};
var _default = exports.default = CoreManager;
}).call(this)}).call(this,_dereq_('_process'))
},{"@babel/runtime-corejs3/core-js-stable/instance/for-each":74,"@babel/runtime-corejs3/core-js-stable/object/define-property":91,"@babel/runtime-corejs3/helpers/interopRequireDefault":104,"_process":108}],5:[function(_dereq_,module,exports){
"use strict";
var _Object$defineProperty = _dereq_("@babel/runtime-corejs3/core-js-stable/object/define-property");
var _interopRequireDefault = _dereq_("@babel/runtime-corejs3/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _stringify = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/json/stringify"));
let AES;
let ENC;
AES = _dereq_('crypto-js/aes');
ENC = _dereq_('crypto-js/enc-utf8');
const CryptoController = {
encrypt(obj, secretKey) {
const encrypted = AES.encrypt((0, _stringify.default)(obj), secretKey);
return encrypted.toString();
},
decrypt(encryptedText, secretKey) {
const decryptedStr = AES.decrypt(encryptedText, secretKey).toString(ENC);
return decryptedStr;
}
};
var _default = exports.default = CryptoController;
},{"@babel/runtime-corejs3/core-js-stable/json/stringify":86,"@babel/runtime-corejs3/core-js-stable/object/define-property":91,"@babel/runtime-corejs3/helpers/interopRequireDefault":104,"crypto-js/aes":481,"crypto-js/enc-utf8":485}],6:[function(_dereq_,module,exports){
"use strict";
var _Object$defineProperty = _dereq_("@babel/runtime-corejs3/core-js-stable/object/define-property");
_Object$defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
/**
* This is a simple wrapper to unify EventEmitter implementations across platforms.
*/
let EventEmitter;
try {
EventEmitter = _dereq_('events').EventEmitter;
} catch (_) {
// EventEmitter unavailable
}
var _default = exports.default = EventEmitter;
},{"@babel/runtime-corejs3/core-js-stable/object/define-property":91,"events":490}],7:[function(_dereq_,module,exports){
"use strict";
var _Object$defineProperty = _dereq_("@babel/runtime-corejs3/core-js-stable/object/define-property");
var _interopRequireDefault = _dereq_("@babel/runtime-corejs3/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _stringify = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/json/stringify"));
var _splice = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/instance/splice"));
var _findIndex = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/instance/find-index"));
var _setInterval2 = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/set-interval"));
var _find = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/instance/find"));
var _CoreManager = _interopRequireDefault(_dereq_("./CoreManager"));
var _ParseError = _interopRequireDefault(_dereq_("./ParseError"));
var _ParseObject = _interopRequireDefault(_dereq_("./ParseObject"));
var _ParseQuery = _interopRequireDefault(_dereq_("./ParseQuery"));
var _Storage = _interopRequireDefault(_dereq_("./Storage"));
const QUEUE_KEY = 'Parse/Eventually/Queue';
let queueCache = [];
let dirtyCache = true;
let polling = undefined;
/**
* Provides utility functions to queue objects that will be
* saved to the server at a later date.
*
* @class Parse.EventuallyQueue
* @static
*/
const EventuallyQueue = {
/**
* Add object to queue with save operation.
*
* @function save
* @name Parse.EventuallyQueue.save
* @param {ParseObject} object Parse.Object to be saved eventually
* @param {object} [serverOptions] See {@link https://parseplatform.org/Parse-SDK-JS/api/master/Parse.Object.html#save Parse.Object.save} options.
* @returns {Promise} A promise that is fulfilled if object is added to queue.
* @static
* @see Parse.Object#saveEventually
*/
save(object, serverOptions) {
return this.enqueue('save', object, serverOptions);
},
/**
* Add object to queue with save operation.
*
* @function destroy
* @name Parse.EventuallyQueue.destroy
* @param {ParseObject} object Parse.Object to be destroyed eventually
* @param {object} [serverOptions] See {@link https://parseplatform.org/Parse-SDK-JS/api/master/Parse.Object.html#destroy Parse.Object.destroy} options
* @returns {Promise} A promise that is fulfilled if object is added to queue.
* @static
* @see Parse.Object#destroyEventually
*/
destroy(object, serverOptions) {
return this.enqueue('destroy', object, serverOptions);
},
/**
* Generate unique identifier to avoid duplicates and maintain previous state.
*
* @param {string} action save / destroy
* @param {object} object Parse.Object to be queued
* @returns {string}
* @static
* @ignore
*/
generateQueueId(action, object) {
object._getId();
const {
className,
id,
_localId
} = object;
const uniqueId = object.get('hash') || _localId;
return [action, className, id, uniqueId].join('_');
},
/**
* Build queue object and add to queue.
*
* @param {string} action save / destroy
* @param {object} object Parse.Object to be queued
* @param {object} [serverOptions]
* @returns {Promise} A promise that is fulfilled if object is added to queue.
* @static
* @ignore
*/
async enqueue(action, object, serverOptions) {
const queueData = await this.getQueue();
const queueId = this.generateQueueId(action, object);
let index = this.queueItemExists(queueData, queueId);
if (index > -1) {
// Add cached values to new object if they don't exist
for (const prop in queueData[index].object) {
if (typeof object.get(prop) === 'undefined') {
object.set(prop, queueData[index].object[prop]);
}
}
} else {
index = queueData.length;
}
queueData[index] = {
queueId,
action,
object: object.toJSON(),
serverOptions: serverOptions || {},
id: object.id,
className: object.className,
hash: object.get('hash'),
createdAt: new Date()
};
return this.setQueue(queueData);
},
store(data) {
return _Storage.default.setItemAsync(QUEUE_KEY, (0, _stringify.default)(data));
},
load() {
return _Storage.default.getItemAsync(QUEUE_KEY);
},
/**
* Sets the in-memory queue from local storage and returns.
*
* @function getQueue
* @name Parse.EventuallyQueue.getQueue
* @returns {Promise<Queue>}
* @static
*/
async getQueue() {
if (dirtyCache) {
queueCache = JSON.parse((await this.load()) || '[]');
dirtyCache = false;
}
return queueCache;
},
/**
* Saves the queue to local storage
*
* @param {Queue} queue Queue containing Parse.Object data.
* @returns {Promise} A promise that is fulfilled when queue is stored.
* @static
* @ignore
*/
setQueue(queue) {
queueCache = queue;
return this.store(queueCache);
},
/**
* Removes Parse.Object data from queue.
*
* @param {string} queueId Unique identifier for Parse.Object data.
* @returns {Promise} A promise that is fulfilled when queue is stored.
* @static
* @ignore
*/
async remove(queueId) {
const queueData = await this.getQueue();
const index = this.queueItemExists(queueData, queueId);
if (index > -1) {
(0, _splice.default)(queueData).call(queueData, index, 1);
await this.setQueue(queueData);
}
},
/**
* Removes all objects from queue.
*
* @function clear
* @name Parse.EventuallyQueue.clear
* @returns {Promise} A promise that is fulfilled when queue is cleared.
* @static
*/
clear() {
queueCache = [];
return this.store([]);
},
/**
* Return the index of a queueId in the queue. Returns -1 if not found.
*
* @param {Queue} queue Queue containing Parse.Object data.
* @param {string} queueId Unique identifier for Parse.Object data.
* @returns {number}
* @static
* @ignore
*/
queueItemExists(queue, queueId) {
return (0, _findIndex.default)(queue).call(queue, data => data.queueId === queueId);
},
/**
* Return the number of objects in the queue.
*
* @function length
* @name Parse.EventuallyQueue.length
* @returns {Promise<number>}
* @static
*/
async length() {
const queueData = await this.getQueue();
return queueData.length;
},
/**
* Sends the queue to the server.
*
* @function sendQueue
* @name Parse.EventuallyQueue.sendQueue
* @returns {Promise<boolean>} Returns true if queue was sent successfully.
* @static
*/
async sendQueue() {
const queue = await this.getQueue();
const queueData = [...queue];
if (queueData.length === 0) {
return false;
}
for (let i = 0; i < queueData.length; i += 1) {
const queueObject = queueData[i];
const {
id,
hash,
className
} = queueObject;
const ObjectType = _ParseObject.default.extend(className);
if (id) {
await this.process.byId(ObjectType, queueObject);
} else if (hash) {
await this.process.byHash(ObjectType, queueObject);
} else {
await this.process.create(ObjectType, queueObject);
}
}
return true;
},
/**
* Build queue object and add to queue.
*
* @param {ParseObject} object Parse.Object to be processed
* @param {QueueObject} queueObject Parse.Object data from the queue
* @returns {Promise} A promise that is fulfilled when operation is performed.
* @static
* @ignore
*/
async sendQueueCallback(object, queueObject) {
if (!object) {
return this.remove(queueObject.queueId);
}
switch (queueObject.action) {
case 'save':
// Queued update was overwritten by other request. Do not save
if (typeof object.updatedAt !== 'undefined' && object.updatedAt > new Date(queueObject.object.createdAt)) {
return this.remove(queueObject.queueId);
}
try {
await object.save(queueObject.object, queueObject.serverOptions);
await this.remove(queueObject.queueId);
} catch (e) {
if (e.code !== _ParseError.default.CONNECTION_FAILED) {
await this.remove(queueObject.queueId);
}
}
break;
case 'destroy':
try {
await object.destroy(queueObject.serverOptions);
await this.remove(queueObject.queueId);
} catch (e) {
if (e.code !== _ParseError.default.CONNECTION_FAILED) {
await this.remove(queueObject.queueId);
}
}
break;
}
},
/**
* Start polling server for network connection.
* Will send queue if connection is established.
*
* @function poll
* @name Parse.EventuallyQueue.poll
* @param [ms] Milliseconds to ping the server. Default 2000ms
* @static
*/
poll(ms) {
if (polling) {
return;
}
polling = (0, _setInterval2.default)(() => {
const RESTController = _CoreManager.default.getRESTController();
RESTController.request('GET', 'health').then(_ref => {
let {
status
} = _ref;
if (status === 'ok') {
this.stopPoll();
return this.sendQueue();
}
}).catch(e => e);
}, ms || 2000);
},
/**
* Turns off polling.
*
* @function stopPoll
* @name Parse.EventuallyQueue.stopPoll
* @static
*/
stopPoll() {
clearInterval(polling);
polling = undefined;
},
/**
* Return true if pinging the server.
*
* @function isPolling
* @name Parse.EventuallyQueue.isPolling
* @returns {boolean}
* @static
*/
isPolling() {
return !!polling;
},
_setPolling(flag) {
polling = flag;
},
process: {
create(ObjectType, queueObject) {
const object = new ObjectType();
return EventuallyQueue.sendQueueCallback(object, queueObject);
},
async byId(ObjectType, queueObject) {
const {
sessionToken
} = queueObject.serverOptions;
const query = new _ParseQuery.default(ObjectType);
query.equalTo('objectId', queueObject.id);
const results = await (0, _find.default)(query).call(query, {
sessionToken
});
return EventuallyQueue.sendQueueCallback(results[0], queueObject);
},
async byHash(ObjectType, queueObject) {
const {
sessionToken
} = queueObject.serverOptions;
const query = new _ParseQuery.default(ObjectType);
query.equalTo('hash', queueObject.hash);
const results = await (0, _find.default)(query).call(query, {
sessionToken
});
if (results.length > 0) {
return EventuallyQueue.sendQueueCallback(results[0], queueObject);
}
return EventuallyQueue.process.create(ObjectType, queueObject);
}
}
};
var _default = exports.default = EventuallyQueue;
},{"./CoreManager":4,"./ParseError":24,"./ParseObject":30,"./ParseQuery":33,"./Storage":43,"@babel/runtime-corejs3/core-js-stable/instance/find":73,"@babel/runtime-corejs3/core-js-stable/instance/find-index":72,"@babel/runtime-corejs3/core-js-stable/instance/splice":83,"@babel/runtime-corejs3/core-js-stable/json/stringify":86,"@babel/runtime-corejs3/core-js-stable/object/define-property":91,"@babel/runtime-corejs3/core-js-stable/set-interval":99,"@babel/runtime-corejs3/helpers/interopRequireDefault":104}],8:[function(_dereq_,module,exports){
"use strict";
var _Object$defineProperty = _dereq_("@babel/runtime-corejs3/core-js-stable/object/define-property");
var _interopRequireDefault = _dereq_("@babel/runtime-corejs3/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _ParseUser = _interopRequireDefault(_dereq_("./ParseUser"));
/* global FB */
let initialized = false;
let requestedPermissions;
let initOptions;
const provider = {
authenticate(options) {
if (typeof FB === 'undefined') {
options.error(this, 'Facebook SDK not found.');
}
FB.login(response => {
if (response.authResponse) {
if (options.success) {
options.success(this, {
id: response.authResponse.userID,
access_token: response.authResponse.accessToken,
expiration_date: new Date(response.authResponse.expiresIn * 1000 + new Date().getTime()).toJSON()
});
}
} else {
if (options.error) {
options.error(this, response);
}
}
}, {
scope: requestedPermissions
});
},
restoreAuthentication(authData) {
if (authData) {
const newOptions = {};
if (initOptions) {
for (const key in initOptions) {
newOptions[key] = initOptions[key];
}
}
// Suppress checks for login status from the browser.
newOptions.status = false;
// If the user doesn't match the one known by the FB SDK, log out.
// Most of the time, the users will match -- it's only in cases where
// the FB SDK knows of a different user than the one being restored
// from a Parse User that logged in with username/password.
const existingResponse = FB.getAuthResponse();
if (existingResponse && existingResponse.userID !== authData.id) {
FB.logout();
}
FB.init(newOptions);
}
return true;
},
getAuthType() {
return 'facebook';
},
deauthenticate() {
this.restoreAuthentication(null);
}
};
/**
* Provides a set of utilities for using Parse with Facebook.
*
* @class Parse.FacebookUtils
* @static
* @hideconstructor
*/
const FacebookUtils = {
/**
* Initializes Parse Facebook integration. Call this function after you
* have loaded the Facebook Javascript SDK with the same parameters
* as you would pass to<code>
* <a href=
* "https://developers.facebook.com/docs/reference/javascript/FB.init/">
* FB.init()</a></code>. Parse.FacebookUtils will invoke FB.init() for you
* with these arguments.
*
* @function init
* @name Parse.FacebookUtils.init
* @param {object} options Facebook options argument as described here:
* <a href=
* "https://developers.facebook.com/docs/reference/javascript/FB.init/">
* FB.init()</a>. The status flag will be coerced to 'false' because it
* interferes with Parse Facebook integration. Call FB.getLoginStatus()
* explicitly if this behavior is required by your application.
*/
init(options) {
if (typeof FB === 'undefined') {
throw new Error('The Facebook JavaScript SDK must be loaded before calling init.');
}
initOptions = {};
if (options) {
for (const key in options) {
initOptions[key] = options[key];
}
}
if (initOptions.status && typeof console !== 'undefined') {
const warn = console.warn || console.log || function () {};
warn.call(console, 'The "status" flag passed into' + ' FB.init, when set to true, can interfere with Parse Facebook' + ' integration, so it has been suppressed. Please call' + ' FB.getLoginStatus() explicitly if you require this behavior.');
}
initOptions.status = false;
FB.init(initOptions);
_ParseUser.default._registerAuthenticationProvider(provider);
initialized = true;
},
/**
* Gets whether the user has their account linked to Facebook.
*
* @function isLinked
* @name Parse.FacebookUtils.isLinked
* @param {Parse.User} user User to check for a facebook link.
* The user must be logged in on this device.
* @returns {boolean} <code>true</code> if the user has their account
* linked to Facebook.
*/
isLinked(user) {
return user._isLinked('facebook');
},
/**
* Logs in a user using Facebook. This method delegates to the Facebook
* SDK to authenticate the user, and then automatically logs in (or
* creates, in the case where it is a new user) a Parse.User.
*
* Standard API:
*
* <code>logIn(permission: string, authData: Object);</code>
*
* Advanced API: Used for handling your own oAuth tokens
* {@link https://docs.parseplatform.org/rest/guide/#linking-users}
*
* <code>logIn(authData: Object, options?: Object);</code>
*
* @function logIn
* @name Parse.FacebookUtils.logIn
* @param {(string | object)} permissions The permissions required for Facebook
* log in. This is a comma-separated string of permissions.
* Alternatively, supply a Facebook authData object as described in our
* REST API docs if you want to handle getting facebook auth tokens
* yourself.
* @param {object} options MasterKey / SessionToken. Alternatively can be used for authData if permissions is a string
* @returns {Promise}
*/
logIn(permissions, options) {
if (!permissions || typeof permissions === 'string') {
if (!initialized) {
throw new Error('You must initialize FacebookUtils before calling logIn.');
}
requestedPermissions = permissions;
return _ParseUser.default.logInWith('facebook', options);
}
return _ParseUser.default.logInWith('facebook', {
authData: permissions
}, options);
},
/**
* Links Facebook to an existing PFUser. This method delegates to the
* Facebook SDK to authenticate the user, and then automatically links
* the account to the Parse.User.
*
* Standard API:
*
* <code>link(user: Parse.User, permission: string, authData?: Object);</code>
*
* Advanced API: Used for handling your own oAuth tokens
* {@link https://docs.parseplatform.org/rest/guide/#linking-users}
*
* <code>link(user: Parse.User, authData: Object, options?: FullOptions);</code>
*
* @function link
* @name Parse.FacebookUtils.link
* @param {Parse.User} user User to link to Facebook. This must be the
* current user.
* @param {(string | object)} permissions The permissions required for Facebook
* log in. This is a comma-separated string of permissions.
* Alternatively, supply a Facebook authData object as described in our
* REST API docs if you want to handle getting facebook auth tokens
* yourself.
* @param {object} options MasterKey / SessionToken. Alternatively can be used for authData if permissions is a string
* @returns {Promise}
*/
link(user, permissions, options) {
if (!permissions || typeof permissions === 'string') {
if (!initialized) {
throw new Error('You must initialize FacebookUtils before calling link.');
}
requestedPermissions = permissions;
return user.linkWith('facebook', options);
}
return user.linkWith('facebook', {
authData: permissions
}, options);
},
/**
* Unlinks the Parse.User from a Facebook account.
*
* @function unlink
* @name Parse.FacebookUtils.unlink
* @param {Parse.User} user User to unlink from Facebook. This must be the
* current user.
* @param {object} options Standard options object with success and error
* callbacks.
* @returns {Promise}
*/
unlink: function (user, options) {
if (!initialized) {
throw new Error('You must initialize FacebookUtils before calling unlink.');
}
return user._unlinkFrom('facebook', options);
},
// Used for testing purposes
_getAuthProvider() {
return provider;
}
};
var _default = exports.default = FacebookUtils;
},{"./ParseUser":38,"@babel/runtime-corejs3/core-js-stable/object/define-property":91,"@babel/runtime-corejs3/helpers/interopRequireDefault":104}],9:[function(_dereq_,module,exports){
"use strict";
var _keysInstanceProperty = _dereq_("@babel/runtime-corejs3/core-js-stable/instance/keys");
var _Object$defineProperty = _dereq_("@babel/runtime-corejs3/core-js-stable/object/define-property");
_Object$defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _idbKeyval = _dereq_("idb-keyval");
/* global window */
let IndexedDBStorageController;
if (typeof window !== 'undefined' && window.indexedDB) {
try {
const ParseStore = (0, _idbKeyval.createStore)('parseDB', 'parseStore');
IndexedDBStorageController = {
async: 1,
getItemAsync(path) {
return (0, _idbKeyval.get)(path, ParseStore);
},
setItemAsync(path, value) {
return (0, _idbKeyval.set)(path, value, ParseStore);
},
removeItemAsync(path) {
return (0, _idbKeyval.del)(path, ParseStore);
},
getAllKeysAsync() {
return (0, _keysInstanceProperty(_idbKeyval))(ParseStore);
},
clear() {
return (0, _idbKeyval.clear)(ParseStore);
}
};
} catch (_) {
// IndexedDB not accessible
IndexedDBStorageController = undefined;
}
} else {
// IndexedDB not supported
IndexedDBStorageController = undefined;
}
var _default = exports.default = IndexedDBStorageController;
},{"@babel/runtime-corejs3/core-js-stable/instance/keys":77,"@babel/runtime-corejs3/core-js-stable/object/define-property":91,"idb-keyval":491}],10:[function(_dereq_,module,exports){
"use strict";
var _Object$defineProperty = _dereq_("@babel/runtime-corejs3/core-js-stable/object/define-property");
var _interopRequireDefault = _dereq_("@babel/runtime-corejs3/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _stringify = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/json/stringify"));
var _CoreManager = _interopRequireDefault(_dereq_("./CoreManager"));
var _Storage = _interopRequireDefault(_dereq_("./Storage"));
var _ParseInstallation = _interopRequireDefault(_dereq_("./ParseInstallation"));
var _uuid = _interopRequireDefault(_dereq_("./uuid"));
const CURRENT_INSTALLATION_KEY = 'currentInstallation';
const CURRENT_INSTALLATION_ID_KEY = 'currentInstallationId';
let iidCache = null;
let currentInstallationCache = null;
let currentInstallationCacheMatchesDisk = false;
const InstallationController = {
async updateInstallationOnDisk(installation) {
const path = _Storage.default.generatePath(CURRENT_INSTALLATION_KEY);
await _Storage.default.setItemAsync(path, (0, _stringify.default)(installation.toJSON()));
this._setCurrentInstallationCache(installation);
},
async currentInstallationId() {
if (typeof iidCache === 'string') {
return iidCache;
}
const path = _Storage.default.generatePath(CURRENT_INSTALLATION_ID_KEY);
let iid = await _Storage.default.getItemAsync(path);
if (!iid) {
iid = (0, _uuid.default)();
return _Storage.default.setItemAsync(path, iid).then(() => {
iidCache = iid;
return iid;
});
}
iidCache = iid;
return iid;
},
async currentInstallation() {
if (currentInstallationCache) {
return currentInstallationCache;
}
if (currentInstallationCacheMatchesDisk) {
return null;
}
const path = _Storage.default.generatePath(CURRENT_INSTALLATION_KEY);
let installationData = await _Storage.default.getItemAsync(path);
currentInstallationCacheMatchesDisk = true;
if (installationData) {
installationData = JSON.parse(installationData);
installationData.className = '_Installation';
const current = _ParseInstallation.default.fromJSON(installationData);
currentInstallationCache = current;
return current;
}
const installationId = await this.currentInstallationId();
const installation = new _ParseInstallation.default();
installation.set('deviceType', _ParseInstallation.default.DEVICE_TYPES.WEB);
installation.set('installationId', installationId);
installation.set('parseVersion', _CoreManager.default.get('VERSION'));
currentInstallationCache = installation;
await _Storage.default.setItemAsync(path, (0, _stringify.default)(installation.toJSON()));
return installation;
},
_clearCache() {
iidCache = null;
currentInstallationCache = null;
currentInstallationCacheMatchesDisk = false;
},
_setInstallationIdCache(iid) {
iidCache = iid;
},
_setCurrentInstallationCache(installation) {
let matchesDisk = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
currentInstallationCache = installation;
currentInstallationCacheMatchesDisk = matchesDisk;
}
};
var _default = exports.default = InstallationController;
},{"./CoreManager":4,"./ParseInstallation":28,"./Storage":43,"./uuid":64,"@babel/runtime-corejs3/core-js-stable/json/stringify":86,"@babel/runtime-corejs3/core-js-stable/object/define-property":91,"@babel/runtime-corejs3/helpers/interopRequireDefault":104}],11:[function(_dereq_,module,exports){
"use strict";
var _Object$defineProperty = _dereq_("@babel/runtime-corejs3/core-js-stable/object/define-property");
var _interopRequireDefault = _dereq_("@babel/runtime-corejs3/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _indexOf = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/instance/index-of"));
var _map = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/map"));
var _keys = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/instance/keys"));
var _stringify = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/json/stringify"));
var _forEach = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/instance/for-each"));
var _values = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/instance/values"));
var _setTimeout2 = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/set-timeout"));
var _bind = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/core-js-stable/instance/bind"));
var _defineProperty2 = _interopRequireDefault(_dereq_("@babel/runtime-corejs3/helpers/defineProperty"));
var _CoreManager = _interopRequireDefault(_dereq_("./CoreManager"));
var _ParseObject = _interopRequireDefault(_dereq_("./ParseObject"));
var _LiveQuerySubscription = _interopRequireDefault(_dereq_("./LiveQuerySubscription"));
var _promiseUtils = _dereq_("./promiseUtils");
var _ParseError = _interopRequireDefault(_dereq_("./ParseError"));
// The LiveQuery client inner state
const CLIENT_STATE = {
INITIALIZED: 'initialized',
CONNECTING: 'connecting',
CONNECTED: 'connected',
CLOSED: 'closed',
RECONNECTING: 'reconnecting',
DISCONNECTED: 'disconnected'
};
// The event type the LiveQuery client should sent to server
co