unsavedChildren.js 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = unsavedChildren;
  6. var _ParseFile = _interopRequireDefault(require("./ParseFile"));
  7. var _ParseObject = _interopRequireDefault(require("./ParseObject"));
  8. var _ParseRelation = _interopRequireDefault(require("./ParseRelation"));
  9. function _interopRequireDefault(obj) {
  10. return obj && obj.__esModule ? obj : {
  11. default: obj
  12. };
  13. }
  14. /**
  15. * @flow
  16. */
  17. /*:: type EncounterMap = {
  18. objects: { [identifier: string]: ParseObject | boolean },
  19. files: Array<ParseFile>,
  20. };*/
  21. /**
  22. * Return an array of unsaved children, which are either Parse Objects or Files.
  23. * If it encounters any dirty Objects without Ids, it will throw an exception.
  24. *
  25. * @param {Parse.Object} obj
  26. * @param {boolean} allowDeepUnsaved
  27. * @returns {Array}
  28. */
  29. function unsavedChildren(obj /*: ParseObject*/, allowDeepUnsaved /*:: ?: boolean*/) /*: Array<ParseFile | ParseObject>*/{
  30. const encountered = {
  31. objects: {},
  32. files: []
  33. };
  34. const identifier = obj.className + ':' + obj._getId();
  35. encountered.objects[identifier] = obj.dirty() ? obj : true;
  36. const attributes = obj.attributes;
  37. for (const attr in attributes) {
  38. if (typeof attributes[attr] === 'object') {
  39. traverse(attributes[attr], encountered, false, !!allowDeepUnsaved);
  40. }
  41. }
  42. const unsaved = [];
  43. for (const id in encountered.objects) {
  44. if (id !== identifier && encountered.objects[id] !== true) {
  45. unsaved.push(encountered.objects[id]);
  46. }
  47. }
  48. return unsaved.concat(encountered.files);
  49. }
  50. function traverse(obj /*: ParseObject*/, encountered /*: EncounterMap*/, shouldThrow /*: boolean*/, allowDeepUnsaved /*: boolean*/) {
  51. if (obj instanceof _ParseObject.default) {
  52. if (!obj.id && shouldThrow) {
  53. throw new Error('Cannot create a pointer to an unsaved Object.');
  54. }
  55. const identifier = obj.className + ':' + obj._getId();
  56. if (!encountered.objects[identifier]) {
  57. encountered.objects[identifier] = obj.dirty() ? obj : true;
  58. const attributes = obj.attributes;
  59. for (const attr in attributes) {
  60. if (typeof attributes[attr] === 'object') {
  61. traverse(attributes[attr], encountered, !allowDeepUnsaved, allowDeepUnsaved);
  62. }
  63. }
  64. }
  65. return;
  66. }
  67. if (obj instanceof _ParseFile.default) {
  68. if (!obj.url() && encountered.files.indexOf(obj) < 0) {
  69. encountered.files.push(obj);
  70. }
  71. return;
  72. }
  73. if (obj instanceof _ParseRelation.default) {
  74. return;
  75. }
  76. if (Array.isArray(obj)) {
  77. obj.forEach(el => {
  78. if (typeof el === 'object') {
  79. traverse(el, encountered, shouldThrow, allowDeepUnsaved);
  80. }
  81. });
  82. }
  83. for (const k in obj) {
  84. if (typeof obj[k] === 'object') {
  85. traverse(obj[k], encountered, shouldThrow, allowDeepUnsaved);
  86. }
  87. }
  88. }