duplex.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. Object.defineProperty(exports, "__esModule", { value: true });
  2. /*!
  3. * https://github.com/Starcounter-Jack/JSON-Patch
  4. * (c) 2017-2021 Joachim Wester
  5. * MIT license
  6. */
  7. var helpers_js_1 = require("./helpers.js");
  8. var core_js_1 = require("./core.js");
  9. var beforeDict = new WeakMap();
  10. var Mirror = /** @class */ (function () {
  11. function Mirror(obj) {
  12. this.observers = new Map();
  13. this.obj = obj;
  14. }
  15. return Mirror;
  16. }());
  17. var ObserverInfo = /** @class */ (function () {
  18. function ObserverInfo(callback, observer) {
  19. this.callback = callback;
  20. this.observer = observer;
  21. }
  22. return ObserverInfo;
  23. }());
  24. function getMirror(obj) {
  25. return beforeDict.get(obj);
  26. }
  27. function getObserverFromMirror(mirror, callback) {
  28. return mirror.observers.get(callback);
  29. }
  30. function removeObserverFromMirror(mirror, observer) {
  31. mirror.observers.delete(observer.callback);
  32. }
  33. /**
  34. * Detach an observer from an object
  35. */
  36. function unobserve(root, observer) {
  37. observer.unobserve();
  38. }
  39. exports.unobserve = unobserve;
  40. /**
  41. * Observes changes made to an object, which can then be retrieved using generate
  42. */
  43. function observe(obj, callback) {
  44. var patches = [];
  45. var observer;
  46. var mirror = getMirror(obj);
  47. if (!mirror) {
  48. mirror = new Mirror(obj);
  49. beforeDict.set(obj, mirror);
  50. }
  51. else {
  52. var observerInfo = getObserverFromMirror(mirror, callback);
  53. observer = observerInfo && observerInfo.observer;
  54. }
  55. if (observer) {
  56. return observer;
  57. }
  58. observer = {};
  59. mirror.value = helpers_js_1._deepClone(obj);
  60. if (callback) {
  61. observer.callback = callback;
  62. observer.next = null;
  63. var dirtyCheck = function () {
  64. generate(observer);
  65. };
  66. var fastCheck = function () {
  67. clearTimeout(observer.next);
  68. observer.next = setTimeout(dirtyCheck);
  69. };
  70. if (typeof window !== 'undefined') { //not Node
  71. window.addEventListener('mouseup', fastCheck);
  72. window.addEventListener('keyup', fastCheck);
  73. window.addEventListener('mousedown', fastCheck);
  74. window.addEventListener('keydown', fastCheck);
  75. window.addEventListener('change', fastCheck);
  76. }
  77. }
  78. observer.patches = patches;
  79. observer.object = obj;
  80. observer.unobserve = function () {
  81. generate(observer);
  82. clearTimeout(observer.next);
  83. removeObserverFromMirror(mirror, observer);
  84. if (typeof window !== 'undefined') {
  85. window.removeEventListener('mouseup', fastCheck);
  86. window.removeEventListener('keyup', fastCheck);
  87. window.removeEventListener('mousedown', fastCheck);
  88. window.removeEventListener('keydown', fastCheck);
  89. window.removeEventListener('change', fastCheck);
  90. }
  91. };
  92. mirror.observers.set(callback, new ObserverInfo(callback, observer));
  93. return observer;
  94. }
  95. exports.observe = observe;
  96. /**
  97. * Generate an array of patches from an observer
  98. */
  99. function generate(observer, invertible) {
  100. if (invertible === void 0) { invertible = false; }
  101. var mirror = beforeDict.get(observer.object);
  102. _generate(mirror.value, observer.object, observer.patches, "", invertible);
  103. if (observer.patches.length) {
  104. core_js_1.applyPatch(mirror.value, observer.patches);
  105. }
  106. var temp = observer.patches;
  107. if (temp.length > 0) {
  108. observer.patches = [];
  109. if (observer.callback) {
  110. observer.callback(temp);
  111. }
  112. }
  113. return temp;
  114. }
  115. exports.generate = generate;
  116. // Dirty check if obj is different from mirror, generate patches and update mirror
  117. function _generate(mirror, obj, patches, path, invertible) {
  118. if (obj === mirror) {
  119. return;
  120. }
  121. if (typeof obj.toJSON === "function") {
  122. obj = obj.toJSON();
  123. }
  124. var newKeys = helpers_js_1._objectKeys(obj);
  125. var oldKeys = helpers_js_1._objectKeys(mirror);
  126. var changed = false;
  127. var deleted = false;
  128. //if ever "move" operation is implemented here, make sure this test runs OK: "should not generate the same patch twice (move)"
  129. for (var t = oldKeys.length - 1; t >= 0; t--) {
  130. var key = oldKeys[t];
  131. var oldVal = mirror[key];
  132. if (helpers_js_1.hasOwnProperty(obj, key) && !(obj[key] === undefined && oldVal !== undefined && Array.isArray(obj) === false)) {
  133. var newVal = obj[key];
  134. if (typeof oldVal == "object" && oldVal != null && typeof newVal == "object" && newVal != null && Array.isArray(oldVal) === Array.isArray(newVal)) {
  135. _generate(oldVal, newVal, patches, path + "/" + helpers_js_1.escapePathComponent(key), invertible);
  136. }
  137. else {
  138. if (oldVal !== newVal) {
  139. changed = true;
  140. if (invertible) {
  141. patches.push({ op: "test", path: path + "/" + helpers_js_1.escapePathComponent(key), value: helpers_js_1._deepClone(oldVal) });
  142. }
  143. patches.push({ op: "replace", path: path + "/" + helpers_js_1.escapePathComponent(key), value: helpers_js_1._deepClone(newVal) });
  144. }
  145. }
  146. }
  147. else if (Array.isArray(mirror) === Array.isArray(obj)) {
  148. if (invertible) {
  149. patches.push({ op: "test", path: path + "/" + helpers_js_1.escapePathComponent(key), value: helpers_js_1._deepClone(oldVal) });
  150. }
  151. patches.push({ op: "remove", path: path + "/" + helpers_js_1.escapePathComponent(key) });
  152. deleted = true; // property has been deleted
  153. }
  154. else {
  155. if (invertible) {
  156. patches.push({ op: "test", path: path, value: mirror });
  157. }
  158. patches.push({ op: "replace", path: path, value: obj });
  159. changed = true;
  160. }
  161. }
  162. if (!deleted && newKeys.length == oldKeys.length) {
  163. return;
  164. }
  165. for (var t = 0; t < newKeys.length; t++) {
  166. var key = newKeys[t];
  167. if (!helpers_js_1.hasOwnProperty(mirror, key) && obj[key] !== undefined) {
  168. patches.push({ op: "add", path: path + "/" + helpers_js_1.escapePathComponent(key), value: helpers_js_1._deepClone(obj[key]) });
  169. }
  170. }
  171. }
  172. /**
  173. * Create an array of patches from the differences in two objects
  174. */
  175. function compare(tree1, tree2, invertible) {
  176. if (invertible === void 0) { invertible = false; }
  177. var patches = [];
  178. _generate(tree1, tree2, patches, '', invertible);
  179. return patches;
  180. }
  181. exports.compare = compare;