mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-10-25 02:23:22 +00:00
database dedup implemented.
This commit is contained in:
1 parent
531cf0d8a4
commit
f3f0639d95
5 files changed
+433
-132
No files matched your search
@@ -32,7 +32,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var e={105:e=>{e.exports=function(e){return function(){var t=arguments.length;if(t){for(var n=[],r=-1;++r<t;)n[r]=arguments[r];return e.call(this,n)}return e.call(this,[])}};},187:e=>{var t,n="object"==typeof Reflect?Reflect:null,r=n&&"function"==typeof n.apply?n.apply:function(e,t,n){return Function.prototype.apply.call(e,t,n)};t=n&&"function"==typeof n.ownKeys?n.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};var o=Number.isNaN||function(e){return e!=e};function i(){i.init.call(this);}e.exports=i,e.exports.once=function(e,t){return new Promise((function(n,r){function o(n){e.removeListener(t,i),r(n);}function i(){"function"==typeof e.removeListener&&e.removeListener("error",o),n([].slice.call(arguments));}v(e,t,i,{once:!0}),"error"!==t&&function(e,t,n){"function"==typeof e.on&&v(e,"error",t,{once:!0});}(e,o);}))},i.EventEmitter=i,i.prototype._events=void 0,i.prototype._eventsCount=0,i.prototype._maxListeners=void 0;var s=10;function a(e){if("function"!=typeof e)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof e)}function u(e){return void 0===e._maxListeners?i.defaultMaxListeners:e._maxListeners}function c(e,t,n,r){var o,i,s,c;if(a(n),void 0===(i=e._events)?(i=e._events=Object.create(null),e._eventsCount=0):(void 0!==i.newListener&&(e.emit("newListener",t,n.listener?n.listener:n),i=e._events),s=i[t]),void 0===s)s=i[t]=n,++e._eventsCount;else if("function"==typeof s?s=i[t]=r?[n,s]:[s,n]:r?s.unshift(n):s.push(n),(o=u(e))>0&&s.length>o&&!s.warned){s.warned=!0;var f=new Error("Possible EventEmitter memory leak detected. "+s.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");f.name="MaxListenersExceededWarning",f.emitter=e,f.type=t,f.count=s.length,c=f,console&&console.warn&&console.warn(c);}return e}function f(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function l(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},o=f.bind(r);return o.listener=n,r.wrapFn=o,o}function d(e,t,n){var r=e._events;if(void 0===r)return [];var o=r[t];return void 0===o?[]:"function"==typeof o?n?[o.listener||o]:[o]:n?function(e){for(var t=new Array(e.length),n=0;n<t.length;++n)t[n]=e[n].listener||e[n];return t}(o):p(o,o.length)}function h(e){var t=this._events;if(void 0!==t){var n=t[e];if("function"==typeof n)return 1;if(void 0!==n)return n.length}return 0}function p(e,t){for(var n=new Array(t),r=0;r<t;++r)n[r]=e[r];return n}function v(e,t,n,r){if("function"==typeof e.on)r.once?e.once(t,n):e.on(t,n);else {if("function"!=typeof e.addEventListener)throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type '+typeof e);e.addEventListener(t,(function o(i){r.once&&e.removeEventListener(t,o),n(i);}));}}Object.defineProperty(i,"defaultMaxListeners",{enumerable:!0,get:function(){return s},set:function(e){if("number"!=typeof e||e<0||o(e))throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+e+".");s=e;}}),i.init=function(){void 0!==this._events&&this._events!==Object.getPrototypeOf(this)._events||(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0;},i.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||o(e))throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+e+".");return this._maxListeners=e,this},i.prototype.getMaxListeners=function(){return u(this)},i.prototype.emit=function(e){for(var t=[],n=1;n<arguments.length;n++)t.push(arguments[n]);var o="error"===e,i=this._events;if(void 0!==i)o=o&&void 0===i.error;else if(!o)return !1;if(o){var s;if(t.length>0&&(s=t[0]),s instanceof Error)throw s;var a=new Error("Unhandled error."+(s?" ("+s.message+")":""));throw a.context=s,a}var u=i[e];if(void 0===u)return !1;if("function"==typeof u)r(u,this,t);else {var c=u.length,f=p(u,c);for(n=0;n<c;++n)r(f[n],this,t);}return !0},i.prototype.addListener=function(e,t){return c(this,e,t,!1)},i.prototype.on=i.prototype.addListener,i.prototype.prependListener=function(e,t){return c(this,e,t,!0)},i.prototype.once=function(e,t){return a(t),this.on(e,l(this,e,t)),this},i.prototype.prependOnceListener=function(e,t){return a(t),this.prependListener(e,l(this,e,t)),this},i.prototype.removeListener=function(e,t){var n,r,o,i,s;if(a(t),void 0===(r=this._events))return this;if(void 0===(n=r[e]))return this;if(n===t||n.listener===t)0==--this._eventsCount?this._events=Object.create(null):(delete r[e],r.removeListener&&this.emit("removeListener",e,n.listener||t));else if("function"!=typeof n){for(o=-1,i=n.length-1;i>=0;i--)if(n[i]===t||n[i].listener===t){s=n[i].listener,o=i;break}if(o<0)return this;0===o?n.shift():functLine truncated
|
var e$1={105:e=>{e.exports=function(e){return function(){var t=arguments.length;if(t){for(var n=[],r=-1;++r<t;)n[r]=arguments[r];return e.call(this,n)}return e.call(this,[])}};},187:e=>{var t,n="object"==typeof Reflect?Reflect:null,r=n&&"function"==typeof n.apply?n.apply:function(e,t,n){return Function.prototype.apply.call(e,t,n)};t=n&&"function"==typeof n.ownKeys?n.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};var o=Number.isNaN||function(e){return e!=e};function i(){i.init.call(this);}e.exports=i,e.exports.once=function(e,t){return new Promise((function(n,r){function o(n){e.removeListener(t,i),r(n);}function i(){"function"==typeof e.removeListener&&e.removeListener("error",o),n([].slice.call(arguments));}v(e,t,i,{once:!0}),"error"!==t&&function(e,t,n){"function"==typeof e.on&&v(e,"error",t,{once:!0});}(e,o);}))},i.EventEmitter=i,i.prototype._events=void 0,i.prototype._eventsCount=0,i.prototype._maxListeners=void 0;var s=10;function a(e){if("function"!=typeof e)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof e)}function u(e){return void 0===e._maxListeners?i.defaultMaxListeners:e._maxListeners}function c(e,t,n,r){var o,i,s,c;if(a(n),void 0===(i=e._events)?(i=e._events=Object.create(null),e._eventsCount=0):(void 0!==i.newListener&&(e.emit("newListener",t,n.listener?n.listener:n),i=e._events),s=i[t]),void 0===s)s=i[t]=n,++e._eventsCount;else if("function"==typeof s?s=i[t]=r?[n,s]:[s,n]:r?s.unshift(n):s.push(n),(o=u(e))>0&&s.length>o&&!s.warned){s.warned=!0;var f=new Error("Possible EventEmitter memory leak detected. "+s.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");f.name="MaxListenersExceededWarning",f.emitter=e,f.type=t,f.count=s.length,c=f,console&&console.warn&&console.warn(c);}return e}function f(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function l(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},o=f.bind(r);return o.listener=n,r.wrapFn=o,o}function d(e,t,n){var r=e._events;if(void 0===r)return [];var o=r[t];return void 0===o?[]:"function"==typeof o?n?[o.listener||o]:[o]:n?function(e){for(var t=new Array(e.length),n=0;n<t.length;++n)t[n]=e[n].listener||e[n];return t}(o):p(o,o.length)}function h(e){var t=this._events;if(void 0!==t){var n=t[e];if("function"==typeof n)return 1;if(void 0!==n)return n.length}return 0}function p(e,t){for(var n=new Array(t),r=0;r<t;++r)n[r]=e[r];return n}function v(e,t,n,r){if("function"==typeof e.on)r.once?e.once(t,n):e.on(t,n);else {if("function"!=typeof e.addEventListener)throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type '+typeof e);e.addEventListener(t,(function o(i){r.once&&e.removeEventListener(t,o),n(i);}));}}Object.defineProperty(i,"defaultMaxListeners",{enumerable:!0,get:function(){return s},set:function(e){if("number"!=typeof e||e<0||o(e))throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+e+".");s=e;}}),i.init=function(){void 0!==this._events&&this._events!==Object.getPrototypeOf(this)._events||(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0;},i.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||o(e))throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+e+".");return this._maxListeners=e,this},i.prototype.getMaxListeners=function(){return u(this)},i.prototype.emit=function(e){for(var t=[],n=1;n<arguments.length;n++)t.push(arguments[n]);var o="error"===e,i=this._events;if(void 0!==i)o=o&&void 0===i.error;else if(!o)return !1;if(o){var s;if(t.length>0&&(s=t[0]),s instanceof Error)throw s;var a=new Error("Unhandled error."+(s?" ("+s.message+")":""));throw a.context=s,a}var u=i[e];if(void 0===u)return !1;if("function"==typeof u)r(u,this,t);else {var c=u.length,f=p(u,c);for(n=0;n<c;++n)r(f[n],this,t);}return !0},i.prototype.addListener=function(e,t){return c(this,e,t,!1)},i.prototype.on=i.prototype.addListener,i.prototype.prependListener=function(e,t){return c(this,e,t,!0)},i.prototype.once=function(e,t){return a(t),this.on(e,l(this,e,t)),this},i.prototype.prependOnceListener=function(e,t){return a(t),this.prependListener(e,l(this,e,t)),this},i.prototype.removeListener=function(e,t){var n,r,o,i,s;if(a(t),void 0===(r=this._events))return this;if(void 0===(n=r[e]))return this;if(n===t||n.listener===t)0==--this._eventsCount?this._events=Object.create(null):(delete r[e],r.removeListener&&this.emit("removeListener",e,n.listener||t));else if("function"!=typeof n){for(o=-1,i=n.length-1;i>=0;i--)if(n[i]===t||n[i].listener===t){s=n[i].listener,o=i;break}if(o<0)return this;0===o?n.shift():funLine truncated
|
||||||
|
|
||||||
function createCommonjsModule(fn) {
|
function createCommonjsModule(fn) {
|
||||||
var module = { exports: {} };
|
var module = { exports: {} };
|
||||||
@@ -2258,10 +2258,13 @@ module.exports['DIFF_INSERT'] = DIFF_INSERT;
|
|||||||
module.exports['DIFF_EQUAL'] = DIFF_EQUAL;
|
module.exports['DIFF_EQUAL'] = DIFF_EQUAL;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const t=new Uint8Array([0,97,115,109,1,0,0,0,1,13,2,96,2,127,127,0,96,3,127,127,127,1,127,3,3,2,1,0,5,3,1,0,1,7,23,3,3,109,101,109,2,0,5,120,120,104,51,50,0,0,5,120,120,104,54,52,0,1,10,152,9,2,242,2,1,4,127,32,0,32,1,106,33,3,32,1,32,1,65,16,79,4,127,32,3,65,16,107,33,6,32,2,65,168,136,141,161,2,106,33,1,32,2,65,137,235,208,208,7,107,33,4,32,2,65,207,140,162,142,6,106,33,5,3,64,32,1,32,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,1,32,4,32,0,65,4,106,34,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,4,32,2,32,0,65,4,106,34,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,2,32,5,32,0,65,4,106,34,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,5,32,6,32,0,65,4,106,34,0,79,13,0,11,32,2,65,12,119,32,5,65,18,119,106,32,4,65,7,119,106,32,1,65,1,119,106,5,32,2,65,177,207,217,178,1,106,11,106,33,2,3,64,32,3,32,0,65,4,106,79,4,64,32,2,32,0,40,2,0,65,189,220,202,149,124,108,106,65,17,119,65,175,214,211,190,2,108,33,2,32,0,65,4,106,33,0,12,1,11,11,3,64,32,0,32,3,73,4,64,32,2,32,0,45,0,0,65,177,207,217,178,1,108,106,65,11,119,65,177,243,221,241,121,108,33,2,32,0,65,1,106,33,0,12,1,11,11,32,2,32,2,65,15,118,115,65,247,148,175,175,120,108,34,0,65,13,118,32,0,115,65,189,220,202,149,124,108,34,0,65,16,118,32,0,115,11,161,6,2,4,126,3,127,32,0,65,4,106,53,2,0,32,0,53,2,0,66,32,134,132,33,2,32,1,32,0,65,8,106,34,6,106,33,7,32,1,65,32,79,4,126,32,7,65,32,107,33,8,32,2,66,214,235,130,238,234,253,137,245,224,0,124,33,3,32,2,66,177,169,172,193,173,184,212,166,61,125,33,4,32,2,66,249,234,208,208,231,201,161,228,225,0,124,33,5,3,64,32,3,32,6,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,3,32,4,32,6,65,8,106,34,6,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,4,32,2,32,6,65,8,106,34,6,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,2,32,5,32,6,65,8,106,34,6,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,5,32,8,32,6,65,8,106,34,6,79,13,0,11,32,2,66,12,137,32,5,66,18,137,124,32,4,66,7,137,124,32,3,66,1,137,124,32,3,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,4,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,2,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,5,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,5,32,2,66,197,207,217,178,241,229,186,234,39,124,11,32,1,173,124,33,2,3,64,32,7,32,6,65,8,106,79,4,64,32,2,32,6,41,3,0,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,27,137,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,33,2,32,6,65,8,106,33,6,12,1,11,11,32,6,65,4,106,32,7,77,4,64,32,2,32,6,53,2,0,66,135,149,175,175,152,182,222,155,158,127,126,133,66,23,137,66,207,214,211,190,210,199,171,217,66,126,66,249,243,221,241,153,246,153,171,22,124,33,2,32,6,65,4,106,33,6,11,3,64,32,6,32,7,73,4,64,32,2,32,6,49,0,0,66,197,207,217,178,241,229,186,234,39,126,133,66,11,137,66,135,149,175,175,152,182,222,155,158,127,126,33,2,32,6,65,1,106,33,6,12,1,11,11,32,0,32,2,32,2,66,33,136,133,66,207,214,211,190,210,199,171,217,66,126,34,2,66,29,136,32,2,133,66,249,243,221,241,153,246,153,171,22,126,34,2,66,32,136,32,2,133,34,2,66,32,136,62,2,0,32,0,65,4,106,32,2,62,2,0,11]);let e;function n(t,e,n){if(e.buffer.byteLength<t.byteLength+n){const i=Math.ceil((t.byteLength+n-e.buffer.byteLength)/65536);e.grow(i);}new Uint8Array(e.buffer,n).set(t);}async function xxhash(){const{instance:{exports:{mem:i,xxh32:o,xxh64:r}}}=await WebAssembly.instantiate(t);function h(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return n(t,i,0),o(0,t.byteLength,e)>>>0}function c(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;n(t,i,8);const h=new DataView(i.buffer);return h.setUint32(0,e,!0),h.setUint32(4,o,!0),r(0,t.byteLength),h}return {h32:function(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;e||(e=new TextEncoder);const i=e.encode(t);return h(i,n).toString(16)},h32Raw:h,h64:function(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==argumLine truncated
|
||||||
|
|
||||||
// docs should be encoded as base64, so 1 char -> 1 bytes
|
// docs should be encoded as base64, so 1 char -> 1 bytes
|
||||||
// and cloudant limitation is 1MB , we use 900kb;
|
// and cloudant limitation is 1MB , we use 900kb;
|
||||||
// const MAX_DOC_SIZE = 921600;
|
// const MAX_DOC_SIZE = 921600;
|
||||||
const MAX_DOC_SIZE = 921600;
|
const MAX_DOC_SIZE = 200; // for .md file
|
||||||
|
const MAX_DOC_SIZE_BIN = 102400; // 100kb
|
||||||
const DEFAULT_SETTINGS = {
|
const DEFAULT_SETTINGS = {
|
||||||
couchDB_URI: "",
|
couchDB_URI: "",
|
||||||
couchDB_USER: "",
|
couchDB_USER: "",
|
||||||
@@ -2271,6 +2274,7 @@ const DEFAULT_SETTINGS = {
|
|||||||
syncOnStart: false,
|
syncOnStart: false,
|
||||||
savingDelay: 200,
|
savingDelay: 200,
|
||||||
lessInformationInLog: false,
|
lessInformationInLog: false,
|
||||||
|
gcDelay: 30,
|
||||||
};
|
};
|
||||||
//-->Functions.
|
//-->Functions.
|
||||||
function arrayBufferToBase64(buffer) {
|
function arrayBufferToBase64(buffer) {
|
||||||
@@ -2370,13 +2374,25 @@ class LocalPouchDB {
|
|||||||
return "disabled";
|
return "disabled";
|
||||||
}
|
}
|
||||||
initializeDatabase() {
|
initializeDatabase() {
|
||||||
if (this.localDatabase != null)
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
this.localDatabase.close();
|
if (this.localDatabase != null)
|
||||||
this.localDatabase = null;
|
this.localDatabase.close();
|
||||||
this.localDatabase = new o(this.dbname + "-livesync", {
|
this.localDatabase = null;
|
||||||
auto_compaction: true,
|
this.localDatabase = new o(this.dbname + "-livesync", {
|
||||||
revs_limit: 100,
|
auto_compaction: true,
|
||||||
deterministic_revs: true,
|
revs_limit: 100,
|
||||||
|
deterministic_revs: true,
|
||||||
|
});
|
||||||
|
yield this.prepareHashArg();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
prepareHashArg() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (this.h32 != null)
|
||||||
|
return;
|
||||||
|
const { h32, h64 } = yield xxhash();
|
||||||
|
this.h32 = h32;
|
||||||
|
this.h64 = h64;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
getDatabaseDoc(id, opt) {
|
getDatabaseDoc(id, opt) {
|
||||||
@@ -2413,24 +2429,17 @@ class LocalPouchDB {
|
|||||||
// search childrens
|
// search childrens
|
||||||
try {
|
try {
|
||||||
let childrens = [];
|
let childrens = [];
|
||||||
// let childPromise = [];
|
|
||||||
for (var v of obj.children) {
|
for (var v of obj.children) {
|
||||||
// childPromise.push(this.localDatabase.get(v));
|
// childPromise.push(this.localDatabase.get(v));
|
||||||
let elem = yield this.localDatabase.get(v);
|
let elem = yield this.localDatabase.get(v);
|
||||||
if (elem.type && elem.type == "leaf") {
|
if (elem.type && elem.type == "leaf") {
|
||||||
childrens.push(elem);
|
childrens.push(elem.data);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new Error("linked document is not leaf");
|
throw new Error("linked document is not leaf");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// let childrens = await Promise.all(childPromise);
|
let data = childrens.join("");
|
||||||
let data = childrens
|
|
||||||
// .filter((e) => e.type == "leaf")
|
|
||||||
// .map((e) => e as NoteLeaf)
|
|
||||||
.sort((e) => e.seq)
|
|
||||||
.map((e) => e.data)
|
|
||||||
.join("");
|
|
||||||
let doc = {
|
let doc = {
|
||||||
data: data,
|
data: data,
|
||||||
_id: obj._id,
|
_id: obj._id,
|
||||||
@@ -2447,6 +2456,7 @@ class LocalPouchDB {
|
|||||||
if (ex.status && ex.status == 404) {
|
if (ex.status && ex.status == 404) {
|
||||||
this.addLog(`Missing document content!, could not read ${obj._id} from database.`, true);
|
this.addLog(`Missing document content!, could not read ${obj._id} from database.`, true);
|
||||||
// this.addLog(ex);
|
// this.addLog(ex);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
this.addLog(`Something went wrong on reading ${obj._id} from database.`, true);
|
this.addLog(`Something went wrong on reading ${obj._id} from database.`, true);
|
||||||
this.addLog(ex);
|
this.addLog(ex);
|
||||||
@@ -2478,24 +2488,12 @@ class LocalPouchDB {
|
|||||||
}
|
}
|
||||||
//Check it out and fix docs to regular case
|
//Check it out and fix docs to regular case
|
||||||
if (!obj.type || (obj.type && obj.type == "notes")) {
|
if (!obj.type || (obj.type && obj.type == "notes")) {
|
||||||
// let note = obj as Notes;
|
|
||||||
// note._deleted=true;
|
|
||||||
obj._deleted = true;
|
obj._deleted = true;
|
||||||
let r = yield this.localDatabase.put(obj);
|
let r = yield this.localDatabase.put(obj);
|
||||||
return true;
|
return true;
|
||||||
// simple note
|
// simple note
|
||||||
}
|
}
|
||||||
if (obj.type == "newnote") {
|
if (obj.type == "newnote") {
|
||||||
// search childrens
|
|
||||||
for (var v of obj.children) {
|
|
||||||
let d = yield this.localDatabase.get(v);
|
|
||||||
if (d.type != "leaf") {
|
|
||||||
this.addLog(`structure went wrong:${id}-${v}`);
|
|
||||||
}
|
|
||||||
d._deleted = true;
|
|
||||||
yield this.localDatabase.put(d);
|
|
||||||
this.addLog(`content removed:${d.seq}`);
|
|
||||||
}
|
|
||||||
obj._deleted = true;
|
obj._deleted = true;
|
||||||
yield this.localDatabase.put(obj);
|
yield this.localDatabase.put(obj);
|
||||||
this.addLog(`entry removed:${obj._id}`);
|
this.addLog(`entry removed:${obj._id}`);
|
||||||
@@ -2513,25 +2511,84 @@ class LocalPouchDB {
|
|||||||
putDBEntry(note) {
|
putDBEntry(note) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
let leftData = note.data;
|
let leftData = note.data;
|
||||||
let savenNotes = []; // something occured, kill this .
|
let savenNotes = [];
|
||||||
let seq = 0;
|
let processed = 0;
|
||||||
let now = Date.now();
|
let made = 0;
|
||||||
|
let skiped = 0;
|
||||||
|
let pieceSize = MAX_DOC_SIZE;
|
||||||
|
if (!note._id.endsWith(".md")) {
|
||||||
|
pieceSize = MAX_DOC_SIZE_BIN;
|
||||||
|
}
|
||||||
do {
|
do {
|
||||||
let piece = leftData.substring(0, MAX_DOC_SIZE);
|
// To keep low bandwith and database size,
|
||||||
leftData = leftData.substring(MAX_DOC_SIZE);
|
// Dedup pieces on database.
|
||||||
seq++;
|
let piece = leftData.substring(0, pieceSize);
|
||||||
let leafid = note._id + "-" + now + "-" + seq;
|
leftData = leftData.substring(pieceSize);
|
||||||
let d = {
|
processed++;
|
||||||
_id: leafid,
|
// Get has of piece.
|
||||||
parent: note._id,
|
let hashedPiece = this.h32(piece);
|
||||||
data: piece,
|
let leafid = "h:" + hashedPiece;
|
||||||
seq: seq,
|
let hashQ = 0; // if hash collided, **IF**, count it up.
|
||||||
type: "leaf",
|
let tryNextHash = false;
|
||||||
};
|
let needMake = true;
|
||||||
yield this.localDatabase.put(d);
|
do {
|
||||||
|
let nleafid = leafid;
|
||||||
|
try {
|
||||||
|
nleafid = `${leafid}${hashQ}`;
|
||||||
|
// console.log(nleafid);
|
||||||
|
let pieceData = yield this.localDatabase.get(nleafid);
|
||||||
|
if (pieceData.type == "leaf" && pieceData.data == piece) {
|
||||||
|
this.addLog("hashe:data exists.");
|
||||||
|
leafid = nleafid;
|
||||||
|
needMake = false;
|
||||||
|
tryNextHash = false;
|
||||||
|
}
|
||||||
|
else if (pieceData.type == "leaf") {
|
||||||
|
this.addLog("hash:collision!!");
|
||||||
|
hashQ++;
|
||||||
|
tryNextHash = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.addLog("hash:no collision, it's not leaf. what's going on..");
|
||||||
|
leafid = nleafid;
|
||||||
|
tryNextHash = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
if (ex.status && ex.status == 404) {
|
||||||
|
//not found, we can use it.
|
||||||
|
this.addLog(`hash:not found.`);
|
||||||
|
leafid = nleafid;
|
||||||
|
needMake = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
needMake = false;
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (tryNextHash);
|
||||||
|
if (needMake) {
|
||||||
|
//have to make
|
||||||
|
let d = {
|
||||||
|
_id: leafid,
|
||||||
|
data: piece,
|
||||||
|
type: "leaf",
|
||||||
|
};
|
||||||
|
let result = yield this.localDatabase.put(d);
|
||||||
|
if (result.ok) {
|
||||||
|
this.addLog(`ok:saven`);
|
||||||
|
made++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.addLog("save faild");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skiped++;
|
||||||
|
}
|
||||||
savenNotes.push(leafid);
|
savenNotes.push(leafid);
|
||||||
} while (leftData != "");
|
} while (leftData != "");
|
||||||
this.addLog(`note content saven, pieces:${seq}`);
|
this.addLog(`note content saven, pieces:${processed} new:${made}, skip:${skiped}`);
|
||||||
let newDoc = {
|
let newDoc = {
|
||||||
NewNote: true,
|
NewNote: true,
|
||||||
children: savenNotes,
|
children: savenNotes,
|
||||||
@@ -2541,19 +2598,13 @@ class LocalPouchDB {
|
|||||||
size: note.size,
|
size: note.size,
|
||||||
type: "newnote",
|
type: "newnote",
|
||||||
};
|
};
|
||||||
let deldocs = [];
|
|
||||||
// Here for upsert logic,
|
// Here for upsert logic,
|
||||||
try {
|
try {
|
||||||
let old = yield this.localDatabase.get(newDoc._id);
|
let old = yield this.localDatabase.get(newDoc._id);
|
||||||
if (!old.type || old.type == "notes") {
|
if (!old.type || old.type == "notes" || old.type == "newnote") {
|
||||||
// simple use rev for new doc
|
// simple use rev for new doc
|
||||||
newDoc._rev = old._rev;
|
newDoc._rev = old._rev;
|
||||||
}
|
}
|
||||||
if (old.type == "newnote") {
|
|
||||||
//when save finished, we have to garbage collect.
|
|
||||||
deldocs = old.children;
|
|
||||||
newDoc._rev = old._rev;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (ex) {
|
catch (ex) {
|
||||||
if (ex.status && ex.status == 404) ;
|
if (ex.status && ex.status == 404) ;
|
||||||
@@ -2563,15 +2614,6 @@ class LocalPouchDB {
|
|||||||
}
|
}
|
||||||
yield this.localDatabase.put(newDoc);
|
yield this.localDatabase.put(newDoc);
|
||||||
this.addLog(`note saven:${newDoc._id}`);
|
this.addLog(`note saven:${newDoc._id}`);
|
||||||
let items = 0;
|
|
||||||
for (var v of deldocs) {
|
|
||||||
items++;
|
|
||||||
//TODO: Check for missing link
|
|
||||||
let d = yield this.localDatabase.get(v);
|
|
||||||
d._deleted = true;
|
|
||||||
yield this.localDatabase.put(d);
|
|
||||||
}
|
|
||||||
this.addLog(`old content deleted, pieces:${items}`);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
openReplication(setting, keepAlive, showResult, callback) {
|
openReplication(setting, keepAlive, showResult, callback) {
|
||||||
@@ -2704,11 +2746,60 @@ class LocalPouchDB {
|
|||||||
this.addLog("Remote Database Created or Connected", true);
|
this.addLog("Remote Database Created or Connected", true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
garbageCollect() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
// get all documents of NewEntry2
|
||||||
|
// we don't use queries , just use allDocs();
|
||||||
|
let c = 0;
|
||||||
|
let readCount = 0;
|
||||||
|
let hashPieces = [];
|
||||||
|
let usedPieces = [];
|
||||||
|
do {
|
||||||
|
let result = yield this.localDatabase.allDocs({ include_docs: true, skip: c, limit: 100 });
|
||||||
|
readCount = result.rows.length;
|
||||||
|
if (readCount > 0) {
|
||||||
|
//there are some result
|
||||||
|
for (let v of result.rows) {
|
||||||
|
let doc = v.doc;
|
||||||
|
if (doc.type == "newnote") {
|
||||||
|
// used pieces memo.
|
||||||
|
usedPieces = Array.from(new Set([...usedPieces, ...doc.children]));
|
||||||
|
}
|
||||||
|
if (doc.type == "leaf") {
|
||||||
|
// all pieces.
|
||||||
|
hashPieces = Array.from(new Set([...hashPieces, doc._id]));
|
||||||
|
}
|
||||||
|
// this.addLog(`GC:processed:${v.doc._id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c += readCount;
|
||||||
|
} while (readCount != 0);
|
||||||
|
// items collected.
|
||||||
|
const garbages = hashPieces.filter((e) => usedPieces.indexOf(e) == -1);
|
||||||
|
let deleteCount = 0;
|
||||||
|
for (let v of garbages) {
|
||||||
|
try {
|
||||||
|
let item = yield this.localDatabase.get(v);
|
||||||
|
item._deleted = true;
|
||||||
|
yield this.localDatabase.put(item);
|
||||||
|
deleteCount++;
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
if (ex.status && ex.status == 404) ;
|
||||||
|
else {
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.addLog(`GC:deleted ${deleteCount} items.`);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
class ObsidianLiveSyncPlugin extends obsidian.Plugin {
|
class ObsidianLiveSyncPlugin extends obsidian.Plugin {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(...arguments);
|
super(...arguments);
|
||||||
this.logMessage = [];
|
this.logMessage = [];
|
||||||
|
this.gcTimerHandler = null;
|
||||||
}
|
}
|
||||||
onload() {
|
onload() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
@@ -2767,10 +2858,14 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
onunload() {
|
onunload() {
|
||||||
|
if (this.gcTimerHandler != null) {
|
||||||
|
clearTimeout(this.gcTimerHandler);
|
||||||
|
this.gcTimerHandler = null;
|
||||||
|
}
|
||||||
this.localDatabase.closeReplication();
|
this.localDatabase.closeReplication();
|
||||||
this.localDatabase.close();
|
this.localDatabase.close();
|
||||||
this.addLog("unloading plugin");
|
|
||||||
window.removeEventListener("visibilitychange", this.watchWindowVisiblity);
|
window.removeEventListener("visibilitychange", this.watchWindowVisiblity);
|
||||||
|
this.addLog("unloading plugin");
|
||||||
}
|
}
|
||||||
openDatabase() {
|
openDatabase() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
@@ -2779,7 +2874,12 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
|
|||||||
}
|
}
|
||||||
let vaultName = this.app.vault.getName();
|
let vaultName = this.app.vault.getName();
|
||||||
this.localDatabase = new LocalPouchDB(this.app, this, vaultName);
|
this.localDatabase = new LocalPouchDB(this.app, this, vaultName);
|
||||||
this.localDatabase.initializeDatabase();
|
yield this.localDatabase.initializeDatabase();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
garbageCollect() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
yield this.localDatabase.garbageCollect();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
loadSettings() {
|
loadSettings() {
|
||||||
@@ -2792,6 +2892,19 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
|
|||||||
yield this.saveData(this.settings);
|
yield this.saveData(this.settings);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
gcHook() {
|
||||||
|
if (this.settings.gcDelay == 0)
|
||||||
|
return;
|
||||||
|
const GC_DELAY = this.settings.gcDelay * 1000; // if leaving opening window, try GC,
|
||||||
|
if (this.gcTimerHandler != null) {
|
||||||
|
clearTimeout(this.gcTimerHandler);
|
||||||
|
this.gcTimerHandler = null;
|
||||||
|
}
|
||||||
|
this.gcTimerHandler = setTimeout(() => {
|
||||||
|
this.gcTimerHandler = null;
|
||||||
|
this.garbageCollect();
|
||||||
|
}, GC_DELAY);
|
||||||
|
}
|
||||||
registerWatchEvents() {
|
registerWatchEvents() {
|
||||||
this.registerEvent(this.app.vault.on("modify", this.watchVaultChange));
|
this.registerEvent(this.app.vault.on("modify", this.watchVaultChange));
|
||||||
this.registerEvent(this.app.vault.on("delete", this.watchVaultDelete));
|
this.registerEvent(this.app.vault.on("delete", this.watchVaultDelete));
|
||||||
@@ -2814,14 +2927,17 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
|
|||||||
this.localDatabase.openReplication(this.settings, false, false, this.parseReplicationResult);
|
this.localDatabase.openReplication(this.settings, false, false, this.parseReplicationResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.gcHook();
|
||||||
}
|
}
|
||||||
watchWorkspaceOpen(file) {
|
watchWorkspaceOpen(file) {
|
||||||
if (file == null)
|
if (file == null)
|
||||||
return;
|
return;
|
||||||
this.showIfConflicted(file);
|
this.showIfConflicted(file);
|
||||||
|
this.gcHook();
|
||||||
}
|
}
|
||||||
watchVaultChange(file, ...args) {
|
watchVaultChange(file, ...args) {
|
||||||
this.updateIntoDB(file);
|
this.updateIntoDB(file);
|
||||||
|
this.gcHook();
|
||||||
}
|
}
|
||||||
watchVaultDelete(file) {
|
watchVaultDelete(file) {
|
||||||
if (file.children) {
|
if (file.children) {
|
||||||
@@ -2832,6 +2948,7 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
|
|||||||
else {
|
else {
|
||||||
this.deleteFromDB(file);
|
this.deleteFromDB(file);
|
||||||
}
|
}
|
||||||
|
this.gcHook();
|
||||||
}
|
}
|
||||||
watchVaultRename(file, oldFile) {
|
watchVaultRename(file, oldFile) {
|
||||||
if (file.children) {
|
if (file.children) {
|
||||||
@@ -2842,6 +2959,7 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
|
|||||||
this.updateIntoDB(file);
|
this.updateIntoDB(file);
|
||||||
this.deleteFromDBbyPath(oldFile);
|
this.deleteFromDBbyPath(oldFile);
|
||||||
}
|
}
|
||||||
|
this.gcHook();
|
||||||
}
|
}
|
||||||
//--> Basic document Functions
|
//--> Basic document Functions
|
||||||
addLog(message, isNotify) {
|
addLog(message, isNotify) {
|
||||||
@@ -3455,6 +3573,23 @@ class ObsidianLiveSyncSettingTab extends obsidian.PluginSettingTab {
|
|||||||
}));
|
}));
|
||||||
text.inputEl.setAttribute("type", "number");
|
text.inputEl.setAttribute("type", "number");
|
||||||
});
|
});
|
||||||
|
new obsidian.Setting(containerEl)
|
||||||
|
.setName("Auto GC delay")
|
||||||
|
.setDesc("(seconds), if you set zero, you have to run manually.")
|
||||||
|
.addText((text) => {
|
||||||
|
text.setPlaceholder("")
|
||||||
|
.setValue(this.plugin.settings.gcDelay + "")
|
||||||
|
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
let v = Number(value);
|
||||||
|
if (isNaN(v) || v < 200 || v > 5000) {
|
||||||
|
return 30;
|
||||||
|
//text.inputEl.va;
|
||||||
|
}
|
||||||
|
this.plugin.settings.gcDelay = v;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
text.inputEl.setAttribute("type", "number");
|
||||||
|
});
|
||||||
new obsidian.Setting(containerEl)
|
new obsidian.Setting(containerEl)
|
||||||
.setName("Log")
|
.setName("Log")
|
||||||
.setDesc("Reduce log infomations")
|
.setDesc("Reduce log infomations")
|
||||||
@@ -3499,6 +3634,21 @@ class ObsidianLiveSyncSettingTab extends obsidian.PluginSettingTab {
|
|||||||
.onClick(() => __awaiter(this, void 0, void 0, function* () {
|
.onClick(() => __awaiter(this, void 0, void 0, function* () {
|
||||||
//await this.test();
|
//await this.test();
|
||||||
})));
|
})));
|
||||||
|
new obsidian.Setting(containerEl)
|
||||||
|
.setName("Garbage Collect")
|
||||||
|
.addButton((button) => button
|
||||||
|
.setButtonText("Garbage Collection")
|
||||||
|
.setDisabled(false)
|
||||||
|
.onClick(() => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
yield this.plugin.garbageCollect();
|
||||||
|
//await this.test();
|
||||||
|
})))
|
||||||
|
.addButton((button) => button
|
||||||
|
.setButtonText("Reset local files")
|
||||||
|
.setDisabled(false)
|
||||||
|
.onClick(() => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
//await this.test();
|
||||||
|
})));
|
||||||
new obsidian.Setting(containerEl).setName("Remote Database Operations").addButton((button) => button
|
new obsidian.Setting(containerEl).setName("Remote Database Operations").addButton((button) => button
|
||||||
.setButtonText("Reset remote database")
|
.setButtonText("Reset remote database")
|
||||||
.setDisabled(false)
|
.setDisabled(false)
|
||||||
@@ -3517,4 +3667,4 @@ class ObsidianLiveSyncSettingTab extends obsidian.PluginSettingTab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ObsidianLiveSyncPlugin;
|
module.exports = ObsidianLiveSyncPlugin;
|
||||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsInBvdWNoZGItYnJvd3Nlci13ZWJwYWNrL2Rpc3QvcG91Y2hkYi1icm93c2VyLmpzIiwibm9kZV9tb2R1bGVzL2RpZmYtbWF0Y2gtcGF0Y2gvaW5kZXguanMiLCJtYWluLnRzIl0sInNvdXJjZXNDb250ZW50IjpudWxsLCJuYW1lcyI6WyJQb3VjaERCIiwiUGx1Z2luIiwiYWRkSWNvbiIsImRlYm91bmNlIiwiTm90aWNlIiwiZGlmZl9tYXRjaF9wYXRjaCIsIk1vZGFsIiwiRElGRl9ERUxFVEUiLCJESUZGX0VRVUFMIiwiRElGRl9JTlNFUlQiLCJQbHVnaW5TZXR0aW5nVGFiIiwiU2V0dGluZyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXVEQTtBQUNPLFNBQVMsU0FBUyxDQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRTtBQUM3RCxJQUFJLFNBQVMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLE9BQU8sS0FBSyxZQUFZLENBQUMsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsVUFBVSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRTtBQUNoSCxJQUFJLE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRTtBQUMvRCxRQUFRLFNBQVMsU0FBUyxDQUFDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7QUFDbkcsUUFBUSxTQUFTLFFBQVEsQ0FBQyxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7QUFDdEcsUUFBUSxTQUFTLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxNQUFNLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDLEVBQUU7QUFDdEgsUUFBUSxJQUFJLENBQUMsQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsVUFBVSxJQUFJLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7QUFDOUUsS0FBSyxDQUFDLENBQUM7QUFDUDs7QUM3RUEsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sUUFBUSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMscUJBQXFCLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxPQUFPLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxJQUFJLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUMsTUFBTSxJQUFJLFNBQVMsQ0FBQyxrRUFBa0UsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUF
Line truncated
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsInBvdWNoZGItYnJvd3Nlci13ZWJwYWNrL2Rpc3QvcG91Y2hkYi1icm93c2VyLmpzIiwibm9kZV9tb2R1bGVzL2RpZmYtbWF0Y2gtcGF0Y2gvaW5kZXguanMiLCJub2RlX21vZHVsZXMveHhoYXNoLXdhc20vZXNtL3h4aGFzaC13YXNtLmpzIiwibWFpbi50cyJdLCJzb3VyY2VzQ29udGVudCI6bnVsbCwibmFtZXMiOlsiZSIsInQiLCJuIiwiUG91Y2hEQiIsIlBsdWdpbiIsImFkZEljb24iLCJkZWJvdW5jZSIsIk5vdGljZSIsImRpZmZfbWF0Y2hfcGF0Y2giLCJNb2RhbCIsIkRJRkZfREVMRVRFIiwiRElGRl9FUVVBTCIsIkRJRkZfSU5TRVJUIiwiUGx1Z2luU2V0dGluZ1RhYiIsIlNldHRpbmciXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUF1REE7QUFDTyxTQUFTLFNBQVMsQ0FBQyxPQUFPLEVBQUUsVUFBVSxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUU7QUFDN0QsSUFBSSxTQUFTLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxPQUFPLEtBQUssWUFBWSxDQUFDLEdBQUcsS0FBSyxHQUFHLElBQUksQ0FBQyxDQUFDLFVBQVUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUU7QUFDaEgsSUFBSSxPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sRUFBRSxNQUFNLEVBQUU7QUFDL0QsUUFBUSxTQUFTLFNBQVMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO0FBQ25HLFFBQVEsU0FBUyxRQUFRLENBQUMsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO0FBQ3RHLFFBQVEsU0FBUyxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsTUFBTSxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQyxFQUFFO0FBQ3RILFFBQVEsSUFBSSxDQUFDLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLFVBQVUsSUFBSSxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQzlFLEtBQUssQ0FBQyxDQUFDO0FBQ1A7O0FDN0VBLElBQUlBLEdBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsT0FBTyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxRQUFRLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsT0FBTyxNQUFNLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLElBQUksT0FBTyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQyxNQUFNLElBQUksU0FBUyxDQUFDLGtFQUFrRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLFNBQVM
Line truncated
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
import { App, debounce, Modal, Notice, Plugin, PluginSettingTab, Setting, TFile, addIcon, TFolder } from "obsidian";
|
import { App, debounce, Modal, Notice, Plugin, PluginSettingTab, Setting, TFile, addIcon, TFolder } from "obsidian";
|
||||||
import { PouchDB } from "./pouchdb-browser-webpack/dist/pouchdb-browser";
|
import { PouchDB } from "./pouchdb-browser-webpack/dist/pouchdb-browser";
|
||||||
import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diff_match_patch } from "diff-match-patch";
|
import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diff_match_patch } from "diff-match-patch";
|
||||||
|
import xxhash from "xxhash-wasm";
|
||||||
|
|
||||||
// docs should be encoded as base64, so 1 char -> 1 bytes
|
// docs should be encoded as base64, so 1 char -> 1 bytes
|
||||||
// and cloudant limitation is 1MB , we use 900kb;
|
// and cloudant limitation is 1MB , we use 900kb;
|
||||||
// const MAX_DOC_SIZE = 921600;
|
// const MAX_DOC_SIZE = 921600;
|
||||||
const MAX_DOC_SIZE = 921600;
|
const MAX_DOC_SIZE = 200; // for .md file
|
||||||
|
const MAX_DOC_SIZE_BIN = 102400; // 100kb
|
||||||
|
|
||||||
interface ObsidianLiveSyncSettings {
|
interface ObsidianLiveSyncSettings {
|
||||||
couchDB_URI: string;
|
couchDB_URI: string;
|
||||||
@@ -16,6 +18,7 @@ interface ObsidianLiveSyncSettings {
|
|||||||
syncOnStart: boolean;
|
syncOnStart: boolean;
|
||||||
savingDelay: number;
|
savingDelay: number;
|
||||||
lessInformationInLog: boolean;
|
lessInformationInLog: boolean;
|
||||||
|
gcDelay: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_SETTINGS: ObsidianLiveSyncSettings = {
|
const DEFAULT_SETTINGS: ObsidianLiveSyncSettings = {
|
||||||
@@ -27,6 +30,7 @@ const DEFAULT_SETTINGS: ObsidianLiveSyncSettings = {
|
|||||||
syncOnStart: false,
|
syncOnStart: false,
|
||||||
savingDelay: 200,
|
savingDelay: 200,
|
||||||
lessInformationInLog: false,
|
lessInformationInLog: false,
|
||||||
|
gcDelay: 30,
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Entry {
|
interface Entry {
|
||||||
@@ -56,13 +60,11 @@ type LoadedEntry = Entry & {
|
|||||||
|
|
||||||
interface EntryLeaf {
|
interface EntryLeaf {
|
||||||
_id: string;
|
_id: string;
|
||||||
parent: string;
|
|
||||||
seq: number;
|
|
||||||
data: string;
|
data: string;
|
||||||
_rev?: string;
|
|
||||||
_deleted?: boolean;
|
_deleted?: boolean;
|
||||||
type: "leaf";
|
type: "leaf";
|
||||||
}
|
}
|
||||||
|
|
||||||
type EntryDoc = Entry | NewEntry | LoadedEntry | EntryLeaf;
|
type EntryDoc = Entry | NewEntry | LoadedEntry | EntryLeaf;
|
||||||
type diff_result_leaf = {
|
type diff_result_leaf = {
|
||||||
rev: string;
|
rev: string;
|
||||||
@@ -164,6 +166,8 @@ class LocalPouchDB {
|
|||||||
addLog: (message: any, isNotify?: boolean) => Promise<void>;
|
addLog: (message: any, isNotify?: boolean) => Promise<void>;
|
||||||
localDatabase: PouchDB.Database<EntryDoc>;
|
localDatabase: PouchDB.Database<EntryDoc>;
|
||||||
|
|
||||||
|
h32: (input: string, seed?: number) => string;
|
||||||
|
h64: (input: string, seedHigh?: number, seedLow?: number) => string;
|
||||||
constructor(app: App, plugin: ObsidianLiveSyncPlugin, dbname: string) {
|
constructor(app: App, plugin: ObsidianLiveSyncPlugin, dbname: string) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.app = app;
|
this.app = app;
|
||||||
@@ -185,7 +189,7 @@ class LocalPouchDB {
|
|||||||
}
|
}
|
||||||
return "disabled";
|
return "disabled";
|
||||||
}
|
}
|
||||||
initializeDatabase() {
|
async initializeDatabase() {
|
||||||
if (this.localDatabase != null) this.localDatabase.close();
|
if (this.localDatabase != null) this.localDatabase.close();
|
||||||
this.localDatabase = null;
|
this.localDatabase = null;
|
||||||
this.localDatabase = new PouchDB<EntryDoc>(this.dbname + "-livesync", {
|
this.localDatabase = new PouchDB<EntryDoc>(this.dbname + "-livesync", {
|
||||||
@@ -193,8 +197,14 @@ class LocalPouchDB {
|
|||||||
revs_limit: 100,
|
revs_limit: 100,
|
||||||
deterministic_revs: true,
|
deterministic_revs: true,
|
||||||
});
|
});
|
||||||
|
await this.prepareHashArg();
|
||||||
|
}
|
||||||
|
async prepareHashArg() {
|
||||||
|
if (this.h32 != null) return;
|
||||||
|
const { h32, h64 } = await xxhash();
|
||||||
|
this.h32 = h32;
|
||||||
|
this.h64 = h64;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDatabaseDoc(id: string, opt?: any): Promise<false | LoadedEntry> {
|
async getDatabaseDoc(id: string, opt?: any): Promise<false | LoadedEntry> {
|
||||||
try {
|
try {
|
||||||
let obj: EntryDoc & PouchDB.Core.IdMeta & PouchDB.Core.GetMeta = null;
|
let obj: EntryDoc & PouchDB.Core.IdMeta & PouchDB.Core.GetMeta = null;
|
||||||
@@ -229,23 +239,16 @@ class LocalPouchDB {
|
|||||||
// search childrens
|
// search childrens
|
||||||
try {
|
try {
|
||||||
let childrens = [];
|
let childrens = [];
|
||||||
// let childPromise = [];
|
|
||||||
for (var v of obj.children) {
|
for (var v of obj.children) {
|
||||||
// childPromise.push(this.localDatabase.get(v));
|
// childPromise.push(this.localDatabase.get(v));
|
||||||
let elem = await this.localDatabase.get(v);
|
let elem = await this.localDatabase.get(v);
|
||||||
if (elem.type && elem.type == "leaf") {
|
if (elem.type && elem.type == "leaf") {
|
||||||
childrens.push(elem);
|
childrens.push(elem.data);
|
||||||
} else {
|
} else {
|
||||||
throw new Error("linked document is not leaf");
|
throw new Error("linked document is not leaf");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// let childrens = await Promise.all(childPromise);
|
let data = childrens.join("");
|
||||||
let data = childrens
|
|
||||||
// .filter((e) => e.type == "leaf")
|
|
||||||
// .map((e) => e as NoteLeaf)
|
|
||||||
.sort((e) => e.seq)
|
|
||||||
.map((e) => e.data)
|
|
||||||
.join("");
|
|
||||||
let doc: LoadedEntry = {
|
let doc: LoadedEntry = {
|
||||||
data: data,
|
data: data,
|
||||||
_id: obj._id,
|
_id: obj._id,
|
||||||
@@ -261,6 +264,7 @@ class LocalPouchDB {
|
|||||||
if (ex.status && ex.status == 404) {
|
if (ex.status && ex.status == 404) {
|
||||||
this.addLog(`Missing document content!, could not read ${obj._id} from database.`, true);
|
this.addLog(`Missing document content!, could not read ${obj._id} from database.`, true);
|
||||||
// this.addLog(ex);
|
// this.addLog(ex);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
this.addLog(`Something went wrong on reading ${obj._id} from database.`, true);
|
this.addLog(`Something went wrong on reading ${obj._id} from database.`, true);
|
||||||
this.addLog(ex);
|
this.addLog(ex);
|
||||||
@@ -289,24 +293,12 @@ class LocalPouchDB {
|
|||||||
}
|
}
|
||||||
//Check it out and fix docs to regular case
|
//Check it out and fix docs to regular case
|
||||||
if (!obj.type || (obj.type && obj.type == "notes")) {
|
if (!obj.type || (obj.type && obj.type == "notes")) {
|
||||||
// let note = obj as Notes;
|
|
||||||
// note._deleted=true;
|
|
||||||
obj._deleted = true;
|
obj._deleted = true;
|
||||||
let r = await this.localDatabase.put(obj);
|
let r = await this.localDatabase.put(obj);
|
||||||
return true;
|
return true;
|
||||||
// simple note
|
// simple note
|
||||||
}
|
}
|
||||||
if (obj.type == "newnote") {
|
if (obj.type == "newnote") {
|
||||||
// search childrens
|
|
||||||
for (var v of obj.children) {
|
|
||||||
let d = await this.localDatabase.get(v);
|
|
||||||
if (d.type != "leaf") {
|
|
||||||
this.addLog(`structure went wrong:${id}-${v}`);
|
|
||||||
}
|
|
||||||
d._deleted = true;
|
|
||||||
await this.localDatabase.put(d);
|
|
||||||
this.addLog(`content removed:${(d as EntryLeaf).seq}`);
|
|
||||||
}
|
|
||||||
obj._deleted = true;
|
obj._deleted = true;
|
||||||
await this.localDatabase.put(obj);
|
await this.localDatabase.put(obj);
|
||||||
this.addLog(`entry removed:${obj._id}`);
|
this.addLog(`entry removed:${obj._id}`);
|
||||||
@@ -322,25 +314,79 @@ class LocalPouchDB {
|
|||||||
|
|
||||||
async putDBEntry(note: LoadedEntry) {
|
async putDBEntry(note: LoadedEntry) {
|
||||||
let leftData = note.data;
|
let leftData = note.data;
|
||||||
let savenNotes = []; // something occured, kill this .
|
let savenNotes = [];
|
||||||
let seq = 0;
|
let processed = 0;
|
||||||
let now = Date.now();
|
let made = 0;
|
||||||
|
let skiped = 0;
|
||||||
|
let pieceSize = MAX_DOC_SIZE;
|
||||||
|
if (!note._id.endsWith(".md")) {
|
||||||
|
pieceSize = MAX_DOC_SIZE_BIN;
|
||||||
|
}
|
||||||
do {
|
do {
|
||||||
let piece = leftData.substring(0, MAX_DOC_SIZE);
|
// To keep low bandwith and database size,
|
||||||
leftData = leftData.substring(MAX_DOC_SIZE);
|
// Dedup pieces on database.
|
||||||
seq++;
|
let piece = leftData.substring(0, pieceSize);
|
||||||
let leafid = note._id + "-" + now + "-" + seq;
|
leftData = leftData.substring(pieceSize);
|
||||||
let d: EntryLeaf = {
|
processed++;
|
||||||
_id: leafid,
|
// Get has of piece.
|
||||||
parent: note._id,
|
let hashedPiece = this.h32(piece);
|
||||||
data: piece,
|
let leafid = "h:" + hashedPiece;
|
||||||
seq: seq,
|
let hashQ: number = 0; // if hash collided, **IF**, count it up.
|
||||||
type: "leaf",
|
let tryNextHash = false;
|
||||||
};
|
let needMake = true;
|
||||||
let result = await this.localDatabase.put(d);
|
|
||||||
|
do {
|
||||||
|
let nleafid = leafid;
|
||||||
|
try {
|
||||||
|
nleafid = `${leafid}${hashQ}`;
|
||||||
|
// console.log(nleafid);
|
||||||
|
let pieceData = await this.localDatabase.get<EntryLeaf>(nleafid);
|
||||||
|
if (pieceData.type == "leaf" && pieceData.data == piece) {
|
||||||
|
this.addLog("hashe:data exists.");
|
||||||
|
leafid = nleafid;
|
||||||
|
needMake = false;
|
||||||
|
tryNextHash = false;
|
||||||
|
} else if (pieceData.type == "leaf") {
|
||||||
|
this.addLog("hash:collision!!");
|
||||||
|
hashQ++;
|
||||||
|
tryNextHash = true;
|
||||||
|
} else {
|
||||||
|
this.addLog("hash:no collision, it's not leaf. what's going on..");
|
||||||
|
leafid = nleafid;
|
||||||
|
tryNextHash = false;
|
||||||
|
}
|
||||||
|
} catch (ex) {
|
||||||
|
if (ex.status && ex.status == 404) {
|
||||||
|
//not found, we can use it.
|
||||||
|
this.addLog(`hash:not found.`);
|
||||||
|
leafid = nleafid;
|
||||||
|
needMake = true;
|
||||||
|
} else {
|
||||||
|
needMake = false;
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (tryNextHash);
|
||||||
|
if (needMake) {
|
||||||
|
//have to make
|
||||||
|
let d: EntryLeaf = {
|
||||||
|
_id: leafid,
|
||||||
|
data: piece,
|
||||||
|
type: "leaf",
|
||||||
|
};
|
||||||
|
let result = await this.localDatabase.put(d);
|
||||||
|
if (result.ok) {
|
||||||
|
this.addLog(`ok:saven`);
|
||||||
|
made++;
|
||||||
|
} else {
|
||||||
|
this.addLog("save faild");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
skiped++;
|
||||||
|
}
|
||||||
savenNotes.push(leafid);
|
savenNotes.push(leafid);
|
||||||
} while (leftData != "");
|
} while (leftData != "");
|
||||||
this.addLog(`note content saven, pieces:${seq}`);
|
this.addLog(`note content saven, pieces:${processed} new:${made}, skip:${skiped}`);
|
||||||
let newDoc: NewEntry = {
|
let newDoc: NewEntry = {
|
||||||
NewNote: true,
|
NewNote: true,
|
||||||
children: savenNotes,
|
children: savenNotes,
|
||||||
@@ -355,15 +401,10 @@ class LocalPouchDB {
|
|||||||
// Here for upsert logic,
|
// Here for upsert logic,
|
||||||
try {
|
try {
|
||||||
let old = await this.localDatabase.get(newDoc._id);
|
let old = await this.localDatabase.get(newDoc._id);
|
||||||
if (!old.type || old.type == "notes") {
|
if (!old.type || old.type == "notes" || old.type == "newnote") {
|
||||||
// simple use rev for new doc
|
// simple use rev for new doc
|
||||||
newDoc._rev = old._rev;
|
newDoc._rev = old._rev;
|
||||||
}
|
}
|
||||||
if (old.type == "newnote") {
|
|
||||||
//when save finished, we have to garbage collect.
|
|
||||||
deldocs = old.children;
|
|
||||||
newDoc._rev = old._rev;
|
|
||||||
}
|
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (ex.status && ex.status == 404) {
|
if (ex.status && ex.status == 404) {
|
||||||
// NO OP/
|
// NO OP/
|
||||||
@@ -373,15 +414,6 @@ class LocalPouchDB {
|
|||||||
}
|
}
|
||||||
await this.localDatabase.put(newDoc);
|
await this.localDatabase.put(newDoc);
|
||||||
this.addLog(`note saven:${newDoc._id}`);
|
this.addLog(`note saven:${newDoc._id}`);
|
||||||
let items = 0;
|
|
||||||
for (var v of deldocs) {
|
|
||||||
items++;
|
|
||||||
//TODO: Check for missing link
|
|
||||||
let d = await this.localDatabase.get(v);
|
|
||||||
d._deleted = true;
|
|
||||||
await this.localDatabase.put(d);
|
|
||||||
}
|
|
||||||
this.addLog(`old content deleted, pieces:${items}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
syncHandler: PouchDB.Replication.Sync<{}> = null;
|
syncHandler: PouchDB.Replication.Sync<{}> = null;
|
||||||
@@ -506,6 +538,53 @@ class LocalPouchDB {
|
|||||||
if (con2 === false) return;
|
if (con2 === false) return;
|
||||||
this.addLog("Remote Database Created or Connected", true);
|
this.addLog("Remote Database Created or Connected", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async garbageCollect() {
|
||||||
|
// get all documents of NewEntry2
|
||||||
|
// we don't use queries , just use allDocs();
|
||||||
|
let c = 0;
|
||||||
|
let readCount = 0;
|
||||||
|
let hashPieces: string[] = [];
|
||||||
|
let usedPieces: string[] = [];
|
||||||
|
do {
|
||||||
|
let result = await this.localDatabase.allDocs({ include_docs: true, skip: c, limit: 100 });
|
||||||
|
readCount = result.rows.length;
|
||||||
|
if (readCount > 0) {
|
||||||
|
//there are some result
|
||||||
|
for (let v of result.rows) {
|
||||||
|
let doc = v.doc;
|
||||||
|
if (doc.type == "newnote") {
|
||||||
|
// used pieces memo.
|
||||||
|
usedPieces = Array.from(new Set([...usedPieces, ...doc.children]));
|
||||||
|
}
|
||||||
|
if (doc.type == "leaf") {
|
||||||
|
// all pieces.
|
||||||
|
hashPieces = Array.from(new Set([...hashPieces, doc._id]));
|
||||||
|
}
|
||||||
|
// this.addLog(`GC:processed:${v.doc._id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c += readCount;
|
||||||
|
} while (readCount != 0);
|
||||||
|
// items collected.
|
||||||
|
const garbages = hashPieces.filter((e) => usedPieces.indexOf(e) == -1);
|
||||||
|
let deleteCount = 0;
|
||||||
|
for (let v of garbages) {
|
||||||
|
try {
|
||||||
|
let item = await this.localDatabase.get(v);
|
||||||
|
item._deleted = true;
|
||||||
|
await this.localDatabase.put(item);
|
||||||
|
deleteCount++;
|
||||||
|
} catch (ex) {
|
||||||
|
if (ex.status && ex.status == 404) {
|
||||||
|
// NO OP. It should be timing problem.
|
||||||
|
} else {
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.addLog(`GC:deleted ${deleteCount} items.`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class ObsidianLiveSyncPlugin extends Plugin {
|
export default class ObsidianLiveSyncPlugin extends Plugin {
|
||||||
@@ -585,10 +664,14 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onunload() {
|
onunload() {
|
||||||
|
if (this.gcTimerHandler != null) {
|
||||||
|
clearTimeout(this.gcTimerHandler);
|
||||||
|
this.gcTimerHandler = null;
|
||||||
|
}
|
||||||
this.localDatabase.closeReplication();
|
this.localDatabase.closeReplication();
|
||||||
this.localDatabase.close();
|
this.localDatabase.close();
|
||||||
this.addLog("unloading plugin");
|
|
||||||
window.removeEventListener("visibilitychange", this.watchWindowVisiblity);
|
window.removeEventListener("visibilitychange", this.watchWindowVisiblity);
|
||||||
|
this.addLog("unloading plugin");
|
||||||
}
|
}
|
||||||
|
|
||||||
async openDatabase() {
|
async openDatabase() {
|
||||||
@@ -597,7 +680,10 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
let vaultName = this.app.vault.getName();
|
let vaultName = this.app.vault.getName();
|
||||||
this.localDatabase = new LocalPouchDB(this.app, this, vaultName);
|
this.localDatabase = new LocalPouchDB(this.app, this, vaultName);
|
||||||
this.localDatabase.initializeDatabase();
|
await this.localDatabase.initializeDatabase();
|
||||||
|
}
|
||||||
|
async garbageCollect() {
|
||||||
|
await this.localDatabase.garbageCollect();
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadSettings() {
|
async loadSettings() {
|
||||||
@@ -607,7 +693,19 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
async saveSettings() {
|
async saveSettings() {
|
||||||
await this.saveData(this.settings);
|
await this.saveData(this.settings);
|
||||||
}
|
}
|
||||||
|
gcTimerHandler: any = null;
|
||||||
|
gcHook() {
|
||||||
|
if (this.settings.gcDelay == 0) return;
|
||||||
|
const GC_DELAY = this.settings.gcDelay * 1000; // if leaving opening window, try GC,
|
||||||
|
if (this.gcTimerHandler != null) {
|
||||||
|
clearTimeout(this.gcTimerHandler);
|
||||||
|
this.gcTimerHandler = null;
|
||||||
|
}
|
||||||
|
this.gcTimerHandler = setTimeout(() => {
|
||||||
|
this.gcTimerHandler = null;
|
||||||
|
this.garbageCollect();
|
||||||
|
}, GC_DELAY);
|
||||||
|
}
|
||||||
registerWatchEvents() {
|
registerWatchEvents() {
|
||||||
this.registerEvent(this.app.vault.on("modify", this.watchVaultChange));
|
this.registerEvent(this.app.vault.on("modify", this.watchVaultChange));
|
||||||
this.registerEvent(this.app.vault.on("delete", this.watchVaultDelete));
|
this.registerEvent(this.app.vault.on("delete", this.watchVaultDelete));
|
||||||
@@ -630,14 +728,17 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
this.localDatabase.openReplication(this.settings, false, false, this.parseReplicationResult);
|
this.localDatabase.openReplication(this.settings, false, false, this.parseReplicationResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.gcHook();
|
||||||
}
|
}
|
||||||
|
|
||||||
watchWorkspaceOpen(file: TFile) {
|
watchWorkspaceOpen(file: TFile) {
|
||||||
if (file == null) return;
|
if (file == null) return;
|
||||||
this.showIfConflicted(file);
|
this.showIfConflicted(file);
|
||||||
|
this.gcHook();
|
||||||
}
|
}
|
||||||
watchVaultChange(file: TFile, ...args: any[]) {
|
watchVaultChange(file: TFile, ...args: any[]) {
|
||||||
this.updateIntoDB(file);
|
this.updateIntoDB(file);
|
||||||
|
this.gcHook();
|
||||||
}
|
}
|
||||||
watchVaultDelete(file: TFile & TFolder) {
|
watchVaultDelete(file: TFile & TFolder) {
|
||||||
if (file.children) {
|
if (file.children) {
|
||||||
@@ -647,6 +748,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
} else {
|
} else {
|
||||||
this.deleteFromDB(file);
|
this.deleteFromDB(file);
|
||||||
}
|
}
|
||||||
|
this.gcHook();
|
||||||
}
|
}
|
||||||
watchVaultRename(file: TFile & TFolder, oldFile: any) {
|
watchVaultRename(file: TFile & TFolder, oldFile: any) {
|
||||||
if (file.children) {
|
if (file.children) {
|
||||||
@@ -656,6 +758,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
this.updateIntoDB(file);
|
this.updateIntoDB(file);
|
||||||
this.deleteFromDBbyPath(oldFile);
|
this.deleteFromDBbyPath(oldFile);
|
||||||
}
|
}
|
||||||
|
this.gcHook();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--> Basic document Functions
|
//--> Basic document Functions
|
||||||
@@ -1242,6 +1345,23 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
});
|
});
|
||||||
text.inputEl.setAttribute("type", "number");
|
text.inputEl.setAttribute("type", "number");
|
||||||
});
|
});
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName("Auto GC delay")
|
||||||
|
.setDesc("(seconds), if you set zero, you have to run manually.")
|
||||||
|
.addText((text) => {
|
||||||
|
text.setPlaceholder("")
|
||||||
|
.setValue(this.plugin.settings.gcDelay + "")
|
||||||
|
.onChange(async (value) => {
|
||||||
|
let v = Number(value);
|
||||||
|
if (isNaN(v) || v < 200 || v > 5000) {
|
||||||
|
return 30;
|
||||||
|
//text.inputEl.va;
|
||||||
|
}
|
||||||
|
this.plugin.settings.gcDelay = v;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
});
|
||||||
|
text.inputEl.setAttribute("type", "number");
|
||||||
|
});
|
||||||
new Setting(containerEl)
|
new Setting(containerEl)
|
||||||
.setName("Log")
|
.setName("Log")
|
||||||
.setDesc("Reduce log infomations")
|
.setDesc("Reduce log infomations")
|
||||||
@@ -1298,6 +1418,25 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
//await this.test();
|
//await this.test();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName("Garbage Collect")
|
||||||
|
.addButton((button) =>
|
||||||
|
button
|
||||||
|
.setButtonText("Garbage Collection")
|
||||||
|
.setDisabled(false)
|
||||||
|
.onClick(async () => {
|
||||||
|
await this.plugin.garbageCollect();
|
||||||
|
//await this.test();
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.addButton((button) =>
|
||||||
|
button
|
||||||
|
.setButtonText("Reset local files")
|
||||||
|
.setDisabled(false)
|
||||||
|
.onClick(async () => {
|
||||||
|
//await this.test();
|
||||||
|
})
|
||||||
|
);
|
||||||
new Setting(containerEl).setName("Remote Database Operations").addButton((button) =>
|
new Setting(containerEl).setName("Remote Database Operations").addButton((button) =>
|
||||||
button
|
button
|
||||||
.setButtonText("Reset remote database")
|
.setButtonText("Reset remote database")
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "obsidian-livesync",
|
"id": "obsidian-livesync",
|
||||||
"name": "Obsidian Live sync",
|
"name": "Obsidian Live sync",
|
||||||
"version": "0.0.7",
|
"version": "0.0.8",
|
||||||
"minAppVersion": "0.9.12",
|
"minAppVersion": "0.9.12",
|
||||||
"description": "obsidian Live synchronization plugin.",
|
"description": "obsidian Live synchronization plugin.",
|
||||||
"author": "vorotamoroz",
|
"author": "vorotamoroz",
|
||||||
|
|||||||
Generated
+14
-3
@@ -1,15 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "0.0.6",
|
"version": "0.0.8",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "0.0.6",
|
"version": "0.0.8",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"diff-match-patch": "^1.0.5"
|
"diff-match-patch": "^1.0.5",
|
||||||
|
"xxhash-wasm": "^0.4.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-commonjs": "^18.0.0",
|
"@rollup/plugin-commonjs": "^18.0.0",
|
||||||
@@ -539,6 +540,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/xxhash-wasm": {
|
||||||
|
"version": "0.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-0.4.2.tgz",
|
||||||
|
"integrity": "sha512-/eyHVRJQCirEkSZ1agRSCwriMhwlyUcFkXD5TPVSLP+IPzjsqMVzZwdoczLp1SoQU0R3dxz1RpIK+4YNQbCVOA=="
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -975,6 +981,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
},
|
||||||
|
"xxhash-wasm": {
|
||||||
|
"version": "0.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-0.4.2.tgz",
|
||||||
|
"integrity": "sha512-/eyHVRJQCirEkSZ1agRSCwriMhwlyUcFkXD5TPVSLP+IPzjsqMVzZwdoczLp1SoQU0R3dxz1RpIK+4YNQbCVOA=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "0.0.7",
|
"version": "0.0.8",
|
||||||
"description": "obsidian Live synchronization plugin.",
|
"description": "obsidian Live synchronization plugin.",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
"typescript": "^4.2.4"
|
"typescript": "^4.2.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"diff-match-patch": "^1.0.5"
|
"diff-match-patch": "^1.0.5",
|
||||||
|
"xxhash-wasm": "^0.4.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user