ParseObject.js 94 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277
  1. "use strict";
  2. var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
  3. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  4. Object.defineProperty(exports, "__esModule", {
  5. value: true
  6. });
  7. exports.default = void 0;
  8. var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
  9. var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
  10. var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
  11. var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
  12. var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
  13. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
  14. var _CoreManager = _interopRequireDefault(require("./CoreManager"));
  15. var _canBeSerialized = _interopRequireDefault(require("./canBeSerialized"));
  16. var _decode = _interopRequireDefault(require("./decode"));
  17. var _encode = _interopRequireDefault(require("./encode"));
  18. var _escape2 = _interopRequireDefault(require("./escape"));
  19. var _ParseACL = _interopRequireDefault(require("./ParseACL"));
  20. var _parseDate = _interopRequireDefault(require("./parseDate"));
  21. var _ParseError = _interopRequireDefault(require("./ParseError"));
  22. var _ParseFile = _interopRequireDefault(require("./ParseFile"));
  23. var _promiseUtils = require("./promiseUtils");
  24. var _LocalDatastoreUtils = require("./LocalDatastoreUtils");
  25. var _ParseOp = require("./ParseOp");
  26. var _ParseQuery = _interopRequireDefault(require("./ParseQuery"));
  27. var _ParseRelation = _interopRequireDefault(require("./ParseRelation"));
  28. var SingleInstanceStateController = _interopRequireWildcard(require("./SingleInstanceStateController"));
  29. var _unique = _interopRequireDefault(require("./unique"));
  30. var UniqueInstanceStateController = _interopRequireWildcard(require("./UniqueInstanceStateController"));
  31. var _unsavedChildren = _interopRequireDefault(require("./unsavedChildren"));
  32. /**
  33. * Copyright (c) 2015-present, Parse, LLC.
  34. * All rights reserved.
  35. *
  36. * This source code is licensed under the BSD-style license found in the
  37. * LICENSE file in the root directory of this source tree. An additional grant
  38. * of patent rights can be found in the PATENTS file in the same directory.
  39. *
  40. * @flow
  41. */
  42. var DEFAULT_BATCH_SIZE = 20; // Mapping of class names to constructors, so we can populate objects from the
  43. // server with appropriate subclasses of ParseObject
  44. var classMap = {}; // Global counter for generating unique local Ids
  45. var localCount = 0; // Global counter for generating unique Ids for non-single-instance objects
  46. var objectCount = 0; // On web clients, objects are single-instance: any two objects with the same Id
  47. // will have the same attributes. However, this may be dangerous default
  48. // behavior in a server scenario
  49. var singleInstance = !_CoreManager.default.get('IS_NODE');
  50. if (singleInstance) {
  51. _CoreManager.default.setObjectStateController(SingleInstanceStateController);
  52. } else {
  53. _CoreManager.default.setObjectStateController(UniqueInstanceStateController);
  54. }
  55. function getServerUrlPath() {
  56. var serverUrl = _CoreManager.default.get('SERVER_URL');
  57. if (serverUrl[serverUrl.length - 1] !== '/') {
  58. serverUrl += '/';
  59. }
  60. var url = serverUrl.replace(/https?:\/\//, '');
  61. return url.substr(url.indexOf('/'));
  62. }
  63. /**
  64. * Creates a new model with defined attributes.
  65. *
  66. * <p>You won't normally call this method directly. It is recommended that
  67. * you use a subclass of <code>Parse.Object</code> instead, created by calling
  68. * <code>extend</code>.</p>
  69. *
  70. * <p>However, if you don't want to use a subclass, or aren't sure which
  71. * subclass is appropriate, you can use this form:<pre>
  72. * var object = new Parse.Object("ClassName");
  73. * </pre>
  74. * That is basically equivalent to:<pre>
  75. * var MyClass = Parse.Object.extend("ClassName");
  76. * var object = new MyClass();
  77. * </pre></p>
  78. *
  79. * @alias Parse.Object
  80. */
  81. var ParseObject =
  82. /*#__PURE__*/
  83. function () {
  84. /**
  85. * @param {String} className The class name for the object
  86. * @param {Object} attributes The initial set of data to store in the object.
  87. * @param {Object} options The options for this object instance.
  88. */
  89. function ParseObject(className
  90. /*: ?string | { className: string, [attr: string]: mixed }*/
  91. , attributes
  92. /*:: ?: { [attr: string]: mixed }*/
  93. , options
  94. /*:: ?: { ignoreValidation: boolean }*/
  95. ) {
  96. (0, _classCallCheck2.default)(this, ParseObject);
  97. (0, _defineProperty2.default)(this, "id", void 0);
  98. (0, _defineProperty2.default)(this, "_localId", void 0);
  99. (0, _defineProperty2.default)(this, "_objCount", void 0);
  100. (0, _defineProperty2.default)(this, "className", void 0); // Enable legacy initializers
  101. if (typeof this.initialize === 'function') {
  102. this.initialize.apply(this, arguments);
  103. }
  104. var toSet = null;
  105. this._objCount = objectCount++;
  106. if (typeof className === 'string') {
  107. this.className = className;
  108. if (attributes && (0, _typeof2.default)(attributes) === 'object') {
  109. toSet = attributes;
  110. }
  111. } else if (className && (0, _typeof2.default)(className) === 'object') {
  112. this.className = className.className;
  113. toSet = {};
  114. for (var _attr in className) {
  115. if (_attr !== 'className') {
  116. toSet[_attr] = className[_attr];
  117. }
  118. }
  119. if (attributes && (0, _typeof2.default)(attributes) === 'object') {
  120. options = attributes;
  121. }
  122. }
  123. if (toSet && !this.set(toSet, options)) {
  124. throw new Error('Can\'t create an invalid Parse Object');
  125. }
  126. }
  127. /**
  128. * The ID of this object, unique within its class.
  129. * @property id
  130. * @type String
  131. */
  132. (0, _createClass2.default)(ParseObject, [{
  133. key: "_getId",
  134. /** Private methods **/
  135. /**
  136. * Returns a local or server Id used uniquely identify this object
  137. */
  138. value: function ()
  139. /*: string*/
  140. {
  141. if (typeof this.id === 'string') {
  142. return this.id;
  143. }
  144. if (typeof this._localId === 'string') {
  145. return this._localId;
  146. }
  147. var localId = 'local' + String(localCount++);
  148. this._localId = localId;
  149. return localId;
  150. }
  151. /**
  152. * Returns a unique identifier used to pull data from the State Controller.
  153. */
  154. }, {
  155. key: "_getStateIdentifier",
  156. value: function ()
  157. /*: ParseObject | {id: string, className: string}*/
  158. {
  159. if (singleInstance) {
  160. var id = this.id;
  161. if (!id) {
  162. id = this._getId();
  163. }
  164. return {
  165. id: id,
  166. className: this.className
  167. };
  168. } else {
  169. return this;
  170. }
  171. }
  172. }, {
  173. key: "_getServerData",
  174. value: function ()
  175. /*: AttributeMap*/
  176. {
  177. var stateController = _CoreManager.default.getObjectStateController();
  178. return stateController.getServerData(this._getStateIdentifier());
  179. }
  180. }, {
  181. key: "_clearServerData",
  182. value: function () {
  183. var serverData = this._getServerData();
  184. var unset = {};
  185. for (var _attr2 in serverData) {
  186. unset[_attr2] = undefined;
  187. }
  188. var stateController = _CoreManager.default.getObjectStateController();
  189. stateController.setServerData(this._getStateIdentifier(), unset);
  190. }
  191. }, {
  192. key: "_getPendingOps",
  193. value: function ()
  194. /*: Array<OpsMap>*/
  195. {
  196. var stateController = _CoreManager.default.getObjectStateController();
  197. return stateController.getPendingOps(this._getStateIdentifier());
  198. }
  199. /**
  200. * @param {Array<string>} [keysToClear] - if specified, only ops matching
  201. * these fields will be cleared
  202. */
  203. }, {
  204. key: "_clearPendingOps",
  205. value: function (keysToClear
  206. /*:: ?: Array<string>*/
  207. ) {
  208. var pending = this._getPendingOps();
  209. var latest = pending[pending.length - 1];
  210. var keys = keysToClear || Object.keys(latest);
  211. keys.forEach(function (key) {
  212. delete latest[key];
  213. });
  214. }
  215. }, {
  216. key: "_getDirtyObjectAttributes",
  217. value: function ()
  218. /*: AttributeMap*/
  219. {
  220. var attributes = this.attributes;
  221. var stateController = _CoreManager.default.getObjectStateController();
  222. var objectCache = stateController.getObjectCache(this._getStateIdentifier());
  223. var dirty = {};
  224. for (var _attr3 in attributes) {
  225. var val = attributes[_attr3];
  226. if (val && (0, _typeof2.default)(val) === 'object' && !(val instanceof ParseObject) && !(val instanceof _ParseFile.default) && !(val instanceof _ParseRelation.default)) {
  227. // Due to the way browsers construct maps, the key order will not change
  228. // unless the object is changed
  229. try {
  230. var json = (0, _encode.default)(val, false, true);
  231. var stringified = JSON.stringify(json);
  232. if (objectCache[_attr3] !== stringified) {
  233. dirty[_attr3] = val;
  234. }
  235. } catch (e) {
  236. // Error occurred, possibly by a nested unsaved pointer in a mutable container
  237. // No matter how it happened, it indicates a change in the attribute
  238. dirty[_attr3] = val;
  239. }
  240. }
  241. }
  242. return dirty;
  243. }
  244. }, {
  245. key: "_toFullJSON",
  246. value: function (seen
  247. /*:: ?: Array<any>*/
  248. )
  249. /*: AttributeMap*/
  250. {
  251. var json
  252. /*: { [key: string]: mixed }*/
  253. = this.toJSON(seen);
  254. json.__type = 'Object';
  255. json.className = this.className;
  256. return json;
  257. }
  258. }, {
  259. key: "_getSaveJSON",
  260. value: function ()
  261. /*: AttributeMap*/
  262. {
  263. var pending = this._getPendingOps();
  264. var dirtyObjects = this._getDirtyObjectAttributes();
  265. var json = {};
  266. for (var attr in dirtyObjects) {
  267. var isDotNotation = false;
  268. for (var i = 0; i < pending.length; i += 1) {
  269. for (var field in pending[i]) {
  270. // Dot notation operations are handled later
  271. if (field.includes('.')) {
  272. var fieldName = field.split('.')[0];
  273. if (fieldName === attr) {
  274. isDotNotation = true;
  275. break;
  276. }
  277. }
  278. }
  279. }
  280. if (!isDotNotation) {
  281. json[attr] = new _ParseOp.SetOp(dirtyObjects[attr]).toJSON();
  282. }
  283. }
  284. for (attr in pending[0]) {
  285. json[attr] = pending[0][attr].toJSON();
  286. }
  287. return json;
  288. }
  289. }, {
  290. key: "_getSaveParams",
  291. value: function ()
  292. /*: SaveParams*/
  293. {
  294. var method = this.id ? 'PUT' : 'POST';
  295. var body = this._getSaveJSON();
  296. var path = 'classes/' + this.className;
  297. if (this.id) {
  298. path += '/' + this.id;
  299. } else if (this.className === '_User') {
  300. path = 'users';
  301. }
  302. return {
  303. method: method,
  304. body: body,
  305. path: path
  306. };
  307. }
  308. }, {
  309. key: "_finishFetch",
  310. value: function (serverData
  311. /*: AttributeMap*/
  312. ) {
  313. if (!this.id && serverData.objectId) {
  314. this.id = serverData.objectId;
  315. }
  316. var stateController = _CoreManager.default.getObjectStateController();
  317. stateController.initializeState(this._getStateIdentifier());
  318. var decoded = {};
  319. for (var _attr4 in serverData) {
  320. if (_attr4 === 'ACL') {
  321. decoded[_attr4] = new _ParseACL.default(serverData[_attr4]);
  322. } else if (_attr4 !== 'objectId') {
  323. decoded[_attr4] = (0, _decode.default)(serverData[_attr4]);
  324. if (decoded[_attr4] instanceof _ParseRelation.default) {
  325. decoded[_attr4]._ensureParentAndKey(this, _attr4);
  326. }
  327. }
  328. }
  329. if (decoded.createdAt && typeof decoded.createdAt === 'string') {
  330. decoded.createdAt = (0, _parseDate.default)(decoded.createdAt);
  331. }
  332. if (decoded.updatedAt && typeof decoded.updatedAt === 'string') {
  333. decoded.updatedAt = (0, _parseDate.default)(decoded.updatedAt);
  334. }
  335. if (!decoded.updatedAt && decoded.createdAt) {
  336. decoded.updatedAt = decoded.createdAt;
  337. }
  338. stateController.commitServerChanges(this._getStateIdentifier(), decoded);
  339. }
  340. }, {
  341. key: "_setExisted",
  342. value: function (existed
  343. /*: boolean*/
  344. ) {
  345. var stateController = _CoreManager.default.getObjectStateController();
  346. var state = stateController.getState(this._getStateIdentifier());
  347. if (state) {
  348. state.existed = existed;
  349. }
  350. }
  351. }, {
  352. key: "_migrateId",
  353. value: function (serverId
  354. /*: string*/
  355. ) {
  356. if (this._localId && serverId) {
  357. if (singleInstance) {
  358. var stateController = _CoreManager.default.getObjectStateController();
  359. var oldState = stateController.removeState(this._getStateIdentifier());
  360. this.id = serverId;
  361. delete this._localId;
  362. if (oldState) {
  363. stateController.initializeState(this._getStateIdentifier(), oldState);
  364. }
  365. } else {
  366. this.id = serverId;
  367. delete this._localId;
  368. }
  369. }
  370. }
  371. }, {
  372. key: "_handleSaveResponse",
  373. value: function (response
  374. /*: AttributeMap*/
  375. , status
  376. /*: number*/
  377. ) {
  378. var changes = {};
  379. var stateController = _CoreManager.default.getObjectStateController();
  380. var pending = stateController.popPendingState(this._getStateIdentifier());
  381. for (var attr in pending) {
  382. if (pending[attr] instanceof _ParseOp.RelationOp) {
  383. changes[attr] = pending[attr].applyTo(undefined, this, attr);
  384. } else if (!(attr in response)) {
  385. // Only SetOps and UnsetOps should not come back with results
  386. changes[attr] = pending[attr].applyTo(undefined);
  387. }
  388. }
  389. for (attr in response) {
  390. if ((attr === 'createdAt' || attr === 'updatedAt') && typeof response[attr] === 'string') {
  391. changes[attr] = (0, _parseDate.default)(response[attr]);
  392. } else if (attr === 'ACL') {
  393. changes[attr] = new _ParseACL.default(response[attr]);
  394. } else if (attr !== 'objectId') {
  395. changes[attr] = (0, _decode.default)(response[attr]);
  396. if (changes[attr] instanceof _ParseOp.UnsetOp) {
  397. changes[attr] = undefined;
  398. }
  399. }
  400. }
  401. if (changes.createdAt && !changes.updatedAt) {
  402. changes.updatedAt = changes.createdAt;
  403. }
  404. this._migrateId(response.objectId);
  405. if (status !== 201) {
  406. this._setExisted(true);
  407. }
  408. stateController.commitServerChanges(this._getStateIdentifier(), changes);
  409. }
  410. }, {
  411. key: "_handleSaveError",
  412. value: function () {
  413. var stateController = _CoreManager.default.getObjectStateController();
  414. stateController.mergeFirstPendingState(this._getStateIdentifier());
  415. }
  416. /** Public methods **/
  417. }, {
  418. key: "initialize",
  419. value: function () {} // NOOP
  420. /**
  421. * Returns a JSON version of the object suitable for saving to Parse.
  422. * @return {Object}
  423. */
  424. }, {
  425. key: "toJSON",
  426. value: function (seen
  427. /*: Array<any> | void*/
  428. )
  429. /*: AttributeMap*/
  430. {
  431. var seenEntry = this.id ? this.className + ':' + this.id : this;
  432. seen = seen || [seenEntry];
  433. var json = {};
  434. var attrs = this.attributes;
  435. for (var _attr5 in attrs) {
  436. if ((_attr5 === 'createdAt' || _attr5 === 'updatedAt') && attrs[_attr5].toJSON) {
  437. json[_attr5] = attrs[_attr5].toJSON();
  438. } else {
  439. json[_attr5] = (0, _encode.default)(attrs[_attr5], false, false, seen);
  440. }
  441. }
  442. var pending = this._getPendingOps();
  443. for (var _attr6 in pending[0]) {
  444. json[_attr6] = pending[0][_attr6].toJSON();
  445. }
  446. if (this.id) {
  447. json.objectId = this.id;
  448. }
  449. return json;
  450. }
  451. /**
  452. * Determines whether this ParseObject is equal to another ParseObject
  453. * @param {Object} other - An other object ot compare
  454. * @return {Boolean}
  455. */
  456. }, {
  457. key: "equals",
  458. value: function (other
  459. /*: mixed*/
  460. )
  461. /*: boolean*/
  462. {
  463. if (this === other) {
  464. return true;
  465. }
  466. return other instanceof ParseObject && this.className === other.className && this.id === other.id && typeof this.id !== 'undefined';
  467. }
  468. /**
  469. * Returns true if this object has been modified since its last
  470. * save/refresh. If an attribute is specified, it returns true only if that
  471. * particular attribute has been modified since the last save/refresh.
  472. * @param {String} attr An attribute name (optional).
  473. * @return {Boolean}
  474. */
  475. }, {
  476. key: "dirty",
  477. value: function (attr
  478. /*:: ?: string*/
  479. )
  480. /*: boolean*/
  481. {
  482. if (!this.id) {
  483. return true;
  484. }
  485. var pendingOps = this._getPendingOps();
  486. var dirtyObjects = this._getDirtyObjectAttributes();
  487. if (attr) {
  488. if (dirtyObjects.hasOwnProperty(attr)) {
  489. return true;
  490. }
  491. for (var i = 0; i < pendingOps.length; i++) {
  492. if (pendingOps[i].hasOwnProperty(attr)) {
  493. return true;
  494. }
  495. }
  496. return false;
  497. }
  498. if (Object.keys(pendingOps[0]).length !== 0) {
  499. return true;
  500. }
  501. if (Object.keys(dirtyObjects).length !== 0) {
  502. return true;
  503. }
  504. return false;
  505. }
  506. /**
  507. * Returns an array of keys that have been modified since last save/refresh
  508. * @return {String[]}
  509. */
  510. }, {
  511. key: "dirtyKeys",
  512. value: function ()
  513. /*: Array<string>*/
  514. {
  515. var pendingOps = this._getPendingOps();
  516. var keys = {};
  517. for (var i = 0; i < pendingOps.length; i++) {
  518. for (var _attr7 in pendingOps[i]) {
  519. keys[_attr7] = true;
  520. }
  521. }
  522. var dirtyObjects = this._getDirtyObjectAttributes();
  523. for (var _attr8 in dirtyObjects) {
  524. keys[_attr8] = true;
  525. }
  526. return Object.keys(keys);
  527. }
  528. /**
  529. * Returns true if the object has been fetched.
  530. * @return {Boolean}
  531. */
  532. }, {
  533. key: "isDataAvailable",
  534. value: function ()
  535. /*: boolean*/
  536. {
  537. var serverData = this._getServerData();
  538. return !!Object.keys(serverData).length;
  539. }
  540. /**
  541. * Gets a Pointer referencing this Object.
  542. * @return {Pointer}
  543. */
  544. }, {
  545. key: "toPointer",
  546. value: function ()
  547. /*: Pointer*/
  548. {
  549. if (!this.id) {
  550. throw new Error('Cannot create a pointer to an unsaved ParseObject');
  551. }
  552. return {
  553. __type: 'Pointer',
  554. className: this.className,
  555. objectId: this.id
  556. };
  557. }
  558. /**
  559. * Gets the value of an attribute.
  560. * @param {String} attr The string name of an attribute.
  561. */
  562. }, {
  563. key: "get",
  564. value: function (attr
  565. /*: string*/
  566. )
  567. /*: mixed*/
  568. {
  569. return this.attributes[attr];
  570. }
  571. /**
  572. * Gets a relation on the given class for the attribute.
  573. * @param String attr The attribute to get the relation for.
  574. * @return {Parse.Relation}
  575. */
  576. }, {
  577. key: "relation",
  578. value: function (attr
  579. /*: string*/
  580. )
  581. /*: ParseRelation*/
  582. {
  583. var value = this.get(attr);
  584. if (value) {
  585. if (!(value instanceof _ParseRelation.default)) {
  586. throw new Error('Called relation() on non-relation field ' + attr);
  587. }
  588. value._ensureParentAndKey(this, attr);
  589. return value;
  590. }
  591. return new _ParseRelation.default(this, attr);
  592. }
  593. /**
  594. * Gets the HTML-escaped value of an attribute.
  595. * @param {String} attr The string name of an attribute.
  596. */
  597. }, {
  598. key: "escape",
  599. value: function (attr
  600. /*: string*/
  601. )
  602. /*: string*/
  603. {
  604. var val = this.attributes[attr];
  605. if (val == null) {
  606. return '';
  607. }
  608. if (typeof val !== 'string') {
  609. if (typeof val.toString !== 'function') {
  610. return '';
  611. }
  612. val = val.toString();
  613. }
  614. return (0, _escape2.default)(val);
  615. }
  616. /**
  617. * Returns <code>true</code> if the attribute contains a value that is not
  618. * null or undefined.
  619. * @param {String} attr The string name of the attribute.
  620. * @return {Boolean}
  621. */
  622. }, {
  623. key: "has",
  624. value: function (attr
  625. /*: string*/
  626. )
  627. /*: boolean*/
  628. {
  629. var attributes = this.attributes;
  630. if (attributes.hasOwnProperty(attr)) {
  631. return attributes[attr] != null;
  632. }
  633. return false;
  634. }
  635. /**
  636. * Sets a hash of model attributes on the object.
  637. *
  638. * <p>You can call it with an object containing keys and values, with one
  639. * key and value, or dot notation. For example:<pre>
  640. * gameTurn.set({
  641. * player: player1,
  642. * diceRoll: 2
  643. * }, {
  644. * error: function(gameTurnAgain, error) {
  645. * // The set failed validation.
  646. * }
  647. * });
  648. *
  649. * game.set("currentPlayer", player2, {
  650. * error: function(gameTurnAgain, error) {
  651. * // The set failed validation.
  652. * }
  653. * });
  654. *
  655. * game.set("finished", true);</pre></p>
  656. *
  657. * game.set("player.score", 10);</pre></p>
  658. *
  659. * @param {String} key The key to set.
  660. * @param {} value The value to give it.
  661. * @param {Object} options A set of options for the set.
  662. * The only supported option is <code>error</code>.
  663. * @return {(ParseObject|Boolean)} true if the set succeeded.
  664. */
  665. }, {
  666. key: "set",
  667. value: function (key
  668. /*: mixed*/
  669. , value
  670. /*: mixed*/
  671. , options
  672. /*:: ?: mixed*/
  673. )
  674. /*: ParseObject | boolean*/
  675. {
  676. var changes = {};
  677. var newOps = {};
  678. if (key && (0, _typeof2.default)(key) === 'object') {
  679. changes = key;
  680. options = value;
  681. } else if (typeof key === 'string') {
  682. changes[key] = value;
  683. } else {
  684. return this;
  685. }
  686. options = options || {};
  687. var readonly = [];
  688. if (typeof this.constructor.readOnlyAttributes === 'function') {
  689. readonly = readonly.concat(this.constructor.readOnlyAttributes());
  690. }
  691. for (var k in changes) {
  692. if (k === 'createdAt' || k === 'updatedAt') {
  693. // This property is read-only, but for legacy reasons we silently
  694. // ignore it
  695. continue;
  696. }
  697. if (readonly.indexOf(k) > -1) {
  698. throw new Error('Cannot modify readonly attribute: ' + k);
  699. }
  700. if (options.unset) {
  701. newOps[k] = new _ParseOp.UnsetOp();
  702. } else if (changes[k] instanceof _ParseOp.Op) {
  703. newOps[k] = changes[k];
  704. } else if (changes[k] && (0, _typeof2.default)(changes[k]) === 'object' && typeof changes[k].__op === 'string') {
  705. newOps[k] = (0, _ParseOp.opFromJSON)(changes[k]);
  706. } else if (k === 'objectId' || k === 'id') {
  707. if (typeof changes[k] === 'string') {
  708. this.id = changes[k];
  709. }
  710. } else if (k === 'ACL' && (0, _typeof2.default)(changes[k]) === 'object' && !(changes[k] instanceof _ParseACL.default)) {
  711. newOps[k] = new _ParseOp.SetOp(new _ParseACL.default(changes[k]));
  712. } else if (changes[k] instanceof _ParseRelation.default) {
  713. var relation = new _ParseRelation.default(this, k);
  714. relation.targetClassName = changes[k].targetClassName;
  715. newOps[k] = new _ParseOp.SetOp(relation);
  716. } else {
  717. newOps[k] = new _ParseOp.SetOp(changes[k]);
  718. }
  719. }
  720. var currentAttributes = this.attributes; // Only set nested fields if exists
  721. var serverData = this._getServerData();
  722. if (typeof key === 'string' && key.includes('.')) {
  723. var field = key.split('.')[0];
  724. if (!serverData[field]) {
  725. return this;
  726. }
  727. } // Calculate new values
  728. var newValues = {};
  729. for (var _attr9 in newOps) {
  730. if (newOps[_attr9] instanceof _ParseOp.RelationOp) {
  731. newValues[_attr9] = newOps[_attr9].applyTo(currentAttributes[_attr9], this, _attr9);
  732. } else if (!(newOps[_attr9] instanceof _ParseOp.UnsetOp)) {
  733. newValues[_attr9] = newOps[_attr9].applyTo(currentAttributes[_attr9]);
  734. }
  735. } // Validate changes
  736. if (!options.ignoreValidation) {
  737. var validation = this.validate(newValues);
  738. if (validation) {
  739. if (typeof options.error === 'function') {
  740. options.error(this, validation);
  741. }
  742. return false;
  743. }
  744. } // Consolidate Ops
  745. var pendingOps = this._getPendingOps();
  746. var last = pendingOps.length - 1;
  747. var stateController = _CoreManager.default.getObjectStateController();
  748. for (var _attr10 in newOps) {
  749. var nextOp = newOps[_attr10].mergeWith(pendingOps[last][_attr10]);
  750. stateController.setPendingOp(this._getStateIdentifier(), _attr10, nextOp);
  751. }
  752. return this;
  753. }
  754. /**
  755. * Remove an attribute from the model. This is a noop if the attribute doesn't
  756. * exist.
  757. * @param {String} attr The string name of an attribute.
  758. * @return {(ParseObject|Boolean)}
  759. */
  760. }, {
  761. key: "unset",
  762. value: function (attr
  763. /*: string*/
  764. , options
  765. /*:: ?: { [opt: string]: mixed }*/
  766. )
  767. /*: ParseObject | boolean*/
  768. {
  769. options = options || {};
  770. options.unset = true;
  771. return this.set(attr, null, options);
  772. }
  773. /**
  774. * Atomically increments the value of the given attribute the next time the
  775. * object is saved. If no amount is specified, 1 is used by default.
  776. *
  777. * @param attr {String} The key.
  778. * @param amount {Number} The amount to increment by (optional).
  779. * @return {(ParseObject|Boolean)}
  780. */
  781. }, {
  782. key: "increment",
  783. value: function (attr
  784. /*: string*/
  785. , amount
  786. /*:: ?: number*/
  787. )
  788. /*: ParseObject | boolean*/
  789. {
  790. if (typeof amount === 'undefined') {
  791. amount = 1;
  792. }
  793. if (typeof amount !== 'number') {
  794. throw new Error('Cannot increment by a non-numeric amount.');
  795. }
  796. return this.set(attr, new _ParseOp.IncrementOp(amount));
  797. }
  798. /**
  799. * Atomically add an object to the end of the array associated with a given
  800. * key.
  801. * @param attr {String} The key.
  802. * @param item {} The item to add.
  803. * @return {(ParseObject|Boolean)}
  804. */
  805. }, {
  806. key: "add",
  807. value: function (attr
  808. /*: string*/
  809. , item
  810. /*: mixed*/
  811. )
  812. /*: ParseObject | boolean*/
  813. {
  814. return this.set(attr, new _ParseOp.AddOp([item]));
  815. }
  816. /**
  817. * Atomically add the objects to the end of the array associated with a given
  818. * key.
  819. * @param attr {String} The key.
  820. * @param items {Object[]} The items to add.
  821. * @return {(ParseObject|Boolean)}
  822. */
  823. }, {
  824. key: "addAll",
  825. value: function (attr
  826. /*: string*/
  827. , items
  828. /*: Array<mixed>*/
  829. )
  830. /*: ParseObject | boolean*/
  831. {
  832. return this.set(attr, new _ParseOp.AddOp(items));
  833. }
  834. /**
  835. * Atomically add an object to the array associated with a given key, only
  836. * if it is not already present in the array. The position of the insert is
  837. * not guaranteed.
  838. *
  839. * @param attr {String} The key.
  840. * @param item {} The object to add.
  841. * @return {(ParseObject|Boolean)}
  842. */
  843. }, {
  844. key: "addUnique",
  845. value: function (attr
  846. /*: string*/
  847. , item
  848. /*: mixed*/
  849. )
  850. /*: ParseObject | boolean*/
  851. {
  852. return this.set(attr, new _ParseOp.AddUniqueOp([item]));
  853. }
  854. /**
  855. * Atomically add the objects to the array associated with a given key, only
  856. * if it is not already present in the array. The position of the insert is
  857. * not guaranteed.
  858. *
  859. * @param attr {String} The key.
  860. * @param items {Object[]} The objects to add.
  861. * @return {(ParseObject|Boolean)}
  862. */
  863. }, {
  864. key: "addAllUnique",
  865. value: function (attr
  866. /*: string*/
  867. , items
  868. /*: Array<mixed>*/
  869. )
  870. /*: ParseObject | boolean*/
  871. {
  872. return this.set(attr, new _ParseOp.AddUniqueOp(items));
  873. }
  874. /**
  875. * Atomically remove all instances of an object from the array associated
  876. * with a given key.
  877. *
  878. * @param attr {String} The key.
  879. * @param item {} The object to remove.
  880. * @return {(ParseObject|Boolean)}
  881. */
  882. }, {
  883. key: "remove",
  884. value: function (attr
  885. /*: string*/
  886. , item
  887. /*: mixed*/
  888. )
  889. /*: ParseObject | boolean*/
  890. {
  891. return this.set(attr, new _ParseOp.RemoveOp([item]));
  892. }
  893. /**
  894. * Atomically remove all instances of the objects from the array associated
  895. * with a given key.
  896. *
  897. * @param attr {String} The key.
  898. * @param items {Object[]} The object to remove.
  899. * @return {(ParseObject|Boolean)}
  900. */
  901. }, {
  902. key: "removeAll",
  903. value: function (attr
  904. /*: string*/
  905. , items
  906. /*: Array<mixed>*/
  907. )
  908. /*: ParseObject | boolean*/
  909. {
  910. return this.set(attr, new _ParseOp.RemoveOp(items));
  911. }
  912. /**
  913. * Returns an instance of a subclass of Parse.Op describing what kind of
  914. * modification has been performed on this field since the last time it was
  915. * saved. For example, after calling object.increment("x"), calling
  916. * object.op("x") would return an instance of Parse.Op.Increment.
  917. *
  918. * @param attr {String} The key.
  919. * @returns {Parse.Op} The operation, or undefined if none.
  920. */
  921. }, {
  922. key: "op",
  923. value: function (attr
  924. /*: string*/
  925. )
  926. /*: ?Op*/
  927. {
  928. var pending = this._getPendingOps();
  929. for (var i = pending.length; i--;) {
  930. if (pending[i][attr]) {
  931. return pending[i][attr];
  932. }
  933. }
  934. }
  935. /**
  936. * Creates a new model with identical attributes to this one.
  937. * @return {Parse.Object}
  938. */
  939. }, {
  940. key: "clone",
  941. value: function clone()
  942. /*: any*/
  943. {
  944. var clone = new this.constructor();
  945. if (!clone.className) {
  946. clone.className = this.className;
  947. }
  948. var attributes = this.attributes;
  949. if (typeof this.constructor.readOnlyAttributes === 'function') {
  950. var readonly = this.constructor.readOnlyAttributes() || []; // Attributes are frozen, so we have to rebuild an object,
  951. // rather than delete readonly keys
  952. var copy = {};
  953. for (var a in attributes) {
  954. if (readonly.indexOf(a) < 0) {
  955. copy[a] = attributes[a];
  956. }
  957. }
  958. attributes = copy;
  959. }
  960. if (clone.set) {
  961. clone.set(attributes);
  962. }
  963. return clone;
  964. }
  965. /**
  966. * Creates a new instance of this object. Not to be confused with clone()
  967. * @return {Parse.Object}
  968. */
  969. }, {
  970. key: "newInstance",
  971. value: function ()
  972. /*: any*/
  973. {
  974. var clone = new this.constructor();
  975. if (!clone.className) {
  976. clone.className = this.className;
  977. }
  978. clone.id = this.id;
  979. if (singleInstance) {
  980. // Just return an object with the right id
  981. return clone;
  982. }
  983. var stateController = _CoreManager.default.getObjectStateController();
  984. if (stateController) {
  985. stateController.duplicateState(this._getStateIdentifier(), clone._getStateIdentifier());
  986. }
  987. return clone;
  988. }
  989. /**
  990. * Returns true if this object has never been saved to Parse.
  991. * @return {Boolean}
  992. */
  993. }, {
  994. key: "isNew",
  995. value: function ()
  996. /*: boolean*/
  997. {
  998. return !this.id;
  999. }
  1000. /**
  1001. * Returns true if this object was created by the Parse server when the
  1002. * object might have already been there (e.g. in the case of a Facebook
  1003. * login)
  1004. * @return {Boolean}
  1005. */
  1006. }, {
  1007. key: "existed",
  1008. value: function ()
  1009. /*: boolean*/
  1010. {
  1011. if (!this.id) {
  1012. return false;
  1013. }
  1014. var stateController = _CoreManager.default.getObjectStateController();
  1015. var state = stateController.getState(this._getStateIdentifier());
  1016. if (state) {
  1017. return state.existed;
  1018. }
  1019. return false;
  1020. }
  1021. /**
  1022. * Checks if the model is currently in a valid state.
  1023. * @return {Boolean}
  1024. */
  1025. }, {
  1026. key: "isValid",
  1027. value: function ()
  1028. /*: boolean*/
  1029. {
  1030. return !this.validate(this.attributes);
  1031. }
  1032. /**
  1033. * You should not call this function directly unless you subclass
  1034. * <code>Parse.Object</code>, in which case you can override this method
  1035. * to provide additional validation on <code>set</code> and
  1036. * <code>save</code>. Your implementation should return
  1037. *
  1038. * @param {Object} attrs The current data to validate.
  1039. * @return {} False if the data is valid. An error object otherwise.
  1040. * @see Parse.Object#set
  1041. */
  1042. }, {
  1043. key: "validate",
  1044. value: function (attrs
  1045. /*: AttributeMap*/
  1046. )
  1047. /*: ParseError | boolean*/
  1048. {
  1049. if (attrs.hasOwnProperty('ACL') && !(attrs.ACL instanceof _ParseACL.default)) {
  1050. return new _ParseError.default(_ParseError.default.OTHER_CAUSE, 'ACL must be a Parse ACL.');
  1051. }
  1052. for (var _key in attrs) {
  1053. if (!/^[A-Za-z][0-9A-Za-z_.]*$/.test(_key)) {
  1054. return new _ParseError.default(_ParseError.default.INVALID_KEY_NAME);
  1055. }
  1056. }
  1057. return false;
  1058. }
  1059. /**
  1060. * Returns the ACL for this object.
  1061. * @returns {Parse.ACL} An instance of Parse.ACL.
  1062. * @see Parse.Object#get
  1063. */
  1064. }, {
  1065. key: "getACL",
  1066. value: function ()
  1067. /*: ?ParseACL*/
  1068. {
  1069. var acl = this.get('ACL');
  1070. if (acl instanceof _ParseACL.default) {
  1071. return acl;
  1072. }
  1073. return null;
  1074. }
  1075. /**
  1076. * Sets the ACL to be used for this object.
  1077. * @param {Parse.ACL} acl An instance of Parse.ACL.
  1078. * @param {Object} options
  1079. * @return {(ParseObject|Boolean)} Whether the set passed validation.
  1080. * @see Parse.Object#set
  1081. */
  1082. }, {
  1083. key: "setACL",
  1084. value: function (acl
  1085. /*: ParseACL*/
  1086. , options
  1087. /*:: ?: mixed*/
  1088. )
  1089. /*: ParseObject | boolean*/
  1090. {
  1091. return this.set('ACL', acl, options);
  1092. }
  1093. /**
  1094. * Clears any (or specific) changes to this object made since the last call to save()
  1095. * @param {string} [keys] - specify which fields to revert
  1096. */
  1097. }, {
  1098. key: "revert",
  1099. value: function ()
  1100. /*: void*/
  1101. {
  1102. var keysToRevert;
  1103. for (var _len = arguments.length, keys = new Array(_len), _key2 = 0; _key2 < _len; _key2++) {
  1104. keys[_key2] = arguments[_key2];
  1105. }
  1106. if (keys.length) {
  1107. keysToRevert = [];
  1108. for (var _i = 0, _keys = keys; _i < _keys.length; _i++) {
  1109. var _key3 = _keys[_i];
  1110. if (typeof _key3 === "string") {
  1111. keysToRevert.push(_key3);
  1112. } else {
  1113. throw new Error("Parse.Object#revert expects either no, or a list of string, arguments.");
  1114. }
  1115. }
  1116. }
  1117. this._clearPendingOps(keysToRevert);
  1118. }
  1119. /**
  1120. * Clears all attributes on a model
  1121. * @return {(ParseObject | boolean)}
  1122. */
  1123. }, {
  1124. key: "clear",
  1125. value: function ()
  1126. /*: ParseObject | boolean*/
  1127. {
  1128. var attributes = this.attributes;
  1129. var erasable = {};
  1130. var readonly = ['createdAt', 'updatedAt'];
  1131. if (typeof this.constructor.readOnlyAttributes === 'function') {
  1132. readonly = readonly.concat(this.constructor.readOnlyAttributes());
  1133. }
  1134. for (var _attr11 in attributes) {
  1135. if (readonly.indexOf(_attr11) < 0) {
  1136. erasable[_attr11] = true;
  1137. }
  1138. }
  1139. return this.set(erasable, {
  1140. unset: true
  1141. });
  1142. }
  1143. /**
  1144. * Fetch the model from the server. If the server's representation of the
  1145. * model differs from its current attributes, they will be overriden.
  1146. *
  1147. * @param {Object} options
  1148. * Valid options are:<ul>
  1149. * <li>useMasterKey: In Cloud Code and Node only, causes the Master Key to
  1150. * be used for this request.
  1151. * <li>sessionToken: A valid session token, used for making a request on
  1152. * behalf of a specific user.
  1153. * <li>include: The name(s) of the key(s) to include. Can be a string, an array of strings,
  1154. * or an array of array of strings.
  1155. * </ul>
  1156. * @return {Promise} A promise that is fulfilled when the fetch
  1157. * completes.
  1158. */
  1159. }, {
  1160. key: "fetch",
  1161. value: function (options
  1162. /*: RequestOptions*/
  1163. )
  1164. /*: Promise*/
  1165. {
  1166. options = options || {};
  1167. var fetchOptions = {};
  1168. if (options.hasOwnProperty('useMasterKey')) {
  1169. fetchOptions.useMasterKey = options.useMasterKey;
  1170. }
  1171. if (options.hasOwnProperty('sessionToken')) {
  1172. fetchOptions.sessionToken = options.sessionToken;
  1173. }
  1174. if (options.hasOwnProperty('include')) {
  1175. fetchOptions.include = [];
  1176. if (Array.isArray(options.include)) {
  1177. options.include.forEach(function (key) {
  1178. if (Array.isArray(key)) {
  1179. fetchOptions.include = fetchOptions.include.concat(key);
  1180. } else {
  1181. fetchOptions.include.push(key);
  1182. }
  1183. });
  1184. } else {
  1185. fetchOptions.include.push(options.include);
  1186. }
  1187. }
  1188. var controller = _CoreManager.default.getObjectController();
  1189. return controller.fetch(this, true, fetchOptions);
  1190. }
  1191. /**
  1192. * Fetch the model from the server. If the server's representation of the
  1193. * model differs from its current attributes, they will be overriden.
  1194. *
  1195. * Includes nested Parse.Objects for the provided key. You can use dot
  1196. * notation to specify which fields in the included object are also fetched.
  1197. *
  1198. * @param {String|Array<string|Array<string>>} keys The name(s) of the key(s) to include.
  1199. * @param {Object} options
  1200. * Valid options are:<ul>
  1201. * <li>useMasterKey: In Cloud Code and Node only, causes the Master Key to
  1202. * be used for this request.
  1203. * <li>sessionToken: A valid session token, used for making a request on
  1204. * behalf of a specific user.
  1205. * </ul>
  1206. * @return {Promise} A promise that is fulfilled when the fetch
  1207. * completes.
  1208. */
  1209. }, {
  1210. key: "fetchWithInclude",
  1211. value: function (keys
  1212. /*: String|Array<string|Array<string>>*/
  1213. , options
  1214. /*: RequestOptions*/
  1215. )
  1216. /*: Promise*/
  1217. {
  1218. options = options || {};
  1219. options.include = keys;
  1220. return this.fetch(options);
  1221. }
  1222. /**
  1223. * Set a hash of model attributes, and save the model to the server.
  1224. * updatedAt will be updated when the request returns.
  1225. * You can either call it as:<pre>
  1226. * object.save();</pre>
  1227. * or<pre>
  1228. * object.save(attrs);</pre>
  1229. * or<pre>
  1230. * object.save(null, options);</pre>
  1231. * or<pre>
  1232. * object.save(attrs, options);</pre>
  1233. * or<pre>
  1234. * object.save(key, value, options);</pre>
  1235. *
  1236. * For example, <pre>
  1237. * gameTurn.save({
  1238. * player: "Jake Cutter",
  1239. * diceRoll: 2
  1240. * }).then(function(gameTurnAgain) {
  1241. * // The save was successful.
  1242. * }, function(error) {
  1243. * // The save failed. Error is an instance of Parse.Error.
  1244. * });</pre>
  1245. *
  1246. * @param {String|Object|null} [attrs]
  1247. * Valid options are:<ul>
  1248. * <li>`Object` - Key/value pairs to update on the object.</li>
  1249. * <li>`String` Key - Key of attribute to update (requires arg2 to also be string)</li>
  1250. * <li>`null` - Passing null for arg1 allows you to save the object with options passed in arg2.</li>
  1251. * </ul>
  1252. *
  1253. * @param {String|Object} [options]
  1254. * <ul>
  1255. * <li>`String` Value - If arg1 was passed as a key, arg2 is the value that should be set on that key.</li>
  1256. * <li>`Object` Options - Valid options are:
  1257. * <ul>
  1258. * <li>useMasterKey: In Cloud Code and Node only, causes the Master Key to
  1259. * be used for this request.
  1260. * <li>sessionToken: A valid session token, used for making a request on
  1261. * behalf of a specific user.
  1262. * </ul>
  1263. * </li>
  1264. * </ul>
  1265. *
  1266. * @param {Object} [options]
  1267. * Used to pass option parameters to method if arg1 and arg2 were both passed as strings.
  1268. * Valid options are:
  1269. * <ul>
  1270. * <li>useMasterKey: In Cloud Code and Node only, causes the Master Key to
  1271. * be used for this request.
  1272. * <li>sessionToken: A valid session token, used for making a request on
  1273. * behalf of a specific user.
  1274. * </ul>
  1275. *
  1276. * @return {Promise} A promise that is fulfilled when the save
  1277. * completes.
  1278. */
  1279. }, {
  1280. key: "save",
  1281. value: function (arg1
  1282. /*: ?string | { [attr: string]: mixed }*/
  1283. , arg2
  1284. /*: FullOptions | mixed*/
  1285. , arg3
  1286. /*:: ?: FullOptions*/
  1287. )
  1288. /*: Promise*/
  1289. {
  1290. var _this = this;
  1291. var attrs;
  1292. var options;
  1293. if ((0, _typeof2.default)(arg1) === 'object' || typeof arg1 === 'undefined') {
  1294. attrs = arg1;
  1295. if ((0, _typeof2.default)(arg2) === 'object') {
  1296. options = arg2;
  1297. }
  1298. } else {
  1299. attrs = {};
  1300. attrs[arg1] = arg2;
  1301. options = arg3;
  1302. } // TODO: safely remove me
  1303. // Support save({ success: function() {}, error: function() {} })
  1304. if (!options && attrs) {
  1305. options = {};
  1306. if (typeof attrs.success === 'function') {
  1307. options.success = attrs.success;
  1308. delete attrs.success;
  1309. }
  1310. if (typeof attrs.error === 'function') {
  1311. options.error = attrs.error;
  1312. delete attrs.error;
  1313. }
  1314. }
  1315. if (attrs) {
  1316. var validation = this.validate(attrs);
  1317. if (validation) {
  1318. if (options && typeof options.error === 'function') {
  1319. options.error(this, validation);
  1320. }
  1321. return Promise.reject(validation);
  1322. }
  1323. this.set(attrs, options);
  1324. }
  1325. options = options || {};
  1326. var saveOptions = {};
  1327. if (options.hasOwnProperty('useMasterKey')) {
  1328. saveOptions.useMasterKey = !!options.useMasterKey;
  1329. }
  1330. if (options.hasOwnProperty('sessionToken') && typeof options.sessionToken === 'string') {
  1331. saveOptions.sessionToken = options.sessionToken;
  1332. }
  1333. var controller = _CoreManager.default.getObjectController();
  1334. var unsaved = (0, _unsavedChildren.default)(this);
  1335. return controller.save(unsaved, saveOptions).then(function () {
  1336. return controller.save(_this, saveOptions);
  1337. });
  1338. }
  1339. /**
  1340. * Destroy this model on the server if it was already persisted.
  1341. *
  1342. * @param {Object} options
  1343. * Valid options are:<ul>
  1344. * <li>useMasterKey: In Cloud Code and Node only, causes the Master Key to
  1345. * be used for this request.
  1346. * <li>sessionToken: A valid session token, used for making a request on
  1347. * behalf of a specific user.
  1348. * </ul>
  1349. * @return {Promise} A promise that is fulfilled when the destroy
  1350. * completes.
  1351. */
  1352. }, {
  1353. key: "destroy",
  1354. value: function (options
  1355. /*: RequestOptions*/
  1356. )
  1357. /*: Promise*/
  1358. {
  1359. options = options || {};
  1360. var destroyOptions = {};
  1361. if (options.hasOwnProperty('useMasterKey')) {
  1362. destroyOptions.useMasterKey = options.useMasterKey;
  1363. }
  1364. if (options.hasOwnProperty('sessionToken')) {
  1365. destroyOptions.sessionToken = options.sessionToken;
  1366. }
  1367. if (!this.id) {
  1368. return Promise.resolve();
  1369. }
  1370. return _CoreManager.default.getObjectController().destroy(this, destroyOptions);
  1371. }
  1372. /**
  1373. * Asynchronously stores the object and every object it points to in the local datastore,
  1374. * recursively, using a default pin name: _default.
  1375. *
  1376. * If those other objects have not been fetched from Parse, they will not be stored.
  1377. * However, if they have changed data, all the changes will be retained.
  1378. *
  1379. * <pre>
  1380. * await object.pin();
  1381. * </pre>
  1382. *
  1383. * To retrieve object:
  1384. * <code>query.fromLocalDatastore()</code> or <code>query.fromPin()</code>
  1385. *
  1386. * @return {Promise} A promise that is fulfilled when the pin completes.
  1387. */
  1388. }, {
  1389. key: "pin",
  1390. value: function ()
  1391. /*: Promise<void>*/
  1392. {
  1393. return ParseObject.pinAllWithName(_LocalDatastoreUtils.DEFAULT_PIN, [this]);
  1394. }
  1395. /**
  1396. * Asynchronously removes the object and every object it points to in the local datastore,
  1397. * recursively, using a default pin name: _default.
  1398. *
  1399. * <pre>
  1400. * await object.unPin();
  1401. * </pre>
  1402. *
  1403. * @return {Promise} A promise that is fulfilled when the unPin completes.
  1404. */
  1405. }, {
  1406. key: "unPin",
  1407. value: function ()
  1408. /*: Promise<void>*/
  1409. {
  1410. return ParseObject.unPinAllWithName(_LocalDatastoreUtils.DEFAULT_PIN, [this]);
  1411. }
  1412. /**
  1413. * Asynchronously returns if the object is pinned
  1414. *
  1415. * <pre>
  1416. * const isPinned = await object.isPinned();
  1417. * </pre>
  1418. *
  1419. * @return {Promise<boolean>} A boolean promise that is fulfilled if object is pinned.
  1420. */
  1421. }, {
  1422. key: "isPinned",
  1423. value: function () {
  1424. var _isPinned = (0, _asyncToGenerator2.default)(
  1425. /*#__PURE__*/
  1426. _regenerator.default.mark(function _callee() {
  1427. var localDatastore, objectKey, pin;
  1428. return _regenerator.default.wrap(function (_context) {
  1429. while (1) {
  1430. switch (_context.prev = _context.next) {
  1431. case 0:
  1432. localDatastore = _CoreManager.default.getLocalDatastore();
  1433. if (localDatastore.isEnabled) {
  1434. _context.next = 3;
  1435. break;
  1436. }
  1437. return _context.abrupt("return", Promise.reject('Parse.enableLocalDatastore() must be called first'));
  1438. case 3:
  1439. objectKey = localDatastore.getKeyForObject(this);
  1440. _context.next = 6;
  1441. return localDatastore.fromPinWithName(objectKey);
  1442. case 6:
  1443. pin = _context.sent;
  1444. return _context.abrupt("return", pin.length > 0);
  1445. case 8:
  1446. case "end":
  1447. return _context.stop();
  1448. }
  1449. }
  1450. }, _callee, this);
  1451. }));
  1452. return function () {
  1453. return _isPinned.apply(this, arguments);
  1454. };
  1455. }()
  1456. /**
  1457. * Asynchronously stores the objects and every object they point to in the local datastore, recursively.
  1458. *
  1459. * If those other objects have not been fetched from Parse, they will not be stored.
  1460. * However, if they have changed data, all the changes will be retained.
  1461. *
  1462. * <pre>
  1463. * await object.pinWithName(name);
  1464. * </pre>
  1465. *
  1466. * To retrieve object:
  1467. * <code>query.fromLocalDatastore()</code> or <code>query.fromPinWithName(name)</code>
  1468. *
  1469. * @param {String} name Name of Pin.
  1470. * @return {Promise} A promise that is fulfilled when the pin completes.
  1471. */
  1472. }, {
  1473. key: "pinWithName",
  1474. value: function (name
  1475. /*: string*/
  1476. )
  1477. /*: Promise<void>*/
  1478. {
  1479. return ParseObject.pinAllWithName(name, [this]);
  1480. }
  1481. /**
  1482. * Asynchronously removes the object and every object it points to in the local datastore, recursively.
  1483. *
  1484. * <pre>
  1485. * await object.unPinWithName(name);
  1486. * </pre>
  1487. *
  1488. * @param {String} name Name of Pin.
  1489. * @return {Promise} A promise that is fulfilled when the unPin completes.
  1490. */
  1491. }, {
  1492. key: "unPinWithName",
  1493. value: function (name
  1494. /*: string*/
  1495. )
  1496. /*: Promise<void>*/
  1497. {
  1498. return ParseObject.unPinAllWithName(name, [this]);
  1499. }
  1500. /**
  1501. * Asynchronously loads data from the local datastore into this object.
  1502. *
  1503. * <pre>
  1504. * await object.fetchFromLocalDatastore();
  1505. * </pre>
  1506. *
  1507. * You can create an unfetched pointer with <code>Parse.Object.createWithoutData()</code>
  1508. * and then call <code>fetchFromLocalDatastore()</code> on it.
  1509. *
  1510. * @return {Promise} A promise that is fulfilled when the fetch completes.
  1511. */
  1512. }, {
  1513. key: "fetchFromLocalDatastore",
  1514. value: function () {
  1515. var _fetchFromLocalDatastore = (0, _asyncToGenerator2.default)(
  1516. /*#__PURE__*/
  1517. _regenerator.default.mark(function _callee2() {
  1518. var localDatastore, objectKey, pinned, result;
  1519. return _regenerator.default.wrap(function (_context2) {
  1520. while (1) {
  1521. switch (_context2.prev = _context2.next) {
  1522. case 0:
  1523. localDatastore = _CoreManager.default.getLocalDatastore();
  1524. if (localDatastore.isEnabled) {
  1525. _context2.next = 3;
  1526. break;
  1527. }
  1528. throw new Error('Parse.enableLocalDatastore() must be called first');
  1529. case 3:
  1530. objectKey = localDatastore.getKeyForObject(this);
  1531. _context2.next = 6;
  1532. return localDatastore._serializeObject(objectKey);
  1533. case 6:
  1534. pinned = _context2.sent;
  1535. if (pinned) {
  1536. _context2.next = 9;
  1537. break;
  1538. }
  1539. throw new Error('Cannot fetch an unsaved ParseObject');
  1540. case 9:
  1541. result = ParseObject.fromJSON(pinned);
  1542. this._finishFetch(result.toJSON());
  1543. return _context2.abrupt("return", this);
  1544. case 12:
  1545. case "end":
  1546. return _context2.stop();
  1547. }
  1548. }
  1549. }, _callee2, this);
  1550. }));
  1551. return function () {
  1552. return _fetchFromLocalDatastore.apply(this, arguments);
  1553. };
  1554. }()
  1555. /** Static methods **/
  1556. }, {
  1557. key: "attributes",
  1558. /** Prototype getters / setters **/
  1559. get: function ()
  1560. /*: AttributeMap*/
  1561. {
  1562. var stateController = _CoreManager.default.getObjectStateController();
  1563. return Object.freeze(stateController.estimateAttributes(this._getStateIdentifier()));
  1564. }
  1565. /**
  1566. * The first time this object was saved on the server.
  1567. * @property createdAt
  1568. * @type Date
  1569. */
  1570. }, {
  1571. key: "createdAt",
  1572. get: function ()
  1573. /*: ?Date*/
  1574. {
  1575. return this._getServerData().createdAt;
  1576. }
  1577. /**
  1578. * The last time this object was updated on the server.
  1579. * @property updatedAt
  1580. * @type Date
  1581. */
  1582. }, {
  1583. key: "updatedAt",
  1584. get: function ()
  1585. /*: ?Date*/
  1586. {
  1587. return this._getServerData().updatedAt;
  1588. }
  1589. }], [{
  1590. key: "_clearAllState",
  1591. value: function () {
  1592. var stateController = _CoreManager.default.getObjectStateController();
  1593. stateController.clearAllState();
  1594. }
  1595. /**
  1596. * Fetches the given list of Parse.Object.
  1597. * If any error is encountered, stops and calls the error handler.
  1598. *
  1599. * <pre>
  1600. * Parse.Object.fetchAll([object1, object2, ...])
  1601. * .then((list) => {
  1602. * // All the objects were fetched.
  1603. * }, (error) => {
  1604. * // An error occurred while fetching one of the objects.
  1605. * });
  1606. * </pre>
  1607. *
  1608. * @param {Array} list A list of <code>Parse.Object</code>.
  1609. * @param {Object} options
  1610. * Valid options are:<ul>
  1611. * <li>useMasterKey: In Cloud Code and Node only, causes the Master Key to
  1612. * be used for this request.
  1613. * <li>sessionToken: A valid session token, used for making a request on
  1614. * behalf of a specific user.
  1615. * <li>include: The name(s) of the key(s) to include. Can be a string, an array of strings,
  1616. * or an array of array of strings.
  1617. * </ul>
  1618. * @static
  1619. */
  1620. }, {
  1621. key: "fetchAll",
  1622. value: function (list
  1623. /*: Array<ParseObject>*/
  1624. ) {
  1625. var options
  1626. /*: RequestOptions*/
  1627. = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  1628. var queryOptions = {};
  1629. if (options.hasOwnProperty('useMasterKey')) {
  1630. queryOptions.useMasterKey = options.useMasterKey;
  1631. }
  1632. if (options.hasOwnProperty('sessionToken')) {
  1633. queryOptions.sessionToken = options.sessionToken;
  1634. }
  1635. if (options.hasOwnProperty('include')) {
  1636. queryOptions.include = [];
  1637. if (Array.isArray(options.include)) {
  1638. options.include.forEach(function (key) {
  1639. if (Array.isArray(key)) {
  1640. queryOptions.include = queryOptions.include.concat(key);
  1641. } else {
  1642. queryOptions.include.push(key);
  1643. }
  1644. });
  1645. } else {
  1646. queryOptions.include.push(options.include);
  1647. }
  1648. }
  1649. return _CoreManager.default.getObjectController().fetch(list, true, queryOptions);
  1650. }
  1651. /**
  1652. * Fetches the given list of Parse.Object.
  1653. *
  1654. * Includes nested Parse.Objects for the provided key. You can use dot
  1655. * notation to specify which fields in the included object are also fetched.
  1656. *
  1657. * If any error is encountered, stops and calls the error handler.
  1658. *
  1659. * <pre>
  1660. * Parse.Object.fetchAllWithInclude([object1, object2, ...], [pointer1, pointer2, ...])
  1661. * .then((list) => {
  1662. * // All the objects were fetched.
  1663. * }, (error) => {
  1664. * // An error occurred while fetching one of the objects.
  1665. * });
  1666. * </pre>
  1667. *
  1668. * @param {Array} list A list of <code>Parse.Object</code>.
  1669. * @param {String|Array<string|Array<string>>} keys The name(s) of the key(s) to include.
  1670. * @param {Object} options
  1671. * Valid options are:<ul>
  1672. * <li>useMasterKey: In Cloud Code and Node only, causes the Master Key to
  1673. * be used for this request.
  1674. * <li>sessionToken: A valid session token, used for making a request on
  1675. * behalf of a specific user.
  1676. * </ul>
  1677. * @static
  1678. */
  1679. }, {
  1680. key: "fetchAllWithInclude",
  1681. value: function (list
  1682. /*: Array<ParseObject>*/
  1683. , keys
  1684. /*: String|Array<string|Array<string>>*/
  1685. , options
  1686. /*: RequestOptions*/
  1687. ) {
  1688. options = options || {};
  1689. options.include = keys;
  1690. return ParseObject.fetchAll(list, options);
  1691. }
  1692. /**
  1693. * Fetches the given list of Parse.Object if needed.
  1694. * If any error is encountered, stops and calls the error handler.
  1695. *
  1696. * <pre>
  1697. * Parse.Object.fetchAllIfNeeded([object1, ...])
  1698. * .then((list) => {
  1699. * // Objects were fetched and updated.
  1700. * }, (error) => {
  1701. * // An error occurred while fetching one of the objects.
  1702. * });
  1703. * </pre>
  1704. *
  1705. * @param {Array} list A list of <code>Parse.Object</code>.
  1706. * @param {Object} options
  1707. * @static
  1708. */
  1709. }, {
  1710. key: "fetchAllIfNeeded",
  1711. value: function (list
  1712. /*: Array<ParseObject>*/
  1713. , options) {
  1714. options = options || {};
  1715. var queryOptions = {};
  1716. if (options.hasOwnProperty('useMasterKey')) {
  1717. queryOptions.useMasterKey = options.useMasterKey;
  1718. }
  1719. if (options.hasOwnProperty('sessionToken')) {
  1720. queryOptions.sessionToken = options.sessionToken;
  1721. }
  1722. return _CoreManager.default.getObjectController().fetch(list, false, queryOptions);
  1723. }
  1724. /**
  1725. * Destroy the given list of models on the server if it was already persisted.
  1726. *
  1727. * <p>Unlike saveAll, if an error occurs while deleting an individual model,
  1728. * this method will continue trying to delete the rest of the models if
  1729. * possible, except in the case of a fatal error like a connection error.
  1730. *
  1731. * <p>In particular, the Parse.Error object returned in the case of error may
  1732. * be one of two types:
  1733. *
  1734. * <ul>
  1735. * <li>A Parse.Error.AGGREGATE_ERROR. This object's "errors" property is an
  1736. * array of other Parse.Error objects. Each error object in this array
  1737. * has an "object" property that references the object that could not be
  1738. * deleted (for instance, because that object could not be found).</li>
  1739. * <li>A non-aggregate Parse.Error. This indicates a serious error that
  1740. * caused the delete operation to be aborted partway through (for
  1741. * instance, a connection failure in the middle of the delete).</li>
  1742. * </ul>
  1743. *
  1744. * <pre>
  1745. * Parse.Object.destroyAll([object1, object2, ...])
  1746. * .then((list) => {
  1747. * // All the objects were deleted.
  1748. * }, (error) => {
  1749. * // An error occurred while deleting one or more of the objects.
  1750. * // If this is an aggregate error, then we can inspect each error
  1751. * // object individually to determine the reason why a particular
  1752. * // object was not deleted.
  1753. * if (error.code === Parse.Error.AGGREGATE_ERROR) {
  1754. * for (var i = 0; i < error.errors.length; i++) {
  1755. * console.log("Couldn't delete " + error.errors[i].object.id +
  1756. * "due to " + error.errors[i].message);
  1757. * }
  1758. * } else {
  1759. * console.log("Delete aborted because of " + error.message);
  1760. * }
  1761. * });
  1762. * </pre>
  1763. *
  1764. * @param {Array} list A list of <code>Parse.Object</code>.
  1765. * @param {Object} options
  1766. * @static
  1767. * Valid options are:<ul>
  1768. * <li>useMasterKey: In Cloud Code and Node only, causes the Master Key to
  1769. * be used for this request.
  1770. * <li>sessionToken: A valid session token, used for making a request on
  1771. * behalf of a specific user.
  1772. * <li>batchSize: Number of objects to process per request
  1773. * </ul>
  1774. * @return {Promise} A promise that is fulfilled when the destroyAll
  1775. * completes.
  1776. */
  1777. }, {
  1778. key: "destroyAll",
  1779. value: function (list
  1780. /*: Array<ParseObject>*/
  1781. ) {
  1782. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  1783. var destroyOptions = {};
  1784. if (options.hasOwnProperty('useMasterKey')) {
  1785. destroyOptions.useMasterKey = options.useMasterKey;
  1786. }
  1787. if (options.hasOwnProperty('sessionToken')) {
  1788. destroyOptions.sessionToken = options.sessionToken;
  1789. }
  1790. if (options.hasOwnProperty('batchSize') && typeof options.batchSize === 'number') {
  1791. destroyOptions.batchSize = options.batchSize;
  1792. }
  1793. return _CoreManager.default.getObjectController().destroy(list, destroyOptions);
  1794. }
  1795. /**
  1796. * Saves the given list of Parse.Object.
  1797. * If any error is encountered, stops and calls the error handler.
  1798. *
  1799. * <pre>
  1800. * Parse.Object.saveAll([object1, object2, ...])
  1801. * .then((list) => {
  1802. * // All the objects were saved.
  1803. * }, (error) => {
  1804. * // An error occurred while saving one of the objects.
  1805. * });
  1806. * </pre>
  1807. *
  1808. * @param {Array} list A list of <code>Parse.Object</code>.
  1809. * @param {Object} options
  1810. * @static
  1811. * Valid options are:<ul>
  1812. * <li>useMasterKey: In Cloud Code and Node only, causes the Master Key to
  1813. * be used for this request.
  1814. * <li>sessionToken: A valid session token, used for making a request on
  1815. * behalf of a specific user.
  1816. * <li>batchSize: Number of objects to process per request
  1817. * </ul>
  1818. */
  1819. }, {
  1820. key: "saveAll",
  1821. value: function (list
  1822. /*: Array<ParseObject>*/
  1823. ) {
  1824. var options
  1825. /*: RequestOptions*/
  1826. = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  1827. var saveOptions = {};
  1828. if (options.hasOwnProperty('useMasterKey')) {
  1829. saveOptions.useMasterKey = options.useMasterKey;
  1830. }
  1831. if (options.hasOwnProperty('sessionToken')) {
  1832. saveOptions.sessionToken = options.sessionToken;
  1833. }
  1834. if (options.hasOwnProperty('batchSize') && typeof options.batchSize === 'number') {
  1835. saveOptions.batchSize = options.batchSize;
  1836. }
  1837. return _CoreManager.default.getObjectController().save(list, saveOptions);
  1838. }
  1839. /**
  1840. * Creates a reference to a subclass of Parse.Object with the given id. This
  1841. * does not exist on Parse.Object, only on subclasses.
  1842. *
  1843. * <p>A shortcut for: <pre>
  1844. * var Foo = Parse.Object.extend("Foo");
  1845. * var pointerToFoo = new Foo();
  1846. * pointerToFoo.id = "myObjectId";
  1847. * </pre>
  1848. *
  1849. * @param {String} id The ID of the object to create a reference to.
  1850. * @static
  1851. * @return {Parse.Object} A Parse.Object reference.
  1852. */
  1853. }, {
  1854. key: "createWithoutData",
  1855. value: function (id
  1856. /*: string*/
  1857. ) {
  1858. var obj = new this();
  1859. obj.id = id;
  1860. return obj;
  1861. }
  1862. /**
  1863. * Creates a new instance of a Parse Object from a JSON representation.
  1864. * @param {Object} json The JSON map of the Object's data
  1865. * @param {boolean} override In single instance mode, all old server data
  1866. * is overwritten if this is set to true
  1867. * @static
  1868. * @return {Parse.Object} A Parse.Object reference
  1869. */
  1870. }, {
  1871. key: "fromJSON",
  1872. value: function (json
  1873. /*: any*/
  1874. , override
  1875. /*:: ?: boolean*/
  1876. ) {
  1877. if (!json.className) {
  1878. throw new Error('Cannot create an object without a className');
  1879. }
  1880. var constructor = classMap[json.className];
  1881. var o = constructor ? new constructor() : new ParseObject(json.className);
  1882. var otherAttributes = {};
  1883. for (var _attr12 in json) {
  1884. if (_attr12 !== 'className' && _attr12 !== '__type') {
  1885. otherAttributes[_attr12] = json[_attr12];
  1886. }
  1887. }
  1888. if (override) {
  1889. // id needs to be set before clearServerData can work
  1890. if (otherAttributes.objectId) {
  1891. o.id = otherAttributes.objectId;
  1892. }
  1893. var preserved = null;
  1894. if (typeof o._preserveFieldsOnFetch === 'function') {
  1895. preserved = o._preserveFieldsOnFetch();
  1896. }
  1897. o._clearServerData();
  1898. if (preserved) {
  1899. o._finishFetch(preserved);
  1900. }
  1901. }
  1902. o._finishFetch(otherAttributes);
  1903. if (json.objectId) {
  1904. o._setExisted(true);
  1905. }
  1906. return o;
  1907. }
  1908. /**
  1909. * Registers a subclass of Parse.Object with a specific class name.
  1910. * When objects of that class are retrieved from a query, they will be
  1911. * instantiated with this subclass.
  1912. * This is only necessary when using ES6 subclassing.
  1913. * @param {String} className The class name of the subclass
  1914. * @param {Class} constructor The subclass
  1915. */
  1916. }, {
  1917. key: "registerSubclass",
  1918. value: function (className
  1919. /*: string*/
  1920. , constructor
  1921. /*: any*/
  1922. ) {
  1923. if (typeof className !== 'string') {
  1924. throw new TypeError('The first argument must be a valid class name.');
  1925. }
  1926. if (typeof constructor === 'undefined') {
  1927. throw new TypeError('You must supply a subclass constructor.');
  1928. }
  1929. if (typeof constructor !== 'function') {
  1930. throw new TypeError('You must register the subclass constructor. ' + 'Did you attempt to register an instance of the subclass?');
  1931. }
  1932. classMap[className] = constructor;
  1933. if (!constructor.className) {
  1934. constructor.className = className;
  1935. }
  1936. }
  1937. /**
  1938. * Creates a new subclass of Parse.Object for the given Parse class name.
  1939. *
  1940. * <p>Every extension of a Parse class will inherit from the most recent
  1941. * previous extension of that class. When a Parse.Object is automatically
  1942. * created by parsing JSON, it will use the most recent extension of that
  1943. * class.</p>
  1944. *
  1945. * <p>You should call either:<pre>
  1946. * var MyClass = Parse.Object.extend("MyClass", {
  1947. * <i>Instance methods</i>,
  1948. * initialize: function(attrs, options) {
  1949. * this.someInstanceProperty = [],
  1950. * <i>Other instance properties</i>
  1951. * }
  1952. * }, {
  1953. * <i>Class properties</i>
  1954. * });</pre>
  1955. * or, for Backbone compatibility:<pre>
  1956. * var MyClass = Parse.Object.extend({
  1957. * className: "MyClass",
  1958. * <i>Instance methods</i>,
  1959. * initialize: function(attrs, options) {
  1960. * this.someInstanceProperty = [],
  1961. * <i>Other instance properties</i>
  1962. * }
  1963. * }, {
  1964. * <i>Class properties</i>
  1965. * });</pre></p>
  1966. *
  1967. * @param {String} className The name of the Parse class backing this model.
  1968. * @param {Object} protoProps Instance properties to add to instances of the
  1969. * class returned from this method.
  1970. * @param {Object} classProps Class properties to add the class returned from
  1971. * this method.
  1972. * @return {Class} A new subclass of Parse.Object.
  1973. */
  1974. }, {
  1975. key: "extend",
  1976. value: function (className
  1977. /*: any*/
  1978. , protoProps
  1979. /*: any*/
  1980. , classProps
  1981. /*: any*/
  1982. ) {
  1983. if (typeof className !== 'string') {
  1984. if (className && typeof className.className === 'string') {
  1985. return ParseObject.extend(className.className, className, protoProps);
  1986. } else {
  1987. throw new Error('Parse.Object.extend\'s first argument should be the className.');
  1988. }
  1989. }
  1990. var adjustedClassName = className;
  1991. if (adjustedClassName === 'User' && _CoreManager.default.get('PERFORM_USER_REWRITE')) {
  1992. adjustedClassName = '_User';
  1993. }
  1994. var parentProto = ParseObject.prototype;
  1995. if (this.hasOwnProperty('__super__') && this.__super__) {
  1996. parentProto = this.prototype;
  1997. } else if (classMap[adjustedClassName]) {
  1998. parentProto = classMap[adjustedClassName].prototype;
  1999. }
  2000. var ParseObjectSubclass = function (attributes, options) {
  2001. this.className = adjustedClassName;
  2002. this._objCount = objectCount++; // Enable legacy initializers
  2003. if (typeof this.initialize === 'function') {
  2004. this.initialize.apply(this, arguments);
  2005. }
  2006. if (attributes && (0, _typeof2.default)(attributes) === 'object') {
  2007. if (!this.set(attributes || {}, options)) {
  2008. throw new Error('Can\'t create an invalid Parse Object');
  2009. }
  2010. }
  2011. };
  2012. ParseObjectSubclass.className = adjustedClassName;
  2013. ParseObjectSubclass.__super__ = parentProto;
  2014. ParseObjectSubclass.prototype = Object.create(parentProto, {
  2015. constructor: {
  2016. value: ParseObjectSubclass,
  2017. enumerable: false,
  2018. writable: true,
  2019. configurable: true
  2020. }
  2021. });
  2022. if (protoProps) {
  2023. for (var prop in protoProps) {
  2024. if (prop !== 'className') {
  2025. Object.defineProperty(ParseObjectSubclass.prototype, prop, {
  2026. value: protoProps[prop],
  2027. enumerable: false,
  2028. writable: true,
  2029. configurable: true
  2030. });
  2031. }
  2032. }
  2033. }
  2034. if (classProps) {
  2035. for (var _prop in classProps) {
  2036. if (_prop !== 'className') {
  2037. Object.defineProperty(ParseObjectSubclass, _prop, {
  2038. value: classProps[_prop],
  2039. enumerable: false,
  2040. writable: true,
  2041. configurable: true
  2042. });
  2043. }
  2044. }
  2045. }
  2046. ParseObjectSubclass.extend = function (name, protoProps, classProps) {
  2047. if (typeof name === 'string') {
  2048. return ParseObject.extend.call(ParseObjectSubclass, name, protoProps, classProps);
  2049. }
  2050. return ParseObject.extend.call(ParseObjectSubclass, adjustedClassName, name, protoProps);
  2051. };
  2052. ParseObjectSubclass.createWithoutData = ParseObject.createWithoutData;
  2053. classMap[adjustedClassName] = ParseObjectSubclass;
  2054. return ParseObjectSubclass;
  2055. }
  2056. /**
  2057. * Enable single instance objects, where any local objects with the same Id
  2058. * share the same attributes, and stay synchronized with each other.
  2059. * This is disabled by default in server environments, since it can lead to
  2060. * security issues.
  2061. * @static
  2062. */
  2063. }, {
  2064. key: "enableSingleInstance",
  2065. value: function () {
  2066. singleInstance = true;
  2067. _CoreManager.default.setObjectStateController(SingleInstanceStateController);
  2068. }
  2069. /**
  2070. * Disable single instance objects, where any local objects with the same Id
  2071. * share the same attributes, and stay synchronized with each other.
  2072. * When disabled, you can have two instances of the same object in memory
  2073. * without them sharing attributes.
  2074. * @static
  2075. */
  2076. }, {
  2077. key: "disableSingleInstance",
  2078. value: function () {
  2079. singleInstance = false;
  2080. _CoreManager.default.setObjectStateController(UniqueInstanceStateController);
  2081. }
  2082. /**
  2083. * Asynchronously stores the objects and every object they point to in the local datastore,
  2084. * recursively, using a default pin name: _default.
  2085. *
  2086. * If those other objects have not been fetched from Parse, they will not be stored.
  2087. * However, if they have changed data, all the changes will be retained.
  2088. *
  2089. * <pre>
  2090. * await Parse.Object.pinAll([...]);
  2091. * </pre>
  2092. *
  2093. * To retrieve object:
  2094. * <code>query.fromLocalDatastore()</code> or <code>query.fromPin()</code>
  2095. *
  2096. * @param {Array} objects A list of <code>Parse.Object</code>.
  2097. * @return {Promise} A promise that is fulfilled when the pin completes.
  2098. * @static
  2099. */
  2100. }, {
  2101. key: "pinAll",
  2102. value: function (objects
  2103. /*: Array<ParseObject>*/
  2104. )
  2105. /*: Promise<void>*/
  2106. {
  2107. var localDatastore = _CoreManager.default.getLocalDatastore();
  2108. if (!localDatastore.isEnabled) {
  2109. return Promise.reject('Parse.enableLocalDatastore() must be called first');
  2110. }
  2111. return ParseObject.pinAllWithName(_LocalDatastoreUtils.DEFAULT_PIN, objects);
  2112. }
  2113. /**
  2114. * Asynchronously stores the objects and every object they point to in the local datastore, recursively.
  2115. *
  2116. * If those other objects have not been fetched from Parse, they will not be stored.
  2117. * However, if they have changed data, all the changes will be retained.
  2118. *
  2119. * <pre>
  2120. * await Parse.Object.pinAllWithName(name, [obj1, obj2, ...]);
  2121. * </pre>
  2122. *
  2123. * To retrieve object:
  2124. * <code>query.fromLocalDatastore()</code> or <code>query.fromPinWithName(name)</code>
  2125. *
  2126. * @param {String} name Name of Pin.
  2127. * @param {Array} objects A list of <code>Parse.Object</code>.
  2128. * @return {Promise} A promise that is fulfilled when the pin completes.
  2129. * @static
  2130. */
  2131. }, {
  2132. key: "pinAllWithName",
  2133. value: function (name
  2134. /*: string*/
  2135. , objects
  2136. /*: Array<ParseObject>*/
  2137. )
  2138. /*: Promise<void>*/
  2139. {
  2140. var localDatastore = _CoreManager.default.getLocalDatastore();
  2141. if (!localDatastore.isEnabled) {
  2142. return Promise.reject('Parse.enableLocalDatastore() must be called first');
  2143. }
  2144. return localDatastore._handlePinAllWithName(name, objects);
  2145. }
  2146. /**
  2147. * Asynchronously removes the objects and every object they point to in the local datastore,
  2148. * recursively, using a default pin name: _default.
  2149. *
  2150. * <pre>
  2151. * await Parse.Object.unPinAll([...]);
  2152. * </pre>
  2153. *
  2154. * @param {Array} objects A list of <code>Parse.Object</code>.
  2155. * @return {Promise} A promise that is fulfilled when the unPin completes.
  2156. * @static
  2157. */
  2158. }, {
  2159. key: "unPinAll",
  2160. value: function (objects
  2161. /*: Array<ParseObject>*/
  2162. )
  2163. /*: Promise<void>*/
  2164. {
  2165. var localDatastore = _CoreManager.default.getLocalDatastore();
  2166. if (!localDatastore.isEnabled) {
  2167. return Promise.reject('Parse.enableLocalDatastore() must be called first');
  2168. }
  2169. return ParseObject.unPinAllWithName(_LocalDatastoreUtils.DEFAULT_PIN, objects);
  2170. }
  2171. /**
  2172. * Asynchronously removes the objects and every object they point to in the local datastore, recursively.
  2173. *
  2174. * <pre>
  2175. * await Parse.Object.unPinAllWithName(name, [obj1, obj2, ...]);
  2176. * </pre>
  2177. *
  2178. * @param {String} name Name of Pin.
  2179. * @param {Array} objects A list of <code>Parse.Object</code>.
  2180. * @return {Promise} A promise that is fulfilled when the unPin completes.
  2181. * @static
  2182. */
  2183. }, {
  2184. key: "unPinAllWithName",
  2185. value: function (name
  2186. /*: string*/
  2187. , objects
  2188. /*: Array<ParseObject>*/
  2189. )
  2190. /*: Promise<void>*/
  2191. {
  2192. var localDatastore = _CoreManager.default.getLocalDatastore();
  2193. if (!localDatastore.isEnabled) {
  2194. return Promise.reject('Parse.enableLocalDatastore() must be called first');
  2195. }
  2196. return localDatastore._handleUnPinAllWithName(name, objects);
  2197. }
  2198. /**
  2199. * Asynchronously removes all objects in the local datastore using a default pin name: _default.
  2200. *
  2201. * <pre>
  2202. * await Parse.Object.unPinAllObjects();
  2203. * </pre>
  2204. *
  2205. * @return {Promise} A promise that is fulfilled when the unPin completes.
  2206. * @static
  2207. */
  2208. }, {
  2209. key: "unPinAllObjects",
  2210. value: function ()
  2211. /*: Promise<void>*/
  2212. {
  2213. var localDatastore = _CoreManager.default.getLocalDatastore();
  2214. if (!localDatastore.isEnabled) {
  2215. return Promise.reject('Parse.enableLocalDatastore() must be called first');
  2216. }
  2217. return localDatastore.unPinWithName(_LocalDatastoreUtils.DEFAULT_PIN);
  2218. }
  2219. /**
  2220. * Asynchronously removes all objects with the specified pin name.
  2221. * Deletes the pin name also.
  2222. *
  2223. * <pre>
  2224. * await Parse.Object.unPinAllObjectsWithName(name);
  2225. * </pre>
  2226. *
  2227. * @param {String} name Name of Pin.
  2228. * @return {Promise} A promise that is fulfilled when the unPin completes.
  2229. * @static
  2230. */
  2231. }, {
  2232. key: "unPinAllObjectsWithName",
  2233. value: function (name
  2234. /*: string*/
  2235. )
  2236. /*: Promise<void>*/
  2237. {
  2238. var localDatastore = _CoreManager.default.getLocalDatastore();
  2239. if (!localDatastore.isEnabled) {
  2240. return Promise.reject('Parse.enableLocalDatastore() must be called first');
  2241. }
  2242. return localDatastore.unPinWithName(_LocalDatastoreUtils.PIN_PREFIX + name);
  2243. }
  2244. }]);
  2245. return ParseObject;
  2246. }();
  2247. var DefaultController = {
  2248. fetch: function (target
  2249. /*: ParseObject | Array<ParseObject>*/
  2250. , forceFetch
  2251. /*: boolean*/
  2252. , options
  2253. /*: RequestOptions*/
  2254. )
  2255. /*: Promise<Array<void> | ParseObject>*/
  2256. {
  2257. var localDatastore = _CoreManager.default.getLocalDatastore();
  2258. if (Array.isArray(target)) {
  2259. if (target.length < 1) {
  2260. return Promise.resolve([]);
  2261. }
  2262. var objs = [];
  2263. var ids = [];
  2264. var className = null;
  2265. var results = [];
  2266. var error = null;
  2267. target.forEach(function (el) {
  2268. if (error) {
  2269. return;
  2270. }
  2271. if (!className) {
  2272. className = el.className;
  2273. }
  2274. if (className !== el.className) {
  2275. error = new _ParseError.default(_ParseError.default.INVALID_CLASS_NAME, 'All objects should be of the same class');
  2276. }
  2277. if (!el.id) {
  2278. error = new _ParseError.default(_ParseError.default.MISSING_OBJECT_ID, 'All objects must have an ID');
  2279. }
  2280. if (forceFetch || !el.isDataAvailable()) {
  2281. ids.push(el.id);
  2282. objs.push(el);
  2283. }
  2284. results.push(el);
  2285. });
  2286. if (error) {
  2287. return Promise.reject(error);
  2288. }
  2289. var query = new _ParseQuery.default(className);
  2290. query.containedIn('objectId', ids);
  2291. if (options && options.include) {
  2292. query.include(options.include);
  2293. }
  2294. query._limit = ids.length;
  2295. return query.find(options).then(
  2296. /*#__PURE__*/
  2297. function () {
  2298. var _ref = (0, _asyncToGenerator2.default)(
  2299. /*#__PURE__*/
  2300. _regenerator.default.mark(function _callee3(objects) {
  2301. var idMap, i, obj, _i2, _obj, id, _i3, _results, object;
  2302. return _regenerator.default.wrap(function (_context3) {
  2303. while (1) {
  2304. switch (_context3.prev = _context3.next) {
  2305. case 0:
  2306. idMap = {};
  2307. objects.forEach(function (o) {
  2308. idMap[o.id] = o;
  2309. });
  2310. i = 0;
  2311. case 3:
  2312. if (!(i < objs.length)) {
  2313. _context3.next = 11;
  2314. break;
  2315. }
  2316. obj = objs[i];
  2317. if (!(!obj || !obj.id || !idMap[obj.id])) {
  2318. _context3.next = 8;
  2319. break;
  2320. }
  2321. if (!forceFetch) {
  2322. _context3.next = 8;
  2323. break;
  2324. }
  2325. return _context3.abrupt("return", Promise.reject(new _ParseError.default(_ParseError.default.OBJECT_NOT_FOUND, 'All objects must exist on the server.')));
  2326. case 8:
  2327. i++;
  2328. _context3.next = 3;
  2329. break;
  2330. case 11:
  2331. if (!singleInstance) {
  2332. // If single instance objects are disabled, we need to replace the
  2333. for (_i2 = 0; _i2 < results.length; _i2++) {
  2334. _obj = results[_i2];
  2335. if (_obj && _obj.id && idMap[_obj.id]) {
  2336. id = _obj.id;
  2337. _obj._finishFetch(idMap[id].toJSON());
  2338. results[_i2] = idMap[id];
  2339. }
  2340. }
  2341. }
  2342. _i3 = 0, _results = results;
  2343. case 13:
  2344. if (!(_i3 < _results.length)) {
  2345. _context3.next = 20;
  2346. break;
  2347. }
  2348. object = _results[_i3];
  2349. _context3.next = 17;
  2350. return localDatastore._updateObjectIfPinned(object);
  2351. case 17:
  2352. _i3++;
  2353. _context3.next = 13;
  2354. break;
  2355. case 20:
  2356. return _context3.abrupt("return", Promise.resolve(results));
  2357. case 21:
  2358. case "end":
  2359. return _context3.stop();
  2360. }
  2361. }
  2362. }, _callee3);
  2363. }));
  2364. return function () {
  2365. return _ref.apply(this, arguments);
  2366. };
  2367. }());
  2368. } else {
  2369. var RESTController = _CoreManager.default.getRESTController();
  2370. var params = {};
  2371. if (options && options.include) {
  2372. params.include = options.include.join();
  2373. }
  2374. return RESTController.request('GET', 'classes/' + target.className + '/' + target._getId(), params, options).then(
  2375. /*#__PURE__*/
  2376. function () {
  2377. var _ref2 = (0, _asyncToGenerator2.default)(
  2378. /*#__PURE__*/
  2379. _regenerator.default.mark(function _callee4(response) {
  2380. return _regenerator.default.wrap(function (_context4) {
  2381. while (1) {
  2382. switch (_context4.prev = _context4.next) {
  2383. case 0:
  2384. if (target instanceof ParseObject) {
  2385. target._clearPendingOps();
  2386. target._clearServerData();
  2387. target._finishFetch(response);
  2388. }
  2389. _context4.next = 3;
  2390. return localDatastore._updateObjectIfPinned(target);
  2391. case 3:
  2392. return _context4.abrupt("return", target);
  2393. case 4:
  2394. case "end":
  2395. return _context4.stop();
  2396. }
  2397. }
  2398. }, _callee4);
  2399. }));
  2400. return function () {
  2401. return _ref2.apply(this, arguments);
  2402. };
  2403. }());
  2404. }
  2405. },
  2406. destroy: function () {
  2407. var _destroy = (0, _asyncToGenerator2.default)(
  2408. /*#__PURE__*/
  2409. _regenerator.default.mark(function _callee7(target
  2410. /*: ParseObject | Array<ParseObject>*/
  2411. , options
  2412. /*: RequestOptions*/
  2413. ) {
  2414. var batchSize, localDatastore, RESTController, batches, deleteCompleted, errors;
  2415. return _regenerator.default.wrap(function (_context7) {
  2416. while (1) {
  2417. switch (_context7.prev = _context7.next) {
  2418. case 0:
  2419. batchSize = options && options.batchSize ? options.batchSize : DEFAULT_BATCH_SIZE;
  2420. localDatastore = _CoreManager.default.getLocalDatastore();
  2421. RESTController = _CoreManager.default.getRESTController();
  2422. if (!Array.isArray(target)) {
  2423. _context7.next = 15;
  2424. break;
  2425. }
  2426. if (!(target.length < 1)) {
  2427. _context7.next = 6;
  2428. break;
  2429. }
  2430. return _context7.abrupt("return", Promise.resolve([]));
  2431. case 6:
  2432. batches = [[]];
  2433. target.forEach(function (obj) {
  2434. if (!obj.id) {
  2435. return;
  2436. }
  2437. batches[batches.length - 1].push(obj);
  2438. if (batches[batches.length - 1].length >= batchSize) {
  2439. batches.push([]);
  2440. }
  2441. });
  2442. if (batches[batches.length - 1].length === 0) {
  2443. // If the last batch is empty, remove it
  2444. batches.pop();
  2445. }
  2446. deleteCompleted = Promise.resolve();
  2447. errors = [];
  2448. batches.forEach(function (batch) {
  2449. deleteCompleted = deleteCompleted.then(function () {
  2450. return RESTController.request('POST', 'batch', {
  2451. requests: batch.map(function (obj) {
  2452. return {
  2453. method: 'DELETE',
  2454. path: getServerUrlPath() + 'classes/' + obj.className + '/' + obj._getId(),
  2455. body: {}
  2456. };
  2457. })
  2458. }, options).then(function (results) {
  2459. for (var i = 0; i < results.length; i++) {
  2460. if (results[i] && results[i].hasOwnProperty('error')) {
  2461. var err = new _ParseError.default(results[i].error.code, results[i].error.error);
  2462. err.object = batch[i];
  2463. errors.push(err);
  2464. }
  2465. }
  2466. });
  2467. });
  2468. });
  2469. return _context7.abrupt("return", deleteCompleted.then(
  2470. /*#__PURE__*/
  2471. (0, _asyncToGenerator2.default)(
  2472. /*#__PURE__*/
  2473. _regenerator.default.mark(function _callee5() {
  2474. var aggregate, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, object;
  2475. return _regenerator.default.wrap(function (_context5) {
  2476. while (1) {
  2477. switch (_context5.prev = _context5.next) {
  2478. case 0:
  2479. if (!errors.length) {
  2480. _context5.next = 4;
  2481. break;
  2482. }
  2483. aggregate = new _ParseError.default(_ParseError.default.AGGREGATE_ERROR);
  2484. aggregate.errors = errors;
  2485. return _context5.abrupt("return", Promise.reject(aggregate));
  2486. case 4:
  2487. _iteratorNormalCompletion = true;
  2488. _didIteratorError = false;
  2489. _iteratorError = undefined;
  2490. _context5.prev = 7;
  2491. _iterator = target[Symbol.iterator]();
  2492. case 9:
  2493. if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
  2494. _context5.next = 16;
  2495. break;
  2496. }
  2497. object = _step.value;
  2498. _context5.next = 13;
  2499. return localDatastore._destroyObjectIfPinned(object);
  2500. case 13:
  2501. _iteratorNormalCompletion = true;
  2502. _context5.next = 9;
  2503. break;
  2504. case 16:
  2505. _context5.next = 22;
  2506. break;
  2507. case 18:
  2508. _context5.prev = 18;
  2509. _context5.t0 = _context5["catch"](7);
  2510. _didIteratorError = true;
  2511. _iteratorError = _context5.t0;
  2512. case 22:
  2513. _context5.prev = 22;
  2514. _context5.prev = 23;
  2515. if (!_iteratorNormalCompletion && _iterator.return != null) {
  2516. _iterator.return();
  2517. }
  2518. case 25:
  2519. _context5.prev = 25;
  2520. if (!_didIteratorError) {
  2521. _context5.next = 28;
  2522. break;
  2523. }
  2524. throw _iteratorError;
  2525. case 28:
  2526. return _context5.finish(25);
  2527. case 29:
  2528. return _context5.finish(22);
  2529. case 30:
  2530. return _context5.abrupt("return", Promise.resolve(target));
  2531. case 31:
  2532. case "end":
  2533. return _context5.stop();
  2534. }
  2535. }
  2536. }, _callee5, null, [[7, 18, 22, 30], [23,, 25, 29]]);
  2537. }))));
  2538. case 15:
  2539. if (!(target instanceof ParseObject)) {
  2540. _context7.next = 17;
  2541. break;
  2542. }
  2543. return _context7.abrupt("return", RESTController.request('DELETE', 'classes/' + target.className + '/' + target._getId(), {}, options).then(
  2544. /*#__PURE__*/
  2545. (0, _asyncToGenerator2.default)(
  2546. /*#__PURE__*/
  2547. _regenerator.default.mark(function _callee6() {
  2548. return _regenerator.default.wrap(function (_context6) {
  2549. while (1) {
  2550. switch (_context6.prev = _context6.next) {
  2551. case 0:
  2552. _context6.next = 2;
  2553. return localDatastore._destroyObjectIfPinned(target);
  2554. case 2:
  2555. return _context6.abrupt("return", Promise.resolve(target));
  2556. case 3:
  2557. case "end":
  2558. return _context6.stop();
  2559. }
  2560. }
  2561. }, _callee6);
  2562. }))));
  2563. case 17:
  2564. _context7.next = 19;
  2565. return localDatastore._destroyObjectIfPinned(target);
  2566. case 19:
  2567. return _context7.abrupt("return", Promise.resolve(target));
  2568. case 20:
  2569. case "end":
  2570. return _context7.stop();
  2571. }
  2572. }
  2573. }, _callee7);
  2574. }));
  2575. return function () {
  2576. return _destroy.apply(this, arguments);
  2577. };
  2578. }(),
  2579. save: function (target
  2580. /*: ParseObject | Array<ParseObject | ParseFile>*/
  2581. , options
  2582. /*: RequestOptions*/
  2583. ) {
  2584. var batchSize = options && options.batchSize ? options.batchSize : DEFAULT_BATCH_SIZE;
  2585. var localDatastore = _CoreManager.default.getLocalDatastore();
  2586. var mapIdForPin = {};
  2587. var RESTController = _CoreManager.default.getRESTController();
  2588. var stateController = _CoreManager.default.getObjectStateController();
  2589. options = options || {};
  2590. options.returnStatus = options.returnStatus || true;
  2591. if (Array.isArray(target)) {
  2592. if (target.length < 1) {
  2593. return Promise.resolve([]);
  2594. }
  2595. var unsaved = target.concat();
  2596. for (var i = 0; i < target.length; i++) {
  2597. if (target[i] instanceof ParseObject) {
  2598. unsaved = unsaved.concat((0, _unsavedChildren.default)(target[i], true));
  2599. }
  2600. }
  2601. unsaved = (0, _unique.default)(unsaved);
  2602. var filesSaved = Promise.resolve();
  2603. var pending
  2604. /*: Array<ParseObject>*/
  2605. = [];
  2606. unsaved.forEach(function (el) {
  2607. if (el instanceof _ParseFile.default) {
  2608. filesSaved = filesSaved.then(function () {
  2609. return el.save();
  2610. });
  2611. } else if (el instanceof ParseObject) {
  2612. pending.push(el);
  2613. }
  2614. });
  2615. return filesSaved.then(function () {
  2616. var objectError = null;
  2617. return (0, _promiseUtils.continueWhile)(function () {
  2618. return pending.length > 0;
  2619. }, function () {
  2620. var batch = [];
  2621. var nextPending = [];
  2622. pending.forEach(function (el) {
  2623. if (batch.length < batchSize && (0, _canBeSerialized.default)(el)) {
  2624. batch.push(el);
  2625. } else {
  2626. nextPending.push(el);
  2627. }
  2628. });
  2629. pending = nextPending;
  2630. if (batch.length < 1) {
  2631. return Promise.reject(new _ParseError.default(_ParseError.default.OTHER_CAUSE, 'Tried to save a batch with a cycle.'));
  2632. } // Queue up tasks for each object in the batch.
  2633. // When every task is ready, the API request will execute
  2634. var res, rej;
  2635. var batchReturned = new Promise(function (resolve, reject) {
  2636. res = resolve;
  2637. rej = reject;
  2638. });
  2639. batchReturned.resolve = res;
  2640. batchReturned.reject = rej;
  2641. var batchReady = [];
  2642. var batchTasks = [];
  2643. batch.forEach(function (obj, index) {
  2644. var res, rej;
  2645. var ready = new Promise(function (resolve, reject) {
  2646. res = resolve;
  2647. rej = reject;
  2648. });
  2649. ready.resolve = res;
  2650. ready.reject = rej;
  2651. batchReady.push(ready);
  2652. stateController.pushPendingState(obj._getStateIdentifier());
  2653. batchTasks.push(stateController.enqueueTask(obj._getStateIdentifier(), function () {
  2654. ready.resolve();
  2655. return batchReturned.then(function (responses) {
  2656. if (responses[index].hasOwnProperty('success')) {
  2657. var objectId = responses[index].success.objectId;
  2658. var status = responses[index]._status;
  2659. delete responses[index]._status;
  2660. mapIdForPin[objectId] = obj._localId;
  2661. obj._handleSaveResponse(responses[index].success, status);
  2662. } else {
  2663. if (!objectError && responses[index].hasOwnProperty('error')) {
  2664. var serverError = responses[index].error;
  2665. objectError = new _ParseError.default(serverError.code, serverError.error); // Cancel the rest of the save
  2666. pending = [];
  2667. }
  2668. obj._handleSaveError();
  2669. }
  2670. });
  2671. }));
  2672. });
  2673. (0, _promiseUtils.when)(batchReady).then(function () {
  2674. // Kick off the batch request
  2675. return RESTController.request('POST', 'batch', {
  2676. requests: batch.map(function (obj) {
  2677. var params = obj._getSaveParams();
  2678. params.path = getServerUrlPath() + params.path;
  2679. return params;
  2680. })
  2681. }, options);
  2682. }).then(batchReturned.resolve, function (error) {
  2683. batchReturned.reject(new _ParseError.default(_ParseError.default.INCORRECT_TYPE, error.message));
  2684. });
  2685. return (0, _promiseUtils.when)(batchTasks);
  2686. }).then(
  2687. /*#__PURE__*/
  2688. (0, _asyncToGenerator2.default)(
  2689. /*#__PURE__*/
  2690. _regenerator.default.mark(function _callee8() {
  2691. var _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, object;
  2692. return _regenerator.default.wrap(function (_context8) {
  2693. while (1) {
  2694. switch (_context8.prev = _context8.next) {
  2695. case 0:
  2696. if (!objectError) {
  2697. _context8.next = 2;
  2698. break;
  2699. }
  2700. return _context8.abrupt("return", Promise.reject(objectError));
  2701. case 2:
  2702. _iteratorNormalCompletion2 = true;
  2703. _didIteratorError2 = false;
  2704. _iteratorError2 = undefined;
  2705. _context8.prev = 5;
  2706. _iterator2 = target[Symbol.iterator]();
  2707. case 7:
  2708. if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) {
  2709. _context8.next = 16;
  2710. break;
  2711. }
  2712. object = _step2.value;
  2713. _context8.next = 11;
  2714. return localDatastore._updateLocalIdForObject(mapIdForPin[object.id], object);
  2715. case 11:
  2716. _context8.next = 13;
  2717. return localDatastore._updateObjectIfPinned(object);
  2718. case 13:
  2719. _iteratorNormalCompletion2 = true;
  2720. _context8.next = 7;
  2721. break;
  2722. case 16:
  2723. _context8.next = 22;
  2724. break;
  2725. case 18:
  2726. _context8.prev = 18;
  2727. _context8.t0 = _context8["catch"](5);
  2728. _didIteratorError2 = true;
  2729. _iteratorError2 = _context8.t0;
  2730. case 22:
  2731. _context8.prev = 22;
  2732. _context8.prev = 23;
  2733. if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
  2734. _iterator2.return();
  2735. }
  2736. case 25:
  2737. _context8.prev = 25;
  2738. if (!_didIteratorError2) {
  2739. _context8.next = 28;
  2740. break;
  2741. }
  2742. throw _iteratorError2;
  2743. case 28:
  2744. return _context8.finish(25);
  2745. case 29:
  2746. return _context8.finish(22);
  2747. case 30:
  2748. return _context8.abrupt("return", Promise.resolve(target));
  2749. case 31:
  2750. case "end":
  2751. return _context8.stop();
  2752. }
  2753. }
  2754. }, _callee8, null, [[5, 18, 22, 30], [23,, 25, 29]]);
  2755. })));
  2756. });
  2757. } else if (target instanceof ParseObject) {
  2758. // copying target lets Flow guarantee the pointer isn't modified elsewhere
  2759. var localId = target._localId;
  2760. var targetCopy = target;
  2761. var task = function () {
  2762. var params = targetCopy._getSaveParams();
  2763. return RESTController.request(params.method, params.path, params.body, options).then(function (response) {
  2764. var status = response._status;
  2765. delete response._status;
  2766. targetCopy._handleSaveResponse(response, status);
  2767. }, function (error) {
  2768. targetCopy._handleSaveError();
  2769. return Promise.reject(error);
  2770. });
  2771. };
  2772. stateController.pushPendingState(target._getStateIdentifier());
  2773. return stateController.enqueueTask(target._getStateIdentifier(), task).then(
  2774. /*#__PURE__*/
  2775. (0, _asyncToGenerator2.default)(
  2776. /*#__PURE__*/
  2777. _regenerator.default.mark(function _callee9() {
  2778. return _regenerator.default.wrap(function (_context9) {
  2779. while (1) {
  2780. switch (_context9.prev = _context9.next) {
  2781. case 0:
  2782. _context9.next = 2;
  2783. return localDatastore._updateLocalIdForObject(localId, target);
  2784. case 2:
  2785. _context9.next = 4;
  2786. return localDatastore._updateObjectIfPinned(target);
  2787. case 4:
  2788. return _context9.abrupt("return", target);
  2789. case 5:
  2790. case "end":
  2791. return _context9.stop();
  2792. }
  2793. }
  2794. }, _callee9);
  2795. })), function (error) {
  2796. return Promise.reject(error);
  2797. });
  2798. }
  2799. return Promise.resolve();
  2800. }
  2801. };
  2802. _CoreManager.default.setObjectController(DefaultController);
  2803. var _default = ParseObject;
  2804. exports.default = _default;