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;
|
---|