trew-sync 0.12.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/trew.mjs +26 -26
  2. package/package.json +7 -3
package/dist/trew.mjs CHANGED
@@ -1,30 +1,30 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __trewRequire } from "node:module"; const require = __trewRequire(import.meta.url);
3
- var Fa=Object.create;var fi=Object.defineProperty;var xa=Object.getOwnPropertyDescriptor;var Ba=Object.getOwnPropertyNames;var $a=Object.getPrototypeOf,Pa=Object.prototype.hasOwnProperty;var Da=(n,e,t)=>()=>{if(t)throw t[0];try{return n&&(e=n(n=0)),e}catch(r){throw t=[r],r}};var Ta=(n,e)=>()=>{try{return e||n((e={exports:{}}).exports,e),e.exports}catch(t){throw e=0,t}};var Ra=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ba(e))!Pa.call(n,i)&&i!==t&&fi(n,i,{get:()=>e[i],enumerable:!(r=xa(e,i))||r.enumerable});return n};var gi=(n,e,t)=>(t=n!=null?Fa($a(n)):{},Ra(e||!n||!n.__esModule?fi(t,"default",{value:n,enumerable:!0}):t,n));function pi(){let n=globalThis.crypto;if(!n?.subtle)throw new Error("WebCrypto is unavailable, so this device cannot name what it sends");return n.subtle}function It(n){let e=globalThis.crypto;if(!e?.getRandomValues)throw new Error("no secure random source is available, so no credential can be made here");return e.getRandomValues(new Uint8Array(n))}async function We(n){let e=await pi().digest("SHA-256",n);return mi(new Uint8Array(e))}async function gn(n,e=Ia){let t=[];for(let r=0;r<n.length;r+=e){let i=await Promise.all(n.slice(r,r+e).map(s=>We(s)));for(let s of i)t.push(s)}return t}async function Ee(n){return mi(new Uint8Array(await pi().digest("SHA-256",n)))}function pt(n){return typeof n=="string"&&/^[0-9a-f]{64}$/.test(n)}function mi(n){let e="";for(let t of n)e+=t.toString(16).padStart(2,"0");return e}function Je(n){let e="";for(let t=0;t<n.length;t+=3){let r=n[t],i=t+1<n.length?n[t+1]:void 0,s=t+2<n.length?n[t+2]:void 0;if(e+=gt[r>>2],e+=gt[(r&3)<<4|(i??0)>>4],i===void 0||(e+=gt[(i&15)<<2|(s??0)>>6],s===void 0))break;e+=gt[s&63]}return e}function je(n){let e=n.length,t=new Uint8Array(Math.floor(e*3/4)),r=0,i=0,s=0;for(let o=0;o<e;o++){let a=n.charCodeAt(o),d=a<128?Oa[a]:-1;if(d<0)throw new Error(`invalid base64url character ${JSON.stringify(n[o])} at position ${o}`);i=i<<6|d,s+=6,s>=8&&(s-=8,t[r++]=i>>s&255)}if(s===6)throw new Error(`this base64url value is ${e} characters, which is one more than a whole number of bytes: the last character adds no byte and something has been added to it or lost from it`);if(s>0&&(i&(1<<s)-1)!==0)throw new Error(`this base64url value ends with ${s} bits that no byte uses, and they are not zero, so it is not the encoding of the bytes it decodes to`);return t.subarray(0,r)}var Ia,gt,Oa,Re=Da(()=>{"use strict";Ia=16;gt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";Oa=(()=>{let n=new Int16Array(128).fill(-1);for(let e=0;e<gt.length;e++)n[gt.charCodeAt(e)]=e;return n})()});var sr=Ta((Dh,mt)=>{var E=function(){this.Diff_Timeout=1,this.Diff_EditCost=4,this.Match_Threshold=.5,this.Match_Distance=1e3,this.Patch_DeleteThreshold=.5,this.Patch_Margin=4,this.Match_MaxBits=32},M=-1,N=1,P=0;E.Diff=function(n,e){return[n,e]};E.prototype.diff_main=function(n,e,t,r){typeof r>"u"&&(this.Diff_Timeout<=0?r=Number.MAX_VALUE:r=new Date().getTime()+this.Diff_Timeout*1e3);var i=r;if(n==null||e==null)throw new Error("Null input. (diff_main)");if(n==e)return n?[new E.Diff(P,n)]:[];typeof t>"u"&&(t=!0);var s=t,o=this.diff_commonPrefix(n,e),a=n.substring(0,o);n=n.substring(o),e=e.substring(o),o=this.diff_commonSuffix(n,e);var d=n.substring(n.length-o);n=n.substring(0,n.length-o),e=e.substring(0,e.length-o);var c=this.diff_compute_(n,e,s,i);return a&&c.unshift(new E.Diff(P,a)),d&&c.push(new E.Diff(P,d)),this.diff_cleanupMerge(c),c};E.prototype.diff_compute_=function(n,e,t,r){var i;if(!n)return[new E.Diff(N,e)];if(!e)return[new E.Diff(M,n)];var s=n.length>e.length?n:e,o=n.length>e.length?e:n,a=s.indexOf(o);if(a!=-1)return i=[new E.Diff(N,s.substring(0,a)),new E.Diff(P,o),new E.Diff(N,s.substring(a+o.length))],n.length>e.length&&(i[0][0]=i[2][0]=M),i;if(o.length==1)return[new E.Diff(M,n),new E.Diff(N,e)];var d=this.diff_halfMatch_(n,e);if(d){var c=d[0],l=d[1],h=d[2],u=d[3],f=d[4],g=this.diff_main(c,h,t,r),m=this.diff_main(l,u,t,r);return g.concat([new E.Diff(P,f)],m)}return t&&n.length>100&&e.length>100?this.diff_lineMode_(n,e,r):this.diff_bisect_(n,e,r)};E.prototype.diff_lineMode_=function(n,e,t){var r=this.diff_linesToChars_(n,e);n=r.chars1,e=r.chars2;var i=r.lineArray,s=this.diff_main(n,e,!1,t);this.diff_charsToLines_(s,i),this.diff_cleanupSemantic(s),s.push(new E.Diff(P,""));for(var o=0,a=0,d=0,c="",l="";o<s.length;){switch(s[o][0]){case N:d++,l+=s[o][1];break;case M:a++,c+=s[o][1];break;case P:if(a>=1&&d>=1){s.splice(o-a-d,a+d),o=o-a-d;for(var h=this.diff_main(c,l,!1,t),u=h.length-1;u>=0;u--)s.splice(o,0,h[u]);o=o+h.length}d=0,a=0,c="",l="";break}o++}return s.pop(),s};E.prototype.diff_bisect_=function(n,e,t){for(var r=n.length,i=e.length,s=Math.ceil((r+i)/2),o=s,a=2*s,d=new Array(a),c=new Array(a),l=0;l<a;l++)d[l]=-1,c[l]=-1;d[o+1]=0,c[o+1]=0;for(var h=r-i,u=h%2!=0,f=0,g=0,m=0,y=0,w=0;w<s&&!(new Date().getTime()>t);w++){for(var b=-w+f;b<=w-g;b+=2){var k=o+b,S;b==-w||b!=w&&d[k-1]<d[k+1]?S=d[k+1]:S=d[k-1]+1;for(var v=S-b;S<r&&v<i&&n.charAt(S)==e.charAt(v);)S++,v++;if(d[k]=S,S>r)g+=2;else if(v>i)f+=2;else if(u){var A=o+h-b;if(A>=0&&A<a&&c[A]!=-1){var F=r-c[A];if(S>=F)return this.diff_bisectSplit_(n,e,S,v,t)}}}for(var x=-w+m;x<=w-y;x+=2){var A=o+x,F;x==-w||x!=w&&c[A-1]<c[A+1]?F=c[A+1]:F=c[A-1]+1;for(var p=F-x;F<r&&p<i&&n.charAt(r-F-1)==e.charAt(i-p-1);)F++,p++;if(c[A]=F,F>r)y+=2;else if(p>i)m+=2;else if(!u){var k=o+h-x;if(k>=0&&k<a&&d[k]!=-1){var S=d[k],v=o+S-k;if(F=r-F,S>=F)return this.diff_bisectSplit_(n,e,S,v,t)}}}}return[new E.Diff(M,n),new E.Diff(N,e)]};E.prototype.diff_bisectSplit_=function(n,e,t,r,i){var s=n.substring(0,t),o=e.substring(0,r),a=n.substring(t),d=e.substring(r),c=this.diff_main(s,o,!1,i),l=this.diff_main(a,d,!1,i);return c.concat(l)};E.prototype.diff_linesToChars_=function(n,e){var t=[],r={};t[0]="";function i(d){for(var c="",l=0,h=-1,u=t.length;h<d.length-1;){h=d.indexOf(`
4
- `,l),h==-1&&(h=d.length-1);var f=d.substring(l,h+1);(r.hasOwnProperty?r.hasOwnProperty(f):r[f]!==void 0)?c+=String.fromCharCode(r[f]):(u==s&&(f=d.substring(l),h=d.length),c+=String.fromCharCode(u),r[f]=u,t[u++]=f),l=h+1}return c}var s=4e4,o=i(n);s=65535;var a=i(e);return{chars1:o,chars2:a,lineArray:t}};E.prototype.diff_charsToLines_=function(n,e){for(var t=0;t<n.length;t++){for(var r=n[t][1],i=[],s=0;s<r.length;s++)i[s]=e[r.charCodeAt(s)];n[t][1]=i.join("")}};E.prototype.diff_commonPrefix=function(n,e){if(!n||!e||n.charAt(0)!=e.charAt(0))return 0;for(var t=0,r=Math.min(n.length,e.length),i=r,s=0;t<i;)n.substring(s,i)==e.substring(s,i)?(t=i,s=t):r=i,i=Math.floor((r-t)/2+t);return i};E.prototype.diff_commonSuffix=function(n,e){if(!n||!e||n.charAt(n.length-1)!=e.charAt(e.length-1))return 0;for(var t=0,r=Math.min(n.length,e.length),i=r,s=0;t<i;)n.substring(n.length-i,n.length-s)==e.substring(e.length-i,e.length-s)?(t=i,s=t):r=i,i=Math.floor((r-t)/2+t);return i};E.prototype.diff_commonOverlap_=function(n,e){var t=n.length,r=e.length;if(t==0||r==0)return 0;t>r?n=n.substring(t-r):t<r&&(e=e.substring(0,t));var i=Math.min(t,r);if(n==e)return i;for(var s=0,o=1;;){var a=n.substring(i-o),d=e.indexOf(a);if(d==-1)return s;o+=d,(d==0||n.substring(i-o)==e.substring(0,o))&&(s=o,o++)}};E.prototype.diff_halfMatch_=function(n,e){if(this.Diff_Timeout<=0)return null;var t=n.length>e.length?n:e,r=n.length>e.length?e:n;if(t.length<4||r.length*2<t.length)return null;var i=this;function s(g,m,y){for(var w=g.substring(y,y+Math.floor(g.length/4)),b=-1,k="",S,v,A,F;(b=m.indexOf(w,b+1))!=-1;){var x=i.diff_commonPrefix(g.substring(y),m.substring(b)),p=i.diff_commonSuffix(g.substring(0,y),m.substring(0,b));k.length<p+x&&(k=m.substring(b-p,b)+m.substring(b,b+x),S=g.substring(0,y-p),v=g.substring(y+x),A=m.substring(0,b-p),F=m.substring(b+x))}return k.length*2>=g.length?[S,v,A,F,k]:null}var o=s(t,r,Math.ceil(t.length/4)),a=s(t,r,Math.ceil(t.length/2)),d;if(!o&&!a)return null;a?o?d=o[4].length>a[4].length?o:a:d=a:d=o;var c,l,h,u;n.length>e.length?(c=d[0],l=d[1],h=d[2],u=d[3]):(h=d[0],u=d[1],c=d[2],l=d[3]);var f=d[4];return[c,l,h,u,f]};E.prototype.diff_cleanupSemantic=function(n){for(var e=!1,t=[],r=0,i=null,s=0,o=0,a=0,d=0,c=0;s<n.length;)n[s][0]==P?(t[r++]=s,o=d,a=c,d=0,c=0,i=n[s][1]):(n[s][0]==N?d+=n[s][1].length:c+=n[s][1].length,i&&i.length<=Math.max(o,a)&&i.length<=Math.max(d,c)&&(n.splice(t[r-1],0,new E.Diff(M,i)),n[t[r-1]+1][0]=N,r--,r--,s=r>0?t[r-1]:-1,o=0,a=0,d=0,c=0,i=null,e=!0)),s++;for(e&&this.diff_cleanupMerge(n),this.diff_cleanupSemanticLossless(n),s=1;s<n.length;){if(n[s-1][0]==M&&n[s][0]==N){var l=n[s-1][1],h=n[s][1],u=this.diff_commonOverlap_(l,h),f=this.diff_commonOverlap_(h,l);u>=f?(u>=l.length/2||u>=h.length/2)&&(n.splice(s,0,new E.Diff(P,h.substring(0,u))),n[s-1][1]=l.substring(0,l.length-u),n[s+1][1]=h.substring(u),s++):(f>=l.length/2||f>=h.length/2)&&(n.splice(s,0,new E.Diff(P,l.substring(0,f))),n[s-1][0]=N,n[s-1][1]=h.substring(0,h.length-f),n[s+1][0]=M,n[s+1][1]=l.substring(f),s++),s++}s++}};E.prototype.diff_cleanupSemanticLossless=function(n){function e(f,g){if(!f||!g)return 6;var m=f.charAt(f.length-1),y=g.charAt(0),w=m.match(E.nonAlphaNumericRegex_),b=y.match(E.nonAlphaNumericRegex_),k=w&&m.match(E.whitespaceRegex_),S=b&&y.match(E.whitespaceRegex_),v=k&&m.match(E.linebreakRegex_),A=S&&y.match(E.linebreakRegex_),F=v&&f.match(E.blanklineEndRegex_),x=A&&g.match(E.blanklineStartRegex_);return F||x?5:v||A?4:w&&!k&&S?3:k||S?2:w||b?1:0}for(var t=1;t<n.length-1;){if(n[t-1][0]==P&&n[t+1][0]==P){var r=n[t-1][1],i=n[t][1],s=n[t+1][1],o=this.diff_commonSuffix(r,i);if(o){var a=i.substring(i.length-o);r=r.substring(0,r.length-o),i=a+i.substring(0,i.length-o),s=a+s}for(var d=r,c=i,l=s,h=e(r,i)+e(i,s);i.charAt(0)===s.charAt(0);){r+=i.charAt(0),i=i.substring(1)+s.charAt(0),s=s.substring(1);var u=e(r,i)+e(i,s);u>=h&&(h=u,d=r,c=i,l=s)}n[t-1][1]!=d&&(d?n[t-1][1]=d:(n.splice(t-1,1),t--),n[t][1]=c,l?n[t+1][1]=l:(n.splice(t+1,1),t--))}t++}};E.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;E.whitespaceRegex_=/\s/;E.linebreakRegex_=/[\r\n]/;E.blanklineEndRegex_=/\n\r?\n$/;E.blanklineStartRegex_=/^\r?\n\r?\n/;E.prototype.diff_cleanupEfficiency=function(n){for(var e=!1,t=[],r=0,i=null,s=0,o=!1,a=!1,d=!1,c=!1;s<n.length;)n[s][0]==P?(n[s][1].length<this.Diff_EditCost&&(d||c)?(t[r++]=s,o=d,a=c,i=n[s][1]):(r=0,i=null),d=c=!1):(n[s][0]==M?c=!0:d=!0,i&&(o&&a&&d&&c||i.length<this.Diff_EditCost/2&&o+a+d+c==3)&&(n.splice(t[r-1],0,new E.Diff(M,i)),n[t[r-1]+1][0]=N,r--,i=null,o&&a?(d=c=!0,r=0):(r--,s=r>0?t[r-1]:-1,d=c=!1),e=!0)),s++;e&&this.diff_cleanupMerge(n)};E.prototype.diff_cleanupMerge=function(n){n.push(new E.Diff(P,""));for(var e=0,t=0,r=0,i="",s="",o;e<n.length;)switch(n[e][0]){case N:r++,s+=n[e][1],e++;break;case M:t++,i+=n[e][1],e++;break;case P:t+r>1?(t!==0&&r!==0&&(o=this.diff_commonPrefix(s,i),o!==0&&(e-t-r>0&&n[e-t-r-1][0]==P?n[e-t-r-1][1]+=s.substring(0,o):(n.splice(0,0,new E.Diff(P,s.substring(0,o))),e++),s=s.substring(o),i=i.substring(o)),o=this.diff_commonSuffix(s,i),o!==0&&(n[e][1]=s.substring(s.length-o)+n[e][1],s=s.substring(0,s.length-o),i=i.substring(0,i.length-o))),e-=t+r,n.splice(e,t+r),i.length&&(n.splice(e,0,new E.Diff(M,i)),e++),s.length&&(n.splice(e,0,new E.Diff(N,s)),e++),e++):e!==0&&n[e-1][0]==P?(n[e-1][1]+=n[e][1],n.splice(e,1)):e++,r=0,t=0,i="",s="";break}n[n.length-1][1]===""&&n.pop();var a=!1;for(e=1;e<n.length-1;)n[e-1][0]==P&&n[e+1][0]==P&&(n[e][1].substring(n[e][1].length-n[e-1][1].length)==n[e-1][1]?(n[e][1]=n[e-1][1]+n[e][1].substring(0,n[e][1].length-n[e-1][1].length),n[e+1][1]=n[e-1][1]+n[e+1][1],n.splice(e-1,1),a=!0):n[e][1].substring(0,n[e+1][1].length)==n[e+1][1]&&(n[e-1][1]+=n[e+1][1],n[e][1]=n[e][1].substring(n[e+1][1].length)+n[e+1][1],n.splice(e+1,1),a=!0)),e++;a&&this.diff_cleanupMerge(n)};E.prototype.diff_xIndex=function(n,e){var t=0,r=0,i=0,s=0,o;for(o=0;o<n.length&&(n[o][0]!==N&&(t+=n[o][1].length),n[o][0]!==M&&(r+=n[o][1].length),!(t>e));o++)i=t,s=r;return n.length!=o&&n[o][0]===M?s:s+(e-i)};E.prototype.diff_prettyHtml=function(n){for(var e=[],t=/&/g,r=/</g,i=/>/g,s=/\n/g,o=0;o<n.length;o++){var a=n[o][0],d=n[o][1],c=d.replace(t,"&amp;").replace(r,"&lt;").replace(i,"&gt;").replace(s,"&para;<br>");switch(a){case N:e[o]='<ins style="background:#e6ffe6;">'+c+"</ins>";break;case M:e[o]='<del style="background:#ffe6e6;">'+c+"</del>";break;case P:e[o]="<span>"+c+"</span>";break}}return e.join("")};E.prototype.diff_text1=function(n){for(var e=[],t=0;t<n.length;t++)n[t][0]!==N&&(e[t]=n[t][1]);return e.join("")};E.prototype.diff_text2=function(n){for(var e=[],t=0;t<n.length;t++)n[t][0]!==M&&(e[t]=n[t][1]);return e.join("")};E.prototype.diff_levenshtein=function(n){for(var e=0,t=0,r=0,i=0;i<n.length;i++){var s=n[i][0],o=n[i][1];switch(s){case N:t+=o.length;break;case M:r+=o.length;break;case P:e+=Math.max(t,r),t=0,r=0;break}}return e+=Math.max(t,r),e};E.prototype.diff_toDelta=function(n){for(var e=[],t=0;t<n.length;t++)switch(n[t][0]){case N:e[t]="+"+encodeURI(n[t][1]);break;case M:e[t]="-"+n[t][1].length;break;case P:e[t]="="+n[t][1].length;break}return e.join(" ").replace(/%20/g," ")};E.prototype.diff_fromDelta=function(n,e){for(var t=[],r=0,i=0,s=e.split(/\t/g),o=0;o<s.length;o++){var a=s[o].substring(1);switch(s[o].charAt(0)){case"+":try{t[r++]=new E.Diff(N,decodeURI(a))}catch{throw new Error("Illegal escape in diff_fromDelta: "+a)}break;case"-":case"=":var d=parseInt(a,10);if(isNaN(d)||d<0)throw new Error("Invalid number in diff_fromDelta: "+a);var c=n.substring(i,i+=d);s[o].charAt(0)=="="?t[r++]=new E.Diff(P,c):t[r++]=new E.Diff(M,c);break;default:if(s[o])throw new Error("Invalid diff operation in diff_fromDelta: "+s[o])}}if(i!=n.length)throw new Error("Delta length ("+i+") does not equal source text length ("+n.length+").");return t};E.prototype.match_main=function(n,e,t){if(n==null||e==null||t==null)throw new Error("Null input. (match_main)");return t=Math.max(0,Math.min(t,n.length)),n==e?0:n.length?n.substring(t,t+e.length)==e?t:this.match_bitap_(n,e,t):-1};E.prototype.match_bitap_=function(n,e,t){if(e.length>this.Match_MaxBits)throw new Error("Pattern too long for this browser.");var r=this.match_alphabet_(e),i=this;function s(S,v){var A=S/e.length,F=Math.abs(t-v);return i.Match_Distance?A+F/i.Match_Distance:F?1:A}var o=this.Match_Threshold,a=n.indexOf(e,t);a!=-1&&(o=Math.min(s(0,a),o),a=n.lastIndexOf(e,t+e.length),a!=-1&&(o=Math.min(s(0,a),o)));var d=1<<e.length-1;a=-1;for(var c,l,h=e.length+n.length,u,f=0;f<e.length;f++){for(c=0,l=h;c<l;)s(f,t+l)<=o?c=l:h=l,l=Math.floor((h-c)/2+c);h=l;var g=Math.max(1,t-l+1),m=Math.min(t+l,n.length)+e.length,y=Array(m+2);y[m+1]=(1<<f)-1;for(var w=m;w>=g;w--){var b=r[n.charAt(w-1)];if(f===0?y[w]=(y[w+1]<<1|1)&b:y[w]=(y[w+1]<<1|1)&b|((u[w+1]|u[w])<<1|1)|u[w+1],y[w]&d){var k=s(f,w-1);if(k<=o)if(o=k,a=w-1,a>t)g=Math.max(1,2*t-a);else break}}if(s(f+1,t)>o)break;u=y}return a};E.prototype.match_alphabet_=function(n){for(var e={},t=0;t<n.length;t++)e[n.charAt(t)]=0;for(var t=0;t<n.length;t++)e[n.charAt(t)]|=1<<n.length-t-1;return e};E.prototype.patch_addContext_=function(n,e){if(e.length!=0){if(n.start2===null)throw Error("patch not initialized");for(var t=e.substring(n.start2,n.start2+n.length1),r=0;e.indexOf(t)!=e.lastIndexOf(t)&&t.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)r+=this.Patch_Margin,t=e.substring(n.start2-r,n.start2+n.length1+r);r+=this.Patch_Margin;var i=e.substring(n.start2-r,n.start2);i&&n.diffs.unshift(new E.Diff(P,i));var s=e.substring(n.start2+n.length1,n.start2+n.length1+r);s&&n.diffs.push(new E.Diff(P,s)),n.start1-=i.length,n.start2-=i.length,n.length1+=i.length+s.length,n.length2+=i.length+s.length}};E.prototype.patch_make=function(n,e,t){var r,i;if(typeof n=="string"&&typeof e=="string"&&typeof t>"u")r=n,i=this.diff_main(r,e,!0),i.length>2&&(this.diff_cleanupSemantic(i),this.diff_cleanupEfficiency(i));else if(n&&typeof n=="object"&&typeof e>"u"&&typeof t>"u")i=n,r=this.diff_text1(i);else if(typeof n=="string"&&e&&typeof e=="object"&&typeof t>"u")r=n,i=e;else if(typeof n=="string"&&typeof e=="string"&&t&&typeof t=="object")r=n,i=t;else throw new Error("Unknown call format to patch_make.");if(i.length===0)return[];for(var s=[],o=new E.patch_obj,a=0,d=0,c=0,l=r,h=r,u=0;u<i.length;u++){var f=i[u][0],g=i[u][1];switch(!a&&f!==P&&(o.start1=d,o.start2=c),f){case N:o.diffs[a++]=i[u],o.length2+=g.length,h=h.substring(0,c)+g+h.substring(c);break;case M:o.length1+=g.length,o.diffs[a++]=i[u],h=h.substring(0,c)+h.substring(c+g.length);break;case P:g.length<=2*this.Patch_Margin&&a&&i.length!=u+1?(o.diffs[a++]=i[u],o.length1+=g.length,o.length2+=g.length):g.length>=2*this.Patch_Margin&&a&&(this.patch_addContext_(o,l),s.push(o),o=new E.patch_obj,a=0,l=h,d=c);break}f!==N&&(d+=g.length),f!==M&&(c+=g.length)}return a&&(this.patch_addContext_(o,l),s.push(o)),s};E.prototype.patch_deepCopy=function(n){for(var e=[],t=0;t<n.length;t++){var r=n[t],i=new E.patch_obj;i.diffs=[];for(var s=0;s<r.diffs.length;s++)i.diffs[s]=new E.Diff(r.diffs[s][0],r.diffs[s][1]);i.start1=r.start1,i.start2=r.start2,i.length1=r.length1,i.length2=r.length2,e[t]=i}return e};E.prototype.patch_apply=function(n,e){if(n.length==0)return[e,[]];n=this.patch_deepCopy(n);var t=this.patch_addPadding(n);e=t+e+t,this.patch_splitMax(n);for(var r=0,i=[],s=0;s<n.length;s++){var o=n[s].start2+r,a=this.diff_text1(n[s].diffs),d,c=-1;if(a.length>this.Match_MaxBits?(d=this.match_main(e,a.substring(0,this.Match_MaxBits),o),d!=-1&&(c=this.match_main(e,a.substring(a.length-this.Match_MaxBits),o+a.length-this.Match_MaxBits),(c==-1||d>=c)&&(d=-1))):d=this.match_main(e,a,o),d==-1)i[s]=!1,r-=n[s].length2-n[s].length1;else{i[s]=!0,r=d-o;var l;if(c==-1?l=e.substring(d,d+a.length):l=e.substring(d,c+this.Match_MaxBits),a==l)e=e.substring(0,d)+this.diff_text2(n[s].diffs)+e.substring(d+a.length);else{var h=this.diff_main(a,l,!1);if(a.length>this.Match_MaxBits&&this.diff_levenshtein(h)/a.length>this.Patch_DeleteThreshold)i[s]=!1;else{this.diff_cleanupSemanticLossless(h);for(var u=0,f,g=0;g<n[s].diffs.length;g++){var m=n[s].diffs[g];m[0]!==P&&(f=this.diff_xIndex(h,u)),m[0]===N?e=e.substring(0,d+f)+m[1]+e.substring(d+f):m[0]===M&&(e=e.substring(0,d+f)+e.substring(d+this.diff_xIndex(h,u+m[1].length))),m[0]!==M&&(u+=m[1].length)}}}}}return e=e.substring(t.length,e.length-t.length),[e,i]};E.prototype.patch_addPadding=function(n){for(var e=this.Patch_Margin,t="",r=1;r<=e;r++)t+=String.fromCharCode(r);for(var r=0;r<n.length;r++)n[r].start1+=e,n[r].start2+=e;var i=n[0],s=i.diffs;if(s.length==0||s[0][0]!=P)s.unshift(new E.Diff(P,t)),i.start1-=e,i.start2-=e,i.length1+=e,i.length2+=e;else if(e>s[0][1].length){var o=e-s[0][1].length;s[0][1]=t.substring(s[0][1].length)+s[0][1],i.start1-=o,i.start2-=o,i.length1+=o,i.length2+=o}if(i=n[n.length-1],s=i.diffs,s.length==0||s[s.length-1][0]!=P)s.push(new E.Diff(P,t)),i.length1+=e,i.length2+=e;else if(e>s[s.length-1][1].length){var o=e-s[s.length-1][1].length;s[s.length-1][1]+=t.substring(0,o),i.length1+=o,i.length2+=o}return t};E.prototype.patch_splitMax=function(n){for(var e=this.Match_MaxBits,t=0;t<n.length;t++)if(!(n[t].length1<=e)){var r=n[t];n.splice(t--,1);for(var i=r.start1,s=r.start2,o="";r.diffs.length!==0;){var a=new E.patch_obj,d=!0;for(a.start1=i-o.length,a.start2=s-o.length,o!==""&&(a.length1=a.length2=o.length,a.diffs.push(new E.Diff(P,o)));r.diffs.length!==0&&a.length1<e-this.Patch_Margin;){var c=r.diffs[0][0],l=r.diffs[0][1];c===N?(a.length2+=l.length,s+=l.length,a.diffs.push(r.diffs.shift()),d=!1):c===M&&a.diffs.length==1&&a.diffs[0][0]==P&&l.length>2*e?(a.length1+=l.length,i+=l.length,d=!1,a.diffs.push(new E.Diff(c,l)),r.diffs.shift()):(l=l.substring(0,e-a.length1-this.Patch_Margin),a.length1+=l.length,i+=l.length,c===P?(a.length2+=l.length,s+=l.length):d=!1,a.diffs.push(new E.Diff(c,l)),l==r.diffs[0][1]?r.diffs.shift():r.diffs[0][1]=r.diffs[0][1].substring(l.length))}o=this.diff_text2(a.diffs),o=o.substring(o.length-this.Patch_Margin);var h=this.diff_text1(r.diffs).substring(0,this.Patch_Margin);h!==""&&(a.length1+=h.length,a.length2+=h.length,a.diffs.length!==0&&a.diffs[a.diffs.length-1][0]===P?a.diffs[a.diffs.length-1][1]+=h:a.diffs.push(new E.Diff(P,h))),d||n.splice(++t,0,a)}}};E.prototype.patch_toText=function(n){for(var e=[],t=0;t<n.length;t++)e[t]=n[t];return e.join("")};E.prototype.patch_fromText=function(n){var e=[];if(!n)return e;for(var t=n.split(`
5
- `),r=0,i=/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/;r<t.length;){var s=t[r].match(i);if(!s)throw new Error("Invalid patch string: "+t[r]);var o=new E.patch_obj;for(e.push(o),o.start1=parseInt(s[1],10),s[2]===""?(o.start1--,o.length1=1):s[2]=="0"?o.length1=0:(o.start1--,o.length1=parseInt(s[2],10)),o.start2=parseInt(s[3],10),s[4]===""?(o.start2--,o.length2=1):s[4]=="0"?o.length2=0:(o.start2--,o.length2=parseInt(s[4],10)),r++;r<t.length;){var a=t[r].charAt(0);try{var d=decodeURI(t[r].substring(1))}catch{throw new Error("Illegal escape in patch_fromText: "+d)}if(a=="-")o.diffs.push(new E.Diff(M,d));else if(a=="+")o.diffs.push(new E.Diff(N,d));else if(a==" ")o.diffs.push(new E.Diff(P,d));else{if(a=="@")break;if(a!=="")throw new Error('Invalid patch mode "'+a+'" in: '+d)}r++}}return e};E.patch_obj=function(){this.diffs=[],this.start1=null,this.start2=null,this.length1=0,this.length2=0};E.patch_obj.prototype.toString=function(){var n,e;this.length1===0?n=this.start1+",0":this.length1==1?n=this.start1+1:n=this.start1+1+","+this.length1,this.length2===0?e=this.start2+",0":this.length2==1?e=this.start2+1:e=this.start2+1+","+this.length2;for(var t=["@@ -"+n+" +"+e+` @@
6
- `],r,i=0;i<this.diffs.length;i++){switch(this.diffs[i][0]){case N:r="+";break;case M:r="-";break;case P:r=" ";break}t[i+1]=r+encodeURI(this.diffs[i][1])+`
7
- `}return t.join("").replace(/%20/g," ")};mt.exports=E;mt.exports.diff_match_patch=E;mt.exports.DIFF_DELETE=M;mt.exports.DIFF_INSERT=N;mt.exports.DIFF_EQUAL=P});Re();var yi="41 61,42 62,43 63,44 64,45 65,46 66,47 67,48 68,49 69,4A 6A,4B 6B,4C 6C,4D 6D,4E 6E,4F 6F,50 70,51 71,52 72,53 73,54 74,55 75,56 76,57 77,58 78,59 79,5A 7A,B5 3BC,C0 E0,C1 E1,C2 E2,C3 E3,C4 E4,C5 E5,C6 E6,C7 E7,C8 E8,C9 E9,CA EA,CB EB,CC EC,CD ED,CE EE,CF EF,D0 F0,D1 F1,D2 F2,D3 F3,D4 F4,D5 F5,D6 F6,D8 F8,D9 F9,DA FA,DB FB,DC FC,DD FD,DE FE,DF 73 73,100 101,102 103,104 105,106 107,108 109,10A 10B,10C 10D,10E 10F,110 111,112 113,114 115,116 117,118 119,11A 11B,11C 11D,11E 11F,120 121,122 123,124 125,126 127,128 129,12A 12B,12C 12D,12E 12F,130 69 307,132 133,134 135,136 137,139 13A,13B 13C,13D 13E,13F 140,141 142,143 144,145 146,147 148,149 2BC 6E,14A 14B,14C 14D,14E 14F,150 151,152 153,154 155,156 157,158 159,15A 15B,15C 15D,15E 15F,160 161,162 163,164 165,166 167,168 169,16A 16B,16C 16D,16E 16F,170 171,172 173,174 175,176 177,178 FF,179 17A,17B 17C,17D 17E,17F 73,181 253,182 183,184 185,186 254,187 188,189 256,18A 257,18B 18C,18E 1DD,18F 259,190 25B,191 192,193 260,194 263,196 269,197 268,198 199,19C 26F,19D 272,19F 275,1A0 1A1,1A2 1A3,1A4 1A5,1A6 280,1A7 1A8,1A9 283,1AC 1AD,1AE 288,1AF 1B0,1B1 28A,1B2 28B,1B3 1B4,1B5 1B6,1B7 292,1B8 1B9,1BC 1BD,1C4 1C6,1C5 1C6,1C7 1C9,1C8 1C9,1CA 1CC,1CB 1CC,1CD 1CE,1CF 1D0,1D1 1D2,1D3 1D4,1D5 1D6,1D7 1D8,1D9 1DA,1DB 1DC,1DE 1DF,1E0 1E1,1E2 1E3,1E4 1E5,1E6 1E7,1E8 1E9,1EA 1EB,1EC 1ED,1EE 1EF,1F0 6A 30C,1F1 1F3,1F2 1F3,1F4 1F5,1F6 195,1F7 1BF,1F8 1F9,1FA 1FB,1FC 1FD,1FE 1FF,200 201,202 203,204 205,206 207,208 209,20A 20B,20C 20D,20E 20F,210 211,212 213,214 215,216 217,218 219,21A 21B,21C 21D,21E 21F,220 19E,222 223,224 225,226 227,228 229,22A 22B,22C 22D,22E 22F,230 231,232 233,23A 2C65,23B 23C,23D 19A,23E 2C66,241 242,243 180,244 289,245 28C,246 247,248 249,24A 24B,24C 24D,24E 24F,345 3B9,370 371,372 373,376 377,37F 3F3,386 3AC,388 3AD,389 3AE,38A 3AF,38C 3CC,38E 3CD,38F 3CE,390 3B9 308 301,391 3B1,392 3B2,393 3B3,394 3B4,395 3B5,396 3B6,397 3B7,398 3B8,399 3B9,39A 3BA,39B 3BB,39C 3BC,39D 3BD,39E 3BE,39F 3BF,3A0 3C0,3A1 3C1,3A3 3C3,3A4 3C4,3A5 3C5,3A6 3C6,3A7 3C7,3A8 3C8,3A9 3C9,3AA 3CA,3AB 3CB,3B0 3C5 308 301,3C2 3C3,3CF 3D7,3D0 3B2,3D1 3B8,3D5 3C6,3D6 3C0,3D8 3D9,3DA 3DB,3DC 3DD,3DE 3DF,3E0 3E1,3E2 3E3,3E4 3E5,3E6 3E7,3E8 3E9,3EA 3EB,3EC 3ED,3EE 3EF,3F0 3BA,3F1 3C1,3F4 3B8,3F5 3B5,3F7 3F8,3F9 3F2,3FA 3FB,3FD 37B,3FE 37C,3FF 37D,400 450,401 451,402 452,403 453,404 454,405 455,406 456,407 457,408 458,409 459,40A 45A,40B 45B,40C 45C,40D 45D,40E 45E,40F 45F,410 430,411 431,412 432,413 433,414 434,415 435,416 436,417 437,418 438,419 439,41A 43A,41B 43B,41C 43C,41D 43D,41E 43E,41F 43F,420 440,421 441,422 442,423 443,424 444,425 445,426 446,427 447,428 448,429 449,42A 44A,42B 44B,42C 44C,42D 44D,42E 44E,42F 44F,460 461,462 463,464 465,466 467,468 469,46A 46B,46C 46D,46E 46F,470 471,472 473,474 475,476 477,478 479,47A 47B,47C 47D,47E 47F,480 481,48A 48B,48C 48D,48E 48F,490 491,492 493,494 495,496 497,498 499,49A 49B,49C 49D,49E 49F,4A0 4A1,4A2 4A3,4A4 4A5,4A6 4A7,4A8 4A9,4AA 4AB,4AC 4AD,4AE 4AF,4B0 4B1,4B2 4B3,4B4 4B5,4B6 4B7,4B8 4B9,4BA 4BB,4BC 4BD,4BE 4BF,4C0 4CF,4C1 4C2,4C3 4C4,4C5 4C6,4C7 4C8,4C9 4CA,4CB 4CC,4CD 4CE,4D0 4D1,4D2 4D3,4D4 4D5,4D6 4D7,4D8 4D9,4DA 4DB,4DC 4DD,4DE 4DF,4E0 4E1,4E2 4E3,4E4 4E5,4E6 4E7,4E8 4E9,4EA 4EB,4EC 4ED,4EE 4EF,4F0 4F1,4F2 4F3,4F4 4F5,4F6 4F7,4F8 4F9,4FA 4FB,4FC 4FD,4FE 4FF,500 501,502 503,504 505,506 507,508 509,50A 50B,50C 50D,50E 50F,510 511,512 513,514 515,516 517,518 519,51A 51B,51C 51D,51E 51F,520 521,522 523,524 525,526 527,528 529,52A 52B,52C 52D,52E 52F,531 561,532 562,533 563,534 564,535 565,536 566,537 567,538 568,539 569,53A 56A,53B 56B,53C 56C,53D 56D,53E 56E,53F 56F,540 570,541 571,542 572,543 573,544 574,545 575,546 576,547 577,548 578,549 579,54A 57A,54B 57B,54C 57C,54D 57D,54E 57E,54F 57F,550 580,551 581,552 582,553 583,554 584,555 585,556 586,587 565 582,10A0 2D00,10A1 2D01,10A2 2D02,10A3 2D03,10A4 2D04,10A5 2D05,10A6 2D06,10A7 2D07,10A8 2D08,10A9 2D09,10AA 2D0A,10AB 2D0B,10AC 2D0C,10AD 2D0D,10AE 2D0E,10AF 2D0F,10B0 2D10,10B1 2D11,10B2 2D12,10B3 2D13,10B4 2D14,10B5 2D15,10B6 2D16,10B7 2D17,10B8 2D18,10B9 2D19,10BA 2D1A,10BB 2D1B,10BC 2D1C,10BD 2D1D,10BE 2D1E,10BF 2D1F,10C0 2D20,10C1 2D21,10C2 2D22,10C3 2D23,10C4 2D24,10C5 2D25,10C7 2D27,10CD 2D2D,13F8 13F0,13F9 13F1,13FA 13F2,13FB 13F3,13FC 13F4,13FD 13F5,1C80 432,1C81 434,1C82 43E,1C83 441,1C84 442,1C85 442,1C86 44A,1C87 463,1C88 A64B,1C90 10D0,1C91 10D1,1C92 10D2,1C93 10D3,1C94 10D4,1C95 10D5,1C96 10D6,1C97 10D7,1C98 10D8,1C99 10D9,1C9A 10DA,1C9B 10DB,1C9C 10DC,1C9D 10DD,1C9E 10DE,1C9F 10DF,1CA0 10E0,1CA1 10E1,1CA2 10E2,1CA3 10E3,1CA4 10E4,1CA5 10E5,1CA6 10E6,1CA7 10E7,1CA8 10E8,1CA9 10E9,1CAA 10EA,1CAB 10EB,1CAC 10EC,1CAD 10ED,1CAE 10EE,1CAF 10EF,1CB0 10F0,1CB1 10F1,1CB2 10F2,1CB3 10F3,1CB4 10F4,1CB5 10F5,1CB6 10F6,1CB7 10F7,1CB8 10F8,1CB9 10F9,1CBA 10FA,1CBD 10FD,1CBE 10FE,1CBF 10FF,1E00 1E01,1E02 1E03,1E04 1E05,1E06 1E07,1E08 1E09,1E0A 1E0B,1E0C 1E0D,1E0E 1E0F,1E10 1E11,1E12 1E13,1E14 1E15,1E16 1E17,1E18 1E19,1E1A 1E1B,1E1C 1E1D,1E1E 1E1F,1E20 1E21,1E22 1E23,1E24 1E25,1E26 1E27,1E28 1E29,1E2A 1E2B,1E2C 1E2D,1E2E 1E2F,1E30 1E31,1E32 1E33,1E34 1E35,1E36 1E37,1E38 1E39,1E3A 1E3B,1E3C 1E3D,1E3E 1E3F,1E40 1E41,1E42 1E43,1E44 1E45,1E46 1E47,1E48 1E49,1E4A 1E4B,1E4C 1E4D,1E4E 1E4F,1E50 1E51,1E52 1E53,1E54 1E55,1E56 1E57,1E58 1E59,1E5A 1E5B,1E5C 1E5D,1E5E 1E5F,1E60 1E61,1E62 1E63,1E64 1E65,1E66 1E67,1E68 1E69,1E6A 1E6B,1E6C 1E6D,1E6E 1E6F,1E70 1E71,1E72 1E73,1E74 1E75,1E76 1E77,1E78 1E79,1E7A 1E7B,1E7C 1E7D,1E7E 1E7F,1E80 1E81,1E82 1E83,1E84 1E85,1E86 1E87,1E88 1E89,1E8A 1E8B,1E8C 1E8D,1E8E 1E8F,1E90 1E91,1E92 1E93,1E94 1E95,1E96 68 331,1E97 74 308,1E98 77 30A,1E99 79 30A,1E9A 61 2BE,1E9B 1E61,1E9E 73 73,1EA0 1EA1,1EA2 1EA3,1EA4 1EA5,1EA6 1EA7,1EA8 1EA9,1EAA 1EAB,1EAC 1EAD,1EAE 1EAF,1EB0 1EB1,1EB2 1EB3,1EB4 1EB5,1EB6 1EB7,1EB8 1EB9,1EBA 1EBB,1EBC 1EBD,1EBE 1EBF,1EC0 1EC1,1EC2 1EC3,1EC4 1EC5,1EC6 1EC7,1EC8 1EC9,1ECA 1ECB,1ECC 1ECD,1ECE 1ECF,1ED0 1ED1,1ED2 1ED3,1ED4 1ED5,1ED6 1ED7,1ED8 1ED9,1EDA 1EDB,1EDC 1EDD,1EDE 1EDF,1EE0 1EE1,1EE2 1EE3,1EE4 1EE5,1EE6 1EE7,1EE8 1EE9,1EEA 1EEB,1EEC 1EED,1EEE 1EEF,1EF0 1EF1,1EF2 1EF3,1EF4 1EF5,1EF6 1EF7,1EF8 1EF9,1EFA 1EFB,1EFC 1EFD,1EFE 1EFF,1F08 1F00,1F09 1F01,1F0A 1F02,1F0B 1F03,1F0C 1F04,1F0D 1F05,1F0E 1F06,1F0F 1F07,1F18 1F10,1F19 1F11,1F1A 1F12,1F1B 1F13,1F1C 1F14,1F1D 1F15,1F28 1F20,1F29 1F21,1F2A 1F22,1F2B 1F23,1F2C 1F24,1F2D 1F25,1F2E 1F26,1F2F 1F27,1F38 1F30,1F39 1F31,1F3A 1F32,1F3B 1F33,1F3C 1F34,1F3D 1F35,1F3E 1F36,1F3F 1F37,1F48 1F40,1F49 1F41,1F4A 1F42,1F4B 1F43,1F4C 1F44,1F4D 1F45,1F50 3C5 313,1F52 3C5 313 300,1F54 3C5 313 301,1F56 3C5 313 342,1F59 1F51,1F5B 1F53,1F5D 1F55,1F5F 1F57,1F68 1F60,1F69 1F61,1F6A 1F62,1F6B 1F63,1F6C 1F64,1F6D 1F65,1F6E 1F66,1F6F 1F67,1F80 1F00 3B9,1F81 1F01 3B9,1F82 1F02 3B9,1F83 1F03 3B9,1F84 1F04 3B9,1F85 1F05 3B9,1F86 1F06 3B9,1F87 1F07 3B9,1F88 1F00 3B9,1F89 1F01 3B9,1F8A 1F02 3B9,1F8B 1F03 3B9,1F8C 1F04 3B9,1F8D 1F05 3B9,1F8E 1F06 3B9,1F8F 1F07 3B9,1F90 1F20 3B9,1F91 1F21 3B9,1F92 1F22 3B9,1F93 1F23 3B9,1F94 1F24 3B9,1F95 1F25 3B9,1F96 1F26 3B9,1F97 1F27 3B9,1F98 1F20 3B9,1F99 1F21 3B9,1F9A 1F22 3B9,1F9B 1F23 3B9,1F9C 1F24 3B9,1F9D 1F25 3B9,1F9E 1F26 3B9,1F9F 1F27 3B9,1FA0 1F60 3B9,1FA1 1F61 3B9,1FA2 1F62 3B9,1FA3 1F63 3B9,1FA4 1F64 3B9,1FA5 1F65 3B9,1FA6 1F66 3B9,1FA7 1F67 3B9,1FA8 1F60 3B9,1FA9 1F61 3B9,1FAA 1F62 3B9,1FAB 1F63 3B9,1FAC 1F64 3B9,1FAD 1F65 3B9,1FAE 1F66 3B9,1FAF 1F67 3B9,1FB2 1F70 3B9,1FB3 3B1 3B9,1FB4 3AC 3B9,1FB6 3B1 342,1FB7 3B1 342 3B9,1FB8 1FB0,1FB9 1FB1,1FBA 1F70,1FBB 1F71,1FBC 3B1 3B9,1FBE 3B9,1FC2 1F74 3B9,1FC3 3B7 3B9,1FC4 3AE 3B9,1FC6 3B7 342,1FC7 3B7 342 3B9,1FC8 1F72,1FC9 1F73,1FCA 1F74,1FCB 1F75,1FCC 3B7 3B9,1FD2 3B9 308 300,1FD3 3B9 308 301,1FD6 3B9 342,1FD7 3B9 308 342,1FD8 1FD0,1FD9 1FD1,1FDA 1F76,1FDB 1F77,1FE2 3C5 308 300,1FE3 3C5 308 301,1FE4 3C1 313,1FE6 3C5 342,1FE7 3C5 308 342,1FE8 1FE0,1FE9 1FE1,1FEA 1F7A,1FEB 1F7B,1FEC 1FE5,1FF2 1F7C 3B9,1FF3 3C9 3B9,1FF4 3CE 3B9,1FF6 3C9 342,1FF7 3C9 342 3B9,1FF8 1F78,1FF9 1F79,1FFA 1F7C,1FFB 1F7D,1FFC 3C9 3B9,2126 3C9,212A 6B,212B E5,2132 214E,2160 2170,2161 2171,2162 2172,2163 2173,2164 2174,2165 2175,2166 2176,2167 2177,2168 2178,2169 2179,216A 217A,216B 217B,216C 217C,216D 217D,216E 217E,216F 217F,2183 2184,24B6 24D0,24B7 24D1,24B8 24D2,24B9 24D3,24BA 24D4,24BB 24D5,24BC 24D6,24BD 24D7,24BE 24D8,24BF 24D9,24C0 24DA,24C1 24DB,24C2 24DC,24C3 24DD,24C4 24DE,24C5 24DF,24C6 24E0,24C7 24E1,24C8 24E2,24C9 24E3,24CA 24E4,24CB 24E5,24CC 24E6,24CD 24E7,24CE 24E8,24CF 24E9,2C00 2C30,2C01 2C31,2C02 2C32,2C03 2C33,2C04 2C34,2C05 2C35,2C06 2C36,2C07 2C37,2C08 2C38,2C09 2C39,2C0A 2C3A,2C0B 2C3B,2C0C 2C3C,2C0D 2C3D,2C0E 2C3E,2C0F 2C3F,2C10 2C40,2C11 2C41,2C12 2C42,2C13 2C43,2C14 2C44,2C15 2C45,2C16 2C46,2C17 2C47,2C18 2C48,2C19 2C49,2C1A 2C4A,2C1B 2C4B,2C1C 2C4C,2C1D 2C4D,2C1E 2C4E,2C1F 2C4F,2C20 2C50,2C21 2C51,2C22 2C52,2C23 2C53,2C24 2C54,2C25 2C55,2C26 2C56,2C27 2C57,2C28 2C58,2C29 2C59,2C2A 2C5A,2C2B 2C5B,2C2C 2C5C,2C2D 2C5D,2C2E 2C5E,2C2F 2C5F,2C60 2C61,2C62 26B,2C63 1D7D,2C64 27D,2C67 2C68,2C69 2C6A,2C6B 2C6C,2C6D 251,2C6E 271,2C6F 250,2C70 252,2C72 2C73,2C75 2C76,2C7E 23F,2C7F 240,2C80 2C81,2C82 2C83,2C84 2C85,2C86 2C87,2C88 2C89,2C8A 2C8B,2C8C 2C8D,2C8E 2C8F,2C90 2C91,2C92 2C93,2C94 2C95,2C96 2C97,2C98 2C99,2C9A 2C9B,2C9C 2C9D,2C9E 2C9F,2CA0 2CA1,2CA2 2CA3,2CA4 2CA5,2CA6 2CA7,2CA8 2CA9,2CAA 2CAB,2CAC 2CAD,2CAE 2CAF,2CB0 2CB1,2CB2 2CB3,2CB4 2CB5,2CB6 2CB7,2CB8 2CB9,2CBA 2CBB,2CBC 2CBD,2CBE 2CBF,2CC0 2CC1,2CC2 2CC3,2CC4 2CC5,2CC6 2CC7,2CC8 2CC9,2CCA 2CCB,2CCC 2CCD,2CCE 2CCF,2CD0 2CD1,2CD2 2CD3,2CD4 2CD5,2CD6 2CD7,2CD8 2CD9,2CDA 2CDB,2CDC 2CDD,2CDE 2CDF,2CE0 2CE1,2CE2 2CE3,2CEB 2CEC,2CED 2CEE,2CF2 2CF3,A640 A641,A642 A643,A644 A645,A646 A647,A648 A649,A64A A64B,A64C A64D,A64E A64F,A650 A651,A652 A653,A654 A655,A656 A657,A658 A659,A65A A65B,A65C A65D,A65E A65F,A660 A661,A662 A663,A664 A665,A666 A667,A668 A669,A66A A66B,A66C A66D,A680 A681,A682 A683,A684 A685,A686 A687,A688 A689,A68A A68B,A68C A68D,A68E A68F,A690 A691,A692 A693,A694 A695,A696 A697,A698 A699,A69A A69B,A722 A723,A724 A725,A726 A727,A728 A729,A72A A72B,A72C A72D,A72E A72F,A732 A733,A734 A735,A736 A737,A738 A739,A73A A73B,A73C A73D,A73E A73F,A740 A741,A742 A743,A744 A745,A746 A747,A748 A749,A74A A74B,A74C A74D,A74E A74F,A750 A751,A752 A753,A754 A755,A756 A757,A758 A759,A75A A75B,A75C A75D,A75E A75F,A760 A761,A762 A763,A764 A765,A766 A767,A768 A769,A76A A76B,A76C A76D,A76E A76F,A779 A77A,A77B A77C,A77D 1D79,A77E A77F,A780 A781,A782 A783,A784 A785,A786 A787,A78B A78C,A78D 265,A790 A791,A792 A793,A796 A797,A798 A799,A79A A79B,A79C A79D,A79E A79F,A7A0 A7A1,A7A2 A7A3,A7A4 A7A5,A7A6 A7A7,A7A8 A7A9,A7AA 266,A7AB 25C,A7AC 261,A7AD 26C,A7AE 26A,A7B0 29E,A7B1 287,A7B2 29D,A7B3 AB53,A7B4 A7B5,A7B6 A7B7,A7B8 A7B9,A7BA A7BB,A7BC A7BD,A7BE A7BF,A7C0 A7C1,A7C2 A7C3,A7C4 A794,A7C5 282,A7C6 1D8E,A7C7 A7C8,A7C9 A7CA,A7D0 A7D1,A7D6 A7D7,A7D8 A7D9,A7F5 A7F6,AB70 13A0,AB71 13A1,AB72 13A2,AB73 13A3,AB74 13A4,AB75 13A5,AB76 13A6,AB77 13A7,AB78 13A8,AB79 13A9,AB7A 13AA,AB7B 13AB,AB7C 13AC,AB7D 13AD,AB7E 13AE,AB7F 13AF,AB80 13B0,AB81 13B1,AB82 13B2,AB83 13B3,AB84 13B4,AB85 13B5,AB86 13B6,AB87 13B7,AB88 13B8,AB89 13B9,AB8A 13BA,AB8B 13BB,AB8C 13BC,AB8D 13BD,AB8E 13BE,AB8F 13BF,AB90 13C0,AB91 13C1,AB92 13C2,AB93 13C3,AB94 13C4,AB95 13C5,AB96 13C6,AB97 13C7,AB98 13C8,AB99 13C9,AB9A 13CA,AB9B 13CB,AB9C 13CC,AB9D 13CD,AB9E 13CE,AB9F 13CF,ABA0 13D0,ABA1 13D1,ABA2 13D2,ABA3 13D3,ABA4 13D4,ABA5 13D5,ABA6 13D6,ABA7 13D7,ABA8 13D8,ABA9 13D9,ABAA 13DA,ABAB 13DB,ABAC 13DC,ABAD 13DD,ABAE 13DE,ABAF 13DF,ABB0 13E0,ABB1 13E1,ABB2 13E2,ABB3 13E3,ABB4 13E4,ABB5 13E5,ABB6 13E6,ABB7 13E7,ABB8 13E8,ABB9 13E9,ABBA 13EA,ABBB 13EB,ABBC 13EC,ABBD 13ED,ABBE 13EE,ABBF 13EF,FB00 66 66,FB01 66 69,FB02 66 6C,FB03 66 66 69,FB04 66 66 6C,FB05 73 74,FB06 73 74,FB13 574 576,FB14 574 565,FB15 574 56B,FB16 57E 576,FB17 574 56D,FF21 FF41,FF22 FF42,FF23 FF43,FF24 FF44,FF25 FF45,FF26 FF46,FF27 FF47,FF28 FF48,FF29 FF49,FF2A FF4A,FF2B FF4B,FF2C FF4C,FF2D FF4D,FF2E FF4E,FF2F FF4F,FF30 FF50,FF31 FF51,FF32 FF52,FF33 FF53,FF34 FF54,FF35 FF55,FF36 FF56,FF37 FF57,FF38 FF58,FF39 FF59,FF3A FF5A,10400 10428,10401 10429,10402 1042A,10403 1042B,10404 1042C,10405 1042D,10406 1042E,10407 1042F,10408 10430,10409 10431,1040A 10432,1040B 10433,1040C 10434,1040D 10435,1040E 10436,1040F 10437,10410 10438,10411 10439,10412 1043A,10413 1043B,10414 1043C,10415 1043D,10416 1043E,10417 1043F,10418 10440,10419 10441,1041A 10442,1041B 10443,1041C 10444,1041D 10445,1041E 10446,1041F 10447,10420 10448,10421 10449,10422 1044A,10423 1044B,10424 1044C,10425 1044D,10426 1044E,10427 1044F,104B0 104D8,104B1 104D9,104B2 104DA,104B3 104DB,104B4 104DC,104B5 104DD,104B6 104DE,104B7 104DF,104B8 104E0,104B9 104E1,104BA 104E2,104BB 104E3,104BC 104E4,104BD 104E5,104BE 104E6,104BF 104E7,104C0 104E8,104C1 104E9,104C2 104EA,104C3 104EB,104C4 104EC,104C5 104ED,104C6 104EE,104C7 104EF,104C8 104F0,104C9 104F1,104CA 104F2,104CB 104F3,104CC 104F4,104CD 104F5,104CE 104F6,104CF 104F7,104D0 104F8,104D1 104F9,104D2 104FA,104D3 104FB,10570 10597,10571 10598,10572 10599,10573 1059A,10574 1059B,10575 1059C,10576 1059D,10577 1059E,10578 1059F,10579 105A0,1057A 105A1,1057C 105A3,1057D 105A4,1057E 105A5,1057F 105A6,10580 105A7,10581 105A8,10582 105A9,10583 105AA,10584 105AB,10585 105AC,10586 105AD,10587 105AE,10588 105AF,10589 105B0,1058A 105B1,1058C 105B3,1058D 105B4,1058E 105B5,1058F 105B6,10590 105B7,10591 105B8,10592 105B9,10594 105BB,10595 105BC,10C80 10CC0,10C81 10CC1,10C82 10CC2,10C83 10CC3,10C84 10CC4,10C85 10CC5,10C86 10CC6,10C87 10CC7,10C88 10CC8,10C89 10CC9,10C8A 10CCA,10C8B 10CCB,10C8C 10CCC,10C8D 10CCD,10C8E 10CCE,10C8F 10CCF,10C90 10CD0,10C91 10CD1,10C92 10CD2,10C93 10CD3,10C94 10CD4,10C95 10CD5,10C96 10CD6,10C97 10CD7,10C98 10CD8,10C99 10CD9,10C9A 10CDA,10C9B 10CDB,10C9C 10CDC,10C9D 10CDD,10C9E 10CDE,10C9F 10CDF,10CA0 10CE0,10CA1 10CE1,10CA2 10CE2,10CA3 10CE3,10CA4 10CE4,10CA5 10CE5,10CA6 10CE6,10CA7 10CE7,10CA8 10CE8,10CA9 10CE9,10CAA 10CEA,10CAB 10CEB,10CAC 10CEC,10CAD 10CED,10CAE 10CEE,10CAF 10CEF,10CB0 10CF0,10CB1 10CF1,10CB2 10CF2,118A0 118C0,118A1 118C1,118A2 118C2,118A3 118C3,118A4 118C4,118A5 118C5,118A6 118C6,118A7 118C7,118A8 118C8,118A9 118C9,118AA 118CA,118AB 118CB,118AC 118CC,118AD 118CD,118AE 118CE,118AF 118CF,118B0 118D0,118B1 118D1,118B2 118D2,118B3 118D3,118B4 118D4,118B5 118D5,118B6 118D6,118B7 118D7,118B8 118D8,118B9 118D9,118BA 118DA,118BB 118DB,118BC 118DC,118BD 118DD,118BE 118DE,118BF 118DF,16E40 16E60,16E41 16E61,16E42 16E62,16E43 16E63,16E44 16E64,16E45 16E65,16E46 16E66,16E47 16E67,16E48 16E68,16E49 16E69,16E4A 16E6A,16E4B 16E6B,16E4C 16E6C,16E4D 16E6D,16E4E 16E6E,16E4F 16E6F,16E50 16E70,16E51 16E71,16E52 16E72,16E53 16E73,16E54 16E74,16E55 16E75,16E56 16E76,16E57 16E77,16E58 16E78,16E59 16E79,16E5A 16E7A,16E5B 16E7B,16E5C 16E7C,16E5D 16E7D,16E5E 16E7E,16E5F 16E7F,1E900 1E922,1E901 1E923,1E902 1E924,1E903 1E925,1E904 1E926,1E905 1E927,1E906 1E928,1E907 1E929,1E908 1E92A,1E909 1E92B,1E90A 1E92C,1E90B 1E92D,1E90C 1E92E,1E90D 1E92F,1E90E 1E930,1E90F 1E931,1E910 1E932,1E911 1E933,1E912 1E934,1E913 1E935,1E914 1E936,1E915 1E937,1E916 1E938,1E917 1E939,1E918 1E93A,1E919 1E93B,1E91A 1E93C,1E91B 1E93D,1E91C 1E93E,1E91D 1E93F,1E91E 1E940,1E91F 1E941,1E920 1E942,1E921 1E943";var Zn;function Ma(){if(Zn!==void 0)return Zn;let n=new Map;for(let e of yi.split(",")){let[t,...r]=e.split(" ").map(i=>Number.parseInt(i,16));if(t===void 0||r.length===0)throw new Error(`the fold table has a malformed entry: ${JSON.stringify(e)}`);n.set(t,String.fromCodePoint(...r))}return Zn=n,n}function Qn(n){let e=Ma(),t="";for(let r of n.normalize("NFC"))t+=e.get(r.codePointAt(0))??r;return t.normalize("NFC")}var er=1024,Ot=255,tr=".trew-tmp-",wi=new TextEncoder;function Na(n){for(let e=0;e<n.length;e++){let t=n.charCodeAt(e);if(t>=55296&&t<=56319){let r=n.charCodeAt(e+1);if(!(r>=56320&&r<=57343))return!1;e++}else if(t>=56320&&t<=57343)return!1}return!0}function vi(n){if(!Na(n))return"utf8";if(n==="")return"empty";if(wi.encode(n).length>er)return"toolong";if(n.split("/").some(t=>wi.encode(t).length>Ot))return"segmenttoolong";if(/[\u0000-\u001f\u007f]/u.test(n))return"control";if(n.normalize("NFC")!==n)return"nfc";if(/[\u00a0\u202f]/u.test(n))return"nbsp";if(n.includes("\\"))return"backslash";if(n.startsWith("/")||n.endsWith("/"))return"slash";let e=n.split("/");if(e.some(t=>t===""))return"emptysegment";if(e.some(t=>t==="."||t===".."))return"dotsegment";if(e.some(t=>t.startsWith(".")))return"dotprefix";if(n.includes(tr))return"staging"}var nr=["md","txt","canvas","json","csv","yml","yaml","base","xml","html","css","js","ts","svg","bib","tex"];function _a(n){return n.replace(/[A-Z]/g,e=>String.fromCharCode(e.charCodeAt(0)+32))}function bi(n){let e=n.lastIndexOf(".");return e<0||e<n.lastIndexOf("/")?!1:nr.includes(_a(n.slice(e+1)))}var He=48,Qe=31,La=1;function Ei(n,e){let t=n>>>0;return Math.floor(t/e)*e===t-La}var ki={min:512,avg:1024,max:4096},Ua=64,za=ki.avg,Wa=64*1024;function Ja(n){let e=Math.sqrt(Ua*Math.max(n,1)),t=Math.min(Wa,Math.max(za,Math.round(e/512)*512));return{min:Math.max(ki.min,t/2),avg:t,max:t*4}}var rr={min:128*1024,avg:256*1024,max:1024*1024},ja=4*1024*1024,Mt=He*4;function Ai(n,e,t=rr.max){(!Number.isFinite(t)||t<=0)&&(t=rr.max);let r=e&&n<ja?Ja(n):rr,i=Math.min(r.max,t),s=Math.max(i,Mt);return{min:Math.min(r.min,s),avg:Math.min(r.avg,s),max:s}}function Ci(n,e,t){let r=t-1;for(;r>e&&(n[r]&192)===128;)r--;if(r<e)return t;let i=n[r],s=i<128?1:(i&224)===192?2:(i&240)===224?3:(i&248)===240?4:1;return t-r>=s?t:r>e?r:t}function*Nt(n,e,t){let{min:r,avg:i,max:s}=e,o=n.length,a=1;for(let l=0;l<He-1;l++)a=Math.imul(a,Qe);let d=0,c=0;for(let l=0;l<o;l++){let h=n[l];l>=d+He?(c=c-Math.imul(n[l-He],a)|0,c=Math.imul(c,Qe),c=c+h|0):(c=Math.imul(c,Qe),c=c+h|0);let u=l-d+1,f=u>=r&&Ei(c,i);if(u>=s&&(f=!0),f){let g=t?Ci(n,d,l+1):l+1;yield{offset:d,bytes:n.subarray(d,g)},d=g,c=0,l=g-1}}d<o&&(yield{offset:d,bytes:n.subarray(d,o)})}var ir=class{constructor(e,t,r){this.buf=e;this.sizes=t;this.pPowW=r}buf;sizes;pPowW;used=0;hash=0;scanTo(e,t){let{min:r,avg:i,max:s}=this.sizes,o=this.buf,a=this.pPowW,d=this.used,c=this.hash;for(let l=t;l<e.length;l++){let h=e[l];if(o[d++]=h,d>=He+1?(c=c-Math.imul(o[d-1-He],a)|0,c=Math.imul(c,Qe),c=c+h|0):(c=Math.imul(c,Qe),c=c+h|0),d>=s||d>=r&&Ei(c,i))return this.used=d,this.hash=c,l+1}return this.used=d,this.hash=c,-1}};async function*pn(n,e,t){let{max:r}=e,i=1;for(let h=0;h<He-1;h++)i=Math.imul(i,Qe);let s=new Uint8Array(Math.max(r,He*2)),o=0,a=0,d=0,c=()=>{let h=t?Ci(s,0,o):o,u={offset:d,bytes:s.slice(0,h)};d+=h;let f=o-h;s.copyWithin(0,h,o),o=f,a=0;for(let g=0;g<f;g++)a=Math.imul(a,Qe),a=a+s[g]|0;return u},l=new ir(s,e,i);for await(let h of n){let u=0;for(;;){let f=l.scanTo(h,u);if(f<0)break;o=l.used,yield c(),l.used=o,l.hash=a,u=f}o=l.used}if(o>0){let h={offset:d,bytes:s.slice(0,o)};d+=o,o=0,yield h}}var $h=new Set(nr);function Ve(n){return bi(n)}var Ha=new Set(["canvas","json"]),Va=new Set(["base","yml","yaml"]);function Si(n){let e=n.lastIndexOf(".");return e<0?!1:Va.has(n.slice(e+1).toLowerCase())}function Fi(n){let e=n.lastIndexOf(".");return e<0?!1:Ha.has(n.slice(e+1).toLowerCase())}var cr=gi(sr(),1);var Bi=gi(sr(),1),Ga=-1,qa=0,Xa=4e6;function Ka(n,e,t){let r=n.diff_commonPrefix(e,t),i=n.diff_commonSuffix(e.slice(r),t.slice(r)),s=e.length-r-i,o=t.length-r-i;return s<=0||o<=0?0:s*o}function $i(n){return n.match(/[^\n]*\n|[^\n]+$/g)??[]}function xi(n,e,t,r){let i=$i(t),s=new Bi.diff_match_patch;s.Diff_Timeout=0;let{chars1:o,chars2:a,lineArray:d}=s.diff_linesToChars_(n,t);if(o.length!==e.length||a.length!==i.length||d.length>65535||Ka(s,o,a)>Xa)return;let c=s.diff_main(o,a,!1),l=[],h=0,u=0,f,g=()=>{f!==void 0&&(l.push({mine:r,start:f.start,end:h,text:i.slice(f.from,u).join("")}),f=void 0)};for(let[m,y]of c){let w=y.length;m===qa?(g(),h+=w,u+=w):(f??={start:h,from:u},m===Ga?h+=w:u+=w)}return g(),l}function Pi(n,e,t){let r=$i(n),i=xi(n,r,e,!0),s=xi(n,r,t,!1);if(i===void 0||s===void 0)return;let o=[...i,...s].sort((h,u)=>h.start-u.start||h.end-h.start-(u.end-u.start)),a=[0];for(let h of r)a.push(a[a.length-1]+h.length);let d=[],c=0,l=h=>{if(h<=c)return;let u=r.slice(c,h).join("");d.push({changed:"none",base:u,mine:u,theirs:u,at:a[c],firstLine:c,lastLine:h}),c=h};for(let h=0;h<o.length;){let u=o[h],f=u.end,g=h+1;for(;g<o.length;){let S=o[g],v=S.start<f,A=S.start===S.end&&S.start===u.start&&u.end===f;if(!v&&!(A&&f===u.start))break;f=Math.max(f,S.end),g++}let m=o.slice(h,g),y=u.start,w=m.filter(S=>S.mine),b=m.filter(S=>!S.mine),k=S=>{let v="",A=y;for(let F of S)v+=r.slice(A,F.start).join("")+F.text,A=F.end;return v+r.slice(A,f).join("")};l(y),d.push({changed:w.length>0&&b.length>0?"both":w.length>0?"mine":"theirs",base:r.slice(y,f).join(""),mine:k(w),theirs:k(b),at:a[y],firstLine:y,lastLine:f}),c=f,h=g}return l(r.length),d}function _t(n,e){for(let t of n.split("/"))if(t.startsWith(".")&&t!=="."&&t!==".."||e.has(t))return!0;return!1}function et(n){let e=n.lastIndexOf("/"),t=n.lastIndexOf(".");return t<=e+1?{stem:n,ext:""}:{stem:n.slice(0,t),ext:n.slice(t)}}async function Ie(n,e,t=Za(n)){if(!await e(n))return n;for(let r=1;r<=Ti;r++){let i=t(r);if(!await e(i))return i}throw new Error(`cannot find an unused name beside ${n}`)}var Ti=998,Ya=` ${Ti+1}`.length;function Za(n){let{stem:e,ext:t}=et(n);return r=>`${e} ${r+1}${t}`}var Qa=new TextEncoder,ne=n=>Qa.encode(n).length;function or(n){return Math.min(Ot,er-ne(n))-Ya}function mn(n,e,t){let r=n.lastIndexOf("/")+1,i=n.slice(0,r),s=n.slice(r),o=or(i);ne(t)+ne(e)+1>o&&(s+=t,t="");let a=ne(s)+ne(e)+ne(t)-o;return a>0&&(s=ar(s,ne(s)-a)),`${i}${s}${e}${t}`}function ar(n,e){let t="",r=0;for(let s of ed(n)){let o=ne(s);if(t!==""&&r+o>e)break;t+=s,r+=o}let i=t.replace(/[\s.-]+$/u,"");return i===""?t:i}var Di=typeof Intl<"u"&&"Segmenter"in Intl?new Intl.Segmenter:void 0;function ed(n){return Di===void 0?n:Array.from(Di.segment(n),e=>e.segment)}function de(n){return n.normalize("NFC")}function Ri(n){return n.replace(/[\u00a0\u202f]/gu," ")}function Q(n){return Qn(n)}function Lt(n,e){return Q(n)===Q(e)}function Ii(n){let e="";for(let t of n){let r=t.codePointAt(0);e+=r>=32&&r<127?t:`\\u{${r.toString(16)}}`}return e}function Oi(n){let e=new Error(n);return e.code="neversync",e}function Mi(n){let e=new Error(n);return e.code="ignored",e}function Ni(n,e){let t=!1;for(let r of n.split("/")){if(r.startsWith(".")&&r!=="."&&r!=="..")return!1;e.has(r)&&(t=!0)}return t}function yn(n){let e=n.replace(/^\/+|\/+$/g,"");if(e===""||e.includes("/"))throw new Error(`refusing to sync: the config folder ${JSON.stringify(n)} is not a plain name`);return e}var dr=8*1024;function td(n,e,t){return!(n.length>dr||e.length>dr||t.length>dr)}var Wi=-1,Ji=0,nd=1;function _i(n){let e=[],t=0;for(let[r,i]of n)r===Ji?t+=i.length:r===Wi?(e.push({start:t,end:t+i.length,text:i}),t+=i.length):e.push({start:t,end:t,text:i});return e}function rd(n,e){for(let t of n)for(let r of e){let i=t.start===t.end,s=r.start===r.end;if(!(i&&s)){if(i){if(r.start<t.start&&t.start<r.end)return t;continue}if(s){if(t.start<r.start&&r.start<t.end)return r;continue}if(t.start<r.end&&r.start<t.end)return t}}}function Li(n,e,t){let r=c=>c<0||c>=n.length||n[c]===`
8
- `,i=e.filter(c=>c.start<c.end),s=[...i,...t.filter(c=>c.start<c.end)],o=t.filter(c=>c.start===c.end),a=(c,l)=>{let h=l.find(u=>u.start===c);return h===void 0?c:a(h.end,l)},d=(c,l)=>{let h=l.find(u=>u.end===c);return h===void 0?c:d(h.start,l)};for(let c of e)if(c.start===c.end){if(!c.text.startsWith(`
9
- `)&&r(d(c.start,i)-1)){let l=d(c.start,s);if(!r(l-1))return c;for(let h of o)if(l<=h.start&&h.start<=c.start&&!h.text.endsWith(`
3
+ var Ta=Object.create;var vr=Object.defineProperty;var Ia=Object.getOwnPropertyDescriptor;var Ra=Object.getOwnPropertyNames;var Oa=Object.getPrototypeOf,Ma=Object.prototype.hasOwnProperty;var Na=(n,e,t)=>()=>{if(t)throw t[0];try{return n&&(e=n(n=0)),e}catch(i){throw t=[i],i}};var _a=(n,e)=>()=>{try{return e||n((e={exports:{}}).exports,e),e.exports}catch(t){throw e=0,t}};var La=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Ra(e))!Ma.call(n,r)&&r!==t&&vr(n,r,{get:()=>e[r],enumerable:!(i=Ia(e,r))||i.enumerable});return n};var br=(n,e,t)=>(t=n!=null?Ta(Oa(n)):{},La(e||!n||!n.__esModule?vr(t,"default",{value:n,enumerable:!0}):t,n));function Er(){let n=globalThis.crypto;if(!n?.subtle)throw new Error("WebCrypto is unavailable, so this device cannot name what it sends");return n.subtle}function Lt(n){let e=globalThis.crypto;if(!e?.getRandomValues)throw new Error("no secure random source is available, so no credential can be made here");return e.getRandomValues(new Uint8Array(n))}async function Je(n){let e=await Er().digest("SHA-256",n);return kr(new Uint8Array(e))}async function vn(n,e=Ua){let t=[];for(let i=0;i<n.length;i+=e){let r=await Promise.all(n.slice(i,i+e).map(s=>Je(s)));for(let s of r)t.push(s)}return t}async function ke(n){return kr(new Uint8Array(await Er().digest("SHA-256",n)))}function vt(n){return typeof n=="string"&&/^[0-9a-f]{64}$/.test(n)}function kr(n){let e="";for(let t of n)e+=t.toString(16).padStart(2,"0");return e}function je(n){let e="";for(let t=0;t<n.length;t+=3){let i=n[t],r=t+1<n.length?n[t+1]:void 0,s=t+2<n.length?n[t+2]:void 0;if(e+=wt[i>>2],e+=wt[(i&3)<<4|(r??0)>>4],r===void 0||(e+=wt[(r&15)<<2|(s??0)>>6],s===void 0))break;e+=wt[s&63]}return e}function He(n){let e=n.length,t=new Uint8Array(Math.floor(e*3/4)),i=0,r=0,s=0;for(let o=0;o<e;o++){let a=n.charCodeAt(o),d=a<128?za[a]:-1;if(d<0)throw new Error(`invalid base64url character ${JSON.stringify(n[o])} at position ${o}`);r=r<<6|d,s+=6,s>=8&&(s-=8,t[i++]=r>>s&255)}if(s===6)throw new Error(`this base64url value is ${e} characters, which is one more than a whole number of bytes: the last character adds no byte and something has been added to it or lost from it`);if(s>0&&(r&(1<<s)-1)!==0)throw new Error(`this base64url value ends with ${s} bits that no byte uses, and they are not zero, so it is not the encoding of the bytes it decodes to`);return t.subarray(0,i)}var Ua,wt,za,Re=Na(()=>{"use strict";Ua=16;wt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";za=(()=>{let n=new Int16Array(128).fill(-1);for(let e=0;e<wt.length;e++)n[wt.charCodeAt(e)]=e;return n})()});var ci=_a((Xh,bt)=>{var E=function(){this.Diff_Timeout=1,this.Diff_EditCost=4,this.Match_Threshold=.5,this.Match_Distance=1e3,this.Patch_DeleteThreshold=.5,this.Patch_Margin=4,this.Match_MaxBits=32},M=-1,N=1,$=0;E.Diff=function(n,e){return[n,e]};E.prototype.diff_main=function(n,e,t,i){typeof i>"u"&&(this.Diff_Timeout<=0?i=Number.MAX_VALUE:i=new Date().getTime()+this.Diff_Timeout*1e3);var r=i;if(n==null||e==null)throw new Error("Null input. (diff_main)");if(n==e)return n?[new E.Diff($,n)]:[];typeof t>"u"&&(t=!0);var s=t,o=this.diff_commonPrefix(n,e),a=n.substring(0,o);n=n.substring(o),e=e.substring(o),o=this.diff_commonSuffix(n,e);var d=n.substring(n.length-o);n=n.substring(0,n.length-o),e=e.substring(0,e.length-o);var c=this.diff_compute_(n,e,s,r);return a&&c.unshift(new E.Diff($,a)),d&&c.push(new E.Diff($,d)),this.diff_cleanupMerge(c),c};E.prototype.diff_compute_=function(n,e,t,i){var r;if(!n)return[new E.Diff(N,e)];if(!e)return[new E.Diff(M,n)];var s=n.length>e.length?n:e,o=n.length>e.length?e:n,a=s.indexOf(o);if(a!=-1)return r=[new E.Diff(N,s.substring(0,a)),new E.Diff($,o),new E.Diff(N,s.substring(a+o.length))],n.length>e.length&&(r[0][0]=r[2][0]=M),r;if(o.length==1)return[new E.Diff(M,n),new E.Diff(N,e)];var d=this.diff_halfMatch_(n,e);if(d){var c=d[0],l=d[1],h=d[2],u=d[3],f=d[4],g=this.diff_main(c,h,t,i),m=this.diff_main(l,u,t,i);return g.concat([new E.Diff($,f)],m)}return t&&n.length>100&&e.length>100?this.diff_lineMode_(n,e,i):this.diff_bisect_(n,e,i)};E.prototype.diff_lineMode_=function(n,e,t){var i=this.diff_linesToChars_(n,e);n=i.chars1,e=i.chars2;var r=i.lineArray,s=this.diff_main(n,e,!1,t);this.diff_charsToLines_(s,r),this.diff_cleanupSemantic(s),s.push(new E.Diff($,""));for(var o=0,a=0,d=0,c="",l="";o<s.length;){switch(s[o][0]){case N:d++,l+=s[o][1];break;case M:a++,c+=s[o][1];break;case $:if(a>=1&&d>=1){s.splice(o-a-d,a+d),o=o-a-d;for(var h=this.diff_main(c,l,!1,t),u=h.length-1;u>=0;u--)s.splice(o,0,h[u]);o=o+h.length}d=0,a=0,c="",l="";break}o++}return s.pop(),s};E.prototype.diff_bisect_=function(n,e,t){for(var i=n.length,r=e.length,s=Math.ceil((i+r)/2),o=s,a=2*s,d=new Array(a),c=new Array(a),l=0;l<a;l++)d[l]=-1,c[l]=-1;d[o+1]=0,c[o+1]=0;for(var h=i-r,u=h%2!=0,f=0,g=0,m=0,y=0,w=0;w<s&&!(new Date().getTime()>t);w++){for(var b=-w+f;b<=w-g;b+=2){var k=o+b,S;b==-w||b!=w&&d[k-1]<d[k+1]?S=d[k+1]:S=d[k-1]+1;for(var v=S-b;S<i&&v<r&&n.charAt(S)==e.charAt(v);)S++,v++;if(d[k]=S,S>i)g+=2;else if(v>r)f+=2;else if(u){var A=o+h-b;if(A>=0&&A<a&&c[A]!=-1){var F=i-c[A];if(S>=F)return this.diff_bisectSplit_(n,e,S,v,t)}}}for(var x=-w+m;x<=w-y;x+=2){var A=o+x,F;x==-w||x!=w&&c[A-1]<c[A+1]?F=c[A+1]:F=c[A-1]+1;for(var p=F-x;F<i&&p<r&&n.charAt(i-F-1)==e.charAt(r-p-1);)F++,p++;if(c[A]=F,F>i)y+=2;else if(p>r)m+=2;else if(!u){var k=o+h-x;if(k>=0&&k<a&&d[k]!=-1){var S=d[k],v=o+S-k;if(F=i-F,S>=F)return this.diff_bisectSplit_(n,e,S,v,t)}}}}return[new E.Diff(M,n),new E.Diff(N,e)]};E.prototype.diff_bisectSplit_=function(n,e,t,i,r){var s=n.substring(0,t),o=e.substring(0,i),a=n.substring(t),d=e.substring(i),c=this.diff_main(s,o,!1,r),l=this.diff_main(a,d,!1,r);return c.concat(l)};E.prototype.diff_linesToChars_=function(n,e){var t=[],i={};t[0]="";function r(d){for(var c="",l=0,h=-1,u=t.length;h<d.length-1;){h=d.indexOf(`
4
+ `,l),h==-1&&(h=d.length-1);var f=d.substring(l,h+1);(i.hasOwnProperty?i.hasOwnProperty(f):i[f]!==void 0)?c+=String.fromCharCode(i[f]):(u==s&&(f=d.substring(l),h=d.length),c+=String.fromCharCode(u),i[f]=u,t[u++]=f),l=h+1}return c}var s=4e4,o=r(n);s=65535;var a=r(e);return{chars1:o,chars2:a,lineArray:t}};E.prototype.diff_charsToLines_=function(n,e){for(var t=0;t<n.length;t++){for(var i=n[t][1],r=[],s=0;s<i.length;s++)r[s]=e[i.charCodeAt(s)];n[t][1]=r.join("")}};E.prototype.diff_commonPrefix=function(n,e){if(!n||!e||n.charAt(0)!=e.charAt(0))return 0;for(var t=0,i=Math.min(n.length,e.length),r=i,s=0;t<r;)n.substring(s,r)==e.substring(s,r)?(t=r,s=t):i=r,r=Math.floor((i-t)/2+t);return r};E.prototype.diff_commonSuffix=function(n,e){if(!n||!e||n.charAt(n.length-1)!=e.charAt(e.length-1))return 0;for(var t=0,i=Math.min(n.length,e.length),r=i,s=0;t<r;)n.substring(n.length-r,n.length-s)==e.substring(e.length-r,e.length-s)?(t=r,s=t):i=r,r=Math.floor((i-t)/2+t);return r};E.prototype.diff_commonOverlap_=function(n,e){var t=n.length,i=e.length;if(t==0||i==0)return 0;t>i?n=n.substring(t-i):t<i&&(e=e.substring(0,t));var r=Math.min(t,i);if(n==e)return r;for(var s=0,o=1;;){var a=n.substring(r-o),d=e.indexOf(a);if(d==-1)return s;o+=d,(d==0||n.substring(r-o)==e.substring(0,o))&&(s=o,o++)}};E.prototype.diff_halfMatch_=function(n,e){if(this.Diff_Timeout<=0)return null;var t=n.length>e.length?n:e,i=n.length>e.length?e:n;if(t.length<4||i.length*2<t.length)return null;var r=this;function s(g,m,y){for(var w=g.substring(y,y+Math.floor(g.length/4)),b=-1,k="",S,v,A,F;(b=m.indexOf(w,b+1))!=-1;){var x=r.diff_commonPrefix(g.substring(y),m.substring(b)),p=r.diff_commonSuffix(g.substring(0,y),m.substring(0,b));k.length<p+x&&(k=m.substring(b-p,b)+m.substring(b,b+x),S=g.substring(0,y-p),v=g.substring(y+x),A=m.substring(0,b-p),F=m.substring(b+x))}return k.length*2>=g.length?[S,v,A,F,k]:null}var o=s(t,i,Math.ceil(t.length/4)),a=s(t,i,Math.ceil(t.length/2)),d;if(!o&&!a)return null;a?o?d=o[4].length>a[4].length?o:a:d=a:d=o;var c,l,h,u;n.length>e.length?(c=d[0],l=d[1],h=d[2],u=d[3]):(h=d[0],u=d[1],c=d[2],l=d[3]);var f=d[4];return[c,l,h,u,f]};E.prototype.diff_cleanupSemantic=function(n){for(var e=!1,t=[],i=0,r=null,s=0,o=0,a=0,d=0,c=0;s<n.length;)n[s][0]==$?(t[i++]=s,o=d,a=c,d=0,c=0,r=n[s][1]):(n[s][0]==N?d+=n[s][1].length:c+=n[s][1].length,r&&r.length<=Math.max(o,a)&&r.length<=Math.max(d,c)&&(n.splice(t[i-1],0,new E.Diff(M,r)),n[t[i-1]+1][0]=N,i--,i--,s=i>0?t[i-1]:-1,o=0,a=0,d=0,c=0,r=null,e=!0)),s++;for(e&&this.diff_cleanupMerge(n),this.diff_cleanupSemanticLossless(n),s=1;s<n.length;){if(n[s-1][0]==M&&n[s][0]==N){var l=n[s-1][1],h=n[s][1],u=this.diff_commonOverlap_(l,h),f=this.diff_commonOverlap_(h,l);u>=f?(u>=l.length/2||u>=h.length/2)&&(n.splice(s,0,new E.Diff($,h.substring(0,u))),n[s-1][1]=l.substring(0,l.length-u),n[s+1][1]=h.substring(u),s++):(f>=l.length/2||f>=h.length/2)&&(n.splice(s,0,new E.Diff($,l.substring(0,f))),n[s-1][0]=N,n[s-1][1]=h.substring(0,h.length-f),n[s+1][0]=M,n[s+1][1]=l.substring(f),s++),s++}s++}};E.prototype.diff_cleanupSemanticLossless=function(n){function e(f,g){if(!f||!g)return 6;var m=f.charAt(f.length-1),y=g.charAt(0),w=m.match(E.nonAlphaNumericRegex_),b=y.match(E.nonAlphaNumericRegex_),k=w&&m.match(E.whitespaceRegex_),S=b&&y.match(E.whitespaceRegex_),v=k&&m.match(E.linebreakRegex_),A=S&&y.match(E.linebreakRegex_),F=v&&f.match(E.blanklineEndRegex_),x=A&&g.match(E.blanklineStartRegex_);return F||x?5:v||A?4:w&&!k&&S?3:k||S?2:w||b?1:0}for(var t=1;t<n.length-1;){if(n[t-1][0]==$&&n[t+1][0]==$){var i=n[t-1][1],r=n[t][1],s=n[t+1][1],o=this.diff_commonSuffix(i,r);if(o){var a=r.substring(r.length-o);i=i.substring(0,i.length-o),r=a+r.substring(0,r.length-o),s=a+s}for(var d=i,c=r,l=s,h=e(i,r)+e(r,s);r.charAt(0)===s.charAt(0);){i+=r.charAt(0),r=r.substring(1)+s.charAt(0),s=s.substring(1);var u=e(i,r)+e(r,s);u>=h&&(h=u,d=i,c=r,l=s)}n[t-1][1]!=d&&(d?n[t-1][1]=d:(n.splice(t-1,1),t--),n[t][1]=c,l?n[t+1][1]=l:(n.splice(t+1,1),t--))}t++}};E.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;E.whitespaceRegex_=/\s/;E.linebreakRegex_=/[\r\n]/;E.blanklineEndRegex_=/\n\r?\n$/;E.blanklineStartRegex_=/^\r?\n\r?\n/;E.prototype.diff_cleanupEfficiency=function(n){for(var e=!1,t=[],i=0,r=null,s=0,o=!1,a=!1,d=!1,c=!1;s<n.length;)n[s][0]==$?(n[s][1].length<this.Diff_EditCost&&(d||c)?(t[i++]=s,o=d,a=c,r=n[s][1]):(i=0,r=null),d=c=!1):(n[s][0]==M?c=!0:d=!0,r&&(o&&a&&d&&c||r.length<this.Diff_EditCost/2&&o+a+d+c==3)&&(n.splice(t[i-1],0,new E.Diff(M,r)),n[t[i-1]+1][0]=N,i--,r=null,o&&a?(d=c=!0,i=0):(i--,s=i>0?t[i-1]:-1,d=c=!1),e=!0)),s++;e&&this.diff_cleanupMerge(n)};E.prototype.diff_cleanupMerge=function(n){n.push(new E.Diff($,""));for(var e=0,t=0,i=0,r="",s="",o;e<n.length;)switch(n[e][0]){case N:i++,s+=n[e][1],e++;break;case M:t++,r+=n[e][1],e++;break;case $:t+i>1?(t!==0&&i!==0&&(o=this.diff_commonPrefix(s,r),o!==0&&(e-t-i>0&&n[e-t-i-1][0]==$?n[e-t-i-1][1]+=s.substring(0,o):(n.splice(0,0,new E.Diff($,s.substring(0,o))),e++),s=s.substring(o),r=r.substring(o)),o=this.diff_commonSuffix(s,r),o!==0&&(n[e][1]=s.substring(s.length-o)+n[e][1],s=s.substring(0,s.length-o),r=r.substring(0,r.length-o))),e-=t+i,n.splice(e,t+i),r.length&&(n.splice(e,0,new E.Diff(M,r)),e++),s.length&&(n.splice(e,0,new E.Diff(N,s)),e++),e++):e!==0&&n[e-1][0]==$?(n[e-1][1]+=n[e][1],n.splice(e,1)):e++,i=0,t=0,r="",s="";break}n[n.length-1][1]===""&&n.pop();var a=!1;for(e=1;e<n.length-1;)n[e-1][0]==$&&n[e+1][0]==$&&(n[e][1].substring(n[e][1].length-n[e-1][1].length)==n[e-1][1]?(n[e][1]=n[e-1][1]+n[e][1].substring(0,n[e][1].length-n[e-1][1].length),n[e+1][1]=n[e-1][1]+n[e+1][1],n.splice(e-1,1),a=!0):n[e][1].substring(0,n[e+1][1].length)==n[e+1][1]&&(n[e-1][1]+=n[e+1][1],n[e][1]=n[e][1].substring(n[e+1][1].length)+n[e+1][1],n.splice(e+1,1),a=!0)),e++;a&&this.diff_cleanupMerge(n)};E.prototype.diff_xIndex=function(n,e){var t=0,i=0,r=0,s=0,o;for(o=0;o<n.length&&(n[o][0]!==N&&(t+=n[o][1].length),n[o][0]!==M&&(i+=n[o][1].length),!(t>e));o++)r=t,s=i;return n.length!=o&&n[o][0]===M?s:s+(e-r)};E.prototype.diff_prettyHtml=function(n){for(var e=[],t=/&/g,i=/</g,r=/>/g,s=/\n/g,o=0;o<n.length;o++){var a=n[o][0],d=n[o][1],c=d.replace(t,"&amp;").replace(i,"&lt;").replace(r,"&gt;").replace(s,"&para;<br>");switch(a){case N:e[o]='<ins style="background:#e6ffe6;">'+c+"</ins>";break;case M:e[o]='<del style="background:#ffe6e6;">'+c+"</del>";break;case $:e[o]="<span>"+c+"</span>";break}}return e.join("")};E.prototype.diff_text1=function(n){for(var e=[],t=0;t<n.length;t++)n[t][0]!==N&&(e[t]=n[t][1]);return e.join("")};E.prototype.diff_text2=function(n){for(var e=[],t=0;t<n.length;t++)n[t][0]!==M&&(e[t]=n[t][1]);return e.join("")};E.prototype.diff_levenshtein=function(n){for(var e=0,t=0,i=0,r=0;r<n.length;r++){var s=n[r][0],o=n[r][1];switch(s){case N:t+=o.length;break;case M:i+=o.length;break;case $:e+=Math.max(t,i),t=0,i=0;break}}return e+=Math.max(t,i),e};E.prototype.diff_toDelta=function(n){for(var e=[],t=0;t<n.length;t++)switch(n[t][0]){case N:e[t]="+"+encodeURI(n[t][1]);break;case M:e[t]="-"+n[t][1].length;break;case $:e[t]="="+n[t][1].length;break}return e.join(" ").replace(/%20/g," ")};E.prototype.diff_fromDelta=function(n,e){for(var t=[],i=0,r=0,s=e.split(/\t/g),o=0;o<s.length;o++){var a=s[o].substring(1);switch(s[o].charAt(0)){case"+":try{t[i++]=new E.Diff(N,decodeURI(a))}catch{throw new Error("Illegal escape in diff_fromDelta: "+a)}break;case"-":case"=":var d=parseInt(a,10);if(isNaN(d)||d<0)throw new Error("Invalid number in diff_fromDelta: "+a);var c=n.substring(r,r+=d);s[o].charAt(0)=="="?t[i++]=new E.Diff($,c):t[i++]=new E.Diff(M,c);break;default:if(s[o])throw new Error("Invalid diff operation in diff_fromDelta: "+s[o])}}if(r!=n.length)throw new Error("Delta length ("+r+") does not equal source text length ("+n.length+").");return t};E.prototype.match_main=function(n,e,t){if(n==null||e==null||t==null)throw new Error("Null input. (match_main)");return t=Math.max(0,Math.min(t,n.length)),n==e?0:n.length?n.substring(t,t+e.length)==e?t:this.match_bitap_(n,e,t):-1};E.prototype.match_bitap_=function(n,e,t){if(e.length>this.Match_MaxBits)throw new Error("Pattern too long for this browser.");var i=this.match_alphabet_(e),r=this;function s(S,v){var A=S/e.length,F=Math.abs(t-v);return r.Match_Distance?A+F/r.Match_Distance:F?1:A}var o=this.Match_Threshold,a=n.indexOf(e,t);a!=-1&&(o=Math.min(s(0,a),o),a=n.lastIndexOf(e,t+e.length),a!=-1&&(o=Math.min(s(0,a),o)));var d=1<<e.length-1;a=-1;for(var c,l,h=e.length+n.length,u,f=0;f<e.length;f++){for(c=0,l=h;c<l;)s(f,t+l)<=o?c=l:h=l,l=Math.floor((h-c)/2+c);h=l;var g=Math.max(1,t-l+1),m=Math.min(t+l,n.length)+e.length,y=Array(m+2);y[m+1]=(1<<f)-1;for(var w=m;w>=g;w--){var b=i[n.charAt(w-1)];if(f===0?y[w]=(y[w+1]<<1|1)&b:y[w]=(y[w+1]<<1|1)&b|((u[w+1]|u[w])<<1|1)|u[w+1],y[w]&d){var k=s(f,w-1);if(k<=o)if(o=k,a=w-1,a>t)g=Math.max(1,2*t-a);else break}}if(s(f+1,t)>o)break;u=y}return a};E.prototype.match_alphabet_=function(n){for(var e={},t=0;t<n.length;t++)e[n.charAt(t)]=0;for(var t=0;t<n.length;t++)e[n.charAt(t)]|=1<<n.length-t-1;return e};E.prototype.patch_addContext_=function(n,e){if(e.length!=0){if(n.start2===null)throw Error("patch not initialized");for(var t=e.substring(n.start2,n.start2+n.length1),i=0;e.indexOf(t)!=e.lastIndexOf(t)&&t.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)i+=this.Patch_Margin,t=e.substring(n.start2-i,n.start2+n.length1+i);i+=this.Patch_Margin;var r=e.substring(n.start2-i,n.start2);r&&n.diffs.unshift(new E.Diff($,r));var s=e.substring(n.start2+n.length1,n.start2+n.length1+i);s&&n.diffs.push(new E.Diff($,s)),n.start1-=r.length,n.start2-=r.length,n.length1+=r.length+s.length,n.length2+=r.length+s.length}};E.prototype.patch_make=function(n,e,t){var i,r;if(typeof n=="string"&&typeof e=="string"&&typeof t>"u")i=n,r=this.diff_main(i,e,!0),r.length>2&&(this.diff_cleanupSemantic(r),this.diff_cleanupEfficiency(r));else if(n&&typeof n=="object"&&typeof e>"u"&&typeof t>"u")r=n,i=this.diff_text1(r);else if(typeof n=="string"&&e&&typeof e=="object"&&typeof t>"u")i=n,r=e;else if(typeof n=="string"&&typeof e=="string"&&t&&typeof t=="object")i=n,r=t;else throw new Error("Unknown call format to patch_make.");if(r.length===0)return[];for(var s=[],o=new E.patch_obj,a=0,d=0,c=0,l=i,h=i,u=0;u<r.length;u++){var f=r[u][0],g=r[u][1];switch(!a&&f!==$&&(o.start1=d,o.start2=c),f){case N:o.diffs[a++]=r[u],o.length2+=g.length,h=h.substring(0,c)+g+h.substring(c);break;case M:o.length1+=g.length,o.diffs[a++]=r[u],h=h.substring(0,c)+h.substring(c+g.length);break;case $:g.length<=2*this.Patch_Margin&&a&&r.length!=u+1?(o.diffs[a++]=r[u],o.length1+=g.length,o.length2+=g.length):g.length>=2*this.Patch_Margin&&a&&(this.patch_addContext_(o,l),s.push(o),o=new E.patch_obj,a=0,l=h,d=c);break}f!==N&&(d+=g.length),f!==M&&(c+=g.length)}return a&&(this.patch_addContext_(o,l),s.push(o)),s};E.prototype.patch_deepCopy=function(n){for(var e=[],t=0;t<n.length;t++){var i=n[t],r=new E.patch_obj;r.diffs=[];for(var s=0;s<i.diffs.length;s++)r.diffs[s]=new E.Diff(i.diffs[s][0],i.diffs[s][1]);r.start1=i.start1,r.start2=i.start2,r.length1=i.length1,r.length2=i.length2,e[t]=r}return e};E.prototype.patch_apply=function(n,e){if(n.length==0)return[e,[]];n=this.patch_deepCopy(n);var t=this.patch_addPadding(n);e=t+e+t,this.patch_splitMax(n);for(var i=0,r=[],s=0;s<n.length;s++){var o=n[s].start2+i,a=this.diff_text1(n[s].diffs),d,c=-1;if(a.length>this.Match_MaxBits?(d=this.match_main(e,a.substring(0,this.Match_MaxBits),o),d!=-1&&(c=this.match_main(e,a.substring(a.length-this.Match_MaxBits),o+a.length-this.Match_MaxBits),(c==-1||d>=c)&&(d=-1))):d=this.match_main(e,a,o),d==-1)r[s]=!1,i-=n[s].length2-n[s].length1;else{r[s]=!0,i=d-o;var l;if(c==-1?l=e.substring(d,d+a.length):l=e.substring(d,c+this.Match_MaxBits),a==l)e=e.substring(0,d)+this.diff_text2(n[s].diffs)+e.substring(d+a.length);else{var h=this.diff_main(a,l,!1);if(a.length>this.Match_MaxBits&&this.diff_levenshtein(h)/a.length>this.Patch_DeleteThreshold)r[s]=!1;else{this.diff_cleanupSemanticLossless(h);for(var u=0,f,g=0;g<n[s].diffs.length;g++){var m=n[s].diffs[g];m[0]!==$&&(f=this.diff_xIndex(h,u)),m[0]===N?e=e.substring(0,d+f)+m[1]+e.substring(d+f):m[0]===M&&(e=e.substring(0,d+f)+e.substring(d+this.diff_xIndex(h,u+m[1].length))),m[0]!==M&&(u+=m[1].length)}}}}}return e=e.substring(t.length,e.length-t.length),[e,r]};E.prototype.patch_addPadding=function(n){for(var e=this.Patch_Margin,t="",i=1;i<=e;i++)t+=String.fromCharCode(i);for(var i=0;i<n.length;i++)n[i].start1+=e,n[i].start2+=e;var r=n[0],s=r.diffs;if(s.length==0||s[0][0]!=$)s.unshift(new E.Diff($,t)),r.start1-=e,r.start2-=e,r.length1+=e,r.length2+=e;else if(e>s[0][1].length){var o=e-s[0][1].length;s[0][1]=t.substring(s[0][1].length)+s[0][1],r.start1-=o,r.start2-=o,r.length1+=o,r.length2+=o}if(r=n[n.length-1],s=r.diffs,s.length==0||s[s.length-1][0]!=$)s.push(new E.Diff($,t)),r.length1+=e,r.length2+=e;else if(e>s[s.length-1][1].length){var o=e-s[s.length-1][1].length;s[s.length-1][1]+=t.substring(0,o),r.length1+=o,r.length2+=o}return t};E.prototype.patch_splitMax=function(n){for(var e=this.Match_MaxBits,t=0;t<n.length;t++)if(!(n[t].length1<=e)){var i=n[t];n.splice(t--,1);for(var r=i.start1,s=i.start2,o="";i.diffs.length!==0;){var a=new E.patch_obj,d=!0;for(a.start1=r-o.length,a.start2=s-o.length,o!==""&&(a.length1=a.length2=o.length,a.diffs.push(new E.Diff($,o)));i.diffs.length!==0&&a.length1<e-this.Patch_Margin;){var c=i.diffs[0][0],l=i.diffs[0][1];c===N?(a.length2+=l.length,s+=l.length,a.diffs.push(i.diffs.shift()),d=!1):c===M&&a.diffs.length==1&&a.diffs[0][0]==$&&l.length>2*e?(a.length1+=l.length,r+=l.length,d=!1,a.diffs.push(new E.Diff(c,l)),i.diffs.shift()):(l=l.substring(0,e-a.length1-this.Patch_Margin),a.length1+=l.length,r+=l.length,c===$?(a.length2+=l.length,s+=l.length):d=!1,a.diffs.push(new E.Diff(c,l)),l==i.diffs[0][1]?i.diffs.shift():i.diffs[0][1]=i.diffs[0][1].substring(l.length))}o=this.diff_text2(a.diffs),o=o.substring(o.length-this.Patch_Margin);var h=this.diff_text1(i.diffs).substring(0,this.Patch_Margin);h!==""&&(a.length1+=h.length,a.length2+=h.length,a.diffs.length!==0&&a.diffs[a.diffs.length-1][0]===$?a.diffs[a.diffs.length-1][1]+=h:a.diffs.push(new E.Diff($,h))),d||n.splice(++t,0,a)}}};E.prototype.patch_toText=function(n){for(var e=[],t=0;t<n.length;t++)e[t]=n[t];return e.join("")};E.prototype.patch_fromText=function(n){var e=[];if(!n)return e;for(var t=n.split(`
5
+ `),i=0,r=/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/;i<t.length;){var s=t[i].match(r);if(!s)throw new Error("Invalid patch string: "+t[i]);var o=new E.patch_obj;for(e.push(o),o.start1=parseInt(s[1],10),s[2]===""?(o.start1--,o.length1=1):s[2]=="0"?o.length1=0:(o.start1--,o.length1=parseInt(s[2],10)),o.start2=parseInt(s[3],10),s[4]===""?(o.start2--,o.length2=1):s[4]=="0"?o.length2=0:(o.start2--,o.length2=parseInt(s[4],10)),i++;i<t.length;){var a=t[i].charAt(0);try{var d=decodeURI(t[i].substring(1))}catch{throw new Error("Illegal escape in patch_fromText: "+d)}if(a=="-")o.diffs.push(new E.Diff(M,d));else if(a=="+")o.diffs.push(new E.Diff(N,d));else if(a==" ")o.diffs.push(new E.Diff($,d));else{if(a=="@")break;if(a!=="")throw new Error('Invalid patch mode "'+a+'" in: '+d)}i++}}return e};E.patch_obj=function(){this.diffs=[],this.start1=null,this.start2=null,this.length1=0,this.length2=0};E.patch_obj.prototype.toString=function(){var n,e;this.length1===0?n=this.start1+",0":this.length1==1?n=this.start1+1:n=this.start1+1+","+this.length1,this.length2===0?e=this.start2+",0":this.length2==1?e=this.start2+1:e=this.start2+1+","+this.length2;for(var t=["@@ -"+n+" +"+e+` @@
6
+ `],i,r=0;r<this.diffs.length;r++){switch(this.diffs[r][0]){case N:i="+";break;case M:i="-";break;case $:i=" ";break}t[r+1]=i+encodeURI(this.diffs[r][1])+`
7
+ `}return t.join("").replace(/%20/g," ")};bt.exports=E;bt.exports.diff_match_patch=E;bt.exports.DIFF_DELETE=M;bt.exports.DIFF_INSERT=N;bt.exports.DIFF_EQUAL=$});Re();var Ar="41 61,42 62,43 63,44 64,45 65,46 66,47 67,48 68,49 69,4A 6A,4B 6B,4C 6C,4D 6D,4E 6E,4F 6F,50 70,51 71,52 72,53 73,54 74,55 75,56 76,57 77,58 78,59 79,5A 7A,B5 3BC,C0 E0,C1 E1,C2 E2,C3 E3,C4 E4,C5 E5,C6 E6,C7 E7,C8 E8,C9 E9,CA EA,CB EB,CC EC,CD ED,CE EE,CF EF,D0 F0,D1 F1,D2 F2,D3 F3,D4 F4,D5 F5,D6 F6,D8 F8,D9 F9,DA FA,DB FB,DC FC,DD FD,DE FE,DF 73 73,100 101,102 103,104 105,106 107,108 109,10A 10B,10C 10D,10E 10F,110 111,112 113,114 115,116 117,118 119,11A 11B,11C 11D,11E 11F,120 121,122 123,124 125,126 127,128 129,12A 12B,12C 12D,12E 12F,130 69 307,132 133,134 135,136 137,139 13A,13B 13C,13D 13E,13F 140,141 142,143 144,145 146,147 148,149 2BC 6E,14A 14B,14C 14D,14E 14F,150 151,152 153,154 155,156 157,158 159,15A 15B,15C 15D,15E 15F,160 161,162 163,164 165,166 167,168 169,16A 16B,16C 16D,16E 16F,170 171,172 173,174 175,176 177,178 FF,179 17A,17B 17C,17D 17E,17F 73,181 253,182 183,184 185,186 254,187 188,189 256,18A 257,18B 18C,18E 1DD,18F 259,190 25B,191 192,193 260,194 263,196 269,197 268,198 199,19C 26F,19D 272,19F 275,1A0 1A1,1A2 1A3,1A4 1A5,1A6 280,1A7 1A8,1A9 283,1AC 1AD,1AE 288,1AF 1B0,1B1 28A,1B2 28B,1B3 1B4,1B5 1B6,1B7 292,1B8 1B9,1BC 1BD,1C4 1C6,1C5 1C6,1C7 1C9,1C8 1C9,1CA 1CC,1CB 1CC,1CD 1CE,1CF 1D0,1D1 1D2,1D3 1D4,1D5 1D6,1D7 1D8,1D9 1DA,1DB 1DC,1DE 1DF,1E0 1E1,1E2 1E3,1E4 1E5,1E6 1E7,1E8 1E9,1EA 1EB,1EC 1ED,1EE 1EF,1F0 6A 30C,1F1 1F3,1F2 1F3,1F4 1F5,1F6 195,1F7 1BF,1F8 1F9,1FA 1FB,1FC 1FD,1FE 1FF,200 201,202 203,204 205,206 207,208 209,20A 20B,20C 20D,20E 20F,210 211,212 213,214 215,216 217,218 219,21A 21B,21C 21D,21E 21F,220 19E,222 223,224 225,226 227,228 229,22A 22B,22C 22D,22E 22F,230 231,232 233,23A 2C65,23B 23C,23D 19A,23E 2C66,241 242,243 180,244 289,245 28C,246 247,248 249,24A 24B,24C 24D,24E 24F,345 3B9,370 371,372 373,376 377,37F 3F3,386 3AC,388 3AD,389 3AE,38A 3AF,38C 3CC,38E 3CD,38F 3CE,390 3B9 308 301,391 3B1,392 3B2,393 3B3,394 3B4,395 3B5,396 3B6,397 3B7,398 3B8,399 3B9,39A 3BA,39B 3BB,39C 3BC,39D 3BD,39E 3BE,39F 3BF,3A0 3C0,3A1 3C1,3A3 3C3,3A4 3C4,3A5 3C5,3A6 3C6,3A7 3C7,3A8 3C8,3A9 3C9,3AA 3CA,3AB 3CB,3B0 3C5 308 301,3C2 3C3,3CF 3D7,3D0 3B2,3D1 3B8,3D5 3C6,3D6 3C0,3D8 3D9,3DA 3DB,3DC 3DD,3DE 3DF,3E0 3E1,3E2 3E3,3E4 3E5,3E6 3E7,3E8 3E9,3EA 3EB,3EC 3ED,3EE 3EF,3F0 3BA,3F1 3C1,3F4 3B8,3F5 3B5,3F7 3F8,3F9 3F2,3FA 3FB,3FD 37B,3FE 37C,3FF 37D,400 450,401 451,402 452,403 453,404 454,405 455,406 456,407 457,408 458,409 459,40A 45A,40B 45B,40C 45C,40D 45D,40E 45E,40F 45F,410 430,411 431,412 432,413 433,414 434,415 435,416 436,417 437,418 438,419 439,41A 43A,41B 43B,41C 43C,41D 43D,41E 43E,41F 43F,420 440,421 441,422 442,423 443,424 444,425 445,426 446,427 447,428 448,429 449,42A 44A,42B 44B,42C 44C,42D 44D,42E 44E,42F 44F,460 461,462 463,464 465,466 467,468 469,46A 46B,46C 46D,46E 46F,470 471,472 473,474 475,476 477,478 479,47A 47B,47C 47D,47E 47F,480 481,48A 48B,48C 48D,48E 48F,490 491,492 493,494 495,496 497,498 499,49A 49B,49C 49D,49E 49F,4A0 4A1,4A2 4A3,4A4 4A5,4A6 4A7,4A8 4A9,4AA 4AB,4AC 4AD,4AE 4AF,4B0 4B1,4B2 4B3,4B4 4B5,4B6 4B7,4B8 4B9,4BA 4BB,4BC 4BD,4BE 4BF,4C0 4CF,4C1 4C2,4C3 4C4,4C5 4C6,4C7 4C8,4C9 4CA,4CB 4CC,4CD 4CE,4D0 4D1,4D2 4D3,4D4 4D5,4D6 4D7,4D8 4D9,4DA 4DB,4DC 4DD,4DE 4DF,4E0 4E1,4E2 4E3,4E4 4E5,4E6 4E7,4E8 4E9,4EA 4EB,4EC 4ED,4EE 4EF,4F0 4F1,4F2 4F3,4F4 4F5,4F6 4F7,4F8 4F9,4FA 4FB,4FC 4FD,4FE 4FF,500 501,502 503,504 505,506 507,508 509,50A 50B,50C 50D,50E 50F,510 511,512 513,514 515,516 517,518 519,51A 51B,51C 51D,51E 51F,520 521,522 523,524 525,526 527,528 529,52A 52B,52C 52D,52E 52F,531 561,532 562,533 563,534 564,535 565,536 566,537 567,538 568,539 569,53A 56A,53B 56B,53C 56C,53D 56D,53E 56E,53F 56F,540 570,541 571,542 572,543 573,544 574,545 575,546 576,547 577,548 578,549 579,54A 57A,54B 57B,54C 57C,54D 57D,54E 57E,54F 57F,550 580,551 581,552 582,553 583,554 584,555 585,556 586,587 565 582,10A0 2D00,10A1 2D01,10A2 2D02,10A3 2D03,10A4 2D04,10A5 2D05,10A6 2D06,10A7 2D07,10A8 2D08,10A9 2D09,10AA 2D0A,10AB 2D0B,10AC 2D0C,10AD 2D0D,10AE 2D0E,10AF 2D0F,10B0 2D10,10B1 2D11,10B2 2D12,10B3 2D13,10B4 2D14,10B5 2D15,10B6 2D16,10B7 2D17,10B8 2D18,10B9 2D19,10BA 2D1A,10BB 2D1B,10BC 2D1C,10BD 2D1D,10BE 2D1E,10BF 2D1F,10C0 2D20,10C1 2D21,10C2 2D22,10C3 2D23,10C4 2D24,10C5 2D25,10C7 2D27,10CD 2D2D,13F8 13F0,13F9 13F1,13FA 13F2,13FB 13F3,13FC 13F4,13FD 13F5,1C80 432,1C81 434,1C82 43E,1C83 441,1C84 442,1C85 442,1C86 44A,1C87 463,1C88 A64B,1C90 10D0,1C91 10D1,1C92 10D2,1C93 10D3,1C94 10D4,1C95 10D5,1C96 10D6,1C97 10D7,1C98 10D8,1C99 10D9,1C9A 10DA,1C9B 10DB,1C9C 10DC,1C9D 10DD,1C9E 10DE,1C9F 10DF,1CA0 10E0,1CA1 10E1,1CA2 10E2,1CA3 10E3,1CA4 10E4,1CA5 10E5,1CA6 10E6,1CA7 10E7,1CA8 10E8,1CA9 10E9,1CAA 10EA,1CAB 10EB,1CAC 10EC,1CAD 10ED,1CAE 10EE,1CAF 10EF,1CB0 10F0,1CB1 10F1,1CB2 10F2,1CB3 10F3,1CB4 10F4,1CB5 10F5,1CB6 10F6,1CB7 10F7,1CB8 10F8,1CB9 10F9,1CBA 10FA,1CBD 10FD,1CBE 10FE,1CBF 10FF,1E00 1E01,1E02 1E03,1E04 1E05,1E06 1E07,1E08 1E09,1E0A 1E0B,1E0C 1E0D,1E0E 1E0F,1E10 1E11,1E12 1E13,1E14 1E15,1E16 1E17,1E18 1E19,1E1A 1E1B,1E1C 1E1D,1E1E 1E1F,1E20 1E21,1E22 1E23,1E24 1E25,1E26 1E27,1E28 1E29,1E2A 1E2B,1E2C 1E2D,1E2E 1E2F,1E30 1E31,1E32 1E33,1E34 1E35,1E36 1E37,1E38 1E39,1E3A 1E3B,1E3C 1E3D,1E3E 1E3F,1E40 1E41,1E42 1E43,1E44 1E45,1E46 1E47,1E48 1E49,1E4A 1E4B,1E4C 1E4D,1E4E 1E4F,1E50 1E51,1E52 1E53,1E54 1E55,1E56 1E57,1E58 1E59,1E5A 1E5B,1E5C 1E5D,1E5E 1E5F,1E60 1E61,1E62 1E63,1E64 1E65,1E66 1E67,1E68 1E69,1E6A 1E6B,1E6C 1E6D,1E6E 1E6F,1E70 1E71,1E72 1E73,1E74 1E75,1E76 1E77,1E78 1E79,1E7A 1E7B,1E7C 1E7D,1E7E 1E7F,1E80 1E81,1E82 1E83,1E84 1E85,1E86 1E87,1E88 1E89,1E8A 1E8B,1E8C 1E8D,1E8E 1E8F,1E90 1E91,1E92 1E93,1E94 1E95,1E96 68 331,1E97 74 308,1E98 77 30A,1E99 79 30A,1E9A 61 2BE,1E9B 1E61,1E9E 73 73,1EA0 1EA1,1EA2 1EA3,1EA4 1EA5,1EA6 1EA7,1EA8 1EA9,1EAA 1EAB,1EAC 1EAD,1EAE 1EAF,1EB0 1EB1,1EB2 1EB3,1EB4 1EB5,1EB6 1EB7,1EB8 1EB9,1EBA 1EBB,1EBC 1EBD,1EBE 1EBF,1EC0 1EC1,1EC2 1EC3,1EC4 1EC5,1EC6 1EC7,1EC8 1EC9,1ECA 1ECB,1ECC 1ECD,1ECE 1ECF,1ED0 1ED1,1ED2 1ED3,1ED4 1ED5,1ED6 1ED7,1ED8 1ED9,1EDA 1EDB,1EDC 1EDD,1EDE 1EDF,1EE0 1EE1,1EE2 1EE3,1EE4 1EE5,1EE6 1EE7,1EE8 1EE9,1EEA 1EEB,1EEC 1EED,1EEE 1EEF,1EF0 1EF1,1EF2 1EF3,1EF4 1EF5,1EF6 1EF7,1EF8 1EF9,1EFA 1EFB,1EFC 1EFD,1EFE 1EFF,1F08 1F00,1F09 1F01,1F0A 1F02,1F0B 1F03,1F0C 1F04,1F0D 1F05,1F0E 1F06,1F0F 1F07,1F18 1F10,1F19 1F11,1F1A 1F12,1F1B 1F13,1F1C 1F14,1F1D 1F15,1F28 1F20,1F29 1F21,1F2A 1F22,1F2B 1F23,1F2C 1F24,1F2D 1F25,1F2E 1F26,1F2F 1F27,1F38 1F30,1F39 1F31,1F3A 1F32,1F3B 1F33,1F3C 1F34,1F3D 1F35,1F3E 1F36,1F3F 1F37,1F48 1F40,1F49 1F41,1F4A 1F42,1F4B 1F43,1F4C 1F44,1F4D 1F45,1F50 3C5 313,1F52 3C5 313 300,1F54 3C5 313 301,1F56 3C5 313 342,1F59 1F51,1F5B 1F53,1F5D 1F55,1F5F 1F57,1F68 1F60,1F69 1F61,1F6A 1F62,1F6B 1F63,1F6C 1F64,1F6D 1F65,1F6E 1F66,1F6F 1F67,1F80 1F00 3B9,1F81 1F01 3B9,1F82 1F02 3B9,1F83 1F03 3B9,1F84 1F04 3B9,1F85 1F05 3B9,1F86 1F06 3B9,1F87 1F07 3B9,1F88 1F00 3B9,1F89 1F01 3B9,1F8A 1F02 3B9,1F8B 1F03 3B9,1F8C 1F04 3B9,1F8D 1F05 3B9,1F8E 1F06 3B9,1F8F 1F07 3B9,1F90 1F20 3B9,1F91 1F21 3B9,1F92 1F22 3B9,1F93 1F23 3B9,1F94 1F24 3B9,1F95 1F25 3B9,1F96 1F26 3B9,1F97 1F27 3B9,1F98 1F20 3B9,1F99 1F21 3B9,1F9A 1F22 3B9,1F9B 1F23 3B9,1F9C 1F24 3B9,1F9D 1F25 3B9,1F9E 1F26 3B9,1F9F 1F27 3B9,1FA0 1F60 3B9,1FA1 1F61 3B9,1FA2 1F62 3B9,1FA3 1F63 3B9,1FA4 1F64 3B9,1FA5 1F65 3B9,1FA6 1F66 3B9,1FA7 1F67 3B9,1FA8 1F60 3B9,1FA9 1F61 3B9,1FAA 1F62 3B9,1FAB 1F63 3B9,1FAC 1F64 3B9,1FAD 1F65 3B9,1FAE 1F66 3B9,1FAF 1F67 3B9,1FB2 1F70 3B9,1FB3 3B1 3B9,1FB4 3AC 3B9,1FB6 3B1 342,1FB7 3B1 342 3B9,1FB8 1FB0,1FB9 1FB1,1FBA 1F70,1FBB 1F71,1FBC 3B1 3B9,1FBE 3B9,1FC2 1F74 3B9,1FC3 3B7 3B9,1FC4 3AE 3B9,1FC6 3B7 342,1FC7 3B7 342 3B9,1FC8 1F72,1FC9 1F73,1FCA 1F74,1FCB 1F75,1FCC 3B7 3B9,1FD2 3B9 308 300,1FD3 3B9 308 301,1FD6 3B9 342,1FD7 3B9 308 342,1FD8 1FD0,1FD9 1FD1,1FDA 1F76,1FDB 1F77,1FE2 3C5 308 300,1FE3 3C5 308 301,1FE4 3C1 313,1FE6 3C5 342,1FE7 3C5 308 342,1FE8 1FE0,1FE9 1FE1,1FEA 1F7A,1FEB 1F7B,1FEC 1FE5,1FF2 1F7C 3B9,1FF3 3C9 3B9,1FF4 3CE 3B9,1FF6 3C9 342,1FF7 3C9 342 3B9,1FF8 1F78,1FF9 1F79,1FFA 1F7C,1FFB 1F7D,1FFC 3C9 3B9,2126 3C9,212A 6B,212B E5,2132 214E,2160 2170,2161 2171,2162 2172,2163 2173,2164 2174,2165 2175,2166 2176,2167 2177,2168 2178,2169 2179,216A 217A,216B 217B,216C 217C,216D 217D,216E 217E,216F 217F,2183 2184,24B6 24D0,24B7 24D1,24B8 24D2,24B9 24D3,24BA 24D4,24BB 24D5,24BC 24D6,24BD 24D7,24BE 24D8,24BF 24D9,24C0 24DA,24C1 24DB,24C2 24DC,24C3 24DD,24C4 24DE,24C5 24DF,24C6 24E0,24C7 24E1,24C8 24E2,24C9 24E3,24CA 24E4,24CB 24E5,24CC 24E6,24CD 24E7,24CE 24E8,24CF 24E9,2C00 2C30,2C01 2C31,2C02 2C32,2C03 2C33,2C04 2C34,2C05 2C35,2C06 2C36,2C07 2C37,2C08 2C38,2C09 2C39,2C0A 2C3A,2C0B 2C3B,2C0C 2C3C,2C0D 2C3D,2C0E 2C3E,2C0F 2C3F,2C10 2C40,2C11 2C41,2C12 2C42,2C13 2C43,2C14 2C44,2C15 2C45,2C16 2C46,2C17 2C47,2C18 2C48,2C19 2C49,2C1A 2C4A,2C1B 2C4B,2C1C 2C4C,2C1D 2C4D,2C1E 2C4E,2C1F 2C4F,2C20 2C50,2C21 2C51,2C22 2C52,2C23 2C53,2C24 2C54,2C25 2C55,2C26 2C56,2C27 2C57,2C28 2C58,2C29 2C59,2C2A 2C5A,2C2B 2C5B,2C2C 2C5C,2C2D 2C5D,2C2E 2C5E,2C2F 2C5F,2C60 2C61,2C62 26B,2C63 1D7D,2C64 27D,2C67 2C68,2C69 2C6A,2C6B 2C6C,2C6D 251,2C6E 271,2C6F 250,2C70 252,2C72 2C73,2C75 2C76,2C7E 23F,2C7F 240,2C80 2C81,2C82 2C83,2C84 2C85,2C86 2C87,2C88 2C89,2C8A 2C8B,2C8C 2C8D,2C8E 2C8F,2C90 2C91,2C92 2C93,2C94 2C95,2C96 2C97,2C98 2C99,2C9A 2C9B,2C9C 2C9D,2C9E 2C9F,2CA0 2CA1,2CA2 2CA3,2CA4 2CA5,2CA6 2CA7,2CA8 2CA9,2CAA 2CAB,2CAC 2CAD,2CAE 2CAF,2CB0 2CB1,2CB2 2CB3,2CB4 2CB5,2CB6 2CB7,2CB8 2CB9,2CBA 2CBB,2CBC 2CBD,2CBE 2CBF,2CC0 2CC1,2CC2 2CC3,2CC4 2CC5,2CC6 2CC7,2CC8 2CC9,2CCA 2CCB,2CCC 2CCD,2CCE 2CCF,2CD0 2CD1,2CD2 2CD3,2CD4 2CD5,2CD6 2CD7,2CD8 2CD9,2CDA 2CDB,2CDC 2CDD,2CDE 2CDF,2CE0 2CE1,2CE2 2CE3,2CEB 2CEC,2CED 2CEE,2CF2 2CF3,A640 A641,A642 A643,A644 A645,A646 A647,A648 A649,A64A A64B,A64C A64D,A64E A64F,A650 A651,A652 A653,A654 A655,A656 A657,A658 A659,A65A A65B,A65C A65D,A65E A65F,A660 A661,A662 A663,A664 A665,A666 A667,A668 A669,A66A A66B,A66C A66D,A680 A681,A682 A683,A684 A685,A686 A687,A688 A689,A68A A68B,A68C A68D,A68E A68F,A690 A691,A692 A693,A694 A695,A696 A697,A698 A699,A69A A69B,A722 A723,A724 A725,A726 A727,A728 A729,A72A A72B,A72C A72D,A72E A72F,A732 A733,A734 A735,A736 A737,A738 A739,A73A A73B,A73C A73D,A73E A73F,A740 A741,A742 A743,A744 A745,A746 A747,A748 A749,A74A A74B,A74C A74D,A74E A74F,A750 A751,A752 A753,A754 A755,A756 A757,A758 A759,A75A A75B,A75C A75D,A75E A75F,A760 A761,A762 A763,A764 A765,A766 A767,A768 A769,A76A A76B,A76C A76D,A76E A76F,A779 A77A,A77B A77C,A77D 1D79,A77E A77F,A780 A781,A782 A783,A784 A785,A786 A787,A78B A78C,A78D 265,A790 A791,A792 A793,A796 A797,A798 A799,A79A A79B,A79C A79D,A79E A79F,A7A0 A7A1,A7A2 A7A3,A7A4 A7A5,A7A6 A7A7,A7A8 A7A9,A7AA 266,A7AB 25C,A7AC 261,A7AD 26C,A7AE 26A,A7B0 29E,A7B1 287,A7B2 29D,A7B3 AB53,A7B4 A7B5,A7B6 A7B7,A7B8 A7B9,A7BA A7BB,A7BC A7BD,A7BE A7BF,A7C0 A7C1,A7C2 A7C3,A7C4 A794,A7C5 282,A7C6 1D8E,A7C7 A7C8,A7C9 A7CA,A7D0 A7D1,A7D6 A7D7,A7D8 A7D9,A7F5 A7F6,AB70 13A0,AB71 13A1,AB72 13A2,AB73 13A3,AB74 13A4,AB75 13A5,AB76 13A6,AB77 13A7,AB78 13A8,AB79 13A9,AB7A 13AA,AB7B 13AB,AB7C 13AC,AB7D 13AD,AB7E 13AE,AB7F 13AF,AB80 13B0,AB81 13B1,AB82 13B2,AB83 13B3,AB84 13B4,AB85 13B5,AB86 13B6,AB87 13B7,AB88 13B8,AB89 13B9,AB8A 13BA,AB8B 13BB,AB8C 13BC,AB8D 13BD,AB8E 13BE,AB8F 13BF,AB90 13C0,AB91 13C1,AB92 13C2,AB93 13C3,AB94 13C4,AB95 13C5,AB96 13C6,AB97 13C7,AB98 13C8,AB99 13C9,AB9A 13CA,AB9B 13CB,AB9C 13CC,AB9D 13CD,AB9E 13CE,AB9F 13CF,ABA0 13D0,ABA1 13D1,ABA2 13D2,ABA3 13D3,ABA4 13D4,ABA5 13D5,ABA6 13D6,ABA7 13D7,ABA8 13D8,ABA9 13D9,ABAA 13DA,ABAB 13DB,ABAC 13DC,ABAD 13DD,ABAE 13DE,ABAF 13DF,ABB0 13E0,ABB1 13E1,ABB2 13E2,ABB3 13E3,ABB4 13E4,ABB5 13E5,ABB6 13E6,ABB7 13E7,ABB8 13E8,ABB9 13E9,ABBA 13EA,ABBB 13EB,ABBC 13EC,ABBD 13ED,ABBE 13EE,ABBF 13EF,FB00 66 66,FB01 66 69,FB02 66 6C,FB03 66 66 69,FB04 66 66 6C,FB05 73 74,FB06 73 74,FB13 574 576,FB14 574 565,FB15 574 56B,FB16 57E 576,FB17 574 56D,FF21 FF41,FF22 FF42,FF23 FF43,FF24 FF44,FF25 FF45,FF26 FF46,FF27 FF47,FF28 FF48,FF29 FF49,FF2A FF4A,FF2B FF4B,FF2C FF4C,FF2D FF4D,FF2E FF4E,FF2F FF4F,FF30 FF50,FF31 FF51,FF32 FF52,FF33 FF53,FF34 FF54,FF35 FF55,FF36 FF56,FF37 FF57,FF38 FF58,FF39 FF59,FF3A FF5A,10400 10428,10401 10429,10402 1042A,10403 1042B,10404 1042C,10405 1042D,10406 1042E,10407 1042F,10408 10430,10409 10431,1040A 10432,1040B 10433,1040C 10434,1040D 10435,1040E 10436,1040F 10437,10410 10438,10411 10439,10412 1043A,10413 1043B,10414 1043C,10415 1043D,10416 1043E,10417 1043F,10418 10440,10419 10441,1041A 10442,1041B 10443,1041C 10444,1041D 10445,1041E 10446,1041F 10447,10420 10448,10421 10449,10422 1044A,10423 1044B,10424 1044C,10425 1044D,10426 1044E,10427 1044F,104B0 104D8,104B1 104D9,104B2 104DA,104B3 104DB,104B4 104DC,104B5 104DD,104B6 104DE,104B7 104DF,104B8 104E0,104B9 104E1,104BA 104E2,104BB 104E3,104BC 104E4,104BD 104E5,104BE 104E6,104BF 104E7,104C0 104E8,104C1 104E9,104C2 104EA,104C3 104EB,104C4 104EC,104C5 104ED,104C6 104EE,104C7 104EF,104C8 104F0,104C9 104F1,104CA 104F2,104CB 104F3,104CC 104F4,104CD 104F5,104CE 104F6,104CF 104F7,104D0 104F8,104D1 104F9,104D2 104FA,104D3 104FB,10570 10597,10571 10598,10572 10599,10573 1059A,10574 1059B,10575 1059C,10576 1059D,10577 1059E,10578 1059F,10579 105A0,1057A 105A1,1057C 105A3,1057D 105A4,1057E 105A5,1057F 105A6,10580 105A7,10581 105A8,10582 105A9,10583 105AA,10584 105AB,10585 105AC,10586 105AD,10587 105AE,10588 105AF,10589 105B0,1058A 105B1,1058C 105B3,1058D 105B4,1058E 105B5,1058F 105B6,10590 105B7,10591 105B8,10592 105B9,10594 105BB,10595 105BC,10C80 10CC0,10C81 10CC1,10C82 10CC2,10C83 10CC3,10C84 10CC4,10C85 10CC5,10C86 10CC6,10C87 10CC7,10C88 10CC8,10C89 10CC9,10C8A 10CCA,10C8B 10CCB,10C8C 10CCC,10C8D 10CCD,10C8E 10CCE,10C8F 10CCF,10C90 10CD0,10C91 10CD1,10C92 10CD2,10C93 10CD3,10C94 10CD4,10C95 10CD5,10C96 10CD6,10C97 10CD7,10C98 10CD8,10C99 10CD9,10C9A 10CDA,10C9B 10CDB,10C9C 10CDC,10C9D 10CDD,10C9E 10CDE,10C9F 10CDF,10CA0 10CE0,10CA1 10CE1,10CA2 10CE2,10CA3 10CE3,10CA4 10CE4,10CA5 10CE5,10CA6 10CE6,10CA7 10CE7,10CA8 10CE8,10CA9 10CE9,10CAA 10CEA,10CAB 10CEB,10CAC 10CEC,10CAD 10CED,10CAE 10CEE,10CAF 10CEF,10CB0 10CF0,10CB1 10CF1,10CB2 10CF2,118A0 118C0,118A1 118C1,118A2 118C2,118A3 118C3,118A4 118C4,118A5 118C5,118A6 118C6,118A7 118C7,118A8 118C8,118A9 118C9,118AA 118CA,118AB 118CB,118AC 118CC,118AD 118CD,118AE 118CE,118AF 118CF,118B0 118D0,118B1 118D1,118B2 118D2,118B3 118D3,118B4 118D4,118B5 118D5,118B6 118D6,118B7 118D7,118B8 118D8,118B9 118D9,118BA 118DA,118BB 118DB,118BC 118DC,118BD 118DD,118BE 118DE,118BF 118DF,16E40 16E60,16E41 16E61,16E42 16E62,16E43 16E63,16E44 16E64,16E45 16E65,16E46 16E66,16E47 16E67,16E48 16E68,16E49 16E69,16E4A 16E6A,16E4B 16E6B,16E4C 16E6C,16E4D 16E6D,16E4E 16E6E,16E4F 16E6F,16E50 16E70,16E51 16E71,16E52 16E72,16E53 16E73,16E54 16E74,16E55 16E75,16E56 16E76,16E57 16E77,16E58 16E78,16E59 16E79,16E5A 16E7A,16E5B 16E7B,16E5C 16E7C,16E5D 16E7D,16E5E 16E7E,16E5F 16E7F,1E900 1E922,1E901 1E923,1E902 1E924,1E903 1E925,1E904 1E926,1E905 1E927,1E906 1E928,1E907 1E929,1E908 1E92A,1E909 1E92B,1E90A 1E92C,1E90B 1E92D,1E90C 1E92E,1E90D 1E92F,1E90E 1E930,1E90F 1E931,1E910 1E932,1E911 1E933,1E912 1E934,1E913 1E935,1E914 1E936,1E915 1E937,1E916 1E938,1E917 1E939,1E918 1E93A,1E919 1E93B,1E91A 1E93C,1E91B 1E93D,1E91C 1E93E,1E91D 1E93F,1E91E 1E940,1E91F 1E941,1E920 1E942,1E921 1E943";var ii;function Wa(){if(ii!==void 0)return ii;let n=new Map;for(let e of Ar.split(",")){let[t,...i]=e.split(" ").map(r=>Number.parseInt(r,16));if(t===void 0||i.length===0)throw new Error(`the fold table has a malformed entry: ${JSON.stringify(e)}`);n.set(t,String.fromCodePoint(...i))}return ii=n,n}function nt(n){let e=Wa(),t="";for(let i of n.normalize("NFC"))t+=e.get(i.codePointAt(0))??i;return t.normalize("NFC")}var ri=1024,Ut=255,si=".trew-tmp-",Sr="trew-sync",Ja=[Sr,"obsidian-git","obsidian-local-rest-api","obsidian-livesync","remotely-save","basalt-sync","supersync"],ja="community-plugins.json",Ha="data (conflicted copy ";var Va=/^\.obsidian(?:-[a-z0-9][a-z0-9-]{0,31})?$/u;function pe(n){let e=n.indexOf("/");return Va.test(e<0?n:n.slice(0,e))}var Cr=new TextEncoder;function Ga(n){for(let e=0;e<n.length;e++){let t=n.charCodeAt(e);if(t>=55296&&t<=56319){let i=n.charCodeAt(e+1);if(!(i>=56320&&i<=57343))return!1;e++}else if(t>=56320&&t<=57343)return!1}return!0}function Fr(n){return xr(n,!1)}function bn(n,e=!1){return xr(n,!0,e)}function qa(n,e){let t=n.map(nt),[i,r]=t;if(t.length>=2&&i==="plugins"&&r===Sr||e&&t.length>=2&&i==="plugins"&&Ja.includes(r))return"devicelocal";if(!(e&&t.length===3&&i==="plugins"&&t[2]==="data.json")&&!(e&&t.length===3&&i==="plugins"&&t[2].startsWith(Ha)&&t[2].endsWith(".json"))){if(t.length===1&&(i==="workspace.json"||i==="workspace-mobile.json"))return"devicelocal";if(!(t.length===1&&i?.endsWith(".json")&&i!==ja)&&!(t.length===3&&i==="themes")&&!(t.length===2&&i==="snippets"&&r?.endsWith(".css")))return"configscope"}}function xr(n,e,t=!1){if(!Ga(n))return"utf8";if(n==="")return"empty";if(Cr.encode(n).length>ri)return"toolong";if(n.split("/").some(s=>Cr.encode(s).length>Ut))return"segmenttoolong";if(/[\u0000-\u001f\u007f]/u.test(n))return"control";if(n.normalize("NFC")!==n)return"nfc";if(/[\u00a0\u202f]/u.test(n))return"nbsp";if(n.includes("\\"))return"backslash";if(n.startsWith("/")||n.endsWith("/"))return"slash";let i=n.split("/");if(i.some(s=>s===""))return"emptysegment";if(i.some(s=>s==="."||s===".."))return"dotsegment";let r=e&&pe(n);if((r?i.slice(1):i).some(s=>s.startsWith(".")))return"dotprefix";if(n.includes(si))return"staging";if(r)return qa(i.slice(1),t)}var oi=["md","txt","canvas","json","csv","yml","yaml","base","xml","html","css","js","ts","svg","bib","tex"];function Xa(n){return n.replace(/[A-Z]/g,e=>String.fromCharCode(e.charCodeAt(0)+32))}function Br(n){let e=n.lastIndexOf(".");return e<0||e<n.lastIndexOf("/")?!1:oi.includes(Xa(n.slice(e+1)))}var Ve=48,it=31,Ya=1;function Pr(n,e){let t=n>>>0;return Math.floor(t/e)*e===t-Ya}var $r={min:512,avg:1024,max:4096},Ka=64,Za=$r.avg,Qa=64*1024;function ed(n){let e=Math.sqrt(Ka*Math.max(n,1)),t=Math.min(Qa,Math.max(Za,Math.round(e/512)*512));return{min:Math.max($r.min,t/2),avg:t,max:t*4}}var ai={min:128*1024,avg:256*1024,max:1024*1024},td=4*1024*1024,zt=Ve*4;function Dr(n,e,t=ai.max){(!Number.isFinite(t)||t<=0)&&(t=ai.max);let i=e&&n<td?ed(n):ai,r=Math.min(i.max,t),s=Math.max(r,zt);return{min:Math.min(i.min,s),avg:Math.min(i.avg,s),max:s}}function Tr(n,e,t){let i=t-1;for(;i>e&&(n[i]&192)===128;)i--;if(i<e)return t;let r=n[i],s=r<128?1:(r&224)===192?2:(r&240)===224?3:(r&248)===240?4:1;return t-i>=s?t:i>e?i:t}function*Wt(n,e,t){let{min:i,avg:r,max:s}=e,o=n.length,a=1;for(let l=0;l<Ve-1;l++)a=Math.imul(a,it);let d=0,c=0;for(let l=0;l<o;l++){let h=n[l];l>=d+Ve?(c=c-Math.imul(n[l-Ve],a)|0,c=Math.imul(c,it),c=c+h|0):(c=Math.imul(c,it),c=c+h|0);let u=l-d+1,f=u>=i&&Pr(c,r);if(u>=s&&(f=!0),f){let g=t?Tr(n,d,l+1):l+1;yield{offset:d,bytes:n.subarray(d,g)},d=g,c=0,l=g-1}}d<o&&(yield{offset:d,bytes:n.subarray(d,o)})}var di=class{constructor(e,t,i){this.buf=e;this.sizes=t;this.pPowW=i}buf;sizes;pPowW;used=0;hash=0;scanTo(e,t){let{min:i,avg:r,max:s}=this.sizes,o=this.buf,a=this.pPowW,d=this.used,c=this.hash;for(let l=t;l<e.length;l++){let h=e[l];if(o[d++]=h,d>=Ve+1?(c=c-Math.imul(o[d-1-Ve],a)|0,c=Math.imul(c,it),c=c+h|0):(c=Math.imul(c,it),c=c+h|0),d>=s||d>=i&&Pr(c,r))return this.used=d,this.hash=c,l+1}return this.used=d,this.hash=c,-1}};async function*En(n,e,t){let{max:i}=e,r=1;for(let h=0;h<Ve-1;h++)r=Math.imul(r,it);let s=new Uint8Array(Math.max(i,Ve*2)),o=0,a=0,d=0,c=()=>{let h=t?Tr(s,0,o):o,u={offset:d,bytes:s.slice(0,h)};d+=h;let f=o-h;s.copyWithin(0,h,o),o=f,a=0;for(let g=0;g<f;g++)a=Math.imul(a,it),a=a+s[g]|0;return u},l=new di(s,e,r);for await(let h of n){let u=0;for(;;){let f=l.scanTo(h,u);if(f<0)break;o=l.used,yield c(),l.used=o,l.hash=a,u=f}o=l.used}if(o>0){let h={offset:d,bytes:s.slice(0,o)};d+=o,o=0,yield h}}var Gh=new Set(oi);function Ge(n){return Br(n)}var nd=new Set(["canvas","json"]),id=new Set(["base","yml","yaml"]);function Ir(n){let e=n.lastIndexOf(".");return e<0?!1:id.has(n.slice(e+1).toLowerCase())}function qe(n){let e=n.lastIndexOf(".");return e<0?!1:nd.has(n.slice(e+1).toLowerCase())}var fi=br(ci(),1);var Or=br(ci(),1),rd=-1,sd=0,od=4e6;function ad(n,e,t){let i=n.diff_commonPrefix(e,t),r=n.diff_commonSuffix(e.slice(i),t.slice(i)),s=e.length-i-r,o=t.length-i-r;return s<=0||o<=0?0:s*o}function Mr(n){return n.match(/[^\n]*\n|[^\n]+$/g)??[]}function Rr(n,e,t,i){let r=Mr(t),s=new Or.diff_match_patch;s.Diff_Timeout=0;let{chars1:o,chars2:a,lineArray:d}=s.diff_linesToChars_(n,t);if(o.length!==e.length||a.length!==r.length||d.length>65535||ad(s,o,a)>od)return;let c=s.diff_main(o,a,!1),l=[],h=0,u=0,f,g=()=>{f!==void 0&&(l.push({mine:i,start:f.start,end:h,text:r.slice(f.from,u).join("")}),f=void 0)};for(let[m,y]of c){let w=y.length;m===sd?(g(),h+=w,u+=w):(f??={start:h,from:u},m===rd?h+=w:u+=w)}return g(),l}function Nr(n,e,t){let i=Mr(n),r=Rr(n,i,e,!0),s=Rr(n,i,t,!1);if(r===void 0||s===void 0)return;let o=[...r,...s].sort((h,u)=>h.start-u.start||h.end-h.start-(u.end-u.start)),a=[0];for(let h of i)a.push(a[a.length-1]+h.length);let d=[],c=0,l=h=>{if(h<=c)return;let u=i.slice(c,h).join("");d.push({changed:"none",base:u,mine:u,theirs:u,at:a[c],firstLine:c,lastLine:h}),c=h};for(let h=0;h<o.length;){let u=o[h],f=u.end,g=h+1;for(;g<o.length;){let S=o[g],v=S.start<f,A=S.start===S.end&&S.start===u.start&&u.end===f;if(!v&&!(A&&f===u.start))break;f=Math.max(f,S.end),g++}let m=o.slice(h,g),y=u.start,w=m.filter(S=>S.mine),b=m.filter(S=>!S.mine),k=S=>{let v="",A=y;for(let F of S)v+=i.slice(A,F.start).join("")+F.text,A=F.end;return v+i.slice(A,f).join("")};l(y),d.push({changed:w.length>0&&b.length>0?"both":w.length>0?"mine":"theirs",base:i.slice(y,f).join(""),mine:k(w),theirs:k(b),at:a[y],firstLine:y,lastLine:f}),c=f,h=g}return l(i.length),d}function kn(n,e){for(let t of n.split("/"))if(t.startsWith(".")&&t!=="."&&t!==".."||e.has(t))return!0;return!1}function rt(n){let e=n.lastIndexOf("/"),t=n.lastIndexOf(".");return t<=e+1?{stem:n,ext:""}:{stem:n.slice(0,t),ext:n.slice(t)}}async function Oe(n,e,t=cd(n)){if(!await e(n))return n;for(let i=1;i<=Lr;i++){let r=t(i);if(!await e(r))return r}throw new Error(`cannot find an unused name beside ${n}`)}var Lr=998,dd=` ${Lr+1}`.length;function cd(n){let{stem:e,ext:t}=rt(n);return i=>`${e} ${i+1}${t}`}var ld=new TextEncoder,re=n=>ld.encode(n).length;function li(n){return Math.min(Ut,ri-re(n))-dd}function An(n,e,t){let i=n.lastIndexOf("/")+1,r=n.slice(0,i),s=n.slice(i),o=li(r);re(t)+re(e)+1>o&&(s+=t,t="");let a=re(s)+re(e)+re(t)-o;return a>0&&(s=hi(s,re(s)-a)),`${r}${s}${e}${t}`}function hi(n,e){let t="",i=0;for(let s of hd(n)){let o=re(s);if(t!==""&&i+o>e)break;t+=s,i+=o}let r=t.replace(/[\s.-]+$/u,"");return r===""?t:r}var _r=typeof Intl<"u"&&"Segmenter"in Intl?new Intl.Segmenter:void 0;function hd(n){return _r===void 0?n:Array.from(_r.segment(n),e=>e.segment)}function se(n){return n.normalize("NFC")}function Ur(n){return n.replace(/[\u00a0\u202f]/gu," ")}function ee(n){return nt(n)}function Jt(n,e){return ee(n)===ee(e)}function zr(n){let e="";for(let t of n){let i=t.codePointAt(0);e+=i>=32&&i<127?t:`\\u{${i.toString(16)}}`}return e}function Wr(n){let e=new Error(n);return e.code="neversync",e}function Jr(n){let e=new Error(n);return e.code="ignored",e}function jr(n,e){let t=!1;for(let i of n.split("/")){if(i.startsWith(".")&&i!=="."&&i!=="..")return!1;e.has(i)&&(t=!0)}return t}function Cn(n){let e=n.replace(/^\/+|\/+$/g,"");if(e===""||e.includes("/"))throw new Error(`refusing to sync: the config folder ${JSON.stringify(n)} is not a plain name`);return e}var ui=8*1024;function ud(n,e,t){return!(n.length>ui||e.length>ui||t.length>ui)}var Xr=-1,Yr=0,fd=1;function Hr(n){let e=[],t=0;for(let[i,r]of n)i===Yr?t+=r.length:i===Xr?(e.push({start:t,end:t+r.length,text:r}),t+=r.length):e.push({start:t,end:t,text:r});return e}function gd(n,e){for(let t of n)for(let i of e){let r=t.start===t.end,s=i.start===i.end;if(!(r&&s)){if(r){if(i.start<t.start&&t.start<i.end)return t;continue}if(s){if(t.start<i.start&&i.start<t.end)return i;continue}if(t.start<i.end&&i.start<t.end)return t}}}function Vr(n,e,t){let i=c=>c<0||c>=n.length||n[c]===`
8
+ `,r=e.filter(c=>c.start<c.end),s=[...r,...t.filter(c=>c.start<c.end)],o=t.filter(c=>c.start===c.end),a=(c,l)=>{let h=l.find(u=>u.start===c);return h===void 0?c:a(h.end,l)},d=(c,l)=>{let h=l.find(u=>u.end===c);return h===void 0?c:d(h.start,l)};for(let c of e)if(c.start===c.end){if(!c.text.startsWith(`
9
+ `)&&i(d(c.start,r)-1)){let l=d(c.start,s);if(!i(l-1))return c;for(let h of o)if(l<=h.start&&h.start<=c.start&&!h.text.endsWith(`
10
10
  `))return c}if(!c.text.endsWith(`
11
- `)&&r(a(c.start,i))){let l=a(c.start,s);if(!r(l))return c;for(let h of o)if(c.start<=h.start&&h.start<=l&&!h.text.startsWith(`
12
- `))return c}}}function id(n,e,t){let r=l=>l.filter(h=>h.start===h.end),i=r(e),s=r(t);if(i.length===0||s.length===0)return;let o=[...e,...t].filter(l=>l.start<l.end);if(o.length===0)return;let a=new Uint8Array(n.length);for(let l of o)a.fill(1,l.start,l.end);let d=new Int32Array(n.length+1);for(let l=0;l<n.length;l++){let h=n[l];d[l+1]=d[l]+(a[l]===1||h===" "||h===" "?0:1)}let c=(l,h)=>l.text.endsWith(`
11
+ `)&&i(a(c.start,r))){let l=a(c.start,s);if(!i(l))return c;for(let h of o)if(c.start<=h.start&&h.start<=l&&!h.text.startsWith(`
12
+ `))return c}}}function pd(n,e,t){let i=l=>l.filter(h=>h.start===h.end),r=i(e),s=i(t);if(r.length===0||s.length===0)return;let o=[...e,...t].filter(l=>l.start<l.end);if(o.length===0)return;let a=new Uint8Array(n.length);for(let l of o)a.fill(1,l.start,l.end);let d=new Int32Array(n.length+1);for(let l=0;l<n.length;l++){let h=n[l];d[l+1]=d[l]+(a[l]===1||h===" "||h===" "?0:1)}let c=(l,h)=>l.text.endsWith(`
13
13
  `)||h.text.startsWith(`
14
- `);for(let l of i)for(let h of s){let[u,f]=l.start<=h.start?[l,h]:[h,l];if(u.start===f.start){if(c(u,f)&&c(f,u))continue;if(o.some(m=>m.start<=u.start&&m.end>=u.start))return u;continue}if(c(u,f)&&c(f,u)||d[f.start]-d[u.start]>0)continue;if(o.some(m=>m.start<=f.start&&m.end>=u.start&&m.text.includes(`
15
- `)))return u}}function sd(n,e,t,r=()=>!0){return ji(n,e,t,r,0)}function ji(n,e,t,r,i){if(e===t)return{kind:"take",text:e,why:"both sides already agree"};if(n===e)return{kind:"take",text:t,why:"no local change since the last sync"};if(n===t)return{kind:"take",text:e,why:"no remote change since the last sync"};let s=new cr.diff_match_patch,o=td(n,e,t);o&&(s.Diff_Timeout=0);let a=o?s.diff_main(n,e,!0):s.diff_main(n,e,!0,0);a.length>2&&(s.diff_cleanupSemantic(a),s.diff_cleanupEfficiency(a));let d=o?s.diff_main(n,t,!0):s.diff_main(n,t,!0,0);d.length>2&&(s.diff_cleanupSemantic(d),s.diff_cleanupEfficiency(d));let c=_i(a),l=_i(d),h=rd(c,l);if(h!==void 0)return{kind:"conflict",why:`both devices changed the same text, at characters ${i+h.start} to ${i+h.end} of the last synced version`};let u=Li(n,c,l)??Li(n,l,c);if(u!==void 0)return{kind:"conflict",why:`a line added on one device would run into text changed on the other, at character ${i+u.start} of the last synced version`};let f=id(n,c,l);if(f!==void 0)return{kind:"conflict",why:`each device rewrote the same line differently, and the two rewrites would run together at character ${i+f.start} of the last synced version`};let g=zi(s,n,a,t),m=zi(s,n,d,e);if(g.failed>0||m.failed>0){let b=Math.max(g.failed,m.failed),k=Math.max(g.total,m.total);return{kind:"conflict",why:`${b} of ${k} changes could not be placed in the other version`}}if(!od(n,g.text,m.text))return{kind:"conflict",why:"merging the two versions in either order gives different content, so at least one change was placed wrongly"};let y=ad(a,g.text);if(y!==void 0)return{kind:"conflict",why:`the merge reported success but ${cd(y)} is not in the result`};let w=dd(n,e,t,g.text);return w!==void 0?{kind:"conflict",why:`the merge produced ${JSON.stringify(w.slice(0,40))}, which is not a word in the last synced version or in either device's`}:r(g.text)?{kind:"merged",text:g.text}:{kind:"conflict",why:"both sides merged cleanly and the result is no longer a valid file of its kind"}}function Hi(n,e,t,r=()=>!0){if(e===t)return{kind:"take",text:e,why:"both sides already agree"};if(n===e)return{kind:"take",text:t,why:"no local change since the last sync"};if(n===t)return{kind:"take",text:e,why:"no remote change since the last sync"};let i=Pi(n,e,t);if(i===void 0)return sd(n,e,t,r);let s=[];for(let a of i)if(a.changed==="none")s.push(a.base);else if(a.changed==="mine")s.push(a.mine);else if(a.changed==="theirs")s.push(a.theirs);else if(a.base===""&&a.mine===a.theirs)s.push(a.mine+a.theirs);else{let d=ji(a.base,a.mine,a.theirs,()=>!0,a.at);if(d.kind==="conflict")return d;s.push(d.text)}for(let a=s.length-1,d=!1;a>=0;a--){let c=s[a];if(c!==""){if(d&&!c.endsWith(`
16
- `)){let l=i[a];return{kind:"conflict",why:`a change on one device would run into the next line, at character ${l.at+l.base.length} of the last synced version`}}d=!0}}let o=s.join("");return r(o)?{kind:"merged",text:o}:{kind:"conflict",why:"both sides merged cleanly and the result is no longer a valid file of its kind"}}function od(n,e,t){if(e===t)return!0;let r=Ui(n,e),i=Ui(n,t);if(r.length!==i.length)return!1;for(let s=0;s<r.length;s++)if(r[s]!==i[s])return!1;return!0}function Ui(n,e){let t=new cr.diff_match_patch;t.Diff_Timeout=0;let{chars1:r,chars2:i,lineArray:s}=t.diff_linesToChars_(n,e),o=t.diff_main(r,i,!1);t.diff_charsToLines_(o,s);let a=[],d=0;for(let[c,l]of o){let h=l.match(/[^\n]*\n|[^\n]+$/g)??[];if(c===Ji)d+=h.length;else if(c===Wi)for(let u of h)a.push(`-${d++} ${u}`);else for(let u of h)a.push(`+${d} ${u}`)}return a.sort()}function zi(n,e,t,r){let[i,s]=n.patch_apply(n.patch_make(e,t),r);return{text:i,failed:s.filter(o=>!o).length,total:s.length}}function ad(n,e){for(let[t,r]of n)if(t===nd&&!e.includes(r))return r}function dd(n,e,t,r){let i=new Set;for(let s of[n,e,t])for(let o of s.split(/\s+/))i.add(o);for(let s of r.split(/\s+/))if(s!==""&&!i.has(s))return s}function cd(n){let e=n.replace(/\s+/g," ").trim(),t=e.length>60?`${e.slice(0,57)}...`:e;return`a local edit (${JSON.stringify(t)})`}function wn(n,e,t){let{stem:r,ext:i}=et(n),s=(a,d=2)=>String(a).padStart(d,"0"),o=`${t.getFullYear()}${s(t.getMonth()+1)}${s(t.getDate())}${s(t.getHours())}${s(t.getMinutes())}`;return hd(r,lr(e)||"device",` ${o})`,i)}var Vi=" (Conflicted copy ",ld=32;function hd(n,e,t,r){let i=n.slice(0,n.lastIndexOf("/")+1),s=a=>`${Vi}${a}${t}`,o=ne(n)-ne(i)+ne(s(e))+ne(r)-or(i);return o>0&&(e=ar(e,ne(e)-o)),mn(n,s(e),r)}function lr(n){return[...n.replace(/[\ud800-\udfff]/gu,"-").normalize("NFC").replace(/[\u061c\u200e\u200f\u202a-\u202e\u2066-\u2069]/gu,"").replace(/[\\/:*?"<>|]/gu,"-").replace(/[\s\p{Cc}]+/gu," ").replaceAll(tr,"-trew-tmp-").replaceAll(Vi.trimStart(),"Conflicted copy ").replace(/-{2,}/gu,"-").replace(/^[\s.-]+|[\s.-]+$/gu,"")].slice(0,ld).join("").replace(/[\s.-]+$/u,"")}var Gi=128*1024;function ud(n){let e=/^(.*) \(Conflicted copy [^/]+ \d{12}\)(?: \d+)?(\.[^/]*)?$/.exec(n);return e?e[1]+(e[2]??""):void 0}async function hr(n,e){if(n.contentDigest){let t=await n.contentDigest(e);if(t===void 0&&await n.stat(e))throw new Error("Cannot read a conflict file. Nothing was resolved.");return t}if(await n.stat(e))return Ee(await n.read(e))}async function qi(n,e){let t=await n.stat(e);if(!t)return;if(t.folder)throw new Error("A conflict path is now a folder. Review it in the file explorer.");if(Ve(e)&&t.size<=Gi){let i=await n.read(e),s=i.length<=Gi?new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(i):void 0;return{path:e,stat:t,digest:await Ee(i),...s!==void 0?{text:s}:{}}}let r=await hr(n,e);if(r!==void 0)return{path:e,stat:t,digest:r}}async function Xi(n,e){if(e.original===e.copy||ud(e.copy)!==e.original)throw new Error("Choose a TrewSync conflict copy to review.");let t=await qi(n,e.original),r=await qi(n,e.copy);if(!r)throw new Error("This conflict copy has moved or was already removed. Refresh the list.");return{...e,...t?{current:t}:{},preserved:r}}async function Ki(n,e,t,r,i){if(!n.replace||!n.removeExpecting)throw new Error("This vault cannot safely resolve conflicts.");if(r==="original"&&!t.current)throw new Error("The original file no longer exists.");if(r==="edited"&&(i===void 0||t.current?.text===void 0||t.preserved.text===void 0))throw new Error("Open these files to edit them; they cannot be merged in this preview.");if(await hr(n,t.original)!==t.current?.digest||await hr(n,t.copy)!==t.preserved.digest)throw new Error("One of these files changed. Refresh the comparison before choosing a version.");let s=a=>Ie(wn(a,e,new Date),d=>n.exists(d));if(r!=="original"){let a=r==="edited"?new TextEncoder().encode(i):await n.read(t.copy);if(r==="copy"&&await Ee(a)!==t.preserved.digest)throw new Error("The conflict copy changed. Refresh the comparison.");let d=await n.replace(t.original,t.current?{contentId:t.current.digest,idOf:Ee}:void 0,a,{mtime:Date.now(),ctime:t.current?.stat.ctime??t.preserved.stat.ctime},await s(t.original));if(!d.landed||d.keptAt)throw new Error("A file changed while applying your choice. Both versions were kept; refresh the list.");await n.flush?.()}let o=await n.removeExpecting(t.copy,{contentId:t.preserved.digest,idOf:Ee},await s(t.copy));if(await n.flush?.(),o.keptAt||!o.landed)throw new Error("The copy changed while resolving it. Its latest version was preserved; refresh the list.")}function Oe(n,e){try{n?.(e)}catch{}}function Ut(n){let e=[],t,r=!0,i=0,s="";for(let o of n.split(`
17
- `)){let a=o.replace(/\r$/,"");if(a.trim()==="")continue;let d=a.length-a.replace(/^[ \t]*/,"").length,c=a.slice(0,d);if(t!==void 0){if(d>t)continue;t=void 0}if(i>0||s!==""){({flow:i,openQuote:s}=vn(a,i,s));continue}if(c.includes(" "))return!1;let l=a.slice(d);if(l.startsWith("#"))continue;if(l==="---"||l==="..."||l.startsWith("--- ")){e.length=0,r=!0;continue}let h=/^-(\s+|$)/.exec(l);if(h){if(Yi(e,d,r)==="nowhere")return!1;let y=l.slice(h[0].length);if(y===""||y.startsWith("#")){r=!0;continue}({flow:i,openQuote:s}=vn(y,0,""));let w=d+h[0].length;e.push({indent:w,keys:new Set});let b=ur(y);b!==void 0&&e[e.length-1].keys.add(b),Zi(y)&&(t=w),r=b!==void 0&&fr(y)==="";continue}let u=Yi(e,d,r);if(u==="nowhere")return!1;if(u==="continued"){if(ur(l)!==void 0)return!1;({flow:i,openQuote:s}=vn(l,0,""));continue}({flow:i,openQuote:s}=vn(l,0,""));let f=ur(l);if(f===void 0){r=!1;continue}let g=e[e.length-1];if(g.keys.has(f))return!1;g.keys.add(f),Zi(l)&&(t=d),r=fr(l)===""}return!0}function vn(n,e,t){let r=t;for(let i=0;i<n.length;i++){let s=n[i];if(r){s==="\\"&&r==='"'?i++:s===r&&(r="");continue}if(s==='"'||s==="'")r=s;else if(s==="["||s==="{")e++;else if(s==="]"||s==="}")e=Math.max(0,e-1);else if(s==="#"&&e===0&&(i===0||/\s/.test(n[i-1])))break}return{flow:e,openQuote:r}}function Yi(n,e,t){let r=n[n.length-1];if(r===void 0||e>r.indent)return!t&&r!==void 0?"continued":(n.push({indent:e,keys:new Set}),"here");for(;n.length>1&&e<n[n.length-1].indent;)n.pop();return e===n[n.length-1].indent?"here":"nowhere"}function ur(n){let e=0,t="";for(;e<n.length;e++){let s=n[e];if(t){s==="\\"&&t==='"'?e++:s===t&&(t="");continue}if(s==='"'||s==="'"){if(e!==0)return;t=s;continue}if(s===":"&&(e+1===n.length||n[e+1]===" "))break;if(s==="["||s==="{"||s==="#")return}if(t||e>=n.length)return;let r=n.slice(0,e).trim();return r===""?void 0:(r.startsWith('"')&&r.endsWith('"')||r.startsWith("'")&&r.endsWith("'"))&&r.length>=2?r.slice(1,-1):r}function fr(n){let e=n.indexOf(": "),t=e>=0?n.slice(e+2):n.endsWith(":")?"":n,r=fd(t).trim();for(let i=0;i<2;i++){let s=/^(?:&[^\s]+|![^\s]*)(?:\s+|$)/.exec(r);if(!s)break;r=r.slice(s[0].length).trim()}return r}function fd(n){let e="";for(let t=0;t<n.length;t++){let r=n[t];if(e){r==="\\"&&e==='"'?t++:r===e&&(e="");continue}if(r==='"'||r==="'")e=r;else if(r==="#"&&(t===0||/\s/.test(n[t-1])))return n.slice(0,t)}return n}function Zi(n){return/^[|>](?:[+-]\d*|\d*[+-]?)$/.test(fr(n))}var gd=/\n##? Drawing\n[^`]*```json\n([\s\S]*?)```\n/;function bn(n){let e=gd.exec(n);if(e===null)return;let t=e[1],r=t.substring(0,t.lastIndexOf("}")+1);if(r==="")return;let i;try{i=JSON.parse(r.replaceAll("&#91;","["))}catch{return!1}return Array.isArray(i?.elements)}function Qi(n){return n.toLowerCase().endsWith(".excalidraw.md")}function es(n,e,t){if(bn(n)===!0&&bn(e)===!0&&bn(t)===!0)return r=>bn(r)===!0}function ts(n){let e=/[A-Za-z_:][-A-Za-z0-9_:.]*/y,t=[],r=0,i=0;for(;i<n.length;){let s=n.indexOf("<",i);if(s<0)break;if(i=s+1,n.startsWith("!--",i)){let h=n.indexOf("-->",i+3);if(h<0)return!1;i=h+3;continue}if(n.startsWith("![CDATA[",i)){let h=n.indexOf("]]>",i+8);if(h<0)return!1;i=h+3;continue}if(n.startsWith("?",i)){let h=n.indexOf("?>",i+1);if(h<0)return!1;i=h+2;continue}if(n.startsWith("!",i)){let h=0,u=i+1;for(;u<n.length;u++){let f=n[u];if(f==="[")h++;else if(f==="]")h--;else if(f===">"&&h<=0)break}if(u>=n.length)return!1;i=u+1;continue}let o=n[i]==="/";o&&i++,e.lastIndex=i;let a=e.exec(n);if(a===null)return!1;let d=a[0];i=e.lastIndex;let c=!1,l=!1;for(;i<n.length;){let h=n[i];if(h==='"'||h==="'"){let u=n.indexOf(h,i+1);if(u<0)return!1;i=u+1;continue}if(h==="<")return!1;if(h==="/"){c=!0,i++;continue}if(h===">"){i++,l=!0;break}if(c)return!1;i++}if(!l)return!1;if(o){if(c||t.pop()!==d)return!1;t.length===0&&r++}else c?t.length===0&&r++:t.push(d)}return t.length===0&&r===1}var pd=new Set(["svg","xml","xhtml","html","htm"]);function ns(n){let e=n.lastIndexOf(".");return e<0?!1:pd.has(n.slice(e+1).toLowerCase())}Re();var md=["CON","PRN","AUX","NUL",...[..."0123456789\xB9\xB2\xB3"].map(n=>`COM${n}`),...[..."0123456789\xB9\xB2\xB3"].map(n=>`LPT${n}`)],yd=new Set(md);function wd(n){return n.replace(/[a-z]/g,e=>String.fromCharCode(e.charCodeAt(0)-32))}function rs(n){for(let e of n.split("/")){if(/[<>:"|?*]/.test(e))return"character";if(e.endsWith(".")||e.endsWith(" "))return"trailing";let t=e.split(".",1)[0].replace(/ +$/,"");if(yd.has(wd(t)))return"reserved"}}function is(n){switch(n){case"character":return'Windows does not allow < > : " | ? * in a file or folder name';case"trailing":return"Windows does not allow a file or folder name to end with a dot or a space";case"reserved":return"Windows reserves this name for a device (CON, PRN, AUX, NUL, COM and LPT names)"}}function En(n){return{path:n,prev:"",folder:!1,ctime:0,mtime:0,size:0,hash:"",chunks:[],synchash:"",syncuid:0,synctime:0}}function kn(n){let{local:e,remote:t,index:r,mergeable:i}=n,s=r.synchash;return e?.folder||t?.folder?vd(e,t,r):e===void 0&&(t===void 0||t.deleted)?{kind:"nothing",why:"absent on both sides"}:t===void 0?{kind:"upload",why:"new file, the server has never held this path"}:e===void 0?bd(t,r):t.deleted?e.hash===s&&s!==""?{kind:"deleteLocal",why:"deleted on another device and unchanged here"}:s===""?{kind:"upload",why:"deleted on the server but never synced from here"}:{kind:"upload",why:"deleted on another device but edited here, so the edit is kept and re-sent"}:e.hash===t.hash?{kind:"nothing",why:"the two sides hold the same content"}:s===""?{kind:"conflict",why:"both sides have content and there is no last-synced version to merge from"}:e.hash===s?{kind:"download",why:"changed on another device and unchanged here"}:t.hash===s?{kind:"upload",why:"changed here and unchanged on the server"}:i?{kind:"merge",why:"changed on both sides since the last sync"}:{kind:"conflict",why:"changed on both sides and this file cannot be merged"}}function vd(n,e,t){return n!==void 0&&n.folder?e===void 0?{kind:"upload",why:"new folder, the server has never held this path"}:e.deleted?ss(t)?{kind:"removeLocalFolder",why:"folder deleted on another device, so it goes here once nothing is left in it"}:{kind:"upload",why:"folder deleted on the server but never synced from here"}:e.folder?{kind:"nothing",why:"folder exists on both sides"}:{kind:"clash",why:"a folder here and a file of the same name on another device"}:e?.folder&&!e.deleted?n!==void 0?{kind:"clash",why:"a file here and a folder of the same name on another device"}:ss(t)&&t.syncuid===e.uid?{kind:"deleteRemoteFolder",why:"folder removed here"}:{kind:"createLocalFolder",why:"folder exists on the server and not here"}:{kind:"nothing",why:"folder absent on both sides"}}function ss(n){return n.synctime>0&&n.synchash===""}function bd(n,e){let t=e.synchash;return n.deleted?{kind:"nothing",why:"deleted on both sides"}:t===""?{kind:"download",why:"new on the server"}:n.hash===t&&n.uid===e.syncuid?{kind:"deleteRemote",why:"deleted here and unchanged on the server"}:n.hash===t?{kind:"restoreLocal",why:"deleted here, and written again since as a version this device never synced, so it is restored"}:{kind:"restoreLocal",why:"deleted here but changed on another device, so the newer content is restored"}}function yt(n,e,t,r){return r!==void 0&&r!==n.changeId?!0:n.hash==="-empty-"&&n.size===0?n.mtime!==e||t!==0:n.hash===""||n.chunks.length===0?!0:n.mtime!==e||n.size!==t}function tt(n,e){let t=Math.ceil(e.mtime),r=Math.ceil(e.ctime);if(e.folder){n.folder=!0,n.mtime=0,n.ctime=0,n.size=0,n.hash="",n.chunks=[];return}yt(n,t,e.size,e.changeId)&&(n.hash="",n.chunks=[]),n.folder=!1,n.mtime=t,n.ctime=r,n.size=e.size,e.changeId!==void 0&&(n.changeId=e.changeId)}function os(n,e,t){n.path=t,n.prev===""&&(n.prev=e),n.prev===t&&(n.prev=""),n.synctime=0}function nt(n,e,t,r,i){n.hash===e&&n.synchash===e&&n.syncuid===r&&n.prev===""&&n.chunks.length===t.length&&n.chunks.every((o,a)=>o===t[a])&&n.synctime!==0||(n.hash=e,n.chunks=[...t],n.synchash=e,n.syncuid=r,n.synctime=i,n.prev="")}function zt(n,e,t,r){n.synchash===e&&n.syncuid===t||(n.synchash=e,n.syncuid=t,n.synctime=r)}function gr(n){if(!n.synctime)return 0;let e=n.size>102400?5e3:n.size>10240?2e3:1e3;return n.synctime+e}function as(n,e){return n.synctime>e||e>=gr(n)}Re();import{createRequire as Ed}from"module";var kd=Ed("/"),wt,Ad,Cd;try{wt=kd("worker_threads"),Ad=wt.Worker,Cd=wt.isMarkedAsUntransferable}catch{}var j=Uint8Array,ce=Uint16Array,kr=Int32Array,An=new j([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),Cn=new j([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),wr=new j([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),hs=function(n,e){for(var t=new ce(31),r=0;r<31;++r)t[r]=e+=1<<n[r-1];for(var i=new kr(t[30]),r=1;r<30;++r)for(var s=t[r];s<t[r+1];++s)i[s]=s-t[r]<<5|r;return{b:t,r:i}},wt=hs(An,2),us=wt.b,vr=wt.r;us[28]=258,vr[258]=28;var fs=hs(Cn,0),Sd=fs.b,ds=fs.r,br=new ce(32768);for(O=0;O<32768;++O)Me=(O&43690)>>1|(O&21845)<<1,Me=(Me&52428)>>2|(Me&13107)<<2,Me=(Me&61680)>>4|(Me&3855)<<4,br[O]=((Me&65280)>>8|(Me&255)<<8)>>1;var Me,O,xe=(function(n,e,t){for(var r=n.length,i=0,s=new ce(e);i<r;++i)n[i]&&++s[n[i]-1];var o=new ce(e);for(i=1;i<e;++i)o[i]=o[i-1]+s[i-1]<<1;var a;if(t){a=new ce(1<<e);var d=15-e;for(i=0;i<r;++i)if(n[i])for(var c=i<<4|n[i],l=e-n[i],h=o[n[i]-1]++<<l,u=h|(1<<l)-1;h<=u;++h)a[br[h]>>d]=c}else for(a=new ce(r),i=0;i<r;++i)n[i]&&(a[i]=br[o[n[i]-1]++]>>15-n[i]);return a}),Ge=new j(288);for(O=0;O<144;++O)Ge[O]=8;var O;for(O=144;O<256;++O)Ge[O]=9;var O;for(O=256;O<280;++O)Ge[O]=7;var O;for(O=280;O<288;++O)Ge[O]=8;var O,Ht=new j(32);for(O=0;O<32;++O)Ht[O]=5;var O,Fd=xe(Ge,9,0),xd=xe(Ge,9,1),Bd=xe(Ht,5,0),$d=xe(Ht,5,1),pr=function(n){for(var e=n[0],t=1;t<n.length;++t)n[t]>e&&(e=n[t]);return e},ke=function(n,e,t){var r=e/8|0;return(n[r]|n[r+1]<<8)>>(e&7)&t},mr=function(n,e){var t=e/8|0;return(n[t]|n[t+1]<<8|n[t+2]<<16)>>(e&7)},Ar=function(n){return(n+7)/8|0},jt=function(n,e,t){return(e==null||e<0)&&(e=0),(t==null||t>n.length)&&(t=n.length),new j(n.subarray(e,t))};var Pd=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],Ae=function(n,e,t){var r=new Error(e||Pd[n]);if(r.code=n,Error.captureStackTrace&&Error.captureStackTrace(r,Ae),!t)throw r;return r},Dd=function(n,e,t,r){var i=n.length,s=r?r.length:0;if(!i||e.f&&!e.l)return t||new j(0);var o=!t,a=o||e.i!=2,d=e.i;o&&(t=new j(i*3));var c=function(Tt){var Rt=t.length;if(Tt>Rt){var ft=new j(Math.max(Rt*2,Tt));ft.set(t),t=ft}},l=e.f||0,h=e.p||0,u=e.b||0,f=e.l,g=e.d,m=e.m,y=e.n,w=i*8;do{if(!f){l=ke(n,h,1);var b=ke(n,h+1,3);if(h+=3,b)if(b==1)f=xd,g=$d,m=9,y=5;else if(b==2){var A=ke(n,h,31)+257,F=ke(n,h+10,15)+4,x=A+ke(n,h+5,31)+1;h+=14;for(var p=new j(x),B=new j(19),T=0;T<F;++T)B[wr[T]]=ke(n,h+T*3,7);h+=F*3;for(var _=pr(B),fe=(1<<_)-1,q=xe(B,_,1),T=0;T<x;){var H=q[ke(n,h,fe)];h+=H&15;var k=H>>4;if(k<16)p[T++]=k;else{var W=0,I=0;for(k==16?(I=3+ke(n,h,3),h+=2,W=p[T-1]):k==17?(I=3+ke(n,h,7),h+=3):k==18&&(I=11+ke(n,h,127),h+=7);I--;)p[T++]=W}}var te=p.subarray(0,A),X=p.subarray(A);m=pr(te),y=pr(X),f=xe(te,m,1),g=xe(X,y,1)}else Ae(1);else{var k=Ar(h)+4,S=n[k-4]|n[k-3]<<8,v=k+S;if(v>i){d&&Ae(0);break}a&&c(u+S),t.set(n.subarray(k,v),u),e.b=u+=S,e.p=h=v*8,e.f=l;continue}if(h>w){d&&Ae(0);break}}a&&c(u+131072);for(var Dt=(1<<m)-1,ge=(1<<y)-1,Te=h;;Te=h){var W=f[mr(n,h)&Dt],oe=W>>4;if(h+=W&15,h>w){d&&Ae(0);break}if(W||Ae(2),oe<256)t[u++]=oe;else if(oe==256){Te=h,f=null;break}else{var ae=oe-254;if(oe>264){var T=oe-257,L=An[T];ae=ke(n,h,(1<<L)-1)+us[T],h+=L}var Fe=g[mr(n,h)&ge],ht=Fe>>4;Fe||Ae(3),h+=Fe&15;var X=Sd[ht];if(ht>3){var L=Cn[ht];X+=mr(n,h)&(1<<L)-1,h+=L}if(h>w){d&&Ae(0);break}a&&c(u+131072);var ut=u+ae;if(u<X){var un=s-X,fn=Math.min(X,ut);for(un+u<0&&Ae(3);u<fn;++u)t[u]=r[un+u]}for(;u<ut;++u)t[u]=t[u-X]}}e.l=f,e.p=Te,e.b=u,e.f=l,f&&(l=1,e.m=m,e.d=g,e.n=y)}while(!l);return u!=t.length&&o?jt(t,0,u):t.subarray(0,u)},Ne=function(n,e,t){t<<=e&7;var r=e/8|0;n[r]|=t,n[r+1]|=t>>8},Wt=function(n,e,t){t<<=e&7;var r=e/8|0;n[r]|=t,n[r+1]|=t>>8,n[r+2]|=t>>16},yr=function(n,e){for(var t=[],r=0;r<n.length;++r)n[r]&&t.push({s:r,f:n[r]});var i=t.length,s=t.slice();if(!i)return{t:ps,l:0};if(i==1){var o=new j(t[0].s+1);return o[t[0].s]=1,{t:o,l:1}}t.sort(function(v,A){return v.f-A.f}),t.push({s:-1,f:25001});var a=t[0],d=t[1],c=0,l=1,h=2;for(t[0]={s:-1,f:a.f+d.f,l:a,r:d};l!=i-1;)a=t[t[c].f<t[h].f?c++:h++],d=t[c!=l&&t[c].f<t[h].f?c++:h++],t[l++]={s:-1,f:a.f+d.f,l:a,r:d};for(var u=s[0].s,r=1;r<i;++r)s[r].s>u&&(u=s[r].s);var f=new ce(u+1),g=Er(t[l-1],f,0);if(g>e){var r=0,m=0,y=g-e,w=1<<y;for(s.sort(function(A,F){return f[F.s]-f[A.s]||A.f-F.f});r<i;++r){var b=s[r].s;if(f[b]>e)m+=w-(1<<g-f[b]),f[b]=e;else break}for(m>>=y;m>0;){var k=s[r].s;f[k]<e?m-=1<<e-f[k]++-1:++r}for(;r>=0&&m;--r){var S=s[r].s;f[S]==e&&(--f[S],++m)}g=e}return{t:new j(f),l:g}},Er=function(n,e,t){return n.s==-1?Math.max(Er(n.l,e,t+1),Er(n.r,e,t+1)):e[n.s]=t},cs=function(n){for(var e=n.length;e&&!n[--e];);for(var t=new ce(++e),r=0,i=n[0],s=1,o=function(d){t[r++]=d},a=1;a<=e;++a)if(n[a]==i&&a!=e)++s;else{if(!i&&s>2){for(;s>138;s-=138)o(32754);s>2&&(o(s>10?s-11<<5|28690:s-3<<5|12305),s=0)}else if(s>3){for(o(i),--s;s>6;s-=6)o(8304);s>2&&(o(s-3<<5|8208),s=0)}for(;s--;)o(i);s=1,i=n[a]}return{c:t.subarray(0,r),n:e}},Jt=function(n,e){for(var t=0,r=0;r<e.length;++r)t+=n[r]*e[r];return t},gs=function(n,e,t){var r=t.length,i=Ar(e+2);n[i]=r&255,n[i+1]=r>>8,n[i+2]=n[i]^255,n[i+3]=n[i+1]^255;for(var s=0;s<r;++s)n[i+s+4]=t[s];return(i+4+r)*8},ls=function(n,e,t,r,i,s,o,a,d,c,l){Ne(e,l++,t),++i[256];for(var h=yr(i,15),u=h.t,f=h.l,g=yr(s,15),m=g.t,y=g.l,w=cs(u),b=w.c,k=w.n,S=cs(m),v=S.c,A=S.n,F=new ce(19),x=0;x<b.length;++x)++F[b[x]&31];for(var x=0;x<v.length;++x)++F[v[x]&31];for(var p=yr(F,7),B=p.t,T=p.l,_=19;_>4&&!B[wr[_-1]];--_);var fe=c+5<<3,q=Jt(i,Ge)+Jt(s,Ht)+o,H=Jt(i,u)+Jt(s,m)+o+14+3*_+Jt(F,B)+2*F[16]+3*F[17]+7*F[18];if(d>=0&&fe<=q&&fe<=H)return gs(e,l,n.subarray(d,d+c));var W,I,te,X;if(Ne(e,l,1+(H<q)),l+=2,H<q){W=xe(u,f,0),I=u,te=xe(m,y,0),X=m;var Dt=xe(B,T,0);Ne(e,l,k-257),Ne(e,l+5,A-1),Ne(e,l+10,_-4),l+=14;for(var x=0;x<_;++x)Ne(e,l+3*x,B[wr[x]]);l+=3*_;for(var ge=[b,v],Te=0;Te<2;++Te)for(var oe=ge[Te],x=0;x<oe.length;++x){var ae=oe[x]&31;Ne(e,l,Dt[ae]),l+=B[ae],ae>15&&(Ne(e,l,oe[x]>>5&127),l+=oe[x]>>12)}}else W=Fd,I=Ge,te=Bd,X=Ht;for(var x=0;x<a;++x){var L=r[x];if(L>255){var ae=L>>18&31;Wt(e,l,W[ae+257]),l+=I[ae+257],ae>7&&(Ne(e,l,L>>23&31),l+=An[ae]);var Fe=L&31;Wt(e,l,te[Fe]),l+=X[Fe],Fe>3&&(Wt(e,l,L>>5&8191),l+=Cn[Fe])}else Wt(e,l,W[L]),l+=I[L]}return Wt(e,l,W[256]),l+I[256]},Td=new kr([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),ps=new j(0),Rd=function(n,e,t,r,i,s){var o=s.z||n.length,a=new j(r+o+5*(1+Math.ceil(o/7e3))+i),d=a.subarray(r,a.length-i),c=s.l,l=(s.r||0)&7;if(e){l&&(d[0]=s.r>>3);for(var h=Td[e-1],u=h>>13,f=h&8191,g=(1<<t)-1,m=s.p||new ce(32768),y=s.h||new ce(g+1),w=Math.ceil(t/3),b=2*w,k=function(Yn){return(n[Yn]^n[Yn+1]<<w^n[Yn+2]<<b)&g},S=new kr(25e3),v=new ce(288),A=new ce(32),F=0,x=0,p=s.i||0,B=0,T=s.w||0,_=0;p+2<o;++p){var fe=k(p),q=p&32767,H=y[fe];if(m[q]=H,y[fe]=q,T<=p){var W=o-p;if((F>7e3||B>24576)&&(W>423||!c)){l=ls(n,d,0,S,v,A,x,B,_,p-_,l),B=F=x=0,_=p;for(var I=0;I<286;++I)v[I]=0;for(var I=0;I<30;++I)A[I]=0}var te=2,X=0,Dt=f,ge=q-H&32767;if(W>2&&fe==k(p-ge))for(var Te=Math.min(u,W)-1,oe=Math.min(32767,p),ae=Math.min(258,W);ge<=oe&&--Dt&&q!=H;){if(n[p+te]==n[p+te-ge]){for(var L=0;L<ae&&n[p+L]==n[p+L-ge];++L);if(L>te){if(te=L,X=ge,L>Te)break;for(var Fe=Math.min(ge,L-2),ht=0,I=0;I<Fe;++I){var ut=p-ge+I&32767,un=m[ut],fn=ut-un&32767;fn>ht&&(ht=fn,H=ut)}}}q=H,H=m[q],ge+=q-H&32767}if(X){S[B++]=268435456|vr[te]<<18|ds[X];var Tt=vr[te]&31,Rt=ds[X]&31;x+=An[Tt]+Cn[Rt],++v[257+Tt],++A[Rt],T=p+te,++F}else S[B++]=n[p],++v[n[p]]}}for(p=Math.max(p,T);p<o;++p)S[B++]=n[p],++v[n[p]];l=ls(n,d,c,S,v,A,x,B,_,p-_,l),c||(s.r=l&7|d[l/8|0]<<3,l-=7,s.h=y,s.p=m,s.i=p,s.w=T)}else{for(var p=s.w||0;p<o+c;p+=65535){var ft=p+65535;ft>=o&&(d[l/8|0]=c,ft=o),l=gs(d,l+1,n.subarray(p,ft))}s.i=o}return jt(a,0,r+Ar(l)+i)};var Id=function(n,e,t,r,i){if(!i&&(i={l:1},e.dictionary)){var s=e.dictionary.subarray(-32768),o=new j(s.length+n.length);o.set(s),o.set(n,s.length),n=o,i.w=s.length}return Rd(n,e.level==null?6:e.level,e.mem==null?i.l?Math.ceil(Math.max(8,Math.min(13,Math.log(n.length)))*1.5):20:12+e.mem,t,r,i)};function Cr(n,e){return Id(n,e||{},0,0)}var ms=(function(){function n(e,t){typeof e=="function"&&(t=e,e={}),this.ondata=t;var r=e&&e.dictionary&&e.dictionary.subarray(-32768);this.s={i:0,b:r?r.length:0},this.o=new j(32768),this.p=new j(0),r&&this.o.set(r)}return n.prototype.e=function(e){if(this.ondata||Ae(5),this.d&&Ae(4),!this.p.length)this.p=e;else if(e.length){var t=new j(this.p.length+e.length);t.set(this.p),t.set(e,this.p.length),this.p=t}},n.prototype.c=function(e){this.s.i=+(this.d=e||!1);var t=this.s.b,r=Dd(this.p,this.s,this.o);this.ondata(jt(r,t,this.s.b),this.d),this.o=jt(r,this.s.b-32768),this.s.b=this.o.length,this.p=jt(this.p,this.s.p/8|0),this.s.p&=7},n.prototype.push=function(e,t){this.e(e),this.c(t)},n})();var Od=typeof TextDecoder<"u"&&new TextDecoder,Md=0;try{Od.decode(ps,{stream:!0}),Md=1}catch{}var vs=0,bs=1,le=class extends Error{constructor(t,r){super(r);this.kind=t;this.name="FrameError"}kind},ys=4096;function Nd(n){if(n.length<=ys*2)return!0;let e=n.subarray(0,ys);return Cr(e,{level:6}).length<e.length}function Es(n){if(n.length>0&&Nd(n)){let t=Cr(n,{level:6});if(t.length<n.length){let r=new Uint8Array(1+t.length);return r[0]=bs,r.set(t,1),r}}let e=new Uint8Array(1+n.length);return e[0]=vs,e.set(n,1),e}var ws=4096;function ks(n,e){if(n.length===0)throw new le("empty","a frame with no marker");if(n.length>e+1)throw new le("toolarge",`a ${n.length}-byte frame for a ${e}-byte limit`);let t=n.subarray(1);if(n[0]===vs){if(t.length===0)throw new le("empty","a raw chunk of no bytes");return t}if(n[0]!==bs)throw new le("marker",`unknown marker ${n[0]}`);let r=[],i=0,s=!1,o=new ms((c,l)=>{i+=c.length,i<=e&&r.push(c),l&&(s=!0)});try{for(let c=0;c<t.length&&!s;c+=ws){let l=Math.min(c+ws,t.length);if(o.push(t.subarray(c,l),l===t.length),i>e)throw new le("toolarge",`inflates past ${e} bytes`)}s||o.push(new Uint8Array(0),!0)}catch(c){throw c instanceof le?c:new le("corrupt",`undecodable deflate stream: ${c.message}`)}if(!s)throw new le("corrupt","the deflate stream ends early");if(i===0)throw new le("empty","a deflated chunk of no bytes");let a=new Uint8Array(i),d=0;for(let c of r)a.set(c,d),d+=c.length;return a}var Vt=2,_d=6e4,xn=64,Bn=65536;var vt=256;function Ps(n){return{size:n.size,ctime:n.ctime,mtime:n.mtime,folder:n.folder??!1,deleted:n.deleted??!1,...n.prev?{prev:n.prev}:{}}}function Ds(n,e,t){return{base:e??0,...n.prev?{prevBase:t??0}:{}}}function Ts(n){return{path:n.path,meta:Ps(n.meta),chunks:[...n.names],...Ds(n.meta,n.base,n.prevBase)}}var Ld=new TextEncoder;function Rs(n){return Ld.encode(n).length}function Is(n){return Rs(JSON.stringify(Ts(n)))+1}var $r=64,Ud=new Set(["proto","auth","cursor","busy","protostate","nospace","internal"]);function zd(n){return n==="busy"||n==="nospace"||n==="internal"||n==="toomany"}var C=class extends Error{constructor(t,r,i={}){super(r);this.code=t;this.name="ProtocolError",this.retryable=i.retryable??zd(t),this.retryAfterMs=i.retryAfterMs}code;retryable;retryAfterMs;get fatal(){return!this.retryable}get endsSession(){return Ud.has(this.code)}};function Sr(n){let e=n.retryable,t=n.retryAfterMs,r=n.code,i=n.msg;return new C(typeof r=="string"?r:"unknown",typeof i=="string"?i:"no message",{retryable:typeof e=="boolean"?e:void 0,retryAfterMs:typeof t=="number"&&t>0?t:void 0})}function Wd(n){return n.startsWith("wss://")?`. If that server has no TLS in front of it, pair with ws://${n.slice(6)} instead`:""}var R=class extends Error{constructor(e){super(e),this.name="ConnectionError"}},Jd=1<<20,As=1<<20,Fr=16<<20,jd=64<<20,Cs=1<<20,bt=class n{constructor(e,t){this.url=e;this.opts=t}url;opts;socket;pending=new Map;nextId=1;pinging;pingPromise;collecting;requestsSent=0;closed=!1;closeReason;cursor=0;notifying=Promise.resolve();limits;replaced=!1;textFrameCeiling(){return this.limits===void 0?Jd:2*Fr}log(e,...t){this.opts.log?.(e,...t)}get appliedCursor(){return this.cursor}get serverLimits(){return this.limits}get historyReplaced(){return this.replaced}async connect(){if(this.socket)throw new Error("already connected");let t=(this.opts.socketFactory??Hd)(this.url);t.binaryType="arraybuffer",this.socket=t;let r=this.timeoutMs;await new Promise((i,s)=>{let o=setTimeout(()=>{s(new R(`no connection to ${this.url} within ${r}ms`));try{t.close()}catch{}},r),a=d=>{clearTimeout(o),d()};t.onopen=()=>a(i),t.onerror=()=>a(()=>s(new R(`could not connect to ${this.url}${Wd(this.url)}`))),t.onclose=d=>a(()=>s(new R(`connection closed before opening: ${Bs(d)}`)))}),t.onerror=()=>this.die(new R("the connection failed")),t.onclose=i=>this.die(new R(`the connection closed: ${Bs(i)}`)),t.onmessage=i=>this.onFrame(i.data)}die(e){if(this.closed)return;this.closed=!0,this.closeReason=e,this.log("transport closed",e.message);let t=[...this.pending.values()];this.pending.clear();let r=this.pinging;this.pinging=void 0;let i=this.collecting?.waiter;this.collecting=void 0;for(let s of t)this.disarm(s),s.reject(e);r&&(this.disarm(r),r.reject(e)),i?.();try{this.socket?.close()}catch{}try{this.opts.onClosed?.(e)}catch{}}get timeoutMs(){return this.opts.timeoutMs??_d}arm(e){e.timer!==void 0&&clearTimeout(e.timer),e.armed=!0;let t=this.timeoutMs;e.timer=setTimeout(()=>{this.die(new R(`no ${e.what} within ${t}ms`))},t)}disarm(e){e.timer!==void 0&&clearTimeout(e.timer),e.timer=void 0,e.armed=!1}close(){this.die(new R("closed by this device"))}get isClosed(){return this.closed}onFrame(e){if(typeof e=="string"){if(e.length>this.textFrameCeiling()){this.die(new C("toolarge",`server sent a ${e.length} character frame, over the ${this.textFrameCeiling()} this device will parse`));return}let o;try{o=JSON.parse(e)}catch{this.die(new C("protostate",`server sent a frame that is not JSON: ${e.slice(0,120)}`));return}if(typeof o!="object"||o===null||Array.isArray(o)){this.die(new C("protostate",`server sent a frame that is not an object: ${e.slice(0,120)}`));return}this.onTextFrame(o,e.length);return}let t=Kd(e);if(t===void 0){this.die(new C("protostate","server sent a frame of an unexpected type"));return}let r=this.collecting;if(!r||r.got.length>=r.want){this.die(new C("protostate",`server sent a ${t.length} byte body with nothing outstanding to receive it`));return}r.bytes+=t.length;let i=this.limits?.maxFetchBytes??As;if(r.bytes>i+r.want){this.die(new C("toolarge",`server sent ${r.bytes} bytes of bodies for a fetch it said would hold at most ${i}`));return}this.arm(r.pending),r.got.push(t);let s=r.waiter;s&&(delete r.waiter,s())}onTextFrame(e,t=0){if(e.op==="batch"){this.queueNotification(()=>this.onBatchFrame(e),t);return}if(e.op==="caught-up"){let i=Br(e.cursor);this.queueNotification(async()=>{if(i!==this.cursor){this.die(new C("protostate",`server says caught up at ${i}, this device reached ${this.cursor}`));return}this.opts.onCaughtUp?.(i)});return}let r=e.id;if(r!==void 0){if(typeof r!="number"||!Number.isInteger(r)){this.die(new C("protostate",`server sent a reply whose id is ${JSON.stringify(r)}`));return}let i=this.pending.get(r);if(!i){this.die(new C("protostate",`server sent a reply to request ${r}, which is not in flight: ${JSON.stringify(e)}`));return}this.pending.delete(r),this.disarm(i);try{i.onArrival?.(e)}catch{}i.resolve(e);return}if(e.res==="pong"){let i=this.pinging;if(!i){this.die(new C("protostate","server sent a pong with no ping in flight"));return}this.pinging=void 0,this.disarm(i),i.resolve(e);return}if(e.res==="err"){this.die(Sr(e));return}this.die(new C("protostate",`server sent an unexpected reply: ${JSON.stringify(e)}`))}static MAX_BACKLOG=1024;static MAX_BACKLOG_BYTES=4*Fr;backlog=0;backlogBytes=0;queueNotification(e,t=0){if(this.backlogBytes+t>n.MAX_BACKLOG_BYTES){this.die(new C("protostate",`server sent ${this.backlogBytes+t} bytes of notifications faster than this device could apply them, over the ${n.MAX_BACKLOG_BYTES} it will hold`));return}if(this.backlog>=n.MAX_BACKLOG){this.die(new C("protostate",`server sent more than ${n.MAX_BACKLOG} notifications faster than this device could apply them`));return}this.backlog++,this.backlogBytes+=t,this.notifying=this.notifying.then(e).catch(r=>{this.die(r instanceof Error?r:new Error(String(r)))}).finally(()=>{this.backlog--,this.backlogBytes-=t})}async onBatchFrame(e){let t=Br(e.from),r=Br(e.to),i=e.entries;if(!Array.isArray(i))throw new C("protostate",`batch ${t} to ${r} carries no entries array, so an empty batch cannot be told from a lost one`);let s=i;if(t!==this.cursor+1)throw new C("protostate",`batch covers ${t} to ${r} but this device has applied up to ${this.cursor}, so something was skipped`);if(r<t)throw new C("protostate",`batch covers an empty range, ${t} to ${r}`);for(let o of s){if(typeof o?.uid!="number"||!Number.isFinite(o.uid))throw new C("protostate",`batch ${t}..${r} contains an entry with no uid`);if(typeof o.path!="string"||o.path==="")throw new C("protostate",`batch ${t}..${r} contains uid ${o.uid} with no path`);if(!Array.isArray(o.chunks))throw new C("protostate",`batch ${t}..${r} contains uid ${o.uid} with no chunks array`);for(let a of o.chunks)if(!pt(a))throw new C("protostate",`batch ${t}..${r} contains uid ${o.uid} naming ${JSON.stringify(a)}, which is not a chunk name`);if(o.uid<t||o.uid>r)throw new C("protostate",`batch ${t}..${r} contains uid ${o.uid}`)}await this.opts.onBatch({from:t,to:r,entries:s}),this.cursor=r}send(e){if(this.closed||!this.socket)throw this.closeReason??new R("not connected");this.socket.send(e)}takeId(){for(let e=0;e<8;e++){let t=this.nextId;if(this.nextId=this.nextId>=4294967295?1:this.nextId+1,!this.pending.has(t))return t}throw new Error("every request id is in flight, which cannot happen")}begin(e,t,r=!0,i){let s=this.takeId(),o=JSON.stringify({...e,id:s});this.requestsSent++;let a=new Promise((d,c)=>{if(this.closed){c(this.closeReason??new R("not connected"));return}let l={what:t,resolve:d,reject:c,timer:void 0,armed:!1,...i?{onArrival:i}:{}};this.pending.set(s,l),r&&this.arm(l);try{this.send(o)}catch(h){this.pending.delete(s),this.disarm(l),c(h instanceof Error?h:new Error(String(h)))}});return a.catch(()=>{}),a}async awaitReply(e){let t=await e;if(t.res==="err"){let r=Sr(t);throw r.endsSession&&this.die(r),r}return t}async request(e,t,r){return this.awaitReply(this.begin(e,t,!0,r))}async hello(e){Sn("vault",e.vault),Sn("device",e.device),this.cursor=e.cursor,this.replaced=!1;let t;try{t=await this.request({op:"hello",proto:Vt,vault:e.vault,deviceId:e.deviceId,token:e.token,device:e.device,cursor:e.cursor,...e.epoch!==void 0?{epoch:e.epoch}:{}},"ready",r=>{let i=r.epoch;r.res==="ready"&&e.epoch!==void 0&&typeof i=="string"&&i!==e.epoch&&(this.cursor=0,this.replaced=!0)})}catch(r){throw Ss(r)}return this.readReady(t)}async redeem(e){Sn("vault",e.vault),Sn("device",e.device);let t;try{t=await this.request({op:"hello",proto:Vt,vault:e.vault,device:e.device,invite:e.invite,deviceId:e.deviceId,token:e.token},"redeemed")}catch(r){throw Ss(r)}if(t.res!=="redeemed")throw new C("protostate",`expected redeemed, got ${JSON.stringify(t)}`);if(t.deviceId!==e.deviceId)throw this.malformed(`a redeemed naming device ${JSON.stringify(t.deviceId)}, which is not the ${JSON.stringify(e.deviceId)} that was redeemed for`);return{deviceId:e.deviceId}}readReady(e){if(e.res!=="ready")throw new C("protostate",`expected ready, got ${JSON.stringify(e)}`);let t=e.serverVersion,r=e.epoch;if(typeof r!="string"||r==="")throw this.malformed("a ready with no epoch, so which history it serves cannot be told");let i={proto:this.count(e,"proto","ready"),minProto:this.count(e,"minProto","ready"),serverVersion:typeof t=="string"?t:"unknown",epoch:r,cursor:this.count(e,"cursor","ready"),perFileMax:this.count(e,"perFileMax","ready"),chunkMax:Math.min(this.count(e,"chunkMax","ready"),Cs),maxChunks:this.count(e,"maxChunks","ready"),maxBatchBytes:Math.min(this.count(e,"maxBatchBytes","ready"),Fr),maxFetchBytes:Math.min(this.count(e,"maxFetchBytes","ready"),jd)};if(i.proto!==Vt){let s=new C("proto",`server (version ${i.serverVersion}) answered in protocol ${i.proto}, this client speaks ${Vt}; upgrade the server first`);throw this.die(s),s}return this.limits=i,this.log("ready",i),i}async put(e,t,r,i,s,o,a){Oe(o,0);let d=await this.request({op:"put",path:e,meta:Ps(t),chunks:[...r],...Ds(t,s.base,s.prevBase)},"want or have");if(d.res==="have")return await this.drainReceived(),{uid:this.uid(d,"have"),uploaded:0,bytes:0};if(d.res!=="want")throw new C("protostate",`expected want or have, got ${JSON.stringify(d)}`);let c=new Set(r),l=this.wanted(d,c),h=xr(d),u=this.expectMore(h,"acknowledgement"),f=await this.sendBodies(l,c,i,"put",o,a),g=await this.awaitPhase(u,h);if(g.res!=="ack")throw new C("protostate",`expected ack, got ${JSON.stringify(g)}`);return await this.drainReceived(),{uid:this.uid(g,"ack"),uploaded:l.length,bytes:f}}async putMany(e,t,r){if(Oe(r,0),e.length===0)return{results:[],uploaded:0,bytes:0};if(e.length>vt)throw new C("toolarge",`${e.length} entries in one batch, the limit is ${vt}`);let i={op:"putmany",entries:e.map(Ts)},s=this.limits?.maxBatchBytes;if(s!==void 0&&s>0){let u=Rs(JSON.stringify(i))+24;if(u>s)throw new Error(`a putmany of ${e.length} entries encodes to ${u} bytes, over the server's ${s}; it should have been split`)}let o=await this.request(i,"want or acks"),a=o,d=0,c=0;if(o.res==="want"){let u=new Set;for(let y of e)for(let w of y.names)u.add(w);let f=this.wanted(o,u),g=xr(o),m=this.expectMore(g,"acknowledgement");c=await this.sendBodies(f,u,t,"batch",r),d=f.length,a=await this.awaitPhase(m,g)}if(a.res!=="acks")throw new C("protostate",`expected acks, got ${JSON.stringify(a)}`);let l=a.results;if(!Array.isArray(l)||l.length!==e.length)throw new C("protostate",`${e.length} entries went up and ${Array.isArray(l)?l.length:"no"} results came back`);let h=l.map((u,f)=>{if(typeof u!="object"||u===null)throw this.malformed(`acks[${f}] is not an object`);let g=u;if(g.code!==void 0){if(typeof g.code!="string")throw this.malformed(`acks[${f}].code is not a string`);return{uid:0,error:Sr(g)}}return{uid:this.uid(g,`acks[${f}]`)}});for(let u of h)u.error?.endsSession&&this.die(u.error);return await this.drainReceived(),{results:h,uploaded:d,bytes:c}}async drainReceived(){if(await this.notifying,this.closed)throw this.closeReason??new R("not connected")}async sendBodies(e,t,r,i,s,o){let a=0,d=0,c=s===void 0?void 0:()=>{let l=Math.max(0,a-(this.socket?.bufferedAmount??0));l>d&&(d=l,Oe(s,l))};for(let l of e){if(await o?.(),!t.has(l))throw new C("badchunk",`server asked for ${l}, which this ${i} does not contain`);let h;try{h=await r(l)}catch(f){throw this.die(new R(`${i} could not produce ${l}, so the connection was ended rather than left owing the server bodies: ${f.message}`)),f}await o?.();let u=Es(h);this.send(u),a+=u.length,await this.drained(o?256*1024:Vd,c,o)}return await this.drained(0,c,o),a}async drained(e,t,r){t?.();let i=this.socket;if(!i||i.bufferedAmount===void 0)return;let s=i.bufferedAmount,o=Date.now(),a=Fs;for(;i.bufferedAmount>e;){if(this.closed)throw this.closeReason??new R("not connected");if(await qd(a),r){let c=Date.now();await r(),o+=Date.now()-c}let d=i.bufferedAmount;if(t?.(),d<s)s=d,o=Date.now(),a=Fs;else{if(Date.now()-o>this.timeoutMs)throw this.die(new R(`upload stalled: ${d} bytes unsent for ${this.timeoutMs}ms`)),this.closeReason??new R("not connected");a=Math.min(a*2,Gd)}}}expectMore(e,t){if(this.pending.has(e))throw new Error(`request ${e} is already waiting for a reply`);let r=new Promise((i,s)=>{if(this.closed){s(this.closeReason??new R("not connected"));return}this.pending.set(e,{what:t,resolve:i,reject:s,timer:void 0,armed:!1})});return r.catch(()=>{}),r}async awaitPhase(e,t){let r=this.pending.get(t);return r&&this.arm(r),this.awaitReply(e)}async get(e){let t=await this.request({op:"get",uid:e},"chunks");if(t.res!=="chunks")throw new C("protostate",`expected chunks, got ${JSON.stringify(t)}`);return{uid:this.uid(t,"chunks"),size:this.count(t,"size","chunks"),chunks:this.chunkNames(t.chunks,"chunks")}}async resend(e,t){let r=await this.request({op:"resend",chunks:[...e]},"want or resent");if(r.res==="resent")return{stored:Fn(r,"stored"),missing:Fn(r,"missing"),bytes:0};if(r.res!=="want")throw new C("protostate",`expected want or resent, got ${JSON.stringify(r)}`);let i=new Set(e),s=this.wanted(r,i),o=xr(r),a=this.expectMore(o,"resent"),d=await this.sendBodies(s,i,t,"resend"),c=await this.awaitPhase(a,o);if(c.res!=="resent")throw new C("protostate",`expected resent, got ${JSON.stringify(c)}`);return{stored:Fn(c,"stored"),missing:Fn(c,"missing"),bytes:d}}async history(e,t={}){let r=await this.request({op:"history",path:e,...t.before!==void 0?{before:t.before}:{},...t.limit!==void 0?{limit:t.limit}:{}},"history");if(r.res!=="history")throw new C("protostate",`expected history, got ${JSON.stringify(r)}`);return $s(r.entries,"history")}async deleted(e,t){let r=await this.request({op:"deleted",...e!==void 0?{limit:e}:{},...t!==void 0&&t>0?{before:t}:{}},"deleted");if(r.res!=="deleted")throw new C("protostate",`expected deleted, got ${JSON.stringify(r)}`);return{entries:$s(r.entries,"deleted"),more:r.more===!0}}async fetch(e,t,r){if(e.length===0)return[];if(e.length>Bn)throw new Error(`a fetch of ${e.length} chunks is over the ${Bn} the server takes; it should have been split`);if(this.collecting)throw new Error("a fetch is already collecting bodies");let i={what:"chunk body",resolve:()=>{},reject:()=>{},timer:void 0,armed:!1},s=[],o=[],a=0,d=0;Oe(t,0),this.collecting={pending:i,want:e.length,got:s,bytes:0};let c=this.limits?.chunkMax??Cs,l=this.limits?.maxFetchBytes??As,h=[],u,f,g=new Promise((m,y)=>{f=y});g.catch(()=>{});try{let m=this.begin({op:"fetch",chunks:[...e]},"bodies"),y=await this.awaitReply(m);if(y.res!=="bodies")throw new C("protostate",`expected bodies, got ${JSON.stringify(y)}`);let w=this.count(y,"count","bodies");if(w!==e.length)throw this.malformed(`bodies announcing ${w} frames for a fetch of ${e.length}`);this.arm(i);for(let b=0;b<w;b++){let k=await Promise.race([this.body(b),g]);a+=k.length,Oe(t,a);let S;try{S=ks(k,c)}catch(A){if(!(A instanceof le))throw A;let F=new C(A.kind==="toolarge"?"toolarge":"badchunk",`asked for ${e[b]} and received a body that does not decode: ${A.message}`);throw this.die(F),F}if(s[b]=Xd,d+=S.length,d>l){let A=new C("toolarge",`server sent bodies decoding to ${d} bytes for a fetch it said would hold at most ${l}`);throw this.die(A),A}o.push(S),r&&await r();let v=e[b];h.push(We(S).then(A=>{if(A===v)return;let F=new C("badchunk",`asked for ${v} and received ${S.length} bytes that hash to ${A}`);u===void 0&&(u=F,f?.(F))}))}if(await Promise.all(h),u!==void 0)throw u}catch(m){throw m instanceof C&&m.code==="badchunk"&&this.die(m),m}finally{this.disarm(i),this.collecting=void 0}return o}async body(e){let t=this.collecting;if(!t||this.closed)throw this.closeReason??new R("not connected");if(t.got.length<=e&&(await new Promise(r=>{t.waiter=r}),this.closed))throw this.closeReason??new R("not connected");return t.got[e]}async invite(e={}){let t=await this.request({op:"invite",...e.ttlMs!==void 0?{ttlMs:e.ttlMs}:{},...e.label!==void 0&&e.label!==""?{label:e.label}:{}},"invited");if(t.res!=="invited")throw new C("protostate",`expected invited, got ${JSON.stringify(t)}`);let r=t.invite;if(typeof r!="string"||r==="")throw this.malformed("an invited with no invite id");let i=t.token,s;try{s=typeof i=="string"?je(i):void 0}catch{s=void 0}if(typeof i!="string"||s?.length!==xs)throw this.malformed(`an invited whose token is not ${xs} bytes`);return{invite:r,token:i,expiresAt:this.expiry(t.expiresAt,"invited")}}async uninvite(e){let t=await this.request({op:"uninvite",invite:e},"uninvited");if(t.res!=="uninvited")throw new C("protostate",`expected uninvited, got ${JSON.stringify(t)}`);if(t.invite!==e)throw this.malformed(`an uninvited naming ${JSON.stringify(t.invite)}, which is not the ${JSON.stringify(e)} that was cancelled`)}async devices(){let e=await this.request({op:"devices"},"devices");if(e.res!=="devices")throw new C("protostate",`expected devices, got ${JSON.stringify(e)}`);let t=e.devices;if(!Array.isArray(t))throw this.malformed("a devices reply with no list of devices");let r=e.invites;if(!Array.isArray(r))throw this.malformed("a devices reply with no list of invites");return{devices:t.map((i,s)=>this.deviceRow(i,s)),invites:r.map((i,s)=>this.inviteRow(i,s))}}async applied(e){let t=await this.request({op:"applied",applied:e},"applied");if(t.res!=="applied"||this.count(t,"cursor","applied")!==e)throw this.malformed("an applied reply that does not match the checkpoint")}inviteRow(e,t){let r=e,i=r?.invite;if(typeof i!="string"||i==="")throw this.malformed(`a devices reply whose invite ${t} has no id`);let s=r.label;return{invite:i,label:typeof s=="string"?s:"",expiresAt:this.expiry(r.expiresAt,`a devices reply's invite ${t}`)}}expiry(e,t){if(e===null)return null;if(typeof e!="number"||!Number.isSafeInteger(e)||e<=0)throw this.malformed(`${t} with expiresAt = ${JSON.stringify(e)}, not a time or null`);return e}deviceRow(e,t){let r=e,i=r?.id;if(typeof i!="string"||i==="")throw this.malformed(`a devices reply whose entry ${t} has no id`);let s=r.name;if(typeof r.online!="boolean"||!(r.applied===null||typeof r.applied=="number"&&Number.isSafeInteger(r.applied)&&r.applied>=0)||r.online===!1&&r.applied!==null)throw this.malformed(`a devices reply with invalid delivery state at entry ${t}`);let o=a=>{let d=r[a];return typeof d=="number"&&Number.isFinite(d)&&d>=0?d:0};return{id:i,name:typeof s=="string"?s:"",createdAt:o("createdAt"),lastSeen:o("lastSeen"),online:r.online,applied:r.applied}}async revoke(e){let t=await this.request({op:"revoke",deviceId:e.deviceId},"revoked");if(t.res!=="revoked")throw new C("protostate",`expected revoked, got ${JSON.stringify(t)}`);let r=t.deviceId;if(r!==e.deviceId)throw this.malformed(`a revoked naming device ${JSON.stringify(r)}, which is not the ${JSON.stringify(e.deviceId)} that was revoked`);return{deviceId:r,self:t.self===!0}}async undo(e,t={}){if(e==="")throw new Error("an undo names the operation it undoes");let r=await this.request({op:"undo",opId:e,...t.toCopy===!0?{toCopy:!0}:{}},"undone");if(r.res!=="undone")throw new C("protostate",`expected undone, got ${JSON.stringify(r)}`);let i=r.opId;if(typeof i!="string"||i===""||r.undoes!==e)throw this.malformed(`an undone for ${JSON.stringify(r.undoes)}, which is not the ${JSON.stringify(e)} that was undone`);if(r.toCopy!==(t.toCopy===!0))throw this.malformed("an undone that did not do what was asked, in place or as a copy");let s=r.steps,o=r.entries;if(!Array.isArray(s)||!Array.isArray(o))throw this.malformed("an undone with no list of steps or entries");let a=(d,c)=>{let l=d[c];return typeof l=="string"&&l!==""?l:void 0};return{opId:i,undoes:e,toCopy:t.toCopy===!0,committedAt:this.count(r,"committedAt","undone"),steps:s.map((d,c)=>{let l=d,h=a(l??{},"action"),u=a(l??{},"path");if(h===void 0||u===void 0)throw this.malformed(`an undone whose step ${c} names no action or no path`);let f={action:h,path:u};for(let g of["from","copy","why"]){let m=a(l,g);m!==void 0&&(f[g]=m)}for(let g of["before","after"]){let m=l[g];typeof m=="number"&&Number.isSafeInteger(m)&&m>0&&(f[g]=m)}return f}),entries:o.map((d,c)=>{let l=d,h=a(l??{},"path"),u=l?.uid,f=l?.previousUid;if(h===void 0||typeof u!="number"||!Number.isSafeInteger(u)||u<=0||typeof f!="number"||!Number.isSafeInteger(f)||f<0)throw this.malformed(`an undone whose entry ${c} is not a path and two uids`);let g=a(l,"prev");return{path:h,uid:u,previousUid:f,...g!==void 0?{prev:g}:{}}})}}async search(e){let t=await this.request({op:"search",query:e.query,...e.mode!==void 0&&e.mode!=="content"?{mode:e.mode}:{},...e.folder!==void 0&&e.folder!==""?{folder:e.folder}:{},...e.caseSensitive===!0?{caseSensitive:!0}:{},...e.includeChildren===!1?{includeChildren:!1}:{},...e.contextLines!==void 0&&e.contextLines>0?{contextLines:e.contextLines}:{},...e.limit!==void 0?{limit:e.limit}:{},...e.after!==void 0&&e.after!==""?{after:e.after}:{}},"searched");if(t.res!=="searched")throw new C("protostate",`expected searched, got ${JSON.stringify(t)}`);let r=t.matches,i=t.skipped,s=t.index,o=t.nextAfter;if(!Array.isArray(r)||!Array.isArray(i))throw this.malformed("a searched with no list of matches or skipped notes");if(o!==null&&(typeof o!="string"||o===""))throw this.malformed("a searched whose nextAfter is neither a continuation nor null");if(typeof t.complete!="boolean"||t.complete===!0&&o!==null)throw this.malformed("a searched that says it is complete and continues");if(typeof s!="object"||s===null||typeof s.usable!="boolean")throw this.malformed("a searched that does not say what its index did");let a=c=>Array.isArray(c)&&c.every(l=>typeof l=="string"),d=s.why;return{matches:r.map((c,l)=>{let h=c??{},{path:u,uid:f,line:g,column:m,text:y,before:w,after:b,clipped:k,kind:S}=h;if(typeof u!="string"||u===""||typeof f!="number"||!Number.isSafeInteger(f)||f<=0||typeof g!="number"||!Number.isSafeInteger(g)||g<0||typeof m!="number"||!Number.isSafeInteger(m)||m<1||typeof y!="string"||!a(w)||!a(b)||typeof k!="boolean"||S!==void 0&&S!=="filename"&&S!=="tag")throw this.malformed(`a searched whose match ${l} is not a place in a note`);return{path:u,uid:f,line:g,column:m,text:y,before:w,after:b,clipped:k,...S!==void 0?{kind:S}:{}}}),skipped:i.map((c,l)=>{let h=c??{};if(typeof h.path!="string"||typeof h.why!="string")throw this.malformed(`a searched whose skipped note ${l} has no path or reason`);return{path:h.path,why:h.why}}),nextAfter:o,complete:t.complete,head:this.count(t,"head","searched"),indexedHead:this.count(t,"indexedHead","searched"),index:{usable:s.usable===!0,...typeof d=="string"&&d!==""?{why:d}:{}},scanned:this.count(t,"scanned","searched"),scannedBytes:this.count(t,"scannedBytes","searched")}}async rename(e){let t=await this.request({op:"rename",name:e},"renamed");if(t.res!=="renamed")throw new C("protostate",`expected renamed, got ${JSON.stringify(t)}`);let r=t.name;if(r!==e)throw this.malformed(`a renamed naming ${JSON.stringify(r)}, which is not the ${JSON.stringify(e)} that was sent`);return e}malformed(e){let t=new C("protostate",`server sent ${e}`);return this.die(t),t}count(e,t,r){let i=e[t];if(typeof i!="number"||!Number.isSafeInteger(i)||i<0)throw this.malformed(`${r} with ${t} = ${JSON.stringify(i)}, not a non-negative integer`);return i}uid(e,t){let r=this.count(e,"uid",t);if(r===0)throw this.malformed(`${t} with uid 0, which no version has`);return r}chunkNames(e,t){if(!Array.isArray(e))throw this.malformed(`${t} with no chunks list`);for(let r of e)if(!pt(r))throw this.malformed(`${t} naming ${JSON.stringify(r)}, which is not a chunk name`);return e}wanted(e,t){let r=e.chunks;if(!Array.isArray(r))throw this.malformed("want with no chunks list");let i=new Set;for(let s of r){if(typeof s!="string")throw this.malformed(`want naming ${JSON.stringify(s)}, which is not a chunk name`);if(!t.has(s)){let o=new C("badchunk",`server asked for ${s}, which this put does not contain`);throw this.die(o),o}if(i.has(s))throw this.malformed(`want naming ${s} twice`);i.add(s)}return r}ping(){if(this.pingPromise)return this.pingPromise;let e=this.sendPing();return this.pingPromise=e,e.then(()=>{this.pingPromise=void 0},()=>{this.pingPromise=void 0}),e}async probe(e=2e3){let t=setTimeout(()=>{this.pinging&&this.pending.size===0&&!this.collecting&&this.die(new R("the connection did not respond after resuming"))},e);try{await this.ping()}finally{clearTimeout(t)}}async sendPing(){this.requestsSent++;let e=await new Promise((t,r)=>{if(this.closed){r(this.closeReason??new R("not connected"));return}let i={what:"pong",resolve:t,reject:r,timer:void 0,armed:!1};this.pinging=i,this.arm(i);try{this.send(JSON.stringify({op:"ping"}))}catch(s){this.pinging=void 0,this.disarm(i),r(s instanceof Error?s:new Error(String(s)))}});if(e.res!=="pong")throw new C("protostate",`expected pong, got ${JSON.stringify(e)}`)}};function Sn(n,e){let t=new TextEncoder().encode(e).length;if(t>xn)throw new C("badname",`the ${n} name is ${t} bytes, and the server takes at most ${xn}`);for(let r=0;r<e.length;r++){let i=e.charCodeAt(r);if(i<32||i===127)throw new C("badname",`the ${n} name contains a control character at position ${r}, which the server refuses because the name lands in its log`)}}function Ss(n){return n instanceof C&&n.code==="proto"?new C("proto",`${n.message}. This client speaks protocol ${Vt}; upgrade the server first`,{retryable:!1}):n}function Fn(n,e){let t=n[e];if(typeof t!="number"||!Number.isInteger(t)||t<0)throw new C("protostate",`${e} is ${JSON.stringify(t)}, not a count`);return t}function xr(n){let e=n.id;if(typeof e!="number")throw new Error("a matched reply lost its id, which cannot happen");return e}var $n=class{constructor(e=0,t=3e5,r=5e3,i=!0,s=Math.random){this.min=e;this.max=t;this.base=r;this.jitter=i;this.random=s}min;max;base;jitter;random;count=0;success(){this.count=0}fail(){this.count++}delay(){if(this.count===0)return this.min;let e=this.base*Math.pow(2,this.count-1);return this.jitter&&(e*=.5+.5*this.random()),Math.floor(Math.min(this.max,this.min+e))}};function Hd(n){let e=globalThis.WebSocket;if(!e)throw new Error("no WebSocket available in this environment");return new e(n)}var Vd=4*1024*1024,Fs=5,Gd=50,qd=n=>new Promise(e=>setTimeout(e,n)),Xd=new Uint8Array(0),xs=16;function Kd(n){if(n instanceof Uint8Array)return n;if(n instanceof ArrayBuffer)return new Uint8Array(n);if(ArrayBuffer.isView(n))return new Uint8Array(n.buffer,n.byteOffset,n.byteLength)}function Br(n){return typeof n=="number"&&Number.isFinite(n)?n:0}function Bs(n){let e=n.code??0,t=n.reason?`, ${n.reason}`:"";return`code ${e}${t}`}function $s(n,e){if(!Array.isArray(n))throw new C("protostate",`${e} came back without a list of entries`);return n.forEach((t,r)=>{let i=t;if(typeof i?.uid!="number"||!Number.isSafeInteger(i.uid)||i.uid<=0)throw new C("protostate",`${e}[${r}] has no usable uid`);if(typeof i.path!="string"||i.path==="")throw new C("protostate",`${e}[${r}] has no path`);if(!Array.isArray(i.chunks))throw new C("protostate",`${e}[${r}] has no chunks list`);for(let s of i.chunks)if(!pt(s))throw new C("protostate",`${e}[${r}] names ${JSON.stringify(s)}, which is not a chunk name`);if(i.op!==void 0){let s=i.op;if(typeof s?.id!="string"||s.id===""||typeof s.tool!="string"||typeof s.kind!="string"||s.undoneBy!==void 0&&typeof s.undoneBy!="string")throw new C("protostate",`${e}[${r}] names an operation it does not describe`)}}),n}Re();var Yd="Remove the index and sync again: it is rebuilt from the vault and the server, and nothing is lost.";function rt(n){if(n===void 0)return;let e=a=>new Error(`the index cannot be trusted: ${a}. ${Yd}`);if(!Et(n))throw e("it is not an object");let t=n.cursor;if(!Gt(t))throw e(`cursor is ${re(t)}, not a non-negative integer`);let r=n.epoch;if(r!==void 0&&(typeof r!="string"||r===""))throw e(`epoch is ${re(r)}, not the server's epoch`);let i=n.entries;if(!Et(i))throw e("entries is not an object");for(let[a,d]of Object.entries(i))Zd(a,d,e);let s=n.remote;if(!Et(s))throw e("remote is not an object");for(let[a,d]of Object.entries(s))Qd(a,d,e);let o=n.pending;if(!Array.isArray(o))throw e("pending is not a list");o.forEach((a,d)=>{if(!Pn(a))throw e(`pending[${d}] is ${re(a)}, not a path`)});for(let a of o)if(!Object.hasOwn(s,a))throw e(`pending names ${JSON.stringify(a)}, which remote does not hold`);return{cursor:t,...r!==void 0?{epoch:r}:{},entries:i,remote:s,pending:o}}function Zd(n,e,t){let r=`entries[${JSON.stringify(n)}]`;if(!Pn(n))throw t(`${r} has a key that is not a path`);if(!Et(e))throw t(`${r} is not an object`);if("path"in e&&e.path!==n)throw t(`${r}.path is ${re(e.path)}, which is not its key`);for(let o of["size","syncuid","synctime"])if(o in e&&!Gt(e[o]))throw t(`${r}.${o} is ${re(e[o])}, not a non-negative integer`);for(let o of["ctime","mtime"])if(o in e&&!Os(e[o]))throw t(`${r}.${o} is ${re(e[o])}, not a whole number of milliseconds`);if("folder"in e&&typeof e.folder!="boolean")throw t(`${r}.folder is ${re(e.folder)}, not a boolean`);for(let o of["hash","synchash","prev","changeId"])if(o in e&&typeof e[o]!="string")throw t(`${r}.${o} is ${re(e[o])}, not a string`);if("chunks"in e){let o=e.chunks;if(!Array.isArray(o)||!o.every(pt))throw t(`${r}.chunks is not a list of chunk names`)}let i=e.synchash,s=e.chunks;if(typeof i=="string"&&i!==""&&i!=="-empty-"&&e.folder!==!0&&Array.isArray(s)&&s.length===0&&e.hash===i)throw t(`${r} says it is synced as ${i.slice(0,16)}... but names no chunks`)}function Qd(n,e,t){let r=`remote[${JSON.stringify(n)}]`;if(!Pn(n))throw t(`${r} has a key that is not a path`);if(!Et(e))throw t(`${r} is not an object`);if(!Gt(e.uid)||e.uid===0)throw t(`${r}.uid is ${re(e.uid)}, not a positive integer`);for(let i of["folder","deleted"])if(typeof e[i]!="boolean")throw t(`${r}.${i} is ${re(e[i])}, not a boolean`);if(!Os(e.mtime))throw t(`${r}.mtime is ${re(e.mtime)}, not a whole number of milliseconds`);if(!Gt(e.size))throw t(`${r}.size is ${re(e.size)}, not a non-negative integer`);if(typeof e.hash!="string")throw t(`${r}.hash is ${re(e.hash)}, not a string`);if(e.device!==void 0&&typeof e.device!="string")throw t(`${r}.device is ${re(e.device)}, not a string`);if(e.heads!==void 0&&(!Et(e.heads)||!Object.entries(e.heads).every(([i,s])=>Pn(i)&&Gt(s))))throw t(`${r}.heads is not a map of path version numbers`)}function Et(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)}function Gt(n){return typeof n=="number"&&Number.isSafeInteger(n)&&n>=0}function Os(n){return typeof n=="number"&&Number.isSafeInteger(n)}function Pn(n){return typeof n=="string"&&n!==""&&!n.includes("\0")}function re(n){return n===void 0?"missing":n===null?"null":typeof n=="string"?JSON.stringify(n.length>40?`${n.slice(0,40)}...`:n):typeof n=="number"||typeof n=="boolean"?String(n):Array.isArray(n)?"a list":"an object"}function Dn(n){let e=n.split("/");e.pop();let t=[],r="";for(let i of e)r=r?`${r}/${i}`:i,t.push(r);return t}function ec(n){let e={...n};return n.hash===ie(n.chunks)&&delete e.hash,n.synchash===n.hash&&delete e.synchash,e}function tc(n,e){let t={...En(n),...e};return e.hash===void 0&&(t.hash=ie(t.chunks)),e.synchash===void 0&&(t.synchash=t.hash),t}function ie(n){return n.length===0?"-empty-":n.join(",")}function nc(n,e){if(n<e)throw new C("cursor",`this server is at version ${n} and this device has already seen ${e}: refusing to sync, because a server behind its own clients is a restored backup or the wrong vault. ${Mn}`)}var Mn="A restore through trewd backup starts a new epoch and needs nothing from here; this is a data directory copied back behind the server's back. To rejoin it and keep what only this device holds, back the server up, then press Rejoin this server in the TrewSync panel, or unlink this device and pair it again with a new invite. Either resets the merge base, so the next edit made on two devices at once makes conflict copies instead of merging.",rc={perFileMax:1<<28,maxChunks:65536,maxBatchBytes:16<<20,maxFetchBytes:64<<20,chunkMax:1<<20};function ic(n,e){return n>0?Math.min(n,e):e}function Rn(n){if(n.path==="")throw new Error(`version ${n.uid} has an empty path, and no file is called nothing`);for(let[e,t]of[["mtime",n.mtime],["ctime",n.ctime]])if(typeof t!="number"||!Number.isSafeInteger(t))throw new Error(`version ${n.uid} has ${e} ${JSON.stringify(t)}, which is not a time`);if(typeof n.folder!="boolean"||typeof n.deleted!="boolean")throw new Error(`version ${n.uid} does not say plainly whether it is a folder or a deletion`);if(n.folder&&n.deleted)throw new Error(`version ${n.uid} is both a folder and a deletion`);if(typeof n.size!="number"||!Number.isSafeInteger(n.size)||n.size<0)throw new Error(`version ${n.uid} declares ${JSON.stringify(n.size)} bytes, and there is no such file`);for(let e of n.chunks)if(!sc(e))throw new Error(`version ${n.uid} names ${JSON.stringify(e)}, which is not a chunk name`);if(!n.folder&&!n.deleted&&n.size>0&&n.chunks.length===0)throw new Error(`version ${n.uid} declares ${n.size} bytes and names no chunks, which cannot both be true`);if(!n.folder&&!n.deleted&&n.size===0&&n.chunks.length>0)throw new Error(`version ${n.uid} is a zero-byte file naming ${n.chunks.length} chunks`);if(n.chunks.length>0&&(n.folder||n.deleted)){let e=n.folder?"a folder":"a deletion";throw new Error(`version ${n.uid} is ${e} and names ${n.chunks.length} chunks`)}}function sc(n){return/^[0-9a-f]{64}$/.test(n)}function oc(n){return n===""||n==="-empty-"?[]:n.split(",")}var it=5,ac=3,dc=5e3,cc=1e3;function lc(n){switch(n){case"toolarge":return"Make it smaller, or raise the server's -max-file and restart it.";case"badname":return"Rename it to something this server will take, on the device that made it.";case"neversync":return"Nothing syncs under that name here. Move it, or change what this device ignores.";case"badentry":return"The device that wrote it sent something malformed; its logs say what.";case"nochunk":return"The server no longer holds its content. Restore it from a backup, or write it again from a device that still has it.";case"cursor":return"The server has lost history this device applied without starting a new epoch. Back the server up, then unlink this device and pair it again.";case"badpath":return"Rename it on this device to a name the server takes; the rule it broke is named first.";case"collision":return"Another note already has this name in a different case or form. Rename one of the two.";default:return""}}function qt(n,e){n.skipped++,n.skippedPaths.push(e)}function Pr(n,e){n.retrying++,n.retryingPaths.push(e)}function hc(n,e){let t=n??Or(),r=e??Or(),i={};for(let s of[t.filesystemMs,r.filesystemMs])for(let[o,a]of Object.entries(s)){let d=i[o]??={ms:0,calls:0};d.ms+=a.ms,d.calls+=a.calls}return{listMs:t.listMs+r.listMs,decideMs:t.decideMs+r.decideMs,transferMs:t.transferMs+r.transferMs,saveMs:t.saveMs+r.saveMs,journalCompareMs:t.journalCompareMs+r.journalCompareMs,filesystemMs:i,rounds:(n===void 0?0:t.rounds)+r.rounds}}function Or(){return{listMs:0,decideMs:0,transferMs:0,saveMs:0,journalCompareMs:0,filesystemMs:{},rounds:1}}function Ms(){return{uploaded:0,downloaded:0,merged:0,conflicted:0,deletedLocally:0,deletedRemotely:0,restored:0,foldersCreated:0,foldersDeletedLocally:0,foldersDeletedRemotely:0,unchanged:0,waiting:0,retrying:0,skipped:0,skippedPaths:[],retryingPaths:[],heldBack:0,heldBackPaths:[],ignored:0,blocked:0,inTheWay:[],needsAttention:[],chunksSent:0,reusedChunks:0,bytesSent:0}}function Xt(n,e,t,r){return t===e&&!n?.heads&&!n?.wire?{}:{...t!==e?{wire:t}:{},heads:{...n?.heads,...n?{[n.wire??e]:n.uid}:{},[t]:r}}}function Ns(n){return!n.folder&&!n.deleted&&typeof n.device=="string"&&n.device!==""?{device:n.device}:{}}function uc(n,e,t){if(t!==void 0&&n&&n.uid!==t)throw new C("stale","The path changed while preparing this write.");if(!n?.wire)return t??0;let r=n.heads?.[e];return typeof r=="number"?r:0}var In=class{constructor(e){this.opts=e}opts;entries=new Map;remote=new Map;pending=new Set;retries=new Map;skipped=new Map;liveSetShrank=!1;refusedInbound=new Map;staleHeads=new Map;yieldedThisSync=!1;asked=new Map;ignoredPaths=new Map;blocked=new Set;nowBlocked=new Set;cannotStream=!1;outbox=[];outboxBudget=0;outboxFrame=0;inbox=[];inboxBytes=0;limits;cursor=0;epoch;adoptedReplacedHistory=!1;syncing=!1;again=!1;started=!1;now(){return this.opts.now?.()??Date.now()}log(e,...t){this.opts.log?.(e,...t)}activity(e,t,r){try{this.opts.onActivity?.({at:this.now(),action:e,path:t,...r?{copy:r}:{}})}catch{}}mergeable(e){return(this.opts.mergeable??Ve)(e)}sizesFor(e,t){return Ai(e,t,this.limits?.chunkMax)}get coalesce(){return this.opts.coalesceWrites??!0}get merging(){return this.opts.merge??!0}get sending(){return this.opts.readOnly!==!0}heldBack(e,t,r){t.heldBack++,t.heldBackPaths.length<it&&t.heldBackPaths.push(e),this.log("held back",e,r)}serverHasOurs(e){let t=this.entries.get(e);return t===void 0||t.folder?!1:t.syncuid>0&&t.synchash!==""&&t.synchash===t.hash}status(){let e=0;for(let t of this.entries.values())t.folder||e++;return{cursor:this.cursor,files:e,pending:this.pending.size,retrying:this.retries.size,skipped:this.skipped.size+this.refusedInbound.size,ignored:this.ignoredPaths.size,syncing:this.syncing}}async start(){if(this.started)throw new Error("already started");this.started=!0;let e=rt(await this.opts.store.load());if(e){this.cursor=e.cursor,this.epoch=e.epoch;for(let[r,i]of Object.entries(e.entries))this.entries.set(r,tc(r,i));for(let[r,i]of Object.entries(e.remote))this.remote.set(r,i);for(let r of e.pending)this.pending.add(r);this.log("index loaded",{cursor:this.cursor,entries:this.entries.size,pending:this.pending.size})}let t=await this.opts.transport.hello({vault:this.opts.vaultId,deviceId:this.opts.deviceId,token:this.opts.token,device:this.opts.device,cursor:this.cursor,epoch:this.epoch});if(this.opts.transport.historyReplaced&&this.adoptReplacedHistory(t.epoch),this.epoch=t.epoch,nc(t.cursor,this.cursor),t.chunkMax<Mt){let r=new C("protostate",`this server takes chunks of at most ${t.chunkMax} bytes, and this device cannot cut a chunk smaller than ${Mt}, so every file it sent would be refused; the server's chunk limit has to be at least ${Mt}`,{retryable:!1});throw this.opts.transport.close(),r}return this.limits=t,this.log("connected",t),t}adoptReplacedHistory(e){if(!this.adoptedReplacedHistory){this.adoptedReplacedHistory=!0,this.log("the server's history is not the one this device synced against; reading it as new",{was:this.epoch,now:e??this.opts.transport.serverLimits?.epoch,cursor:this.cursor}),this.cursor=0,this.remote.clear(),this.pending.clear(),this.staleHeads.clear(),this.asked.clear();for(let t of this.entries.values())t.synchash="",t.syncuid=0,t.synctime=0}}async acceptBatch(e){this.opts.transport.historyReplaced&&this.adoptReplacedHistory();for(let o of e.entries)Rn(o);let t=e.entries.map(o=>o.path),r=t.map(de),i=e.entries.map(o=>o.prev?o.prev:void 0),s=new Map;for(let o=0;o<e.entries.length;o++){let a=e.entries[o],d=r[o],c=t[o];if(d===""||d.includes("\0")){let l=_s(d)??"a path containing a NUL byte";this.refusedInbound.has(d)||this.log("refused a path from another device",d,l),this.refusedInbound.set(d,l);continue}if(s.set(d,{uid:a.uid,folder:a.folder,deleted:a.deleted,mtime:a.mtime,size:a.size,hash:ie(a.chunks),...Ns(a),...Xt(s.get(d)??this.remote.get(d),d,c,a.uid)}),a.prev){let l=de(i[o]);if(l!==d)s.set(l,{uid:a.uid,folder:!1,deleted:!0,mtime:a.mtime,size:0,hash:"",...Xt(s.get(l)??this.remote.get(l),l,i[o],a.uid)});else{let h=s.get(d);s.set(d,{...h,heads:{...h.heads,[i[o]]:a.uid}})}}}for(let[o,a]of s)this.remote.set(o,a),this.pending.add(o);e.entries.some(o=>o.deleted||o.prev!==void 0&&o.prev!=="")&&(this.liveSetShrank=!0),this.cursor=e.to}async sync(e={}){if(this.syncing)return this.again=!0,Ms();this.syncing=!0,this.again=!1,this.yieldedThisSync=!1;try{if(e.retryFailures||e.verifyContents){let i=this.now();for(let s of this.retries.values())s.at=Math.min(s.at,i)}let t=await this.pass(e),r=1;for(;this.again&&r<8&&!this.opts.transport.isClosed;){this.again=!1,await this.opts.transport.drainReceived(),await this.refreshStaleHeads(t);let i=await this.pass(e);t=Mr(t,i),r++}return this.again&&(t.waiting=Math.max(t.waiting,1),t.nextUploadAt=this.now()+cc,delete t.appliedCursor),t}finally{this.opts.releaseUploadTransport?.(),this.syncing=!1}}refusedName(e){let t=this.refusalOf.get(e);if(t!==void 0)return t.why;let r=_s(e,this.opts.windows===!0);return this.refusalOf.set(e,{why:r}),r}refusalOf=new Map;async refreshStaleHeads(e){if(!(this.staleHeads.size===0||this.opts.transport.isClosed))for(let[t,r]of[...this.staleHeads]){this.staleHeads.delete(t),this.asked.set(t,r);let i=this.remote.get(t),s=i?.wire??t;try{let[o]=await this.opts.transport.history(s,{limit:1});if(o===void 0){this.remote.delete(t),this.pending.delete(t);continue}if(Rn(o),o.path!==s)throw new Error(`the server answered a request for the newest version of ${t} with a version of another note, so the current version of this path is still not known here`);if(i!==void 0&&o.uid<=i.uid)continue;this.remote.set(t,{uid:o.uid,folder:o.folder,deleted:o.deleted,mtime:o.mtime,size:o.size,hash:ie(o.chunks),...Ns(o),...Xt(i,t,s,o.uid)}),this.pending.add(t),this.log("asked the server which version of a refused path it holds",t,{was:i?.uid??0,now:o.uid})}catch(o){this.recordFailure(t,o,e)}}}async preview(e){let t=new Map(this.remote),r={cursor:this.cursor,files:[]},i=new Map((e??await this.opts.vault.list()).map(o=>[o.path,o])),s=new Set([...this.entries].flatMap(([o,a])=>a.prev&&i.has(o)&&!i.has(a.prev)?[a.prev]:[]));for(let o of new Set([...i.keys(),...t.keys(),...this.entries.keys()])){if(s.has(o))continue;let a=i.get(o),d=t.get(o);if(a?.folder||d?.folder||this.entries.get(o)?.folder)continue;let c=this.entries.get(o),l=c?{...c,chunks:[...c.chunks]}:En(o),h;try{if(a){if(tt(l,a),a.size>this.limitOn("perFileMax"))throw new Error("File too large");(this.dirty.has(o)||yt(l,Math.ceil(a.mtime),a.size,a.changeId))&&await this.rehash(l,o,a.size)}let u=a?{folder:!1,mtime:l.mtime,size:l.size,hash:l.hash}:void 0,f=kn({local:u,remote:d,index:l,mergeable:this.mergeable(o)}).kind;h=f==="nothing"?"unchanged":f==="conflict"?"copy":f==="deleteLocal"?"delete-local":f==="deleteRemote"?"delete-server":f==="restoreLocal"?"download":f==="upload"||f==="download"||f==="merge"?f:"blocked",!this.sending&&(h==="upload"||h==="delete-server")&&(h="held-back"),(this.ignoredPaths.has(o)||this.skipped.has(o)||this.refusedName(o)!==void 0)&&(h="blocked")}catch{h="blocked"}r.files.push({path:o,action:h})}return r}firstSyncConfirmed=!1;approvedDeletions=new Set;async confirmWork(e){let t=new Map(e.map(d=>[d.path,d])),r=!this.firstSyncConfirmed&&this.opts.confirmFirstSync&&![...this.entries.values()].some(d=>d.syncuid>0)&&e.some(d=>!d.folder)&&[...this.remote.values()].some(d=>!d.deleted&&!d.folder),i=this.opts.confirmDeletions?[...new Set([...this.entries.keys(),...this.remote.keys()])].filter(d=>this.remote.get(d)?.folder&&this.remote.get(d)?.deleted&&t.has(d)||this.sending&&this.entries.get(d)?.folder&&!t.has(d)&&!this.remote.get(d)?.deleted):[];if(!r&&!i.length)return;let s=await this.preview(e);if(r&&s.files.some(d=>d.action!=="unchanged"&&d.action!=="download")){if(!await this.opts.confirmFirstSync(s))throw new Error("First sync paused for review.");this.firstSyncConfirmed=!0}let o=s.files.filter(d=>d.action==="delete-local"||d.action==="delete-server");if(!i.some(d=>o.filter(c=>c.path.startsWith(`${d}/`)).length>1))return;let a=JSON.stringify(o.map(d=>[d.path,d.action,this.remote.get(d.path)?.uid]).sort());if(!this.approvedDeletions.has(a)){if(!await this.opts.confirmDeletions(s))throw new Error("Folder deletion paused for review.");if(this.cursor!==s.cursor)throw new Error("Server changes arrived during review. Review the updated deletion plan.");this.approvedDeletions.clear(),this.approvedDeletions.add(a)}}async pass(e={}){let t=Ms();if(this.checkpointedAt=Date.now(),this.liveSetShrank){this.liveSetShrank=!1;for(let[p,B]of this.skipped)B.code==="collision"&&this.skipped.delete(p)}let r=this.opts.timing?Or():void 0,i=r===void 0?0:performance.now(),s=p=>{if(r===void 0)return;let B=performance.now();r[p]+=B-i,i=B},o=this.now(),a=e.coalesceWrites??this.coalesce;(this.outbox.length>0||this.inbox.length>0)&&(this.log("a pass ended early, discarding what it had queued",{writes:this.outbox.length,reads:this.inbox.length}),this.outbox=[],this.outboxBudget=0,this.outboxFrame=0,this.inbox=[],this.inboxBytes=0),this.folderDeletes=[],this.folderRemovals=[],this.folderRespellings=[],this.liveFolderSpellings=void 0;let d=await this.opts.vault.list({forceFull:e.verifyContents===!0||e.forceFullScan===!0}),c=new Map(d.map(p=>[p.path,p])),l=new Map,h=[];for(let[p,B]of this.entries)if(!(c.has(p)||B.synchash===""&&B.synctime<=0))try{await this.opts.vault.exists(p)&&h.push(p)}catch(T){let _=T?.code;if(_!=="ignored"&&_!=="neversync")throw T;l.set(p,T)}h.length>0&&(d=await this.opts.vault.list({forceFull:!0,present:h}),c=new Map(d.map(p=>[p.path,p]))),this.recordScannedRenames(c,l),s("listMs"),await this.confirmWork(d);let u=new Set(this.dirty);this.dirty.clear();for(let p of d){let B=this.entryFor(p.path);(u.has(p.path)||e.verifyContents)&&(B.hash="",B.chunks=[]),tt(B,p)}let f=new Set;for(let[p,B]of this.entries){if(!B.prev)continue;let T=de(B.prev);T!==p&&(B.folder&&!Lt(T,p)||(c.has(T)?B.prev="":this.sending&&c.has(p)&&f.add(T)))}let g=new Set;for(let[p,B]of c)B.folder||g.add(p);let m=new Set;this.nowBlocked=m;let y=new Map;for(let p of this.opts.vault.ambiguous?.()??[])y.set(p.path,`${p.spellings.map(B=>`"${Ii(B)}"`).join(" and ")} are one name here, and only one of them can sync.`);this.checkIdentityProbe(),this.localByIdentity=new Map;for(let p of c.keys())this.localByIdentity.set(this.identity(p),p);this.deletingThisPass=new Set;let w=new Set(c.keys());for(let p of this.entries.keys())w.add(p);for(let p of this.remote.keys())w.add(p);for(let p of y.keys())w.add(p);let b=this.opts.activePath?.(),k=p=>c.get(p)?.folder||this.remote.get(p)?.folder?0:Ve(p)?p===b?1:2:3,S=[[],[],[],[]];for(let p of w)S[k(p)].push(p);let v=[];S.forEach((p,B)=>{for(let T of p.sort())v.push({path:T,priority:B})});let A=0,F=!1,x;for(let{path:p,priority:B}of v){let T=b?this.remote.get(b)?.uid:void 0;if(b&&F&&!this.yieldedThisSync&&(this.dirty.has(b)||T!==void 0&&T!==x&&T>(this.entries.get(b)?.syncuid??0))){this.yieldedThisSync=!0,this.again=!0;break}if(p===b&&(F=!0,x=this.remote.get(p)?.uid),f.has(p))continue;let _=c.has(p)||!this.remote.has(p)?void 0:this.refusedName(p);if(_!==void 0){this.refusedInbound.get(p)!==_&&this.log("refused a path from another device",p,_),this.refusedInbound.set(p,_),this.pending.delete(p),qt(t,p);continue}if(A>0&&B>A&&(s("decideMs"),await this.fill(t),await this.flush(t),s("transferMs")),A=B,l.has(p)){this.recordFailure(p,l.get(p),t);continue}if(this.ignoredPaths.has(p)){this.pending.delete(p),t.ignored++;continue}let fe=this.skipped.get(p);if(fe&&!c.has(p)&&!this.remote.has(p))this.skipped.delete(p),this.log("written-off file is gone, and the server never had it",p);else if(fe){if(Dr(this.entries.get(p),this.remote.get(p))===fe.fingerprint){qt(t,p);continue}this.skipped.delete(p),this.log("skipped file changed, trying again",p)}let q=y.size===0?void 0:y.has(p)?p:Dn(p).find(I=>y.has(I));if(q!==void 0){let I=y.get(q);m.add(p),this.blocked.has(p)||this.log("cannot be both",p,I),t.blocked++,t.inTheWay.length<it&&t.inTheWay.push({path:p,blockedBy:q,why:I});continue}let H=c.has(p)?void 0:Dn(p).find(I=>g.has(I));if(H!==void 0){m.add(p),this.blocked.has(p)||this.log("cannot be both",p,`${H} is a file here and a folder elsewhere`),t.blocked++,t.inTheWay.length<it&&t.inTheWay.push({path:p,blockedBy:H});continue}let W=this.retries.get(p);if(W&&W.at>o){Pr(t,p),t.nextUploadAt=Math.min(t.nextUploadAt??1/0,W.at);continue}try{this.opts.onProgress?.(p),await this.reconcile(p,c.get(p),t,o,a),this.retries.delete(p)}catch(I){this.recordFailure(p,I,t)}}s("decideMs"),await this.fill(t),await this.applyDeletes(t),this.wroteThisPass=new Map,await this.flush(t),await this.settleFolders(t),s("transferMs"),this.opts.onProgress?.(void 0);for(let[p]of this.refusedInbound)this.remote.has(p)||qt(t,p);return t.skippedPaths=[...new Set(t.skippedPaths)].sort().slice(0,it),t.retryingPaths=[...new Set(t.retryingPaths)].sort().slice(0,it),this.blocked=m,s("decideMs"),this.prune(c),await this.opts.vault.flush?.(),await this.save(),this.pending.size===0&&t.waiting===0&&t.retrying===0&&t.skipped===0&&t.blocked===0&&t.heldBack===0&&t.conflicted===0&&[...this.remote].every(([p,B])=>this.ignoredPaths.has(p)||(this.entries.get(p)?.syncuid??-1)>=B.uid)&&(t.appliedCursor=this.cursor),t.needsAttention=this.attentionList(t),r!==void 0&&(s("saveMs"),t.phases=r),t}attentionList(e){let t=[],r=new Set,i=(s,o)=>{r.has(s)||(r.add(s),t.push({path:s,why:o}))};for(let s of e.inTheWay)i(s.path,s.why===void 0?`"${s.blockedBy}" is a file here and a folder on another device. Rename one of them, on whichever device meant the other thing.`:`${s.why} Rename one of them here; nothing syncs under that name until you do.`);for(let s of e.skippedPaths){let o=this.skipped.get(s)?.why??this.refusedInbound.get(s)??this.refusedName(s);o!==void 0&&i(s,o)}return t}entryFor(e){let t=this.entries.get(e);return t||(t=En(e),this.entries.set(e,t)),t}dirty=new Set;noteChanged(e){let t=de(e);this.dirty.add(t);let r=this.retries.get(t);r&&(r.at=Math.min(r.at,this.now())),this.syncing&&(this.again=!0)}async reconcile(e,t,r,i,s){let o=this.entryFor(e),a=this.remote.get(e),d=this.limitOn("perFileMax");if(t&&!t.folder&&t.size>d){this.recordFailure(e,Ac(t.size,d),r);return}let c,l;if(t){if(!t.folder&&yt(o,Math.ceil(t.mtime),t.size,t.changeId))try{l=await this.rehash(o,e,t.size)}catch(f){if(!await this.goneSinceListed(e))throw f;this.log("gone before it could be read, so deciding it as deleted",e),t=void 0}t&&(c={folder:t.folder,mtime:o.mtime,size:o.size,hash:o.hash})}let h=kn({local:c,remote:a,index:o,mergeable:this.mergeable(e)});if(h.kind==="deleteRemoteFolder"){let f=this.localByIdentity.get(this.identity(e));f!==void 0&&f!==e&&(h={kind:"nothing",why:`folder is here as ${f}, a spelling this disk folds together`})}else if(c?.folder&&a?.deleted){let f=this.liveFolderSpelledOtherwise(e);f!==void 0&&(h.kind==="removeLocalFolder"&&zt(o,"",a.uid,i),h={kind:"nothing",why:`folder is live on the server as ${f}, a spelling this disk folds together`},this.onlyLiveSpelling(e)===f&&this.folderRespellings.push({from:e,to:f}))}let u=a?.wire;if(u!==void 0&&c!==void 0&&!c.folder&&(o.prev===""&&(o.prev=u),h.kind==="nothing"&&(h={kind:"upload",why:"the server spells this name in another normal form"})),s&&h.kind==="upload"&&this.sending&&c&&!t?.folder&&!Ve(e)&&!as(o,i)){r.waiting++,r.nextUploadAt=Math.min(r.nextUploadAt??1/0,gr(o));return}await this.act(e,h,o,c,a,r,i,l),this.pending.delete(e)}async rehash(e,t,r){let i=await this.streamScan(e,t,r);if(i)return i;let s=await this.opts.vault.read(t),o=this.mergeable(t),a=[...Nt(s,this.sizesFor(s.length,o),o)];return e.chunks=await gn(a.map(d=>d.bytes)),e.hash=ie(e.chunks),e.size=s.length,{bytes:s,pieces:a,names:e.chunks}}async streamScan(e,t,r){let i=this.opts.vault;if(!(!i.readBlocks||!i.readRange||this.cannotStream)&&!(r===void 0||r<=Tr))try{return await this.streamed(e,t,r)}catch(s){this.cannotStream=!0,this.log("streaming is not available here, reading whole files instead",t,{why:s.message});return}}async streamed(e,t,r){let i=this.opts.vault,s=this.mergeable(t),o=[],a=[],d=0;for await(let c of pn(i.readBlocks(t),this.sizesFor(r,s),s))o.push(await We(c.bytes)),a.push({start:c.offset,end:c.offset+c.bytes.length}),d+=c.bytes.length;return e.chunks=o,e.hash=ie(o),e.size=d,{names:o,spans:a,path:t,size:d}}async act(e,t,r,i,s,o,a,d){switch(t.kind){case"nothing":o.unchanged++,this.staleHeads.delete(e),this.asked.delete(e),i&&s&&!s.deleted&&(i.folder&&s.folder?nt(r,"",[],s.uid,a):i.hash===s.hash&&nt(r,i.hash,r.chunks,s.uid,a)),i===void 0&&s?.deleted&&this.entries.delete(e);return;case"upload":await this.upload(e,r,o,s?.uid,!0,d);return;case"download":case"restoreLocal":{if(!s)return;await this.receive(e,r,s,t.kind,t.why,o,i);return}case"createLocalFolder":await this.opts.vault.mkdir(e),r.folder=!0,s&&nt(r,"",[],s.uid,a),o.foldersCreated++;return;case"deleteRemoteFolder":if(!this.sending){this.heldBack(e,o,"this device is read-only, so the folder was not deleted anywhere");return}this.folderDeletes.push(e);return;case"removeLocalFolder":this.folderRemovals.push(e);return;case"clash":this.skipped.set(e,{why:`${t.why}. Rename one of them, and it will sync.`,fingerprint:Dr(r,s)}),qt(o,e),this.log("cannot be both",e,t.why);return;case"deleteLocal":if(this.deletingThisPass.add(e),this.pendingDeletes.push({path:e,why:t.why,based:i}),i!==void 0&&!i.folder){let c=await this.syncedDigestOf(e,i);c!==void 0&&this.deleteBaseline.set(e,c)}return;case"deleteRemote":{if(!this.sending){this.heldBack(e,o,"this device is read-only, so it was not deleted anywhere");return}let c=this.now(),l={path:s?.wire??e,meta:{size:0,ctime:0,mtime:c,deleted:!0},names:[]};await this.queue({path:e,size:0,entry:{...l,base:s?.uid??0},bodyOf:Ir,commit:(h,u)=>{u||this.remote.set(e,{uid:h,folder:!1,deleted:!0,mtime:this.now(),size:0,hash:""}),this.entries.delete(e),o.deletedRemotely++,this.log("deleted on the server",e,t.why),this.activity("deleted-server",e)}},o);return}case"merge":await this.merge(e,r,s,o);return;case"conflict":await this.conflict(e,r,s,o,t.why);return}}async upload(e,t,r,i,s=!1,o){let a=uc(this.remote.get(e),e,i);if(!this.sending){this.heldBack(e,r,"this device is read-only, so it was not sent");let y=fc(i,this.remote.get(e));y&&zt(t,y.hash,y.uid,this.now());return}if(t.folder){let y=t.prev!==""&&Lt(de(t.prev),e)?t.prev:"",w=y?this.entries.get(de(y))?.syncuid??0:0,b={path:e,meta:{size:0,ctime:0,mtime:0,folder:!0,...y?{prev:y}:{}},names:[]};await this.queue({path:e,size:0,entry:{...b,base:a,...y?{prevBase:w}:{}},bodyOf:Ir,commit:(k,S)=>{nt(t,"",[],k,this.now()),S||this.remote.set(e,{uid:k,folder:!0,deleted:!1,mtime:0,size:0,hash:""}),y&&this.retireMovedSource(y,e,k,0),s&&r.uploaded++}},r);return}let d=await this.planUpload(t,e,o),c=t.hash,l=[...t.chunks],h=t.size,u=t.mtime,f=t.prev,g=f?this.entries.get(de(f))?.syncuid??0:0,m={path:e,meta:{size:h,ctime:t.ctime,mtime:u,...f?{prev:f}:{}},names:d.names};await this.queue({path:e,size:h,entry:{...m,base:a,prevBase:g},bodyOf:d.bodyOf,commit:(y,w)=>{nt(t,c,l,y,this.now()),w||this.remote.set(e,{uid:y,folder:!1,deleted:!1,mtime:u,size:h,hash:c,...Xt(this.remote.get(e),e,e,y)}),f&&this.retireMovedSource(f,e,y,u),s&&r.uploaded++,this.log("uploaded",e),this.activity("uploaded",e)}},r)}retireMovedSource(e,t,r,i){let s=de(e);if(s!==t)this.entries.delete(s),(this.remote.get(s)?.uid??0)<=r&&(this.remote.set(s,{uid:r,folder:!1,deleted:!0,mtime:i,size:0,hash:"",...Xt(this.remote.get(s),s,e,r)}),this.pending.delete(s));else if(s===t){let o=this.remote.get(t);this.remote.set(t,{...o,heads:{...o.heads,[e]:Math.max(o.heads?.[e]??0,r)}})}}async queue(e,t){let r=this.batchCap,i=e.size,s=Is(e.entry);this.outbox.length>0&&(i>r||this.outboxBudget+i>r||this.outboxFrame+s>r-$r)&&await this.flush(t),this.outbox.push(e),this.outboxBudget+=i,this.outboxFrame+=s,(this.outbox.length>=vt||this.outboxBudget>=r||this.outboxFrame>=r-$r)&&await this.flush(t)}limitOn(e){return ic(this.limits?.[e]??0,rc[e])}get batchCap(){return Math.min(this.limitOn("maxBatchBytes"),this.opts.activePath?.()?2*1024*1024:1/0)}get fetchCap(){return Math.min(this.limitOn("maxFetchBytes"),this.opts.activePath?.()?2*1024*1024:1/0)}async flush(e){if(this.outbox.length===0)return;let t=this.outbox;this.outbox=[],this.outboxBudget=0,this.outboxFrame=0;let r=new Map;for(let o of t)for(let a of o.entry.names)r.has(a)||r.set(a,o.bodyOf);let i=async o=>{let a=r.get(o);if(!a)throw new Error(`server asked for ${o}, which no queued file contains`);return a(o)},s;try{s=await this.transferring("upload",t.filter(o=>o.entry.names.length>0).map(o=>o.path),async o=>{let a=t.length===1?t[0]:void 0;if(a!==void 0&&a.size>this.batchCap){let{entry:d}=a,c=h=>h.put(d.path,d.meta,d.names,i,{base:d.base??0,prevBase:d.prevBase??0},o,h===this.opts.transport?void 0:()=>this.sendInteractiveEdit(e,t.map(u=>u.path))),l=this.opts.withUploadTransport&&!this.servicingInteractive?await this.opts.withUploadTransport(c):await c(this.opts.transport);return{results:[{uid:l.uid}],uploaded:l.uploaded,bytes:l.bytes}}else return await this.opts.transport.putMany(t.map(d=>d.entry),i,o)})}catch(o){for(let a of t)this.recordFailure(a.path,o,e);return}e.chunksSent+=s.uploaded,e.bytesSent+=s.bytes;for(let o=0;o<t.length;o++){let a=t[o],d=s.results[o];if(d.error){this.recordFailure(a.path,d.error,e);continue}this.staleHeads.delete(a.path),this.asked.delete(a.path);let c=(this.remote.get(a.path)?.uid??0)>d.uid;a.commit(d.uid,c),(a.entry.meta.deleted===!0||(a.entry.meta.prev??"")!=="")&&(this.liveSetShrank=!0),c&&(e.waiting++,this.again=!0,this.log("another device wrote after this upload, reconciling next pass",a.path,{uploaded:d.uid,now:this.remote.get(a.path)?.uid}))}}servicingInteractive=!1;lastInteractive=0;async sendInteractiveEdit(e,t){if(this.servicingInteractive||this.dirty.size===0||!this.sending||this.opts.transport.isClosed)return;let r=Date.now();if(r-this.lastInteractive<wc)return;this.lastInteractive=r;let i=this.opts.activePath?.(),s=i&&this.dirty.has(i)?i:[...this.dirty].find(g=>Ve(g));if(!s||!Ve(s)||!this.opts.vault.stat)return;let o=this.entries.get(s),a=this.remote.get(s),d=[...t,...this.outbox.map(g=>g.path),...this.inbox.map(g=>g.path),...this.pendingDeletes.map(g=>g.path)],c=this.identity(s);if(d.some(g=>{let m=this.identity(g);return m===c||m.startsWith(`${c}/`)||c.startsWith(`${m}/`)})||!o||o.folder||o.prev||a?.wire||a?.deleted||a?.folder||(a?.uid??0)!==o.syncuid||this.skipped.has(s)||this.ignoredPaths.has(s)||this.refusedName(s)!==void 0||this.nowBlocked.has(s)||this.pending.has(s)||[...this.entries.values()].some(g=>g.prev&&this.identity(g.prev)===c)||(this.opts.vault.ambiguous?.()??[]).some(g=>this.identity(g.path)===c||c.startsWith(`${this.identity(g.path)}/`)))return;let l=this.retries.get(s);if(l&&l.at>this.now())return;this.servicingInteractive=!0;let h=this.outbox,u=this.outboxBudget,f=this.outboxFrame;this.outbox=[],this.outboxBudget=0,this.outboxFrame=0;try{let g=await this.opts.vault.stat(s);if(!g||g.folder||g.size>Math.min(512*1024,this.limitOn("perFileMax")))return;this.dirty.delete(s),o.hash="",o.chunks=[],tt(o,g);let m;try{m=await this.rehash(o,s,g.size)}catch(b){if(!await this.goneSinceListed(s))throw b;this.dirty.add(s),this.again=!0;return}if(o.size>Math.min(512*1024,this.limitOn("perFileMax"))){this.again=!0;return}let y=this.remote.get(s);if(kn({local:{folder:!1,mtime:o.mtime,size:o.size,hash:o.hash},remote:y,index:o,mergeable:this.mergeable(s)}).kind!=="upload"){this.again=!0;return}await this.upload(s,o,e,y?.uid,!0,m),await this.flush(e)}catch(g){this.recordFailure(s,g,e)}finally{this.outbox=h,this.outboxBudget=u,this.outboxFrame=f,this.servicingInteractive=!1}}async repair(){let e={scanned:0,offered:0,stored:0,couldNotOffer:0,stillMissing:0,failed:[]},t=[];for(let[r,i]of[...this.entries]){if(i.folder||i.chunks.length===0)continue;e.scanned++;let s=i.chunks;if(i.hash!==i.synchash){e.couldNotOffer+=s.length;continue}let o=this.opts.vault.stat?await this.opts.vault.stat(r):void 0;if(o===void 0||o.folder||yt(i,Math.ceil(o.mtime),o.size,o.changeId)){e.couldNotOffer+=s.length;continue}t.push({path:r,entry:i,names:s})}for(let r=0;r<t.length;){let i=[],s=0;for(;r<t.length&&(i.length===0||s+t[r].names.length<=yc);)s+=t[r].names.length,i.push(t[r]),r++;let o=new Map,a=[];for(let h of i)for(let u of h.names)o.has(u)||(o.set(u,h),a.push(u));let d=new Map,c,l=async h=>{let u=o.get(h);if(!u)throw new Error(`the server asked for ${h}, which this repair did not offer`);let f=d.get(u.path);if(f===void 0){if(f=await this.planUpload(u.entry,u.path),f.names.length!==u.names.length||f.names.some((g,m)=>g!==u.names[m]))throw c=u.path,new Error(`${u.path} has changed since the version the server acknowledged, so its chunks were not sent`);d.set(u.path,f)}return f.bodyOf(h)};try{let h=await this.opts.transport.resend(a,l);e.offered+=a.length,e.stored+=h.stored,e.stillMissing+=h.missing}catch(h){for(let u of i)u.path===c?e.couldNotOffer+=u.names.length:e.failed.push({path:u.path,why:h.message});if(this.opts.transport.isClosed)break}}return e}async planUpload(e,t,r){if(r===void 0&&e.chunks.length>0&&e.hash!==""){let a=[...e.chunks],d;return{names:a,bodyOf:async c=>{if(d===void 0){let l=await this.rehash(e,t);if(l.names.length!==a.length||l.names.some((h,u)=>h!==a[u]))throw new Error(`${t} changed while it was being sent, so it was not sent`);d=await this.planUpload(e,t,l)}return d.bodyOf(c)}}}let i=r??await this.rehash(e,t),s=this.opts.vault;if(i.spans){let a=new Map(i.names.map((d,c)=>[d,i.spans[c]]));return{names:i.names,bodyOf:async d=>{let c=a.get(d);if(!c)throw new Error(`no chunk named ${d} in ${t}`);let l=await s.readRange(i.path,c.start,c.end);if(await We(l)!==d)throw new Error(`${t} changed while it was being sent, so it was not sent`);return l}}}let o=new Map;for(let a=0;a<i.names.length;a++)o.set(i.names[a],i.pieces[a].bytes);return{names:i.names,bodyOf:async a=>{let d=o.get(a);if(!d)throw new Error(`no chunk named ${a} in ${t}`);return d}}}async receive(e,t,r,i,s,o,a){let d=oc(r.hash);this.checkChunkCount(r.uid,d.length);let c=a===void 0?await this.respelledHere(e,r):void 0,l=c?.state??a,h=l===void 0||l.folder?void 0:await this.syncedDigestOf(c?.from??e,l);this.inbox.push({path:e,entry:t,remote:r,chunks:d,kind:i,why:s,based:l,baseDigest:h}),this.inboxBytes+=r.size,(this.inbox.length>=vt||this.inboxBytes>=vc)&&await this.fill(o)}async respelledHere(e,t){let r=this.opts.vault;if(r.sameFile===void 0&&r.canonical===void 0)return;let i=this.localByIdentity.get(this.identity(e));if(i===void 0||i===e||!Lt(i,e))return;let s=this.remote.get(i);if(s===void 0||!s.deleted||s.uid!==t.uid)return;let o=this.entries.get(i);if(o===void 0||o.folder||o.synchash===""||o.hash!==o.synchash||r.sameFile!==void 0&&!await r.sameFile(e,i))return;let a=await r.stat(e);if(!(a===void 0||a.folder)&&!(a.size!==o.size||Math.ceil(a.mtime)!==o.mtime))return{from:i,state:{folder:!1,mtime:o.mtime,size:o.size,hash:o.hash}}}async fill(e){if(this.inbox.length===0)return;let t=this.refuseAliases(this.inbox,e);if(this.inbox=[],this.inboxBytes=0,t.length===0)return;let r=new Map,i=this.heldByContent();for(let l of t){let h=i.get(ie(l.chunks));h!==void 0&&h!==l.path&&r.set(l,h)}let s=this.reusableFrom(t,r),o=[],a=new Map;for(let l of t){if(r.has(l))continue;let h=s.get(l),u=Tn(l.remote.size,l.chunks.length);for(let f of l.chunks){if(h?.has(f))continue;let g=a.get(f);g===void 0&&o.push(f),(g===void 0||u>g)&&a.set(f,u)}}let d=new Map,c=!1;if(o.length>0)try{let l=await this.fetchAll(o,h=>a.get(h),t.filter(h=>!r.has(h)).map(h=>h.path),()=>this.sendInteractiveEdit(e,t.map(h=>h.path)));for(let h=0;h<o.length;h++)d.set(o[h],l[h])}catch(l){if(l instanceof C&&l.code==="nochunk"&&!this.opts.transport.isClosed)c=!0;else{for(let h of t)this.recordFailure(h.path,l,e);return}}for(let l of t)try{let h=r.get(l),u=h===void 0?"ask":await this.landFromLocal(l,h,e);if(u!=="ask"&&this.writtenSinceSave++,u==="landed"){l.kind==="download"?(e.downloaded++,this.activity("downloaded",l.path)):e.restored++,this.log(l.kind,l.path,`${l.why}, from ${h} without asking`);continue}if(u==="kept")continue;let f=s.get(l),g=f===void 0?d:await this.withLocalChunks(l,f,d,e),m=h!==void 0||c?await this.land(l,await this.fetchFor(l),e):await this.land(l,g,e);if(this.writtenSinceSave++,!m)continue;l.kind==="download"?(e.downloaded++,this.activity("downloaded",l.path)):e.restored++,this.log(l.kind,l.path,l.why)}catch(h){this.recordFailure(l.path,h,e)}await this.checkpoint()}writtenSinceSave=0;checkpointedAt=0;async checkpoint(){if(this.writtenSinceSave!==0&&!(this.writtenSinceSave<bc&&Date.now()-this.checkpointedAt<Ec))try{await this.opts.vault.flush?.(),await this.save()}catch(e){this.writtenSinceSave=0,this.checkpointedAt=Date.now(),this.log("could not save the index part way through the pass; the end of it will",{why:e.message})}}localByIdentity=new Map;deletingThisPass=new Set;identity(e){let t=this.identityOf.get(e);if(t!==void 0)return t;let r=this.opts.vault,i=r.canonical?r.canonical(e):Q(e);return this.identityOf.set(e,i),i}identityOf=new Map;identityProbe;checkIdentityProbe(){let e=this.opts.vault.canonical?.("Aa");e!==this.identityProbe&&(this.identityProbe=e,this.identityOf.clear())}refuseAliases(e,t){let r=new Map;for(let s of e){let o=this.identity(s.path),a=r.get(o)??[];a.push(s),r.set(o,a)}let i=[];for(let[s,o]of r){let a=this.localByIdentity.get(s),d=a!==void 0&&!this.deletingThisPass.has(a)&&o.some(c=>c.path!==a);if(!d&&o.length===1){i.push(o[0]);continue}for(let c of o){let l=d?a:o.find(h=>h.path!==c.path).path;t.blocked++,t.inTheWay.length<it&&t.inTheWay.push({path:c.path,blockedBy:l}),this.blocked.has(c.path)||this.log("cannot be both",c.path,`${l} is the same file on this disk`),this.nowBlocked.add(c.path)}}return i}pendingDeletes=[];deleteBaseline=new Map;wroteThisPass=new Map;async wouldUndoAWrite(e){let t=this.opts.vault;for(let r of this.wroteThisPass.get(Ls(e))??[])if(r!==e){if(t.sameFile){if(await t.sameFile(r,e))return{wrote:r,sure:!0};continue}if(Lt(r,e))return{wrote:r,sure:!1}}}async applyDeletes(e){let t=this.pendingDeletes;this.pendingDeletes=[];let r=this.deleteBaseline;this.deleteBaseline=new Map;for(let{path:i,why:s,based:o}of t)try{let a=await this.wouldUndoAWrite(i);if(a!==void 0){if(this.entries.delete(i),a.sure){this.log("kept",i,`deleting it would remove ${a.wrote}, which is the same file`);continue}e.blocked++,e.inTheWay.length<it&&e.inTheWay.push({path:i,blockedBy:a.wrote}),this.log("kept",i,`deleting it might remove ${a.wrote}, and this vault cannot say whether they are one file`);continue}if(!await this.unchangedSince(i,o)){e.waiting++,this.again=!0,this.log("kept",i,{why:"it changed after the pass decided to delete it",deletion:s});continue}let d=await this.removedSomethingElse(i,o,r);if(d!==void 0){this.log("kept what was about to be deleted",i,{why:"it changed after the pass decided to delete it",deletion:s,keptAt:d}),this.landed(d),this.activity("conflict",i,d),e.conflicted++,this.entries.delete(i);continue}this.entries.delete(i),e.deletedLocally++,this.log("deleted locally",i,s),this.activity("deleted-local",i)}catch(a){this.recordFailure(i,a,e)}}folderDeletes=[];folderRemovals=[];folderKeptBy=new Map;liveFolderSpellings;liveFolderSpelledOtherwise(e){if(this.liveFolderSpellings===void 0){let t=new Map,r=i=>{let s=this.identity(i),o=t.get(s);o?o.add(i):t.set(s,new Set([i]))};for(let[i,s]of this.remote)if(!s.deleted){s.folder&&r(i);for(let o of Dn(i))r(o)}this.liveFolderSpellings=t}for(let t of this.liveFolderSpellings.get(this.identity(e))??[])if(t!==e)return t}onlyLiveSpelling(e){let t=this.liveFolderSpellings?.get(this.identity(e));return t?.size===1?[...t][0]:void 0}folderRespellings=[];async respellFolders(){let e=this.opts.vault.respellFolder?.bind(this.opts.vault),t=this.folderRespellings;if(this.folderRespellings=[],e===void 0)return;let r=new Map(t.map(i=>[i.from,i.to]));for(let i of Rr([...r.keys()])){let s=r.get(i),o=i.slice(0,i.lastIndexOf("/")+1)+s.slice(s.lastIndexOf("/")+1);if(o!==i)try{await e(i,o)&&this.log("respelled",i,`the server has this folder as ${r.get(i)} now`)}catch(a){this.log("could not respell",i,{to:o,why:a.message})}}}async settleFolders(e){let t=this.folderDeletes,r=this.folderRemovals;this.folderDeletes=[],this.folderRemovals=[],await this.respellFolders(),!(t.length===0&&r.length===0)&&(await this.sendFolderDeletions(t,e),await this.removeEmptiedFolders(r,e),await this.flush(e))}async sendFolderDeletions(e,t){let r=new Set;for(let i of Rr(e))try{let s=this.remote.get(i),o=this.entries.get(i);if(s===void 0||s.deleted||!s.folder||o===void 0||o.syncuid!==s.uid||await this.opts.vault.exists(i))continue;let a=this.liveBeneath(i,r);if(a!==void 0){this.folderKeptBy.get(i)!==a&&this.log("kept on the server",i,`folder removed here, and ${a} is live in it`),this.folderKeptBy.set(i,a);continue}this.folderKeptBy.delete(i),r.add(i);let d={path:s.wire??i,meta:{size:0,ctime:0,mtime:this.now(),deleted:!0},names:[]};await this.queue({path:i,size:0,entry:{...d,base:s.uid},bodyOf:Ir,commit:(c,l)=>{l||this.remote.set(i,{uid:c,folder:!1,deleted:!0,mtime:this.now(),size:0,hash:""}),this.entries.delete(i),t.foldersDeletedRemotely++,this.log("deleted on the server",i,"folder removed here, with nothing left in it"),this.activity("deleted-server",i)}},t)}catch(s){this.recordFailure(i,s,t)}}liveBeneath(e,t){let r=`${e}/`;for(let[i,s]of this.remote)if(!s.deleted&&i.startsWith(r)&&!t.has(i))return i}async removeEmptiedFolders(e,t){let r=new Set,i;for(let s of Rr(e))try{let o=this.remote.get(s),a=this.entries.get(s);if(o===void 0||!o.deleted||a===void 0)continue;let d=await this.opts.vault.stat(s);if(d===void 0){this.entries.delete(s);continue}if(!d.folder)continue;if(await this.opts.vault.removeFolder(s)){this.entries.delete(s),i=void 0,t.foldersDeletedLocally++,this.log("deleted locally",s,"folder deleted on another device, and empty here"),this.activity("deleted-local",s);continue}i??=new Map((await this.opts.vault.list()).map(l=>[l.path,l]));let c=this.keepsFolder(s,o.uid,i,r);if(c===void 0){r.add(s),zt(a,"",o.uid,this.now()),this.log("kept for now",s,"folder deleted on another device; what is left in it is going too");continue}this.log("kept",s,`folder deleted on another device, and ${c} is still in it here`),await this.upload(s,a,t,o.uid,!0)}catch(o){this.recordFailure(s,o,t)}}keepsFolder(e,t,r,i){let s=`${e}/`,o=!1;for(let[a,d]of r){if(!a.startsWith(s))continue;if(o=!0,d.folder){if(i.has(a))continue;return a}let c=this.remote.get(a),l=this.entries.get(a);if(c===void 0||l===void 0||!(l.synchash!==""&&l.hash===l.synchash&&!yt(l,Math.ceil(d.mtime),d.size,d.changeId)))return a;if(!c.deleted&&!(c.uid<t&&l.syncuid===c.uid))return a}return o?void 0:"something this device does not list"}landed(e){let t=Ls(e),r=this.wroteThisPass.get(t);r?r.push(e):this.wroteThisPass.set(t,[e]),this.localByIdentity.set(this.identity(e),e)}heldByContent(){let e=new Map;for(let[t,r]of this.entries)r.folder||r.hash===""||r.hash==="-empty-"||e.set(r.hash,t);return e}reusableFrom(e,t){let r=new Map;for(let i of e){if(t.has(i)||i.remote.size<mc)continue;let s=this.entries.get(i.path);if(!s||s.folder||s.chunks.length===0)continue;let o=new Set(s.chunks),a=new Set(i.chunks.filter(d=>o.has(d)));a.size*2<i.chunks.length||r.set(i,a)}return r}async withLocalChunks(e,t,r,i){let s=new Map(r),o=new Set([...t].filter(h=>!s.has(h)));if(o.size===0)return s;let a=this.entries.get(e.path),d=this.opts.vault,c=this.mergeable(e.path),l=0;try{let h=this.sizesFor(a?.size??e.remote.size,c),u=d.readBlocks&&!this.cannotStream?pn(d.readBlocks(e.path),h,c):(a?.size??1/0)<=Tr?Nt(await d.read(e.path),h,c):[];for await(let f of u){if(o.size===0)break;let g=await We(f.bytes);o.has(g)&&(s.set(g,f.bytes),o.delete(g),l++)}}catch(h){this.log("could not reuse this device's copy, fetching instead",e.path,{why:h.message})}if(o.size>0){let h=Tn(e.remote.size,e.chunks.length),u=[...o],f=await this.fetchAll(u,()=>h,[e.path]);u.forEach((g,m)=>s.set(g,f[m]))}return l>0&&(this.log("reused this device's own copy",e.path,{chunks:l,of:e.chunks.length,fetched:o.size}),i.reusedChunks+=l),s}async fetchFor(e){let t=Tn(e.remote.size,e.chunks.length),r=await this.fetchAll([...e.chunks],()=>t,[e.path]),i=new Map;return e.chunks.forEach((s,o)=>i.set(s,r[o])),i}async fetchAll(e,t,r=[],i){return this.transferring("download",r,async s=>{let o=async(l,h,u)=>{let f=[],g=0,m=async y=>{let w=0,b;try{b=await l.fetch(y,s===void 0?void 0:k=>{w=k,s(g+k)},u)}catch(k){if(!(k instanceof C)||k.code!=="toolarge")throw k;if(y.length>1&&!l.isClosed){let S=Math.ceil(y.length/2);await m(y.slice(0,S)),await m(y.slice(S));return}throw new Error(l.isClosed?`the download ended: ${k.message}`:`the server will not send even one chunk of this file in a fetch: ${k.message}`)}for(let k of b)f.push(k);g+=w};for(let y of kc(e,t,h,Bn))await m(y);return f},a=this.limitOn("maxFetchBytes"),d=this.fetchCap,c=0;for(let l of e)c+=t(l);return this.syncing&&d<a&&c>d&&this.opts.withUploadTransport&&!this.servicingInteractive?await this.opts.withUploadTransport(l=>o(l,a,i)):await o(this.opts.transport,d)})}async transferring(e,t,r){if(t.length===0||this.opts.onTransfer===void 0)return r(void 0);let i={direction:e,files:t.length,...t.length===1?{path:t[0]}:{}},s=o=>Oe(this.opts.onTransfer,{...i,bytes:o});s(0);try{return await r(s)}finally{Oe(this.opts.onTransfer,void 0)}}async landFromLocal(e,t,r){let i;try{i=await this.opts.vault.read(t)}catch{return"ask"}if(i.length!==e.remote.size)return"ask";let s=this.mergeable(t),o=[...Nt(i,this.sizesFor(i.length,s),s)].map(d=>d.bytes),a=await gn(o);return ie(a)!==ie(e.chunks)?"ask":await this.createdWhereNothingWas(e,i)?"landed":await this.unchangedSince(e.path,e.based)?await this.writePreserving(e.path,this.expecting(e.baseDigest),i,{mtime:e.remote.mtime,ctime:e.remote.mtime},r,this.copyAuthor(e.remote))?"kept":(this.settled(e,i.length),"landed"):"ask"}settled(e,t){this.landed(e.path),tt(e.entry,{folder:!1,mtime:e.remote.mtime,ctime:e.remote.mtime,size:t}),e.entry.chunks=[...e.chunks],e.entry.hash=ie(e.chunks),e.entry.size=t,nt(e.entry,e.entry.hash,e.entry.chunks,e.remote.uid,this.now())}async createdWhereNothingWas(e,t){let r=this.opts.vault;if(e.based!==void 0||r.create===void 0)return!1;let i={mtime:e.remote.mtime,ctime:e.remote.mtime};return await r.create(e.path,t,i)?(this.settled(e,t.length),!0):!1}async syncedDigestOf(e,t){if(t.folder||t.hash==="")return;let r=this.opts.vault,i=this.mergeable(e),s,o,a=r.contentDigest;if(r.readBlocks!==void 0&&a!==void 0&&!this.cannotStream&&t.size>Tr)try{o=await a(e);let d=[];for await(let c of pn(r.readBlocks(e),this.sizesFor(t.size,i),i))d.push(await We(c.bytes));if(o===void 0||await a(e)!==o)return;s=d}catch(d){this.cannotStream=!0,this.log("streaming is not available here, reading whole files instead",e,{why:d.message})}try{if(s===void 0){let d=await r.read(e),c=[...Nt(d,this.sizesFor(d.length,i),i)];s=await gn(c.map(l=>l.bytes)),o=await Ee(d)}if(ie(s)!==t.hash){this.log("not the synced version",e,{why:"it changed without its length or timestamp moving, so what is displaced is kept"});return}return o}catch{return}}expecting(e){return e===void 0?void 0:{contentId:e,idOf:Ee}}async writePreserving(e,t,r,i,s,o){let a=this.opts.vault;if(a.replace===void 0)return await a.write(e,r,i),!1;let d=await this.freeConflictPath(e,this.opts.device),c=await a.replace(e,t,r,i,d);if(c.keptAt!==void 0&&(this.log("kept what was already there",e,{why:"it changed while its next version was being fetched",keptAt:c.keptAt}),this.landed(c.keptAt),this.activity("conflict",e,c.keptAt),s.conflicted++),!c.landed){let l=await On(()=>this.freeConflictPath(e,o),r,i,a);this.landed(l),this.log("kept the incoming version beside",e,{at:l}),this.activity("conflict",e,l),c.keptAt===void 0&&s.conflicted++}return c.keptAt!==void 0||!c.landed}async removedSomethingElse(e,t,r){let i=this.opts.vault,s=t===void 0||t.folder?void 0:r.get(e);if(i.removeExpecting===void 0){await i.remove(e);return}let o=await this.freeConflictPath(e,this.opts.device);return(await i.removeExpecting(e,this.expecting(s),o)).keptAt}async goneSinceListed(e){try{return await this.opts.vault.stat(e)===void 0}catch{return!1}}async unchangedSince(e,t){let r;try{r=await this.opts.vault.stat(e)}catch{return!1}if(t===void 0){if(r===void 0)return!0;let i=this.localByIdentity.get(this.identity(e));return i!==void 0&&this.deletingThisPass.has(i)}return r===void 0||r.folder!==t.folder?!1:r.folder?!0:r.size===t.size&&Math.ceil(r.mtime)===t.mtime}async landedOnAChangedFile(e,t,r){this.log("kept the local copy",e.path,{why:"it changed while its next version was being fetched",version:e.remote.uid});let i=this.entryFor(e.path);i.hash="",i.chunks=[],await this.conflict(e.path,i,e.remote,r,"changed during the fetch",t)}async land(e,t,r){let i=e.chunks.map(o=>{let a=t.get(o);if(!a)throw new Error(`the server did not send ${o}, which ${e.path} is made of`);return a}),s=await this.assemble(e.remote.uid,`version ${e.remote.uid} of ${e.path}`,i,e.remote.size);return await this.createdWhereNothingWas(e,s)?!0:await this.unchangedSince(e.path,e.based)?await this.writePreserving(e.path,this.expecting(e.baseDigest),s,{mtime:e.remote.mtime,ctime:e.remote.mtime},r,this.copyAuthor(e.remote))?!1:(this.settled(e,s.length),!0):(await this.landedOnAChangedFile(e,s,r),!1)}async contentOf(e,t,r){let i=await this.opts.transport.get(e);if(t!==void 0&&ie(i.chunks)!==t)throw new Error(`version ${e} is made of chunks this device did not record for it, so it is not the version it is being offered as`);if(r!==void 0&&r!==i.size)throw new Error(`version ${e} is offered as ${i.size} bytes and was listed as ${r} bytes`);let s=r??i.size;if(i.chunks.length===0){if(s!==0)throw new Error(`version ${e} declares ${s} bytes and names no chunks, which cannot both be true`);return new Uint8Array(0)}this.checkChunkCount(e,i.chunks.length);let o=Tn(i.size,i.chunks.length);return await this.assemble(e,`version ${e}`,await this.fetchAll(i.chunks,()=>o),s)}checkChunkCount(e,t){let r=this.limitOn("maxChunks");if(t>r)throw new Error(`version ${e} names ${t} chunks, and this server said it stores at most ${r}`)}async assemble(e,t,r,i){if(r.length===0){if(i!==0)throw new Error(`${t} assembled to 0 bytes, not the ${i} it declares`);return new Uint8Array(0)}let s=this.limitOn("perFileMax");if(i>s)throw new Error(`version ${e} is offered as ${i} bytes, and this server said it stores at most ${s}`);let o=new Uint8Array(i),a=0;for(let d=0;d<r.length;d++){let c=r[d];if(c===void 0)throw new Error(`version ${e} is missing one of its chunks`);if(r[d]=void 0,a+=c.length,a>s)throw new Error(`version ${e} is over ${a} bytes, and this server said it stores at most ${s}`);a<=i&&o.set(c,a-c.length)}if(a!==i)throw new Error(`${t} assembled to ${a} bytes, not the ${i} it declares`);return o}async merge(e,t,r,i){if(!r)return;if(!this.merging){await this.conflict(e,t,r,i,"merging is off on this device");return}let s;try{s=await this.contentOf(t.syncuid,t.synchash)}catch(b){if(!Cc(b))throw b;let k="the version both sides edited from has been purged from the server, so there is nothing to merge against";this.log("merge refused",e,k),await this.conflict(e,t,r,i,k);return}let o=await this.opts.vault.read(e),a=await this.opts.vault.stat(e),d=a&&{folder:a.folder,mtime:Math.ceil(a.mtime),size:a.size,hash:""},c=await this.contentOf(r.uid,r.hash,r.size),l=new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}),h,u,f;try{h=l.decode(s),u=l.decode(o),f=l.decode(c)}catch{let b="one side is not valid UTF-8, so merging it would rewrite bytes nobody edited";this.log("merge refused",e,b),await this.conflict(e,t,r,i,b);return}let g=Hi(h,u,f,gc(e,h,u,f));if(g.kind==="conflict"){this.log("merge refused",e,g.why),await this.conflict(e,t,r,i,g.why);return}let m=g.text,y=o,w=t.mtime;if(m!==u){if(!await this.unchangedSince(e,d)){let b="it changed while the other side of the merge was being fetched";this.log("merge refused",e,b),t.hash="",t.chunks=[],await this.conflict(e,t,r,i,b,c);return}if(y=new TextEncoder().encode(m),w=this.now(),await this.writePreserving(e,{contentId:await Ee(o),idOf:Ee},y,{mtime:w,ctime:t.ctime},i,this.opts.device))return}zt(t,r.hash,r.uid,this.now()),tt(t,{folder:!1,mtime:w,ctime:t.ctime,size:y.length}),await this.upload(e,t,i,r.uid),i.merged++,this.log("merged",e,g.kind==="merged"?"three-way":g.why),this.activity("merged",e)}freeConflictPath(e,t){return Ie(wn(e,t,new Date(this.now())),async r=>{let i=this.remote.get(r);return i!==void 0&&!i.deleted||await this.opts.vault.exists(r)})}copyAuthor(e){let t=e?.device;return t!==void 0&&lr(t)!==""?t:this.opts.device}async conflict(e,t,r,i,s,o){if(!r)return;let a=o??await this.contentOf(r.uid,r.hash,r.size),d=await On(()=>this.freeConflictPath(e,this.copyAuthor(r)),a,{mtime:r.mtime,ctime:r.mtime},this.opts.vault),c=this.entryFor(d);tt(c,{folder:!1,mtime:r.mtime,ctime:r.mtime,size:a.length}),await this.upload(d,c,i,this.remote.get(d)?.uid),await this.upload(e,t,i,r.uid),i.conflicted++,this.log("kept both",e,{copy:d,why:s}),this.activity("conflict",e,d)}recordFailure(e,t,r){let i=t instanceof Error?t.message:String(t),s=t?.code;if(s==="stale"){let d=this.entries.get(e);d?.prev&&de(d.prev)!==e&&(d.prev="");let c=(this.staleHeads.get(e)??this.asked.get(e)??0)+1;if(c<=ac){this.staleHeads.set(e,c),this.retries.delete(e),r.waiting++,this.again=!0,this.log("another device wrote first, reconciling next pass",e);return}this.staleHeads.delete(e),this.asked.delete(e),i=`${i} (refused as out of date ${c} times running, even after asking the server for this path's current version)`}if(t instanceof R){Pr(r,e),r.nextUploadAt=Math.min(r.nextUploadAt??1/0,this.now()+dc),this.log("will retry when the connection is back",e,i);return}if(s==="ignored"){this.ignoredPaths.has(e)||this.log("ignored here",e,i),this.ignoredPaths.set(e,i),this.pending.delete(e),r.ignored++;return}if(s!==void 0&&["badentry","badname","toolarge","neversync","badpath","collision"].includes(s)){let d=lc(s);this.skipped.set(e,{why:d===""?i:`${/[.!?]$/.test(i)?i:`${i}.`} ${d}`,fingerprint:Dr(this.entries.get(e),this.remote.get(e)),code:s}),qt(r,e),this.log("skipped for good",e,i),this.activity("error",e);return}let a=this.retries.get(e)??{count:0,error:"",at:0};a.count++,a.error=i,a.at=this.now()+Math.min(3e5,5e3*Math.pow(2,a.count)),this.retries.set(e,a),Pr(r,e),r.nextUploadAt=Math.min(r.nextUploadAt??1/0,a.at),this.log("will retry",e,{attempt:a.count,error:i}),this.activity("error",e)}prune(e){for(let r of this.entries.keys()){if(e.has(r))continue;let i=this.entries.get(r),s=this.remote.get(r);s&&!s.deleted||i.synchash===""&&i.hash===""&&this.entries.delete(r)}for(let r of this.remote.keys())this.remote.get(r).deleted&&(e.has(r)||this.entries.has(r)||this.pending.has(r)||(this.remote.delete(r),this.staleHeads.delete(r),this.asked.delete(r),this.refusedInbound.delete(r)));let t=e.size+this.entries.size+this.remote.size;if(this.refusalOf.size>t||this.identityOf.size>t){let r=new Set([...e.keys(),...this.entries.keys(),...this.remote.keys()]);for(let i of[this.refusalOf,this.identityOf])for(let s of i.keys())r.has(s)||i.delete(s)}}async save(){let e=Object.create(null);for(let[r,i]of this.entries)e[r]=ec(i);let t=Object.create(null);for(let[r,i]of this.remote)t[r]=i;await this.opts.store.save({cursor:this.cursor,...this.epoch!==void 0?{epoch:this.epoch}:{},entries:e,remote:t,pending:[...this.pending]}),this.writtenSinceSave=0,this.checkpointedAt=Date.now()}recordScannedRenames(e,t){if(!this.sending)return;let r=(a,d)=>{let c=Q(d),l=a.get(c);l?l.push(d):a.set(c,[d])},i=new Map;for(let[a,d]of this.entries){if(e.has(a)||t.has(a)||d.prev!=="")continue;let c=d.folder?d.synctime>0:d.synchash!=="",l=this.remote.get(a);!c||d.syncuid<=0||l===void 0||l.deleted||l.uid!==d.syncuid||l.folder!==d.folder||r(i,a)}if(i.size===0)return;let s=new Set;for(let a of this.entries.values())a.prev!==""&&s.add(de(a.prev));let o=new Map;for(let a of e.keys()){let d=Q(a);if(!i.has(d))continue;let c=this.entries.get(a);c&&(c.syncuid>0||c.synchash!==""||c.prev!=="")||r(o,a)}for(let[a,d]of o){let c=i.get(a);if(d.length!==1||c.length!==1)continue;let l=d[0],h=c[0];s.has(h)||_t(l,new Set)||e.get(l).folder===this.entries.get(h).folder&&(this.log("a rename that changed only case, found by the scan",h,l),this.skipped.delete(l),this.retries.delete(l),this.movePath(h,l))}}noteRename(e,t){if(_t(t,new Set)){this.log("rename into a path that never syncs, not recorded",e,t);return}this.movePath(e,t);let r=`${e}/`,i=new Set([...this.entries.keys(),...this.retries.keys(),...this.skipped.keys()]);for(let s of i)s.startsWith(r)&&this.movePath(s,t+s.slice(e.length))}movePath(e,t){this.moveEntry(e,t);let r=this.retries.get(e);r!==void 0&&(this.retries.delete(e),this.retries.set(t,r));let i=this.skipped.get(e);i!==void 0&&(this.skipped.delete(e),this.skipped.set(t,i))}moveEntry(e,t){let r=this.entries.get(e);if(!r)return;let i=this.entries.get(t),s={...r,chunks:[...r.chunks],synchash:i?.synchash??"",syncuid:i?.syncuid??0};os(s,e,t),this.entries.set(t,s)}};function Mr(n,e){return{uploaded:n.uploaded+e.uploaded,downloaded:n.downloaded+e.downloaded,merged:n.merged+e.merged,conflicted:n.conflicted+e.conflicted,deletedLocally:n.deletedLocally+e.deletedLocally,deletedRemotely:n.deletedRemotely+e.deletedRemotely,restored:n.restored+e.restored,foldersCreated:n.foldersCreated+e.foldersCreated,foldersDeletedLocally:n.foldersDeletedLocally+e.foldersDeletedLocally,foldersDeletedRemotely:n.foldersDeletedRemotely+e.foldersDeletedRemotely,chunksSent:n.chunksSent+e.chunksSent,reusedChunks:n.reusedChunks+e.reusedChunks,...n.phases||e.phases?{phases:hc(n.phases,e.phases)}:{},bytesSent:n.bytesSent+e.bytesSent,unchanged:e.unchanged,waiting:e.waiting,...e.nextUploadAt!==void 0?{nextUploadAt:e.nextUploadAt}:{},...e.appliedCursor!==void 0?{appliedCursor:e.appliedCursor}:{},retrying:e.retrying,skipped:e.skipped,skippedPaths:e.skippedPaths,retryingPaths:e.retryingPaths,heldBack:e.heldBack,heldBackPaths:e.heldBackPaths,ignored:e.ignored,blocked:e.blocked,inTheWay:e.inTheWay,needsAttention:e.needsAttention}}function fc(n,e){if(n!==void 0&&!(!e||e.uid!==n))return{uid:n,hash:e.hash}}function gc(n,e,t,r){if(Fi(n))return Sc;if(Qi(n))return es(e,t,r);if(ns(n))return ts;if(Si(n))return Ut(e)&&Ut(t)&&Ut(r)?Ut:void 0}function _s(n,e=!1){let t=vi(n);if(t===void 0){let r=e?rs(n):void 0;return r===void 0?void 0:is(r)}if(t==="slash")return n.startsWith("/")?"a path starting with a slash is not canonical":"a path ending with a slash is not canonical";if(t==="dotsegment"){let r=n.split("/").find(i=>i==="."||i==="..")??".";return`a path with a ${JSON.stringify(r)} segment is not canonical`}return pc[t]}var pc={utf8:"a path that is not valid UTF-8",empty:"an empty path",toolong:"a path longer than the 1024 bytes the server holds",segmenttoolong:"a path with a name longer than the 255 bytes Android and Linux can hold",control:"a path with a control character in it",nfc:"a path that is not in Unicode NFC",nbsp:"a path with a no-break space in it, which Obsidian would turn into a space",backslash:"a path with a backslash in it, which Obsidian would turn into a slash",slash:"a path starting or ending with a slash is not canonical",emptysegment:"a path with an empty segment (//) is not canonical",dotsegment:"a path with a . or .. segment is not canonical",dotprefix:"a path under a dot-prefixed name never syncs",staging:"a path carrying the name the vaults give files they are staging"};function Dr(n,e){let t=e?.uid??0;return n?`${n.mtime}:${n.size}:${t}`:`gone:${t}`}var Tr=8*1024*1024,mc=1024*1024,yc=4096,wc=200,vc=8*1024*1024,bc=vt,Ec=3e4;function Tn(n,e){return Math.ceil(n/Math.max(1,e))}function kc(n,e,t,r){let i=[],s=[],o=0;for(let a of n){let d=e(a);s.length>0&&(o+d>t||s.length>=r)&&(i.push(s),s=[],o=0),s.push(a),o+=d}return s.length>0&&i.push(s),i}async function On(n,e,t,r){for(let i=0;i<100;i++){let s=await n();if(!r.create)return await r.write(s,e,t),s;if(await r.create(s,e,t))return s}throw new Error("could not find a name beside the note that stayed free long enough to use")}function Ac(n,e){let t=new Error(`${n} bytes, and this server said it stores at most ${e}, so it was not read`);return t.code="toolarge",t}function Ls(n){return Q(n).toUpperCase()}function Rr(n){let e=t=>t.split("/").length;return[...new Set(n)].sort((t,r)=>e(r)-e(t)||(t<r?-1:t>r?1:0))}async function Ir(n){throw new Error(`this put has no bodies, and the server asked for ${n}`)}function Cc(n){let e=n?.code;return e==="nouid"||e==="nochunk"||e==="nocontent"}function Sc(n){try{return JSON.parse(n),!0}catch{return!1}}Re();function Nn(n){let e=4294967295;for(let t of n){e^=t;for(let r=0;r<8;r++)e=e&1?e>>>1^3988292384:e>>>1}return(e^4294967295)>>>0}function Nr(n){let e=Nn(n);return new Uint8Array([e>>>24&255,e>>>16&255,e>>>8&255,e&255])}Re();var kt="trew1i_",_r=1,st=16,Us=64,Lr=new TextEncoder,Fc=new TextDecoder("utf-8",{fatal:!0});function zs(n){let e=n.startsWith("wss://")?n.slice(6):n.startsWith("ws://")?n.slice(5):void 0;if(e===void 0||e==="")throw new Error(`the server address ${JSON.stringify(n)} is not ws:// or wss://`);if(!/^[\x21-\x7e]+$/.test(n))throw new Error("the server address has a character outside printable ASCII");if(n.endsWith("/")||n.length>255)throw new Error(`the server address ${JSON.stringify(n)} is not in canonical form`)}function Ws(n){let e=Lr.encode(n).length;if(n===""||e>Us||/[\x00-\x1f\x7f]/.test(n))throw new Error(`the vault name is empty, over ${Us} bytes, or has a control character`)}function Js(n){if(n.token.length!==st)throw new Error(`an invite token is ${st} bytes, not ${n.token.length}`);zs(n.url),Ws(n.vault);let e=Lr.encode(n.url),t=Lr.encode(n.vault),r=new Uint8Array(1+st+1+e.length+1+t.length),i=0;r[i++]=_r,r.set(n.token,i),i+=st,r[i++]=e.length,r.set(e,i),i+=e.length,r[i++]=t.length,r.set(t,i);let s=new Uint8Array(r.length+4);return s.set(r,0),s.set(Nr(r),r.length),kt+Je(s)}function js(n){let e=n.replace(/^[ \t\r\n]+|[ \t\r\n]+$/g,"");if(!e.startsWith(kt))throw new Error(`not an invite: it should start with ${kt}`);let t;try{t=je(e.slice(kt.length))}catch(c){throw new Error(`this invite is damaged: ${c.message}`)}if(t.length<1+st+2+4)throw new Error("this invite is too short to be complete");let r=t.subarray(0,t.length-4),i=Nr(r);for(let c=0;c<4;c++)if(t[r.length+c]!==i[c])throw new Error("this invite is damaged: it did not survive being copied");if(r[0]!==_r)throw new Error(`this invite is version ${r[0]}, and this device understands ${_r}`);let s=1+st,o=[];for(let c of["server address","vault name"]){if(s>=r.length)throw new Error(`this invite ends before its ${c}`);let l=r[s++];if(s+l>r.length)throw new Error(`this invite ends inside its ${c}`);try{o.push(Fc.decode(r.subarray(s,s+l)))}catch{throw new Error(`this invite's ${c} is not UTF-8`)}s+=l}if(s!==r.length)throw new Error("this invite has more in it than it should");let[a,d]=o;return zs(a),Ws(d),{token:r.slice(1,1+st),url:a,vault:d}}Re();var xc=16,Vs=32,Bc=16;function $c(){for(;;){let n=Je(It(xc));if(!n.startsWith("-"))return n}}function Pc(){return Je(It(Vs))}function Le(n){return typeof n.invite=="string"}function Gs(n,e,t={}){return{url:n.url,vaultId:n.vault,device:e,invite:Je(n.token),deviceId:$c(),deviceToken:Pc(),...t.readOnly===!0?{readOnly:!0}:{},...t.ignore?.length?{ignore:t.ignore}:{}}}function qs(n){return{url:n.url,vaultId:n.vaultId,device:n.device,deviceId:n.deviceId,deviceToken:n.deviceToken,...n.readOnly===!0?{readOnly:!0}:{},...n.ignore?.length?{ignore:n.ignore}:{}}}var _e=class extends Error{};function Xs(n){if(Le(n))throw new _e("this device's pairing has not finished: the invite was sent and no answer has been heard. Pairing again finishes it with the credential already saved here.");let e=[];if(n.deviceId||e.push("a device id"),n.deviceToken||e.push("a device token"),e.length>0||!n.deviceId||!n.deviceToken)throw new _e(`this device has no credential for the vault: it is missing ${e.join(" and ")}. Pair this vault again with an invite, from another device or from trewd invite on the server.`);return{deviceId:n.deviceId,deviceToken:n.deviceToken}}function Kt(n){return{url:n.url,vaultId:n.vaultId,device:n.device,...n.deviceId?{deviceId:n.deviceId}:{},...n.deviceToken?{deviceToken:n.deviceToken}:{},...Le(n)?{invite:n.invite}:{},...n.readOnly===!0?{readOnly:"true"}:{},...n.ignore?.length?{ignore:JSON.stringify(n.ignore)}:{}}}function Dc(n){return n!==""&&n!=="."&&n!==".."&&!n.includes("/")}function Tc(n){let e=n.ignore;if(typeof e!="string"||e==="")return{};let t;try{t=JSON.parse(e)}catch{return{}}if(!Array.isArray(t))return{};let r=t.filter(i=>typeof i=="string"&&Dc(i));return r.length>0?{ignore:[...new Set(r)]}:{}}function Ks(n,e){if(typeof n!="object"||n===null)throw new Error(`${e} does not hold a configuration`);let t=n,r=s=>{let o=t[s];if(typeof o!="string"||o==="")throw new Error(`${e} has no ${s}`);return o},i={url:r("url"),vaultId:r("vaultId"),device:r("device"),...Rc(t,e),...Hs(t,"deviceToken",Vs,"a device token",e),...Hs(t,"invite",Bc,"an invite token",e),...t.readOnly==="true"?{readOnly:!0}:{},...Tc(t)};if(i.deviceId===void 0)throw new Error(`${e} holds no device id, so there is nothing in it to connect with or to finish`);if(i.invite!==void 0&&i.deviceToken===void 0)throw new Error(`${e} holds a pairing in progress with no device token, so it cannot be finished`);return i}function Rc(n,e){let t=n.deviceId;if(t==null)return{};if(typeof t!="string"||!/^[A-Za-z0-9_-]{1,64}$/.test(t))throw new Error(`${e} holds a deviceId that is not base64url of at most 64 characters, which is not an id any server would answer to`);return{deviceId:t}}function Hs(n,e,t,r,i){let s=n[e];if(s==null)return{};if(typeof s!="string"||s==="")throw new Error(`${i} holds a ${e} that is not a string`);let o;try{o=je(s)}catch(a){throw new Error(`${i} holds a ${e} that is not base64url: ${a.message}`)}if(o.length!==t)throw new Error(`${i} holds a ${o.length} byte ${e}, and ${r} is ${t} bytes`);return{[e]:s}}function Ys(n){let e=n.trim();if(e.startsWith("basalt3_")||e.startsWith("basalt3i_"))throw new Error("that is a Basalt string, and TrewSync does not read them. Pair with a trew1i_ invite: trewd invite on the server makes one, and so does a paired device's panel.");return js(n)}var Ic=0,Ce=class extends Error{constructor(t,r){super(r);this.code=t}code},Yt=class{constructor(e){this.opts=e;let t;this.transport=new bt(e.url,{onBatch:async r=>{this.lastBatchAt=Date.now(),this.backlogChanged(),await t.acceptBatch(r),this.reportCatchUp(),r.entries.length>0&&e.inspect!==!0&&this.soon()},onCaughtUp:()=>{this.caughtUp=!0,this.backlogChanged()},onClosed:r=>{this.uploadTransport?.close(),this.endedWith=r,this.backlogChanged(),this.notifyEnded?.(r)},...e.timeoutMs!==void 0?{timeoutMs:e.timeoutMs}:{},...e.log!==void 0?{log:e.log}:{},...e.socketFactory!==void 0?{socketFactory:e.socketFactory}:{}}),t=new In({vault:e.vault,store:e.store,transport:this.transport,withUploadTransport:r=>this.withUploadTransport(r),releaseUploadTransport:()=>this.releaseUploadTransport(),device:e.device,vaultId:e.vaultId,deviceId:e.deviceId,token:e.token,...e.coalesceWrites!==void 0?{coalesceWrites:e.coalesceWrites}:{},...e.timing!==void 0?{timing:e.timing}:{},...e.merge!==void 0?{merge:e.merge}:{},...e.readOnly!==void 0?{readOnly:e.readOnly}:{},...e.windows!==void 0?{windows:e.windows}:{},...e.log!==void 0?{log:e.log}:{},...e.confirmFirstSync?{confirmFirstSync:e.confirmFirstSync}:{},...e.confirmDeletions?{confirmDeletions:e.confirmDeletions}:{},...e.onActivity!==void 0?{onActivity:e.onActivity}:{},...e.onProgress!==void 0?{onProgress:e.onProgress}:{},...e.onTransfer!==void 0?{onTransfer:e.onTransfer}:{},...e.activePath!==void 0?{activePath:e.activePath}:{}}),this.engine=t}opts;engine;transport;uploadTransport;limits;soonTimer;uploadTimer;nextUploadAt;reportedCursor;confirmedPass=!1;watching=!1;caughtUp=!1;lastBatchAt=Date.now();backlogWaiters=new Set;endedWith;notifyEnded;get vault(){return this.opts.vault}async withUploadTransport(e){if(this.closing||this.transport.isClosed)throw new R("this client has closed");if(this.uploadTransport&&!this.uploadTransport.isClosed)try{return await this.completeUpload(e,this.uploadTransport)}catch(r){throw this.releaseUploadTransport(),r}let t=new bt(this.opts.url,{onBatch:()=>{},...this.opts.timeoutMs!==void 0?{timeoutMs:this.opts.timeoutMs}:{},...this.opts.socketFactory?{socketFactory:this.opts.socketFactory}:{}});this.uploadTransport=t;try{await t.connect();let r=this.engine.status().cursor,i=await t.hello({vault:this.opts.vaultId,deviceId:this.opts.deviceId,token:this.opts.token,device:this.opts.device,cursor:r,epoch:this.limits?.epoch});if(t.historyReplaced||i.epoch!==this.limits?.epoch)throw new Error("the server's history changed under this connection; reconnect sync");if(i.cursor<r)throw new C("cursor","upload server is behind this device");for(let s of["perFileMax","chunkMax","maxChunks","maxBatchBytes","maxFetchBytes"])if(i[s]!==this.limits?.[s])throw new Error("upload server limits changed; reconnect sync");if(this.closing||this.transport.isClosed)throw new R("this client has closed");return await this.completeUpload(e,t)}catch(r){throw this.releaseUploadTransport(),r}}releaseUploadTransport(){this.uploadTransport?.close(),this.uploadTransport=void 0}async completeUpload(e,t){let r=await e(t);return await this.transport.ping(),await this.transport.drainReceived(),r}queue=Promise.resolve();serial(e){let t=this.queue.then(e,e);return this.queue=t.catch(()=>{}),t}initiallySettled=!1;pendingMutations=0;cancelMutations=new Set;get writeReady(){return this.initiallySettled&&this.limits!==void 0&&!this.closing&&!this.endedWith&&!this.transport.isClosed&&!this.opts.inspect&&!this.opts.readOnly}mutateLocal(e,t={}){let r=t.waitMs??5e3;if(!Number.isSafeInteger(r)||r<0||r>5e3||this.pendingMutations>=16)return Promise.reject(new Ce("busy","the local mutation queue is full"));this.pendingMutations++;let i=Date.now()+r,s=new Set,o=!1,a,d,c,l,h=new Promise((w,b)=>{c=w,l=b}),u=()=>{clearTimeout(d),t.signal?.removeEventListener("abort",g),this.cancelMutations.delete(m)},f=w=>{o||a||(a=w,u(),l(w))},g=()=>f(new Ce("cancelled","cancelled before the local write started")),m=()=>f(new Ce("stopping","the client is stopping"));return this.cancelMutations.add(m),t.signal?.addEventListener("abort",g,{once:!0}),t.signal?.aborted&&g(),a||(d=setTimeout(()=>f(new Ce("busy","the local write did not start before its queue deadline")),r)),this.serial(async()=>{if(a)throw a;if(this.closing)throw new Ce("stopping","the client is stopping");if(this.opts.inspect||this.opts.readOnly)throw new Ce("read_only","this client does not permit local agent writes");if(!this.writeReady)throw new Ce("not_ready","wait for the initial sync and a live connection before editing");if(t.signal?.aborted)throw new Ce("cancelled","cancelled before the local write started");if(Date.now()>=i)throw new Ce("busy","the local write did not start before its queue deadline");o=!0,u();try{return await e({vault:this.opts.vault,changed:w=>{s.add(w)}})}finally{for(let w of s)this.noteChanged(w)}}).then(c,l).finally(()=>{u(),this.pendingMutations--,s.size>0&&!this.closing&&!this.endedWith&&!this.transport.isClosed&&this.sync()}),h}get serverCursor(){return Math.max(this.limits?.cursor??0,this.transport.appliedCursor)}get deliveryReady(){return!this.closing&&this.confirmedPass&&this.reportedCursor===this.serverCursor}get serverLimits(){return this.limits}async connect(e={}){return await this.transport.connect(),this.lastBatchAt=Date.now(),this.limits=await this.engine.start(),e.waitForBacklog===!1?this.limits:(this.reportCatchUp(),await this.waitForBacklog(),this.limits)}backlogChanged(){for(let e of this.backlogWaiters)e()}waitForBacklog(){let e=this.opts.timeoutMs??3e4;return new Promise((t,r)=>{let i,s=()=>{clearTimeout(i);let o=e-(Date.now()-this.lastBatchAt);if(!this.caughtUp&&!this.endedWith&&o>0){i=setTimeout(s,o);return}this.backlogWaiters.delete(s),this.endedWith?r(this.endedWith):this.caughtUp?t():r(new Error("the server never finished sending what it already had"))};this.backlogWaiters.add(s),s()})}reportCatchUp(){!this.limits||this.caughtUp||this.closing||this.transport.isClosed||this.opts.onCatchUp?.({local:this.engine.status().cursor,server:this.serverCursor})}async settle(e={},t=8){let r=await this.pass(e),i=r;for(let s=0;s<t&&zr(r);s++)r=await this.pass(e),i=Mr(i,r);return this.initiallySettled=!0,i}pass(e,t){return this.serial(async()=>{if(t?.(),this.closing)throw new R("this client has been closed");this.confirmedPass=!1,this.opts.onSyncStart?.();let r=await this.engine.sync(e);return r.appliedCursor!==void 0&&r.appliedCursor!==this.reportedCursor&&(await this.transport.applied(r.appliedCursor),this.reportedCursor=r.appliedCursor),this.confirmedPass=r.appliedCursor!==void 0,this.nextUploadAt=r.nextUploadAt,this.scheduleUpload(),this.opts.onPass?.(r),r})}async drain(){let e;for(;this.queue!==e;)e=this.queue,await e}async runUntilClosed(e=3e4){if(this.endedWith)return this.endedWith;this.watching=!0,this.scheduleUpload();let t=this.opts.vault.watch?.(s=>{this.noteChanged(s),this.sync()}),r=setInterval(()=>{this.sync({forceFullScan:!0}).then(()=>this.keepalive())},e),i;try{i=await new Promise(s=>{this.notifyEnded=s})}finally{this.watching=!1,this.clearUploadTimer(),clearInterval(r),t?.()}return await this.drain(),i}async keepalive(){try{await this.serial(()=>this.transport.ping())}catch{}}probe(){return this.serial(()=>this.transport.probe())}soon(){!this.caughtUp||this.soonTimer!==void 0||(this.soonTimer=setTimeout(()=>{this.transport.drainReceived().then(()=>{this.soonTimer=void 0,this.closing||this.sync()},()=>{this.soonTimer=void 0})},Ic))}clearUploadTimer(){clearTimeout(this.uploadTimer),this.uploadTimer=void 0}scheduleUpload(){this.clearUploadTimer(),!(!this.watching||this.closing||this.transport.isClosed||this.nextUploadAt===void 0)&&(this.uploadTimer=setTimeout(()=>{this.uploadTimer=void 0,this.watching&&!this.closing&&!this.transport.isClosed&&this.sync()},Math.max(0,this.nextUploadAt-Date.now())))}queued;async sync(e={}){if(this.opts.inspect===!0)throw new Error("this client is connected to read, not to sync: an inspection command cannot write to the vault, because it does not hold the lock that makes writing safe");let t=JSON.stringify(e);if(this.queued!==void 0&&this.queuedKey===t)return this.queued;let r=(async()=>{try{return await this.pass(e,()=>{this.queued===r&&(this.queued=void 0,this.queuedKey=void 0)})}catch(i){this.opts.log?.("sync failed",i.message),this.opts.onSyncFailed?.(i);return}})();return this.queued=r,this.queuedKey=t,r}queuedKey;noteRename(e,t){return this.serial(async()=>this.engine.noteRename(e,t))}noteChanged(e){this.engine.noteChanged(e)}async history(e,t={}){let r=await this.serial(()=>this.transport.history(e,t));return this.recoveryIsWellFormed(r),this.recoveryIsAboutThisPath(r,e,t.before),r.map(i=>this.asVersion(i,e,i.prev))}recoveryIsAboutThisPath(e,t,r){let i;for(let s of e){if(s.path!==t)throw new Error(`the server answered a history request for ${t} with a version of some other note, and it is not shown`);if(r!==void 0&&s.uid>=r)throw new Error(`the server answered a history request for versions of ${t} older than ${r} with version ${s.uid}, and it is not shown`);if(i!==void 0&&s.uid>=i)throw new Error(`the server answered a history request for ${t} with versions out of order (${s.uid} after ${i}), and it is not shown`);i=s.uid}}recoveryIsWellFormed(e){for(let t of e)try{Rn(t)}catch(r){throw new Error(`${r.message}, and it is not shown`)}}async repair(){return this.serial(()=>this.engine.repair())}async deleted(e,t){let r=await this.serial(()=>this.transport.deleted(e,t));this.recoveryIsWellFormed(r.entries);let i=[],s;for(let o of r.entries){if(t!==void 0&&t>0&&o.uid>=t)throw new Error(`the server answered a request for deletions older than ${t} with version ${o.uid}, and it is not shown`);if(s!==void 0&&o.uid>=s)throw new Error(`the server answered with deletions out of order (${o.uid} after ${s}), and they are not shown`);s=o.uid,i.push({...this.asVersion(o,o.path),restorable:o.restorable??0})}return{notes:i,more:r.more,...s!==void 0?{oldest:s}:{}}}async contentAt(e){return e.deleted||e.folder?new Uint8Array(0):this.serial(()=>this.engine.contentOf(e.uid,e.contentId,e.size))}preview(e){return this.serial(()=>this.engine.preview(e))}reviewConflict(e){return this.serial(()=>Xi(this.opts.vault,e))}resolveConflict(e,t,r){return this.serial(async()=>{if(this.closing)throw new Error("This client is closed.");if(this.opts.readOnly)throw new Error("Turn off receive-only mode before resolving conflicts.");await Ki(this.opts.vault,this.opts.device,e,t,r),this.engine.noteChanged(e.original),this.engine.noteChanged(e.copy);try{this.opts.onActivity?.({at:Date.now(),action:"resolved",path:e.original,copy:e.copy})}catch{}})}async restore(e,t){return this.serial(async()=>{if(this.closing)throw new Error("this client is closed");if(e.deleted)throw new Error(`version ${e.uid} of ${e.path} is the deletion itself, not a version to restore`);if(e.folder){let c=t??e.path;return await this.opts.vault.mkdir(c),{path:c,bytes:0}}let r=await this.engine.contentOf(e.uid,e.contentId,e.size),i=t??e.path,s=this.opts.vault,o=c=>s.exists(c),a={mtime:e.mtime,ctime:e.ctime};return{path:await On(async()=>await o(i)?Ie(Oc(i,e),o):i,r,a,s),bytes:r.length}})}async newestContentVersion(e){return this.findVersion(e,t=>!t.deleted)}async findVersion(e,t,r=100){let i;for(;;){let s=await this.history(e,i===void 0?{limit:r}:{before:i,limit:r}),o=s.find(t);if(o)return o;if(s.length<r)return;let a=s[s.length-1].uid;if(i!==void 0&&a>=i)throw new Error(`the server is not paging back through the versions of ${e}: it answered a request for versions older than ${i} with a page ending at ${a}`);i=a}}asVersion(e,t,r){return{uid:e.uid,path:t,...r!==void 0&&r!==t?{previousPath:r}:{},size:e.size,ctime:e.ctime,mtime:e.mtime,folder:e.folder,deleted:e.deleted,device:e.device,chunks:e.chunks.length,contentId:ie(e.chunks),...e.op!==void 0?{operation:e.op}:{}}}async invite(e={}){let t=await this.serial(()=>this.transport.invite({...e.ttlMs!==void 0?{ttlMs:e.ttlMs}:{},...e.label!==void 0?{label:e.label}:{}}));return{invite:Js({token:je(t.token),url:this.opts.url,vault:this.opts.vaultId}),id:t.invite,expiresAt:t.expiresAt}}async undo(e,t={}){await this.settle({coalesceWrites:!1});let r=await this.serial(()=>this.transport.undo(e,t));return await this.settle({coalesceWrites:!1}),r}async search(e){return this.serial(()=>this.transport.search(e))}async devices(){return this.serial(()=>this.transport.devices())}async uninvite(e){return this.serial(()=>this.transport.uninvite(e))}async revoke(e){return this.serial(()=>this.transport.revoke({deviceId:e}))}async rename(e){return this.serial(()=>this.transport.rename(e))}get deviceId(){return this.opts.deviceId}closing=!1;async close(){this.closing=!0;for(let e of this.cancelMutations)e();this.clearUploadTimer(),this.soonTimer!==void 0&&(clearTimeout(this.soonTimer),this.soonTimer=void 0),this.transport.close(),this.uploadTransport?.close(),await this.drain()}};function Oc(n,e){let{stem:t,ext:r}=et(n);return mn(t,` (restored ${e.uid})`,r)}var Mc=3;async function Zs(n,e={}){let t=new $n(0,3e5,5e3,!0),r,i=!1,s=async d=>{if(e.keepGoing?.()??!0){if(i){i=!1;return}await new Promise(c=>{let l=!1,h,u=()=>{l||(l=!0,clearTimeout(h),i=!1,r=void 0,c())};r=u,e.sleep?e.sleep(d).then(u):h=setTimeout(u,d)})}};e.onWaiting?.(()=>{t.success(),i=!0,r?.()});let o="",a=0;for(;e.keepGoing?.()??!0;){let d,c,l=!1;try{if(d=new Yt(n),e.onConnecting?.(d),await d.connect(),l=!0,!(e.keepGoing?.()??!0))return;e.onClient?.(d);let f=await d.settle();t.success(),e.onSynced?.(f,d.serverCursor),c=await d.runUntilClosed()}catch(f){c=f}finally{e.onClient?.(void 0),await d?.close()}if(c&&Nc(c)){e.onFatal?.(c);return}if(c&&!(c instanceof R)&&!(c instanceof C)){if(a=c.message===o?a+1:1,o=c.message,a>=Mc){e.onFatal?.(new Error(`${c.message}. This has failed ${a} times in a row with this device at cursor ${d?.engine.status().cursor??0}, so waiting will not help; docs/server.md says how to recover from an entry no device can apply`));return}}else a=0,o="";if(!(e.keepGoing?.()??!0))return;t.fail();let h=c??new Error("the connection ended"),u=_c(h,t.delay());l?e.onDisconnected?.(h,u):e.onUnreachable?.(h,u),await s(u)}}function Nc(n){return n instanceof C&&n.fatal}function _c(n,e,t=Math.random){let r=n instanceof C?n.retryAfterMs??0:0;return e>=r?e:Math.floor(r*(1+.5*t()))}var Ur=class extends R{constructor(t,r){super(t);this.pending=r;this.name="PairingInterrupted"}pending};async function Qs(n,e,t={}){await e.save(n);let r=new bt(n.url,{onBatch:()=>{},...t.timeoutMs!==void 0?{timeoutMs:t.timeoutMs}:{},...t.socketFactory!==void 0?{socketFactory:t.socketFactory}:{},...t.log!==void 0?{log:t.log}:{}}),i=!1;try{await r.connect(),i=!0,t.onSent?.(),await r.redeem({vault:n.vaultId,device:n.device,invite:n.invite,deviceId:n.deviceId,token:n.deviceToken})}catch(o){let a=o instanceof Error?o:new Error(String(o)),d=a instanceof C&&!a.retryable,c=!i&&t.resuming!==!0;if(!d&&!c){let l=a instanceof C?`the server could not take the pairing just now (${a.message})`:i?`the invite was sent and no answer came back (${a.message}), so whether the server registered this device is not known`:`the server could not be reached (${a.message}), and an earlier attempt may have registered this device`;throw new Ur(`${l}. The pairing is kept, and trying again finishes it with the same credential.`,n)}try{await e.forget()}catch(l){throw new Error(`${a.message}; and the pairing saved before it was sent could not be removed: `+l.message,{cause:a})}throw a}finally{r.close()}let s=qs(n);return await e.save(s),t.log?.("paired",{deviceId:s.deviceId}),s}async function eo(n){let e;try{e=await n()}catch(t){return{kind:"unreadable",why:t.message}}return e===void 0?{kind:"nothing"}:Le(e)?{kind:"pending",config:e}:{kind:"credential",config:e}}function to(n){let{remains:e,surface:t,where:r}=n,i=t==="cli";switch(e.kind){case"credential":return i?`This device is paired with the vault and ${r} holds its credential; run trew sync here to finish, or trew unlink to start again.`:"This device is paired with the vault; TrewSync will connect as it on the next attempt.";case"pending":return i?`The invite was sent and no answer came back, so whether the server registered this device is not known. ${r} holds the pairing: run trew pair here again to finish it with the same credential, which works even after the invite has expired if the server did register it.`:"The invite was sent and no answer came back, so whether the server registered this device is not known. TrewSync will finish the pairing with the same credential the next time it connects.";case"unreadable":return`${r} could not be read (${e.why}), so what this device holds is not known and nothing should be revoked on the strength of it: a credential that was written and cannot be read back is still the only copy of its row's token. Fix that first, `+(i?"then trew status here says whether this device has one.":"then reload the plugin, which says whether this device has one.");default:return"Nothing was registered and nothing is saved here, so the invite was not spent by this attempt. Pair again with it, or with a new one if it has expired."}}function no(n){let{deviceId:e,deviceToken:t}=Xs(n);return{url:n.url,token:t,deviceId:e,vaultId:n.vaultId,device:n.device}}function zr(n){return n.uploaded+n.downloaded+n.merged+n.conflicted+n.deletedLocally+n.deletedRemotely+n.restored+n.foldersCreated+n.foldersDeletedLocally+n.foldersDeletedRemotely>0}function Zt(n){return n.skipped+n.blocked}function ro(n,e=""){let t=n.needsAttention??[],r=new Map;for(let{path:o,why:a}of t){let d=r.get(a);d?d.push(o):r.set(a,[o])}let i=[];for(let[o,a]of r)i.push(`${e}${a.sort().join(", ")}: ${o}`);let s=Zt(n)-t.length;return s>0&&i.push(`${e}and ${s} more.`),i}import{mkdir as Mo,readFile as No,rm as rn,stat as _o}from"node:fs/promises";import{join as we}from"node:path";var so=new TextEncoder;function oo(n,e){if(!Number.isSafeInteger(n)||n<1)throw new Error(`a journal sequence must be a positive integer, not ${n}`);let t=JSON.stringify(e),r=Nn(so.encode(t)).toString(16).padStart(8,"0");return`${n} ${r} ${t}
18
- `}function Lc(n){if(n.includes("\0"))return{why:"torn"};let e=n.indexOf(" "),t=n.indexOf(" ",e+1);if(e<1||t<0)return{why:"unparsable"};let r=Number(n.slice(0,e));if(!Number.isSafeInteger(r)||r<1)return{why:"unparsable"};let i=n.slice(e+1,t),s=n.slice(t+1);if(!/^[0-9a-f]{8}$/.test(i))return{why:"unparsable"};if(Nn(so.encode(s)).toString(16).padStart(8,"0")!==i)return{why:"checksum"};let o;try{o=JSON.parse(s)}catch{return{why:"unparsable"}}return o===null||typeof o!="object"||Array.isArray(o)?{why:"unparsable"}:{seq:r,delta:o}}function Uc(n){return n.why!==void 0}function ao(n,e){let t=n.state,r=n.seq,i=0,s={why:"end"},o=!0,a,d=e.split(`
19
- `),c=d.slice(0,-1),l=d[d.length-1]??"";for(let u=0;u<c.length;u++){let f=c[u];if(f===""){s={why:"torn",at:u};break}let g=Lc(f);if(Uc(g)){s={why:g.why,at:u};break}if(!(g.seq<=n.seq)){if(g.seq<=r){s={why:"out-of-order",at:u,seq:g.seq};break}if(o&&g.seq!==n.seq+1){s={why:"gap",at:u,seq:g.seq,after:n.seq};break}o=!1,a??=zc(t),Wc(a,g.delta),r=g.seq,i++}}return s.why==="end"&&l!==""&&(s={why:"torn",at:c.length}),{state:a===void 0?t:a,seq:r,applied:i,stopped:s}}function zc(n){let e=n??{};return{cursor:e.cursor,...e.epoch!==void 0?{epoch:e.epoch}:{},entries:Object.assign(Object.create(null),e.entries),remote:Object.assign(Object.create(null),e.remote),pending:Array.isArray(e.pending)?[...e.pending]:e.pending}}function Wc(n,e){for(let[t,r]of Object.entries(e.set??{}))n.entries[t]=r;for(let t of e.del??[])delete n.entries[t];for(let[t,r]of Object.entries(e.remote??{}))n.remote[t]=r;for(let t of e.unremote??[])delete n.remote[t];e.cursor!==void 0&&(n.cursor=e.cursor),e.epoch!==void 0&&(n.epoch=e.epoch),e.pending!==void 0&&(n.pending=[...e.pending])}function Wr(n){return{cursor:n.cursor,epoch:n.epoch,entries:_n(n.entries),remote:_n(n.remote),pending:lo(n.pending)}}function co(n,e){let t={cursor:e.cursor,epoch:e.epoch,entries:_n(e.entries,n.entries),remote:_n(e.remote,n.remote),pending:lo(e.pending)},r={};n.cursor!==e.cursor&&(r.cursor=e.cursor),e.epoch!==void 0&&n.epoch!==e.epoch&&(r.epoch=e.epoch);let i=io(n.entries,t.entries,e.entries);Object.keys(i.set).length>0&&(r.set=i.set),i.del.length>0&&(r.del=i.del);let s=io(n.remote,t.remote,e.remote);return Object.keys(s.set).length>0&&(r.remote=s.set),s.del.length>0&&(r.unremote=s.del),n.pending.length===t.pending.length&&n.pending.every((a,d)=>a===t.pending[d])||(r.pending=[...t.pending]),{delta:Object.keys(r).length===0?void 0:r,shape:t}}function io(n,e,t){let r=Object.create(null),i=[];for(let[s,o]of e)n.get(s)!==o&&(r[s]=t[s]);for(let s of n.keys())e.has(s)||i.push(s);return{set:r,del:i}}function _n(n,e){let t=new Map;if(typeof n!="object"||n===null||Array.isArray(n))return t;for(let r of Object.keys(n)){let i=n[r],s=e?.get(r);if(s&&Ln(s.value,i))t.set(r,s);else{let o=JSON.stringify(i),a=o===void 0?void 0:JSON.parse(o);t.set(r,s&&Ln(s.value,a)?s:{value:a})}}return t}function Ln(n,e){if(n===e)return!0;if(n===null||e===null||typeof n!="object"||typeof e!="object"||typeof e.toJSON=="function")return!1;if(Array.isArray(n))return Array.isArray(e)&&n.length===e.length&&n.every((s,o)=>Ln(s,e[o]));if(Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);if(t!==Object.prototype&&t!==null)return!1;let r=Object.keys(n),i=Object.keys(e);return r.length===i.length&&r.every((s,o)=>s===i[o]&&Ln(n[s],e[s]))}function lo(n){return Array.isArray(n)?[...n]:[]}var fo={fractionOfSnapshot:.25,maxRecords:1e3,minBytes:64*1024};function Jc(n,e,t,r=fo){return t>=r.maxRecords?!0:n<r.minBytes||e<=0?!1:n>e*r.fractionOfSnapshot}function zn(n){return n.replace(/\.json$/i,"")+".log"}var Un=class{files;policy;say;saved;seq=0;snapshotBytes=0;records=0;left={};mustSnapshot=!1;opts;constructor(e,t={}){this.files=e,this.opts=t,this.policy=t.policy??fo,this.say=t.log??(()=>{})}async load(){let e=await this.files.readSnapshot(),t=await this.files.readLog();if(this.left=await this.files.stamps(),e===void 0){if(t!==void 0&&t!=="")throw new Error("the index has a journal but no snapshot to apply it to, so it cannot be trusted. Remove the journal to start from the server instead.");return}let r;try{r=JSON.parse(e)}catch(d){throw new Error(`the index snapshot is not valid JSON, so it cannot be trusted: ${d.message}`)}let i=Hc(r),s=jc(r);if(this.snapshotBytes=At(e),t===void 0||t==="")return this.settle(s,i??0,0),this.mustSnapshot=i===void 0,s;if(i===void 0)return this.say("the index journal sits beside a snapshot that does not say which records it holds, so something other than this client wrote one of them. Using the snapshot alone, which is older and consistent; the journal will be replaced on the next save."),this.settle(s,0,0),this.mustSnapshot=!0,s;let o={state:s,seq:i},a;try{a=ao(o,t)}catch(d){return this.say(`the index journal could not be replayed (${String(d)}); using the snapshot alone.`),this.settle(s,i,0),this.mustSnapshot=!0,s}return a.stopped.why!=="end"&&this.say(`the index journal stops at record ${a.stopped.at??0} (${a.stopped.why}); ${a.applied} of its records were applied. An older index is safe: anything past that point is work this device will do again.`),!ho(a.state)&&ho(s)?(this.say("the index journal replayed to a state that cannot be trusted; falling back to the snapshot, which is older and consistent."),this.settle(s,i,0),this.mustSnapshot=!0,s):(this.settle(a.state,a.seq,a.applied),a.stopped.why!=="end"&&(this.mustSnapshot=!0),a.state)}async save(e){let t=this.opts.onSave,r=t===void 0?0:performance.now(),i=r,s=(d,c)=>{if(t!==void 0)try{t({compareMs:i-r,writeMs:performance.now()-i,bytes:c,kind:d,records:this.records})}catch{}},o=await this.files.stamps(),a=this.foreignWrite(o);if(this.saved!==void 0&&a===void 0){let{delta:d,shape:c}=co(this.saved,e);if(t!==void 0&&(i=performance.now()),d===void 0){s("unchanged",0);return}if(!this.mustSnapshot&&!Jc(o.log?.size??0,this.snapshotBytes,this.records+1,this.policy)){let l=await this.append(d,c,o.log?.size??0);s("append",l);return}}a!==void 0&&this.say(`${a} is not what this session wrote, so something else is writing the index. Replacing both with a fresh snapshot, which is complete on its own. If two clients share this vault, stop one of them: their indexes will keep overwriting each other.`),s("snapshot",await this.snapshot(e))}foreignWrite(e){if(this.saved!==void 0){if(!uo(this.left.snapshot,e.snapshot))return"the index snapshot";if(!uo(this.left.log,e.log))return"the index journal"}}async append(e,t,r){let i=oo(++this.seq,e);try{await this.files.appendLog(i);let s=await this.files.stamps(),o=(s.log?.size??0)-r;if(o!==At(i))throw new Error(`the index journal grew by ${o} bytes for a ${At(i)} byte record, so the append did not land whole`);return this.records++,this.saved=t,this.left=s,At(i)}catch(s){throw this.mustSnapshot=!0,this.left=await this.files.stamps().catch(()=>this.left),s}}async snapshot(e){let t=JSON.stringify({...e,seq:this.seq});try{return await this.files.writeSnapshot(t),this.snapshotBytes=At(t),await this.files.truncateLog(),this.records=0,this.mustSnapshot=!1,this.saved=Wr(e),At(t)}catch(r){throw this.mustSnapshot=!0,r}finally{this.left=await this.files.stamps().catch(()=>({}))}}settle(e,t,r){this.saved=Wr(e),this.seq=t,this.records=r,this.mustSnapshot=!1}};function jc(n){if(typeof n!="object"||n===null||Array.isArray(n))return n;let{seq:e,...t}=n;return t}function Hc(n){if(typeof n!="object"||n===null||Array.isArray(n))return;let e=n.seq;return typeof e=="number"&&Number.isSafeInteger(e)&&e>=0?e:void 0}function ho(n){try{return rt(n)!==void 0}catch{return!1}}function uo(n,e){return n===void 0||e===void 0?n===e:n.size===e.size&&n.mtime===e.mtime}function At(n){return new TextEncoder().encode(n).length}import{constants as $e,watch as qc}from"node:fs";import{createHash as Bo,randomBytes as ot}from"node:crypto";import{access as Qt,cp as Xc,link as Pe,lstat as z,mkdir as he,open as Se,readFile as $o,readdir as Ue,realpath as en,rename as pe,rm as J,rmdir as Po,stat as me}from"node:fs/promises";import{basename as at,dirname as D,join as $,relative as Y,resolve as Jn,sep as St}from"node:path";var go=new Map;function ee(n){if(go.has(n))throw new Error(`two seams are called ${n}`);let e={name:n,pause:async()=>{},hold(t){let r=e.pause,i=async s=>{await r(s),await t(s)};return e.pause=i,()=>{e.pause===i&&(e.pause=r)}}};return go.set(n,e),e}function qe(n){let e={};for(let[t,r]of Object.entries(n))Object.defineProperty(e,t,{enumerable:!0,get:()=>r.pause,set:i=>{r.pause=i}});return e}var Wn=class{files;say;now;constructor(e,t=()=>{},r=()=>Date.now()){this.files=e,this.say=t,this.now=r}gone=new Set;missing;async record(e){let t=JSON.stringify(e);try{await this.files.append(`
14
+ `);for(let l of r)for(let h of s){let[u,f]=l.start<=h.start?[l,h]:[h,l];if(u.start===f.start){if(c(u,f)&&c(f,u))continue;if(o.some(m=>m.start<=u.start&&m.end>=u.start))return u;continue}if(c(u,f)&&c(f,u)||d[f.start]-d[u.start]>0)continue;if(o.some(m=>m.start<=f.start&&m.end>=u.start&&m.text.includes(`
15
+ `)))return u}}function md(n,e,t,i=()=>!0){return Kr(n,e,t,i,0)}function Kr(n,e,t,i,r){if(e===t)return{kind:"take",text:e,why:"both sides already agree"};if(n===e)return{kind:"take",text:t,why:"no local change since the last sync"};if(n===t)return{kind:"take",text:e,why:"no remote change since the last sync"};let s=new fi.diff_match_patch,o=ud(n,e,t);o&&(s.Diff_Timeout=0);let a=o?s.diff_main(n,e,!0):s.diff_main(n,e,!0,0);a.length>2&&(s.diff_cleanupSemantic(a),s.diff_cleanupEfficiency(a));let d=o?s.diff_main(n,t,!0):s.diff_main(n,t,!0,0);d.length>2&&(s.diff_cleanupSemantic(d),s.diff_cleanupEfficiency(d));let c=Hr(a),l=Hr(d),h=gd(c,l);if(h!==void 0)return{kind:"conflict",why:`both devices changed the same text, at characters ${r+h.start} to ${r+h.end} of the last synced version`};let u=Vr(n,c,l)??Vr(n,l,c);if(u!==void 0)return{kind:"conflict",why:`a line added on one device would run into text changed on the other, at character ${r+u.start} of the last synced version`};let f=pd(n,c,l);if(f!==void 0)return{kind:"conflict",why:`each device rewrote the same line differently, and the two rewrites would run together at character ${r+f.start} of the last synced version`};let g=qr(s,n,a,t),m=qr(s,n,d,e);if(g.failed>0||m.failed>0){let b=Math.max(g.failed,m.failed),k=Math.max(g.total,m.total);return{kind:"conflict",why:`${b} of ${k} changes could not be placed in the other version`}}if(!yd(n,g.text,m.text))return{kind:"conflict",why:"merging the two versions in either order gives different content, so at least one change was placed wrongly"};let y=wd(a,g.text);if(y!==void 0)return{kind:"conflict",why:`the merge reported success but ${bd(y)} is not in the result`};let w=vd(n,e,t,g.text);return w!==void 0?{kind:"conflict",why:`the merge produced ${JSON.stringify(w.slice(0,40))}, which is not a word in the last synced version or in either device's`}:i(g.text)?{kind:"merged",text:g.text}:{kind:"conflict",why:"both sides merged cleanly and the result is no longer a valid file of its kind"}}function Zr(n,e,t,i=()=>!0){if(e===t)return{kind:"take",text:e,why:"both sides already agree"};if(n===e)return{kind:"take",text:t,why:"no local change since the last sync"};if(n===t)return{kind:"take",text:e,why:"no remote change since the last sync"};let r=Nr(n,e,t);if(r===void 0)return md(n,e,t,i);let s=[];for(let a of r)if(a.changed==="none")s.push(a.base);else if(a.changed==="mine")s.push(a.mine);else if(a.changed==="theirs")s.push(a.theirs);else if(a.base===""&&a.mine===a.theirs)s.push(a.mine+a.theirs);else{let d=Kr(a.base,a.mine,a.theirs,()=>!0,a.at);if(d.kind==="conflict")return d;s.push(d.text)}for(let a=s.length-1,d=!1;a>=0;a--){let c=s[a];if(c!==""){if(d&&!c.endsWith(`
16
+ `)){let l=r[a];return{kind:"conflict",why:`a change on one device would run into the next line, at character ${l.at+l.base.length} of the last synced version`}}d=!0}}let o=s.join("");return i(o)?{kind:"merged",text:o}:{kind:"conflict",why:"both sides merged cleanly and the result is no longer a valid file of its kind"}}function yd(n,e,t){if(e===t)return!0;let i=Gr(n,e),r=Gr(n,t);if(i.length!==r.length)return!1;for(let s=0;s<i.length;s++)if(i[s]!==r[s])return!1;return!0}function Gr(n,e){let t=new fi.diff_match_patch;t.Diff_Timeout=0;let{chars1:i,chars2:r,lineArray:s}=t.diff_linesToChars_(n,e),o=t.diff_main(i,r,!1);t.diff_charsToLines_(o,s);let a=[],d=0;for(let[c,l]of o){let h=l.match(/[^\n]*\n|[^\n]+$/g)??[];if(c===Yr)d+=h.length;else if(c===Xr)for(let u of h)a.push(`-${d++} ${u}`);else for(let u of h)a.push(`+${d} ${u}`)}return a.sort()}function qr(n,e,t,i){let[r,s]=n.patch_apply(n.patch_make(e,t),i);return{text:r,failed:s.filter(o=>!o).length,total:s.length}}function wd(n,e){for(let[t,i]of n)if(t===fd&&!e.includes(i))return i}function vd(n,e,t,i){let r=new Set;for(let s of[n,e,t])for(let o of s.split(/\s+/))r.add(o);for(let s of i.split(/\s+/))if(s!==""&&!r.has(s))return s}function bd(n){let e=n.replace(/\s+/g," ").trim(),t=e.length>60?`${e.slice(0,57)}...`:e;return`a local edit (${JSON.stringify(t)})`}function Sn(n,e,t){let{stem:i,ext:r}=rt(n),s=(a,d=2)=>String(a).padStart(d,"0"),o=`${t.getFullYear()}${s(t.getMonth()+1)}${s(t.getDate())}${s(t.getHours())}${s(t.getMinutes())}`;return kd(i,gi(e)||"device",` ${o})`,r)}var Qr=" (Conflicted copy ",Ed=32;function kd(n,e,t,i){let r=n.slice(0,n.lastIndexOf("/")+1),s=a=>`${Qr}${a}${t}`,o=re(n)-re(r)+re(s(e))+re(i)-li(r);return o>0&&(e=hi(e,re(e)-o)),An(n,s(e),i)}function gi(n){return[...n.replace(/[\ud800-\udfff]/gu,"-").normalize("NFC").replace(/[\u061c\u200e\u200f\u202a-\u202e\u2066-\u2069]/gu,"").replace(/[\\/:*?"<>|]/gu,"-").replace(/[\s\p{Cc}]+/gu," ").replaceAll(si,"-trew-tmp-").replaceAll(Qr.trimStart(),"Conflicted copy ").replace(/-{2,}/gu,"-").replace(/^[\s.-]+|[\s.-]+$/gu,"")].slice(0,Ed).join("").replace(/[\s.-]+$/u,"")}var es=128*1024;function Ad(n){let e=/^(.*) \(Conflicted copy [^/]+ \d{12}\)(?: \d+)?(\.[^/]*)?$/.exec(n);return e?e[1]+(e[2]??""):void 0}async function pi(n,e){if(n.contentDigest){let t=await n.contentDigest(e);if(t===void 0&&await n.stat(e))throw new Error("Cannot read a conflict file. Nothing was resolved.");return t}if(await n.stat(e))return ke(await n.read(e))}async function ts(n,e){let t=await n.stat(e);if(!t)return;if(t.folder)throw new Error("A conflict path is now a folder. Review it in the file explorer.");if(Ge(e)&&t.size<=es){let r=await n.read(e),s=r.length<=es?new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(r):void 0;return{path:e,stat:t,digest:await ke(r),...s!==void 0?{text:s}:{}}}let i=await pi(n,e);if(i!==void 0)return{path:e,stat:t,digest:i}}async function ns(n,e){if(e.original===e.copy||Ad(e.copy)!==e.original)throw new Error("Choose a TrewSync conflict copy to review.");let t=await ts(n,e.original),i=await ts(n,e.copy);if(!i)throw new Error("This conflict copy has moved or was already removed. Refresh the list.");return{...e,...t?{current:t}:{},preserved:i}}async function is(n,e,t,i,r){if(!n.replace||!n.removeExpecting)throw new Error("This vault cannot safely resolve conflicts.");if(i==="original"&&!t.current)throw new Error("The original file no longer exists.");if(i==="edited"&&(r===void 0||t.current?.text===void 0||t.preserved.text===void 0))throw new Error("Open these files to edit them; they cannot be merged in this preview.");if(i==="edited"&&qe(t.original))try{JSON.parse(r)}catch{throw new Error("The combined version is not valid JSON. Correct it before saving.")}if(await pi(n,t.original)!==t.current?.digest||await pi(n,t.copy)!==t.preserved.digest)throw new Error("One of these files changed. Refresh the comparison before choosing a version.");let s=a=>Oe(Sn(a,e,new Date),d=>n.exists(d));if(i!=="original"){let a=i==="edited"?new TextEncoder().encode(r):await n.read(t.copy);if(i==="copy"&&await ke(a)!==t.preserved.digest)throw new Error("The conflict copy changed. Refresh the comparison.");let d=await n.replace(t.original,t.current?{contentId:t.current.digest,idOf:ke}:void 0,a,{mtime:Date.now(),ctime:t.current?.stat.ctime??t.preserved.stat.ctime},await s(t.original));if(!d.landed||d.keptAt)throw new Error("A file changed while applying your choice. Both versions were kept; refresh the list.");await n.flush?.()}let o=await n.removeExpecting(t.copy,{contentId:t.preserved.digest,idOf:ke},await s(t.copy));if(await n.flush?.(),o.keptAt||!o.landed)throw new Error("The copy changed while resolving it. Its latest version was preserved; refresh the list.")}function Me(n,e){try{n?.(e)}catch{}}function jt(n){let e=[],t,i=!0,r=0,s="";for(let o of n.split(`
17
+ `)){let a=o.replace(/\r$/,"");if(a.trim()==="")continue;let d=a.length-a.replace(/^[ \t]*/,"").length,c=a.slice(0,d);if(t!==void 0){if(d>t)continue;t=void 0}if(r>0||s!==""){({flow:r,openQuote:s}=Fn(a,r,s));continue}if(c.includes(" "))return!1;let l=a.slice(d);if(l.startsWith("#"))continue;if(l==="---"||l==="..."||l.startsWith("--- ")){e.length=0,i=!0;continue}let h=/^-(\s+|$)/.exec(l);if(h){if(rs(e,d,i)==="nowhere")return!1;let y=l.slice(h[0].length);if(y===""||y.startsWith("#")){i=!0;continue}({flow:r,openQuote:s}=Fn(y,0,""));let w=d+h[0].length;e.push({indent:w,keys:new Set});let b=mi(y);b!==void 0&&e[e.length-1].keys.add(b),ss(y)&&(t=w),i=b!==void 0&&yi(y)==="";continue}let u=rs(e,d,i);if(u==="nowhere")return!1;if(u==="continued"){if(mi(l)!==void 0)return!1;({flow:r,openQuote:s}=Fn(l,0,""));continue}({flow:r,openQuote:s}=Fn(l,0,""));let f=mi(l);if(f===void 0){i=!1;continue}let g=e[e.length-1];if(g.keys.has(f))return!1;g.keys.add(f),ss(l)&&(t=d),i=yi(l)===""}return!0}function Fn(n,e,t){let i=t;for(let r=0;r<n.length;r++){let s=n[r];if(i){s==="\\"&&i==='"'?r++:s===i&&(i="");continue}if(s==='"'||s==="'")i=s;else if(s==="["||s==="{")e++;else if(s==="]"||s==="}")e=Math.max(0,e-1);else if(s==="#"&&e===0&&(r===0||/\s/.test(n[r-1])))break}return{flow:e,openQuote:i}}function rs(n,e,t){let i=n[n.length-1];if(i===void 0||e>i.indent)return!t&&i!==void 0?"continued":(n.push({indent:e,keys:new Set}),"here");for(;n.length>1&&e<n[n.length-1].indent;)n.pop();return e===n[n.length-1].indent?"here":"nowhere"}function mi(n){let e=0,t="";for(;e<n.length;e++){let s=n[e];if(t){s==="\\"&&t==='"'?e++:s===t&&(t="");continue}if(s==='"'||s==="'"){if(e!==0)return;t=s;continue}if(s===":"&&(e+1===n.length||n[e+1]===" "))break;if(s==="["||s==="{"||s==="#")return}if(t||e>=n.length)return;let i=n.slice(0,e).trim();return i===""?void 0:(i.startsWith('"')&&i.endsWith('"')||i.startsWith("'")&&i.endsWith("'"))&&i.length>=2?i.slice(1,-1):i}function yi(n){let e=n.indexOf(": "),t=e>=0?n.slice(e+2):n.endsWith(":")?"":n,i=Cd(t).trim();for(let r=0;r<2;r++){let s=/^(?:&[^\s]+|![^\s]*)(?:\s+|$)/.exec(i);if(!s)break;i=i.slice(s[0].length).trim()}return i}function Cd(n){let e="";for(let t=0;t<n.length;t++){let i=n[t];if(e){i==="\\"&&e==='"'?t++:i===e&&(e="");continue}if(i==='"'||i==="'")e=i;else if(i==="#"&&(t===0||/\s/.test(n[t-1])))return n.slice(0,t)}return n}function ss(n){return/^[|>](?:[+-]\d*|\d*[+-]?)$/.test(yi(n))}var Sd=/\n##? Drawing\n[^`]*```json\n([\s\S]*?)```\n/;function xn(n){let e=Sd.exec(n);if(e===null)return;let t=e[1],i=t.substring(0,t.lastIndexOf("}")+1);if(i==="")return;let r;try{r=JSON.parse(i.replaceAll("&#91;","["))}catch{return!1}return Array.isArray(r?.elements)}function os(n){return n.toLowerCase().endsWith(".excalidraw.md")}function as(n,e,t){if(xn(n)===!0&&xn(e)===!0&&xn(t)===!0)return i=>xn(i)===!0}function ds(n){let e=/[A-Za-z_:][-A-Za-z0-9_:.]*/y,t=[],i=0,r=0;for(;r<n.length;){let s=n.indexOf("<",r);if(s<0)break;if(r=s+1,n.startsWith("!--",r)){let h=n.indexOf("-->",r+3);if(h<0)return!1;r=h+3;continue}if(n.startsWith("![CDATA[",r)){let h=n.indexOf("]]>",r+8);if(h<0)return!1;r=h+3;continue}if(n.startsWith("?",r)){let h=n.indexOf("?>",r+1);if(h<0)return!1;r=h+2;continue}if(n.startsWith("!",r)){let h=0,u=r+1;for(;u<n.length;u++){let f=n[u];if(f==="[")h++;else if(f==="]")h--;else if(f===">"&&h<=0)break}if(u>=n.length)return!1;r=u+1;continue}let o=n[r]==="/";o&&r++,e.lastIndex=r;let a=e.exec(n);if(a===null)return!1;let d=a[0];r=e.lastIndex;let c=!1,l=!1;for(;r<n.length;){let h=n[r];if(h==='"'||h==="'"){let u=n.indexOf(h,r+1);if(u<0)return!1;r=u+1;continue}if(h==="<")return!1;if(h==="/"){c=!0,r++;continue}if(h===">"){r++,l=!0;break}if(c)return!1;r++}if(!l)return!1;if(o){if(c||t.pop()!==d)return!1;t.length===0&&i++}else c?t.length===0&&i++:t.push(d)}return t.length===0&&i===1}var Fd=new Set(["svg","xml","xhtml","html","htm"]);function cs(n){let e=n.lastIndexOf(".");return e<0?!1:Fd.has(n.slice(e+1).toLowerCase())}Re();var xd=["CON","PRN","AUX","NUL",...[..."0123456789\xB9\xB2\xB3"].map(n=>`COM${n}`),...[..."0123456789\xB9\xB2\xB3"].map(n=>`LPT${n}`)],Bd=new Set(xd);function Pd(n){return n.replace(/[a-z]/g,e=>String.fromCharCode(e.charCodeAt(0)-32))}function ls(n){for(let e of n.split("/")){if(/[<>:"|?*]/.test(e))return"character";if(e.endsWith(".")||e.endsWith(" "))return"trailing";let t=e.split(".",1)[0].replace(/ +$/,"");if(Bd.has(Pd(t)))return"reserved"}}function hs(n){switch(n){case"character":return'Windows does not allow < > : " | ? * in a file or folder name';case"trailing":return"Windows does not allow a file or folder name to end with a dot or a space";case"reserved":return"Windows reserves this name for a device (CON, PRN, AUX, NUL, COM and LPT names)"}}function Et(n){return{path:n,prev:"",folder:!1,ctime:0,mtime:0,size:0,hash:"",chunks:[],synchash:"",syncuid:0,synctime:0}}function Bn(n){let{local:e,remote:t,index:i,mergeable:r}=n,s=i.synchash;return e?.folder||t?.folder?$d(e,t,i):e===void 0&&(t===void 0||t.deleted)?{kind:"nothing",why:"absent on both sides"}:t===void 0?{kind:"upload",why:"new file, the server has never held this path"}:e===void 0?Dd(t,i):t.deleted?e.hash===s&&s!==""?{kind:"deleteLocal",why:"deleted on another device and unchanged here"}:s===""?{kind:"upload",why:"deleted on the server but never synced from here"}:{kind:"upload",why:"deleted on another device but edited here, so the edit is kept and re-sent"}:e.hash===t.hash?{kind:"nothing",why:"the two sides hold the same content"}:s===""?{kind:"conflict",why:"both sides have content and there is no last-synced version to merge from"}:e.hash===s?{kind:"download",why:"changed on another device and unchanged here"}:t.hash===s?{kind:"upload",why:"changed here and unchanged on the server"}:r?{kind:"merge",why:"changed on both sides since the last sync"}:{kind:"conflict",why:"changed on both sides and this file cannot be merged"}}function $d(n,e,t){return n!==void 0&&n.folder?e===void 0?{kind:"upload",why:"new folder, the server has never held this path"}:e.deleted?us(t)?{kind:"removeLocalFolder",why:"folder deleted on another device, so it goes here once nothing is left in it"}:{kind:"upload",why:"folder deleted on the server but never synced from here"}:e.folder?{kind:"nothing",why:"folder exists on both sides"}:{kind:"clash",why:"a folder here and a file of the same name on another device"}:e?.folder&&!e.deleted?n!==void 0?{kind:"clash",why:"a file here and a folder of the same name on another device"}:us(t)&&t.syncuid===e.uid?{kind:"deleteRemoteFolder",why:"folder removed here"}:{kind:"createLocalFolder",why:"folder exists on the server and not here"}:{kind:"nothing",why:"folder absent on both sides"}}function us(n){return n.synctime>0&&n.synchash===""}function Dd(n,e){let t=e.synchash;return n.deleted?{kind:"nothing",why:"deleted on both sides"}:t===""?{kind:"download",why:"new on the server"}:n.hash===t&&n.uid===e.syncuid?{kind:"deleteRemote",why:"deleted here and unchanged on the server"}:n.hash===t?{kind:"restoreLocal",why:"deleted here, and written again since as a version this device never synced, so it is restored"}:{kind:"restoreLocal",why:"deleted here but changed on another device, so the newer content is restored"}}function kt(n,e,t,i){return i!==void 0&&i!==n.changeId?!0:n.hash==="-empty-"&&n.size===0?n.mtime!==e||t!==0:n.hash===""||n.chunks.length===0?!0:n.mtime!==e||n.size!==t}function st(n,e){let t=Math.ceil(e.mtime),i=Math.ceil(e.ctime);if(e.folder){n.folder=!0,n.mtime=0,n.ctime=0,n.size=0,n.hash="",n.chunks=[];return}kt(n,t,e.size,e.changeId)&&(n.hash="",n.chunks=[]),n.folder=!1,n.mtime=t,n.ctime=i,n.size=e.size,e.changeId!==void 0&&(n.changeId=e.changeId)}function fs(n,e,t){n.path=t,n.prev===""&&(n.prev=e),n.prev===t&&(n.prev=""),n.synctime=0}function ot(n,e,t,i,r){n.hash===e&&n.synchash===e&&n.syncuid===i&&n.prev===""&&n.chunks.length===t.length&&n.chunks.every((o,a)=>o===t[a])&&n.synctime!==0||(n.hash=e,n.chunks=[...t],n.synchash=e,n.syncuid=i,n.synctime=r,n.prev="")}function Ht(n,e,t,i){n.synchash===e&&n.syncuid===t||(n.synchash=e,n.syncuid=t,n.synctime=i)}function wi(n){if(!n.synctime)return 0;let e=n.size>102400?5e3:n.size>10240?2e3:1e3;return n.synctime+e}function gs(n,e){return n.synctime>e||e>=wi(n)}Re();import{createRequire as Td}from"module";var Id=Td("/"),At,Rd,Od;try{At=Id("worker_threads"),Rd=At.Worker,Od=At.isMarkedAsUntransferable}catch{}var j=Uint8Array,le=Uint16Array,Fi=Int32Array,Pn=new j([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),$n=new j([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),ki=new j([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),ws=function(n,e){for(var t=new le(31),i=0;i<31;++i)t[i]=e+=1<<n[i-1];for(var r=new Fi(t[30]),i=1;i<30;++i)for(var s=t[i];s<t[i+1];++s)r[s]=s-t[i]<<5|i;return{b:t,r}},At=ws(Pn,2),vs=At.b,Ai=At.r;vs[28]=258,Ai[258]=28;var bs=ws($n,0),Md=bs.b,ps=bs.r,Ci=new le(32768);for(O=0;O<32768;++O)Ne=(O&43690)>>1|(O&21845)<<1,Ne=(Ne&52428)>>2|(Ne&13107)<<2,Ne=(Ne&61680)>>4|(Ne&3855)<<4,Ci[O]=((Ne&65280)>>8|(Ne&255)<<8)>>1;var Ne,O,Pe=(function(n,e,t){for(var i=n.length,r=0,s=new le(e);r<i;++r)n[r]&&++s[n[r]-1];var o=new le(e);for(r=1;r<e;++r)o[r]=o[r-1]+s[r-1]<<1;var a;if(t){a=new le(1<<e);var d=15-e;for(r=0;r<i;++r)if(n[r])for(var c=r<<4|n[r],l=e-n[r],h=o[n[r]-1]++<<l,u=h|(1<<l)-1;h<=u;++h)a[Ci[h]>>d]=c}else for(a=new le(i),r=0;r<i;++r)n[r]&&(a[r]=Ci[o[n[r]-1]++]>>15-n[r]);return a}),Xe=new j(288);for(O=0;O<144;++O)Xe[O]=8;var O;for(O=144;O<256;++O)Xe[O]=9;var O;for(O=256;O<280;++O)Xe[O]=7;var O;for(O=280;O<288;++O)Xe[O]=8;var O,Xt=new j(32);for(O=0;O<32;++O)Xt[O]=5;var O,Nd=Pe(Xe,9,0),_d=Pe(Xe,9,1),Ld=Pe(Xt,5,0),Ud=Pe(Xt,5,1),vi=function(n){for(var e=n[0],t=1;t<n.length;++t)n[t]>e&&(e=n[t]);return e},Ae=function(n,e,t){var i=e/8|0;return(n[i]|n[i+1]<<8)>>(e&7)&t},bi=function(n,e){var t=e/8|0;return(n[t]|n[t+1]<<8|n[t+2]<<16)>>(e&7)},xi=function(n){return(n+7)/8|0},qt=function(n,e,t){return(e==null||e<0)&&(e=0),(t==null||t>n.length)&&(t=n.length),new j(n.subarray(e,t))};var zd=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],Ce=function(n,e,t){var i=new Error(e||zd[n]);if(i.code=n,Error.captureStackTrace&&Error.captureStackTrace(i,Ce),!t)throw i;return i},Wd=function(n,e,t,i){var r=n.length,s=i?i.length:0;if(!r||e.f&&!e.l)return t||new j(0);var o=!t,a=o||e.i!=2,d=e.i;o&&(t=new j(r*3));var c=function(Nt){var _t=t.length;if(Nt>_t){var yt=new j(Math.max(_t*2,Nt));yt.set(t),t=yt}},l=e.f||0,h=e.p||0,u=e.b||0,f=e.l,g=e.d,m=e.m,y=e.n,w=r*8;do{if(!f){l=Ae(n,h,1);var b=Ae(n,h+1,3);if(h+=3,b)if(b==1)f=_d,g=Ud,m=9,y=5;else if(b==2){var A=Ae(n,h,31)+257,F=Ae(n,h+10,15)+4,x=A+Ae(n,h+5,31)+1;h+=14;for(var p=new j(x),B=new j(19),T=0;T<F;++T)B[ki[T]]=Ae(n,h+T*3,7);h+=F*3;for(var _=vi(B),fe=(1<<_)-1,q=Pe(B,_,1),T=0;T<x;){var V=q[Ae(n,h,fe)];h+=V&15;var k=V>>4;if(k<16)p[T++]=k;else{var W=0,R=0;for(k==16?(R=3+Ae(n,h,3),h+=2,W=p[T-1]):k==17?(R=3+Ae(n,h,7),h+=3):k==18&&(R=11+Ae(n,h,127),h+=7);R--;)p[T++]=W}}var ie=p.subarray(0,A),X=p.subarray(A);m=vi(ie),y=vi(X),f=Pe(ie,m,1),g=Pe(X,y,1)}else Ce(1);else{var k=xi(h)+4,S=n[k-4]|n[k-3]<<8,v=k+S;if(v>r){d&&Ce(0);break}a&&c(u+S),t.set(n.subarray(k,v),u),e.b=u+=S,e.p=h=v*8,e.f=l;continue}if(h>w){d&&Ce(0);break}}a&&c(u+131072);for(var Mt=(1<<m)-1,ge=(1<<y)-1,Ie=h;;Ie=h){var W=f[bi(n,h)&Mt],de=W>>4;if(h+=W&15,h>w){d&&Ce(0);break}if(W||Ce(2),de<256)t[u++]=de;else if(de==256){Ie=h,f=null;break}else{var ce=de-254;if(de>264){var T=de-257,L=Pn[T];ce=Ae(n,h,(1<<L)-1)+vs[T],h+=L}var Be=g[bi(n,h)&ge],pt=Be>>4;Be||Ce(3),h+=Be&15;var X=Md[pt];if(pt>3){var L=$n[pt];X+=bi(n,h)&(1<<L)-1,h+=L}if(h>w){d&&Ce(0);break}a&&c(u+131072);var mt=u+ce;if(u<X){var yn=s-X,wn=Math.min(X,mt);for(yn+u<0&&Ce(3);u<wn;++u)t[u]=i[yn+u]}for(;u<mt;++u)t[u]=t[u-X]}}e.l=f,e.p=Ie,e.b=u,e.f=l,f&&(l=1,e.m=m,e.d=g,e.n=y)}while(!l);return u!=t.length&&o?qt(t,0,u):t.subarray(0,u)},_e=function(n,e,t){t<<=e&7;var i=e/8|0;n[i]|=t,n[i+1]|=t>>8},Vt=function(n,e,t){t<<=e&7;var i=e/8|0;n[i]|=t,n[i+1]|=t>>8,n[i+2]|=t>>16},Ei=function(n,e){for(var t=[],i=0;i<n.length;++i)n[i]&&t.push({s:i,f:n[i]});var r=t.length,s=t.slice();if(!r)return{t:ks,l:0};if(r==1){var o=new j(t[0].s+1);return o[t[0].s]=1,{t:o,l:1}}t.sort(function(v,A){return v.f-A.f}),t.push({s:-1,f:25001});var a=t[0],d=t[1],c=0,l=1,h=2;for(t[0]={s:-1,f:a.f+d.f,l:a,r:d};l!=r-1;)a=t[t[c].f<t[h].f?c++:h++],d=t[c!=l&&t[c].f<t[h].f?c++:h++],t[l++]={s:-1,f:a.f+d.f,l:a,r:d};for(var u=s[0].s,i=1;i<r;++i)s[i].s>u&&(u=s[i].s);var f=new le(u+1),g=Si(t[l-1],f,0);if(g>e){var i=0,m=0,y=g-e,w=1<<y;for(s.sort(function(A,F){return f[F.s]-f[A.s]||A.f-F.f});i<r;++i){var b=s[i].s;if(f[b]>e)m+=w-(1<<g-f[b]),f[b]=e;else break}for(m>>=y;m>0;){var k=s[i].s;f[k]<e?m-=1<<e-f[k]++-1:++i}for(;i>=0&&m;--i){var S=s[i].s;f[S]==e&&(--f[S],++m)}g=e}return{t:new j(f),l:g}},Si=function(n,e,t){return n.s==-1?Math.max(Si(n.l,e,t+1),Si(n.r,e,t+1)):e[n.s]=t},ms=function(n){for(var e=n.length;e&&!n[--e];);for(var t=new le(++e),i=0,r=n[0],s=1,o=function(d){t[i++]=d},a=1;a<=e;++a)if(n[a]==r&&a!=e)++s;else{if(!r&&s>2){for(;s>138;s-=138)o(32754);s>2&&(o(s>10?s-11<<5|28690:s-3<<5|12305),s=0)}else if(s>3){for(o(r),--s;s>6;s-=6)o(8304);s>2&&(o(s-3<<5|8208),s=0)}for(;s--;)o(r);s=1,r=n[a]}return{c:t.subarray(0,i),n:e}},Gt=function(n,e){for(var t=0,i=0;i<e.length;++i)t+=n[i]*e[i];return t},Es=function(n,e,t){var i=t.length,r=xi(e+2);n[r]=i&255,n[r+1]=i>>8,n[r+2]=n[r]^255,n[r+3]=n[r+1]^255;for(var s=0;s<i;++s)n[r+s+4]=t[s];return(r+4+i)*8},ys=function(n,e,t,i,r,s,o,a,d,c,l){_e(e,l++,t),++r[256];for(var h=Ei(r,15),u=h.t,f=h.l,g=Ei(s,15),m=g.t,y=g.l,w=ms(u),b=w.c,k=w.n,S=ms(m),v=S.c,A=S.n,F=new le(19),x=0;x<b.length;++x)++F[b[x]&31];for(var x=0;x<v.length;++x)++F[v[x]&31];for(var p=Ei(F,7),B=p.t,T=p.l,_=19;_>4&&!B[ki[_-1]];--_);var fe=c+5<<3,q=Gt(r,Xe)+Gt(s,Xt)+o,V=Gt(r,u)+Gt(s,m)+o+14+3*_+Gt(F,B)+2*F[16]+3*F[17]+7*F[18];if(d>=0&&fe<=q&&fe<=V)return Es(e,l,n.subarray(d,d+c));var W,R,ie,X;if(_e(e,l,1+(V<q)),l+=2,V<q){W=Pe(u,f,0),R=u,ie=Pe(m,y,0),X=m;var Mt=Pe(B,T,0);_e(e,l,k-257),_e(e,l+5,A-1),_e(e,l+10,_-4),l+=14;for(var x=0;x<_;++x)_e(e,l+3*x,B[ki[x]]);l+=3*_;for(var ge=[b,v],Ie=0;Ie<2;++Ie)for(var de=ge[Ie],x=0;x<de.length;++x){var ce=de[x]&31;_e(e,l,Mt[ce]),l+=B[ce],ce>15&&(_e(e,l,de[x]>>5&127),l+=de[x]>>12)}}else W=Nd,R=Xe,ie=Ld,X=Xt;for(var x=0;x<a;++x){var L=i[x];if(L>255){var ce=L>>18&31;Vt(e,l,W[ce+257]),l+=R[ce+257],ce>7&&(_e(e,l,L>>23&31),l+=Pn[ce]);var Be=L&31;Vt(e,l,ie[Be]),l+=X[Be],Be>3&&(Vt(e,l,L>>5&8191),l+=$n[Be])}else Vt(e,l,W[L]),l+=R[L]}return Vt(e,l,W[256]),l+R[256]},Jd=new Fi([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),ks=new j(0),jd=function(n,e,t,i,r,s){var o=s.z||n.length,a=new j(i+o+5*(1+Math.ceil(o/7e3))+r),d=a.subarray(i,a.length-r),c=s.l,l=(s.r||0)&7;if(e){l&&(d[0]=s.r>>3);for(var h=Jd[e-1],u=h>>13,f=h&8191,g=(1<<t)-1,m=s.p||new le(32768),y=s.h||new le(g+1),w=Math.ceil(t/3),b=2*w,k=function(ni){return(n[ni]^n[ni+1]<<w^n[ni+2]<<b)&g},S=new Fi(25e3),v=new le(288),A=new le(32),F=0,x=0,p=s.i||0,B=0,T=s.w||0,_=0;p+2<o;++p){var fe=k(p),q=p&32767,V=y[fe];if(m[q]=V,y[fe]=q,T<=p){var W=o-p;if((F>7e3||B>24576)&&(W>423||!c)){l=ys(n,d,0,S,v,A,x,B,_,p-_,l),B=F=x=0,_=p;for(var R=0;R<286;++R)v[R]=0;for(var R=0;R<30;++R)A[R]=0}var ie=2,X=0,Mt=f,ge=q-V&32767;if(W>2&&fe==k(p-ge))for(var Ie=Math.min(u,W)-1,de=Math.min(32767,p),ce=Math.min(258,W);ge<=de&&--Mt&&q!=V;){if(n[p+ie]==n[p+ie-ge]){for(var L=0;L<ce&&n[p+L]==n[p+L-ge];++L);if(L>ie){if(ie=L,X=ge,L>Ie)break;for(var Be=Math.min(ge,L-2),pt=0,R=0;R<Be;++R){var mt=p-ge+R&32767,yn=m[mt],wn=mt-yn&32767;wn>pt&&(pt=wn,V=mt)}}}q=V,V=m[q],ge+=q-V&32767}if(X){S[B++]=268435456|Ai[ie]<<18|ps[X];var Nt=Ai[ie]&31,_t=ps[X]&31;x+=Pn[Nt]+$n[_t],++v[257+Nt],++A[_t],T=p+ie,++F}else S[B++]=n[p],++v[n[p]]}}for(p=Math.max(p,T);p<o;++p)S[B++]=n[p],++v[n[p]];l=ys(n,d,c,S,v,A,x,B,_,p-_,l),c||(s.r=l&7|d[l/8|0]<<3,l-=7,s.h=y,s.p=m,s.i=p,s.w=T)}else{for(var p=s.w||0;p<o+c;p+=65535){var yt=p+65535;yt>=o&&(d[l/8|0]=c,yt=o),l=Es(d,l+1,n.subarray(p,yt))}s.i=o}return qt(a,0,i+xi(l)+r)};var Hd=function(n,e,t,i,r){if(!r&&(r={l:1},e.dictionary)){var s=e.dictionary.subarray(-32768),o=new j(s.length+n.length);o.set(s),o.set(n,s.length),n=o,r.w=s.length}return jd(n,e.level==null?6:e.level,e.mem==null?r.l?Math.ceil(Math.max(8,Math.min(13,Math.log(n.length)))*1.5):20:12+e.mem,t,i,r)};function Bi(n,e){return Hd(n,e||{},0,0)}var As=(function(){function n(e,t){typeof e=="function"&&(t=e,e={}),this.ondata=t;var i=e&&e.dictionary&&e.dictionary.subarray(-32768);this.s={i:0,b:i?i.length:0},this.o=new j(32768),this.p=new j(0),i&&this.o.set(i)}return n.prototype.e=function(e){if(this.ondata||Ce(5),this.d&&Ce(4),!this.p.length)this.p=e;else if(e.length){var t=new j(this.p.length+e.length);t.set(this.p),t.set(e,this.p.length),this.p=t}},n.prototype.c=function(e){this.s.i=+(this.d=e||!1);var t=this.s.b,i=Wd(this.p,this.s,this.o);this.ondata(qt(i,t,this.s.b),this.d),this.o=qt(i,this.s.b-32768),this.s.b=this.o.length,this.p=qt(this.p,this.s.p/8|0),this.s.p&=7},n.prototype.push=function(e,t){this.e(e),this.c(t)},n})();var Vd=typeof TextDecoder<"u"&&new TextDecoder,Gd=0;try{Vd.decode(ks,{stream:!0}),Gd=1}catch{}var Fs=0,xs=1,he=class extends Error{constructor(t,i){super(i);this.kind=t;this.name="FrameError"}kind},Cs=4096;function qd(n){if(n.length<=Cs*2)return!0;let e=n.subarray(0,Cs);return Bi(e,{level:6}).length<e.length}function Bs(n){if(n.length>0&&qd(n)){let t=Bi(n,{level:6});if(t.length<n.length){let i=new Uint8Array(1+t.length);return i[0]=xs,i.set(t,1),i}}let e=new Uint8Array(1+n.length);return e[0]=Fs,e.set(n,1),e}var Ss=4096;function Ps(n,e){if(n.length===0)throw new he("empty","a frame with no marker");if(n.length>e+1)throw new he("toolarge",`a ${n.length}-byte frame for a ${e}-byte limit`);let t=n.subarray(1);if(n[0]===Fs){if(t.length===0)throw new he("empty","a raw chunk of no bytes");return t}if(n[0]!==xs)throw new he("marker",`unknown marker ${n[0]}`);let i=[],r=0,s=!1,o=new As((c,l)=>{r+=c.length,r<=e&&i.push(c),l&&(s=!0)});try{for(let c=0;c<t.length&&!s;c+=Ss){let l=Math.min(c+Ss,t.length);if(o.push(t.subarray(c,l),l===t.length),r>e)throw new he("toolarge",`inflates past ${e} bytes`)}s||o.push(new Uint8Array(0),!0)}catch(c){throw c instanceof he?c:new he("corrupt",`undecodable deflate stream: ${c.message}`)}if(!s)throw new he("corrupt","the deflate stream ends early");if(r===0)throw new he("empty","a deflated chunk of no bytes");let a=new Uint8Array(r),d=0;for(let c of i)a.set(c,d),d+=c.length;return a}var Yt=4,Xd=6e4,In=64,Rn=65536;var Ct=256;function Ns(n){return{size:n.size,ctime:n.ctime,mtime:n.mtime,folder:n.folder??!1,deleted:n.deleted??!1,...n.prev?{prev:n.prev}:{}}}function _s(n,e,t){return{base:e??0,...n.prev?{prevBase:t??0}:{}}}function Ls(n){return{path:n.path,meta:Ns(n.meta),chunks:[...n.names],..._s(n.meta,n.base,n.prevBase)}}var Yd=new TextEncoder;function Us(n){return Yd.encode(n).length}function zs(n){return Us(JSON.stringify(Ls(n)))+1}var Ii=64,Kd=new Set(["proto","auth","cursor","busy","protostate","nospace","internal"]);function Zd(n){return n==="busy"||n==="nospace"||n==="internal"||n==="toomany"}var C=class extends Error{constructor(t,i,r={}){super(i);this.code=t;this.name="ProtocolError",this.retryable=r.retryable??Zd(t),this.retryAfterMs=r.retryAfterMs}code;retryable;retryAfterMs;get fatal(){return!this.retryable}get endsSession(){return Kd.has(this.code)}};function Pi(n){let e=n.retryable,t=n.retryAfterMs,i=n.code,r=n.msg;return new C(typeof i=="string"?i:"unknown",typeof r=="string"?r:"no message",{retryable:typeof e=="boolean"?e:void 0,retryAfterMs:typeof t=="number"&&t>0?t:void 0})}function Qd(n){if(!n.startsWith("wss://"))return"";let e=`ws://${n.slice(6)}`;return`. If that server has no TLS in front of it, pair from an invite naming ${e} instead, made on the server with trewd invite -url ${e}`}var I=class extends Error{constructor(e){super(e),this.name="ConnectionError"}},ec=1<<20,$s=1<<20,$i=16<<20,tc=64<<20,Ds=1<<20,St=class n{constructor(e,t){this.url=e;this.opts=t}url;opts;socket;pending=new Map;nextId=1;pinging;pingPromise;collecting;requestsSent=0;closed=!1;closeReason;cursor=0;notifying=Promise.resolve();limits;replaced=!1;textFrameCeiling(){return this.limits===void 0?ec:2*$i}log(e,...t){this.opts.log?.(e,...t)}get appliedCursor(){return this.cursor}get serverLimits(){return this.limits}get historyReplaced(){return this.replaced}async connect(){if(this.socket)throw new Error("already connected");let t=(this.opts.socketFactory??nc)(this.url);t.binaryType="arraybuffer",this.socket=t;let i=this.timeoutMs;await new Promise((r,s)=>{let o=setTimeout(()=>{s(new I(`no connection to ${this.url} within ${i}ms`));try{t.close()}catch{}},i),a=d=>{clearTimeout(o),d()};t.onopen=()=>a(r),t.onerror=()=>a(()=>s(new I(`could not connect to ${this.url}${Qd(this.url)}`))),t.onclose=d=>a(()=>s(new I(`connection closed before opening: ${Os(d)}`)))}),t.onerror=()=>this.die(new I("the connection failed")),t.onclose=r=>this.die(new I(`the connection closed: ${Os(r)}`)),t.onmessage=r=>this.onFrame(r.data)}die(e){if(this.closed)return;this.closed=!0,this.closeReason=e,this.log("transport closed",e.message);let t=[...this.pending.values()];this.pending.clear();let i=this.pinging;this.pinging=void 0;let r=this.collecting?.waiter;this.collecting=void 0;for(let s of t)this.disarm(s),s.reject(e);i&&(this.disarm(i),i.reject(e)),r?.();try{this.socket?.close()}catch{}try{this.opts.onClosed?.(e)}catch{}}get timeoutMs(){return this.opts.timeoutMs??Xd}arm(e){e.timer!==void 0&&clearTimeout(e.timer),e.armed=!0;let t=this.timeoutMs;e.timer=setTimeout(()=>{this.die(new I(`no ${e.what} within ${t}ms`))},t)}disarm(e){e.timer!==void 0&&clearTimeout(e.timer),e.timer=void 0,e.armed=!1}close(){this.die(new I("closed by this device"))}get isClosed(){return this.closed}onFrame(e){if(typeof e=="string"){if(e.length>this.textFrameCeiling()){this.die(new C("toolarge",`server sent a ${e.length} character frame, over the ${this.textFrameCeiling()} this device will parse`));return}let o;try{o=JSON.parse(e)}catch{this.die(new C("protostate",`server sent a frame that is not JSON: ${e.slice(0,120)}`));return}if(typeof o!="object"||o===null||Array.isArray(o)){this.die(new C("protostate",`server sent a frame that is not an object: ${e.slice(0,120)}`));return}this.onTextFrame(o,e.length);return}let t=ac(e);if(t===void 0){this.die(new C("protostate","server sent a frame of an unexpected type"));return}let i=this.collecting;if(!i||i.got.length>=i.want){this.die(new C("protostate",`server sent a ${t.length} byte body with nothing outstanding to receive it`));return}i.bytes+=t.length;let r=this.limits?.maxFetchBytes??$s;if(i.bytes>r+i.want){this.die(new C("toolarge",`server sent ${i.bytes} bytes of bodies for a fetch it said would hold at most ${r}`));return}this.arm(i.pending),i.got.push(t);let s=i.waiter;s&&(delete i.waiter,s())}onTextFrame(e,t=0){if(e.op==="batch"){this.queueNotification(()=>this.onBatchFrame(e),t);return}if(e.op==="caught-up"){let r=Ti(e.cursor);this.queueNotification(async()=>{if(r!==this.cursor){this.die(new C("protostate",`server says caught up at ${r}, this device reached ${this.cursor}`));return}this.opts.onCaughtUp?.(r)});return}let i=e.id;if(i!==void 0){if(typeof i!="number"||!Number.isInteger(i)){this.die(new C("protostate",`server sent a reply whose id is ${JSON.stringify(i)}`));return}let r=this.pending.get(i);if(!r){this.die(new C("protostate",`server sent a reply to request ${i}, which is not in flight: ${JSON.stringify(e)}`));return}this.pending.delete(i),this.disarm(r);try{r.onArrival?.(e)}catch{}r.resolve(e);return}if(e.res==="pong"){let r=this.pinging;if(!r){this.die(new C("protostate","server sent a pong with no ping in flight"));return}this.pinging=void 0,this.disarm(r),r.resolve(e);return}if(e.res==="err"){this.die(Pi(e));return}this.die(new C("protostate",`server sent an unexpected reply: ${JSON.stringify(e)}`))}static MAX_BACKLOG=1024;static MAX_BACKLOG_BYTES=4*$i;backlog=0;backlogBytes=0;queueNotification(e,t=0){if(this.backlogBytes+t>n.MAX_BACKLOG_BYTES){this.die(new C("protostate",`server sent ${this.backlogBytes+t} bytes of notifications faster than this device could apply them, over the ${n.MAX_BACKLOG_BYTES} it will hold`));return}if(this.backlog>=n.MAX_BACKLOG){this.die(new C("protostate",`server sent more than ${n.MAX_BACKLOG} notifications faster than this device could apply them`));return}this.backlog++,this.backlogBytes+=t,this.notifying=this.notifying.then(e).catch(i=>{this.die(i instanceof Error?i:new Error(String(i)))}).finally(()=>{this.backlog--,this.backlogBytes-=t})}async onBatchFrame(e){let t=Ti(e.from),i=Ti(e.to),r=e.entries;if(!Array.isArray(r))throw new C("protostate",`batch ${t} to ${i} carries no entries array, so an empty batch cannot be told from a lost one`);let s=r;if(t!==this.cursor+1)throw new C("protostate",`batch covers ${t} to ${i} but this device has applied up to ${this.cursor}, so something was skipped`);if(i<t)throw new C("protostate",`batch covers an empty range, ${t} to ${i}`);for(let o of s){if(typeof o?.uid!="number"||!Number.isFinite(o.uid))throw new C("protostate",`batch ${t}..${i} contains an entry with no uid`);if(typeof o.path!="string"||o.path==="")throw new C("protostate",`batch ${t}..${i} contains uid ${o.uid} with no path`);if(!Array.isArray(o.chunks))throw new C("protostate",`batch ${t}..${i} contains uid ${o.uid} with no chunks array`);for(let a of o.chunks)if(!vt(a))throw new C("protostate",`batch ${t}..${i} contains uid ${o.uid} naming ${JSON.stringify(a)}, which is not a chunk name`);if(o.uid<t||o.uid>i)throw new C("protostate",`batch ${t}..${i} contains uid ${o.uid}`)}await this.opts.onBatch({from:t,to:i,entries:s}),this.cursor=i}send(e){if(this.closed||!this.socket)throw this.closeReason??new I("not connected");this.socket.send(e)}takeId(){for(let e=0;e<8;e++){let t=this.nextId;if(this.nextId=this.nextId>=4294967295?1:this.nextId+1,!this.pending.has(t))return t}throw new Error("every request id is in flight, which cannot happen")}begin(e,t,i=!0,r){let s=this.takeId(),o=JSON.stringify({...e,id:s});this.requestsSent++;let a=new Promise((d,c)=>{if(this.closed){c(this.closeReason??new I("not connected"));return}let l={what:t,resolve:d,reject:c,timer:void 0,armed:!1,...r?{onArrival:r}:{}};this.pending.set(s,l),i&&this.arm(l);try{this.send(o)}catch(h){this.pending.delete(s),this.disarm(l),c(h instanceof Error?h:new Error(String(h)))}});return a.catch(()=>{}),a}async awaitReply(e){let t=await e;if(t.res==="err"){let i=Pi(t);throw i.endsSession&&this.die(i),i}return t}async request(e,t,i){return this.awaitReply(this.begin(e,t,!0,i))}async hello(e){Dn("vault",e.vault),Dn("device",e.device),this.cursor=e.cursor,this.replaced=!1;let t;try{t=await this.request({op:"hello",proto:Yt,vault:e.vault,deviceId:e.deviceId,token:e.token,device:e.device,cursor:e.cursor,...e.epoch!==void 0?{epoch:e.epoch}:{}},"ready",i=>{let r=i.epoch;i.res==="ready"&&e.epoch!==void 0&&typeof r=="string"&&r!==e.epoch&&(this.cursor=0,this.replaced=!0)})}catch(i){throw Ts(i)}return this.readReady(t)}async redeem(e){Dn("vault",e.vault),Dn("device",e.device);let t;try{t=await this.request({op:"hello",proto:Yt,vault:e.vault,device:e.device,invite:e.invite,deviceId:e.deviceId,token:e.token},"redeemed")}catch(i){throw Ts(i)}if(t.res!=="redeemed")throw new C("protostate",`expected redeemed, got ${JSON.stringify(t)}`);if(t.deviceId!==e.deviceId)throw this.malformed(`a redeemed naming device ${JSON.stringify(t.deviceId)}, which is not the ${JSON.stringify(e.deviceId)} that was redeemed for`);return{deviceId:e.deviceId}}readReady(e){if(e.res!=="ready")throw new C("protostate",`expected ready, got ${JSON.stringify(e)}`);let t=e.serverVersion,i=e.epoch;if(typeof i!="string"||i==="")throw this.malformed("a ready with no epoch, so which history it serves cannot be told");let r={proto:this.count(e,"proto","ready"),minProto:this.count(e,"minProto","ready"),serverVersion:typeof t=="string"?t:"unknown",epoch:i,cursor:this.count(e,"cursor","ready"),perFileMax:this.count(e,"perFileMax","ready"),chunkMax:Math.min(this.count(e,"chunkMax","ready"),Ds),maxChunks:this.count(e,"maxChunks","ready"),maxBatchBytes:Math.min(this.count(e,"maxBatchBytes","ready"),$i),maxFetchBytes:Math.min(this.count(e,"maxFetchBytes","ready"),tc)};if(r.proto!==Yt){let s=new C("proto",`server (version ${r.serverVersion}) answered in protocol ${r.proto}, this client speaks ${Yt}; upgrade the server first`);throw this.die(s),s}return this.limits=r,this.log("ready",r),r}async put(e,t,i,r,s,o,a){Me(o,0);let d=await this.request({op:"put",path:e,meta:Ns(t),chunks:[...i],..._s(t,s.base,s.prevBase)},"want or have");if(d.res==="have")return await this.drainReceived(),{uid:this.uid(d,"have"),uploaded:0,bytes:0};if(d.res!=="want")throw new C("protostate",`expected want or have, got ${JSON.stringify(d)}`);let c=new Set(i),l=this.wanted(d,c),h=Di(d),u=this.expectMore(h,"acknowledgement"),f=await this.sendBodies(l,c,r,"put",o,a),g=await this.awaitPhase(u,h);if(g.res!=="ack")throw new C("protostate",`expected ack, got ${JSON.stringify(g)}`);return await this.drainReceived(),{uid:this.uid(g,"ack"),uploaded:l.length,bytes:f}}async putMany(e,t,i){if(Me(i,0),e.length===0)return{results:[],uploaded:0,bytes:0};if(e.length>Ct)throw new C("toolarge",`${e.length} entries in one batch, the limit is ${Ct}`);let r={op:"putmany",entries:e.map(Ls)},s=this.limits?.maxBatchBytes;if(s!==void 0&&s>0){let u=Us(JSON.stringify(r))+24;if(u>s)throw new Error(`a putmany of ${e.length} entries encodes to ${u} bytes, over the server's ${s}; it should have been split`)}let o=await this.request(r,"want or acks"),a=o,d=0,c=0;if(o.res==="want"){let u=new Set;for(let y of e)for(let w of y.names)u.add(w);let f=this.wanted(o,u),g=Di(o),m=this.expectMore(g,"acknowledgement");c=await this.sendBodies(f,u,t,"batch",i),d=f.length,a=await this.awaitPhase(m,g)}if(a.res!=="acks")throw new C("protostate",`expected acks, got ${JSON.stringify(a)}`);let l=a.results;if(!Array.isArray(l)||l.length!==e.length)throw new C("protostate",`${e.length} entries went up and ${Array.isArray(l)?l.length:"no"} results came back`);let h=l.map((u,f)=>{if(typeof u!="object"||u===null)throw this.malformed(`acks[${f}] is not an object`);let g=u;if(g.code!==void 0){if(typeof g.code!="string")throw this.malformed(`acks[${f}].code is not a string`);return{uid:0,error:Pi(g)}}return{uid:this.uid(g,`acks[${f}]`)}});for(let u of h)u.error?.endsSession&&this.die(u.error);return await this.drainReceived(),{results:h,uploaded:d,bytes:c}}async drainReceived(){if(await this.notifying,this.closed)throw this.closeReason??new I("not connected")}async sendBodies(e,t,i,r,s,o){let a=0,d=0,c=s===void 0?void 0:()=>{let l=Math.max(0,a-(this.socket?.bufferedAmount??0));l>d&&(d=l,Me(s,l))};for(let l of e){if(await o?.(),!t.has(l))throw new C("badchunk",`server asked for ${l}, which this ${r} does not contain`);let h;try{h=await i(l)}catch(f){throw this.die(new I(`${r} could not produce ${l}, so the connection was ended rather than left owing the server bodies: ${f.message}`)),f}await o?.();let u=Bs(h);this.send(u),a+=u.length,await this.drained(o?256*1024:ic,c,o)}return await this.drained(0,c,o),a}async drained(e,t,i){t?.();let r=this.socket;if(!r||r.bufferedAmount===void 0)return;let s=r.bufferedAmount,o=Date.now(),a=Is;for(;r.bufferedAmount>e;){if(this.closed)throw this.closeReason??new I("not connected");if(await sc(a),i){let c=Date.now();await i(),o+=Date.now()-c}let d=r.bufferedAmount;if(t?.(),d<s)s=d,o=Date.now(),a=Is;else{if(Date.now()-o>this.timeoutMs)throw this.die(new I(`upload stalled: ${d} bytes unsent for ${this.timeoutMs}ms`)),this.closeReason??new I("not connected");a=Math.min(a*2,rc)}}}expectMore(e,t){if(this.pending.has(e))throw new Error(`request ${e} is already waiting for a reply`);let i=new Promise((r,s)=>{if(this.closed){s(this.closeReason??new I("not connected"));return}this.pending.set(e,{what:t,resolve:r,reject:s,timer:void 0,armed:!1})});return i.catch(()=>{}),i}async awaitPhase(e,t){let i=this.pending.get(t);return i&&this.arm(i),this.awaitReply(e)}async get(e){let t=await this.request({op:"get",uid:e},"chunks");if(t.res!=="chunks")throw new C("protostate",`expected chunks, got ${JSON.stringify(t)}`);return{uid:this.uid(t,"chunks"),size:this.count(t,"size","chunks"),chunks:this.chunkNames(t.chunks,"chunks")}}async resend(e,t){let i=await this.request({op:"resend",chunks:[...e]},"want or resent");if(i.res==="resent")return{stored:Tn(i,"stored"),missing:Tn(i,"missing"),bytes:0};if(i.res!=="want")throw new C("protostate",`expected want or resent, got ${JSON.stringify(i)}`);let r=new Set(e),s=this.wanted(i,r),o=Di(i),a=this.expectMore(o,"resent"),d=await this.sendBodies(s,r,t,"resend"),c=await this.awaitPhase(a,o);if(c.res!=="resent")throw new C("protostate",`expected resent, got ${JSON.stringify(c)}`);return{stored:Tn(c,"stored"),missing:Tn(c,"missing"),bytes:d}}async history(e,t={}){let i=await this.request({op:"history",path:e,...t.before!==void 0?{before:t.before}:{},...t.limit!==void 0?{limit:t.limit}:{}},"history");if(i.res!=="history")throw new C("protostate",`expected history, got ${JSON.stringify(i)}`);return Ms(i.entries,"history")}async deleted(e,t){let i=await this.request({op:"deleted",...e!==void 0?{limit:e}:{},...t!==void 0&&t>0?{before:t}:{}},"deleted");if(i.res!=="deleted")throw new C("protostate",`expected deleted, got ${JSON.stringify(i)}`);return{entries:Ms(i.entries,"deleted"),more:i.more===!0}}async fetch(e,t,i){if(e.length===0)return[];if(e.length>Rn)throw new Error(`a fetch of ${e.length} chunks is over the ${Rn} the server takes; it should have been split`);if(this.collecting)throw new Error("a fetch is already collecting bodies");let r={what:"chunk body",resolve:()=>{},reject:()=>{},timer:void 0,armed:!1},s=[],o=[],a=0,d=0;Me(t,0),this.collecting={pending:r,want:e.length,got:s,bytes:0};let c=this.limits?.chunkMax??Ds,l=this.limits?.maxFetchBytes??$s,h=[],u,f,g=new Promise((m,y)=>{f=y});g.catch(()=>{});try{let m=this.begin({op:"fetch",chunks:[...e]},"bodies"),y=await this.awaitReply(m);if(y.res!=="bodies")throw new C("protostate",`expected bodies, got ${JSON.stringify(y)}`);let w=this.count(y,"count","bodies");if(w!==e.length)throw this.malformed(`bodies announcing ${w} frames for a fetch of ${e.length}`);this.arm(r);for(let b=0;b<w;b++){let k=await Promise.race([this.body(b),g]);a+=k.length,Me(t,a);let S;try{S=Ps(k,c)}catch(A){if(!(A instanceof he))throw A;let F=new C(A.kind==="toolarge"?"toolarge":"badchunk",`asked for ${e[b]} and received a body that does not decode: ${A.message}`);throw this.die(F),F}if(s[b]=oc,d+=S.length,d>l){let A=new C("toolarge",`server sent bodies decoding to ${d} bytes for a fetch it said would hold at most ${l}`);throw this.die(A),A}o.push(S),i&&await i();let v=e[b];h.push(Je(S).then(A=>{if(A===v)return;let F=new C("badchunk",`asked for ${v} and received ${S.length} bytes that hash to ${A}`);u===void 0&&(u=F,f?.(F))}))}if(await Promise.all(h),u!==void 0)throw u}catch(m){throw m instanceof C&&m.code==="badchunk"&&this.die(m),m}finally{this.disarm(r),this.collecting=void 0}return o}async body(e){let t=this.collecting;if(!t||this.closed)throw this.closeReason??new I("not connected");if(t.got.length<=e&&(await new Promise(i=>{t.waiter=i}),this.closed))throw this.closeReason??new I("not connected");return t.got[e]}async invite(e={}){let t=await this.request({op:"invite",...e.ttlMs!==void 0?{ttlMs:e.ttlMs}:{},...e.label!==void 0&&e.label!==""?{label:e.label}:{}},"invited");if(t.res!=="invited")throw new C("protostate",`expected invited, got ${JSON.stringify(t)}`);let i=t.invite;if(typeof i!="string"||i==="")throw this.malformed("an invited with no invite id");let r=t.token,s;try{s=typeof r=="string"?He(r):void 0}catch{s=void 0}if(typeof r!="string"||s?.length!==Rs)throw this.malformed(`an invited whose token is not ${Rs} bytes`);return{invite:i,token:r,expiresAt:this.expiry(t.expiresAt,"invited")}}async uninvite(e){let t=await this.request({op:"uninvite",invite:e},"uninvited");if(t.res!=="uninvited")throw new C("protostate",`expected uninvited, got ${JSON.stringify(t)}`);if(t.invite!==e)throw this.malformed(`an uninvited naming ${JSON.stringify(t.invite)}, which is not the ${JSON.stringify(e)} that was cancelled`)}async devices(){let e=await this.request({op:"devices"},"devices");if(e.res!=="devices")throw new C("protostate",`expected devices, got ${JSON.stringify(e)}`);let t=e.devices;if(!Array.isArray(t))throw this.malformed("a devices reply with no list of devices");let i=e.invites;if(!Array.isArray(i))throw this.malformed("a devices reply with no list of invites");return{devices:t.map((r,s)=>this.deviceRow(r,s)),invites:i.map((r,s)=>this.inviteRow(r,s))}}async applied(e){let t=await this.request({op:"applied",applied:e},"applied");if(t.res!=="applied"||this.count(t,"cursor","applied")!==e)throw this.malformed("an applied reply that does not match the checkpoint")}inviteRow(e,t){let i=e,r=i?.invite;if(typeof r!="string"||r==="")throw this.malformed(`a devices reply whose invite ${t} has no id`);let s=i.label;return{invite:r,label:typeof s=="string"?s:"",expiresAt:this.expiry(i.expiresAt,`a devices reply's invite ${t}`)}}expiry(e,t){if(e===null)return null;if(typeof e!="number"||!Number.isSafeInteger(e)||e<=0)throw this.malformed(`${t} with expiresAt = ${JSON.stringify(e)}, not a time or null`);return e}deviceRow(e,t){let i=e,r=i?.id;if(typeof r!="string"||r==="")throw this.malformed(`a devices reply whose entry ${t} has no id`);let s=i.name;if(typeof i.online!="boolean"||!(i.applied===null||typeof i.applied=="number"&&Number.isSafeInteger(i.applied)&&i.applied>=0)||i.online===!1&&i.applied!==null)throw this.malformed(`a devices reply with invalid delivery state at entry ${t}`);let o=a=>{let d=i[a];return typeof d=="number"&&Number.isFinite(d)&&d>=0?d:0};return{id:r,name:typeof s=="string"?s:"",createdAt:o("createdAt"),lastSeen:o("lastSeen"),online:i.online,applied:i.applied}}async revoke(e){let t=await this.request({op:"revoke",deviceId:e.deviceId},"revoked");if(t.res!=="revoked")throw new C("protostate",`expected revoked, got ${JSON.stringify(t)}`);let i=t.deviceId;if(i!==e.deviceId)throw this.malformed(`a revoked naming device ${JSON.stringify(i)}, which is not the ${JSON.stringify(e.deviceId)} that was revoked`);return{deviceId:i,self:t.self===!0}}async undo(e,t={}){if(e==="")throw new Error("an undo names the operation it undoes");let i=await this.request({op:"undo",opId:e,...t.toCopy===!0?{toCopy:!0}:{}},"undone");if(i.res!=="undone")throw new C("protostate",`expected undone, got ${JSON.stringify(i)}`);let r=i.opId;if(typeof r!="string"||r===""||i.undoes!==e)throw this.malformed(`an undone for ${JSON.stringify(i.undoes)}, which is not the ${JSON.stringify(e)} that was undone`);if(i.toCopy!==(t.toCopy===!0))throw this.malformed("an undone that did not do what was asked, in place or as a copy");let s=i.steps,o=i.entries;if(!Array.isArray(s)||!Array.isArray(o))throw this.malformed("an undone with no list of steps or entries");let a=(d,c)=>{let l=d[c];return typeof l=="string"&&l!==""?l:void 0};return{opId:r,undoes:e,toCopy:t.toCopy===!0,committedAt:this.count(i,"committedAt","undone"),steps:s.map((d,c)=>{let l=d,h=a(l??{},"action"),u=a(l??{},"path");if(h===void 0||u===void 0)throw this.malformed(`an undone whose step ${c} names no action or no path`);let f={action:h,path:u};for(let g of["from","copy","why"]){let m=a(l,g);m!==void 0&&(f[g]=m)}for(let g of["before","after"]){let m=l[g];typeof m=="number"&&Number.isSafeInteger(m)&&m>0&&(f[g]=m)}return f}),entries:o.map((d,c)=>{let l=d,h=a(l??{},"path"),u=l?.uid,f=l?.previousUid;if(h===void 0||typeof u!="number"||!Number.isSafeInteger(u)||u<=0||typeof f!="number"||!Number.isSafeInteger(f)||f<0)throw this.malformed(`an undone whose entry ${c} is not a path and two uids`);let g=a(l,"prev");return{path:h,uid:u,previousUid:f,...g!==void 0?{prev:g}:{}}})}}async search(e){let t=await this.request({op:"search",query:e.query,...e.mode!==void 0&&e.mode!=="content"?{mode:e.mode}:{},...e.folder!==void 0&&e.folder!==""?{folder:e.folder}:{},...e.caseSensitive===!0?{caseSensitive:!0}:{},...e.includeChildren===!1?{includeChildren:!1}:{},...e.contextLines!==void 0&&e.contextLines>0?{contextLines:e.contextLines}:{},...e.limit!==void 0?{limit:e.limit}:{},...e.after!==void 0&&e.after!==""?{after:e.after}:{}},"searched");if(t.res!=="searched")throw new C("protostate",`expected searched, got ${JSON.stringify(t)}`);let i=t.matches,r=t.skipped,s=t.index,o=t.nextAfter;if(!Array.isArray(i)||!Array.isArray(r))throw this.malformed("a searched with no list of matches or skipped notes");if(o!==null&&(typeof o!="string"||o===""))throw this.malformed("a searched whose nextAfter is neither a continuation nor null");if(typeof t.complete!="boolean"||t.complete===!0&&o!==null)throw this.malformed("a searched that says it is complete and continues");if(typeof s!="object"||s===null||typeof s.usable!="boolean")throw this.malformed("a searched that does not say what its index did");let a=c=>Array.isArray(c)&&c.every(l=>typeof l=="string"),d=s.why;return{matches:i.map((c,l)=>{let h=c??{},{path:u,uid:f,line:g,column:m,text:y,before:w,after:b,clipped:k,kind:S}=h;if(typeof u!="string"||u===""||typeof f!="number"||!Number.isSafeInteger(f)||f<=0||typeof g!="number"||!Number.isSafeInteger(g)||g<0||typeof m!="number"||!Number.isSafeInteger(m)||m<1||typeof y!="string"||!a(w)||!a(b)||typeof k!="boolean"||S!==void 0&&S!=="filename"&&S!=="tag")throw this.malformed(`a searched whose match ${l} is not a place in a note`);return{path:u,uid:f,line:g,column:m,text:y,before:w,after:b,clipped:k,...S!==void 0?{kind:S}:{}}}),skipped:r.map((c,l)=>{let h=c??{};if(typeof h.path!="string"||typeof h.why!="string")throw this.malformed(`a searched whose skipped note ${l} has no path or reason`);return{path:h.path,why:h.why}}),nextAfter:o,complete:t.complete,head:this.count(t,"head","searched"),indexedHead:this.count(t,"indexedHead","searched"),index:{usable:s.usable===!0,...typeof d=="string"&&d!==""?{why:d}:{}},scanned:this.count(t,"scanned","searched"),scannedBytes:this.count(t,"scannedBytes","searched")}}async rename(e){let t=await this.request({op:"rename",name:e},"renamed");if(t.res!=="renamed")throw new C("protostate",`expected renamed, got ${JSON.stringify(t)}`);let i=t.name;if(i!==e)throw this.malformed(`a renamed naming ${JSON.stringify(i)}, which is not the ${JSON.stringify(e)} that was sent`);return e}malformed(e){let t=new C("protostate",`server sent ${e}`);return this.die(t),t}count(e,t,i){let r=e[t];if(typeof r!="number"||!Number.isSafeInteger(r)||r<0)throw this.malformed(`${i} with ${t} = ${JSON.stringify(r)}, not a non-negative integer`);return r}uid(e,t){let i=this.count(e,"uid",t);if(i===0)throw this.malformed(`${t} with uid 0, which no version has`);return i}chunkNames(e,t){if(!Array.isArray(e))throw this.malformed(`${t} with no chunks list`);for(let i of e)if(!vt(i))throw this.malformed(`${t} naming ${JSON.stringify(i)}, which is not a chunk name`);return e}wanted(e,t){let i=e.chunks;if(!Array.isArray(i))throw this.malformed("want with no chunks list");let r=new Set;for(let s of i){if(typeof s!="string")throw this.malformed(`want naming ${JSON.stringify(s)}, which is not a chunk name`);if(!t.has(s)){let o=new C("badchunk",`server asked for ${s}, which this put does not contain`);throw this.die(o),o}if(r.has(s))throw this.malformed(`want naming ${s} twice`);r.add(s)}return i}ping(){if(this.pingPromise)return this.pingPromise;let e=this.sendPing();return this.pingPromise=e,e.then(()=>{this.pingPromise=void 0},()=>{this.pingPromise=void 0}),e}async probe(e=2e3){let t=setTimeout(()=>{this.pinging&&this.pending.size===0&&!this.collecting&&this.die(new I("the connection did not respond after resuming"))},e);try{await this.ping()}finally{clearTimeout(t)}}async sendPing(){this.requestsSent++;let e=await new Promise((t,i)=>{if(this.closed){i(this.closeReason??new I("not connected"));return}let r={what:"pong",resolve:t,reject:i,timer:void 0,armed:!1};this.pinging=r,this.arm(r);try{this.send(JSON.stringify({op:"ping"}))}catch(s){this.pinging=void 0,this.disarm(r),i(s instanceof Error?s:new Error(String(s)))}});if(e.res!=="pong")throw new C("protostate",`expected pong, got ${JSON.stringify(e)}`)}};function Dn(n,e){let t=new TextEncoder().encode(e).length;if(t>In)throw new C("badname",`the ${n} name is ${t} bytes, and the server takes at most ${In}`);for(let i=0;i<e.length;i++){let r=e.charCodeAt(i);if(r<32||r===127)throw new C("badname",`the ${n} name contains a control character at position ${i}, which the server refuses because the name lands in its log`)}}function Ts(n){return n instanceof C&&n.code==="proto"?new C("proto",`${n.message}. This client speaks protocol ${Yt}; upgrade the server first`,{retryable:!1}):n}function Tn(n,e){let t=n[e];if(typeof t!="number"||!Number.isInteger(t)||t<0)throw new C("protostate",`${e} is ${JSON.stringify(t)}, not a count`);return t}function Di(n){let e=n.id;if(typeof e!="number")throw new Error("a matched reply lost its id, which cannot happen");return e}var On=class{constructor(e=0,t=3e5,i=5e3,r=!0,s=Math.random){this.min=e;this.max=t;this.base=i;this.jitter=r;this.random=s}min;max;base;jitter;random;count=0;success(){this.count=0}fail(){this.count++}delay(){if(this.count===0)return this.min;let e=this.base*Math.pow(2,this.count-1);return this.jitter&&(e*=.5+.5*this.random()),Math.floor(Math.min(this.max,this.min+e))}};function nc(n){let e=globalThis.WebSocket;if(!e)throw new Error("no WebSocket available in this environment");return new e(n)}var ic=4*1024*1024,Is=5,rc=50,sc=n=>new Promise(e=>setTimeout(e,n)),oc=new Uint8Array(0),Rs=16;function ac(n){if(n instanceof Uint8Array)return n;if(n instanceof ArrayBuffer)return new Uint8Array(n);if(ArrayBuffer.isView(n))return new Uint8Array(n.buffer,n.byteOffset,n.byteLength)}function Ti(n){return typeof n=="number"&&Number.isFinite(n)?n:0}function Os(n){let e=n.code??0,t=n.reason?`, ${n.reason}`:"";return`code ${e}${t}`}function Ms(n,e){if(!Array.isArray(n))throw new C("protostate",`${e} came back without a list of entries`);return n.forEach((t,i)=>{let r=t;if(typeof r?.uid!="number"||!Number.isSafeInteger(r.uid)||r.uid<=0)throw new C("protostate",`${e}[${i}] has no usable uid`);if(typeof r.path!="string"||r.path==="")throw new C("protostate",`${e}[${i}] has no path`);if(!Array.isArray(r.chunks))throw new C("protostate",`${e}[${i}] has no chunks list`);for(let s of r.chunks)if(!vt(s))throw new C("protostate",`${e}[${i}] names ${JSON.stringify(s)}, which is not a chunk name`);if(r.op!==void 0){let s=r.op;if(typeof s?.id!="string"||s.id===""||typeof s.tool!="string"||typeof s.kind!="string"||s.undoneBy!==void 0&&typeof s.undoneBy!="string")throw new C("protostate",`${e}[${i}] names an operation it does not describe`)}}),n}Re();var dc="Remove the index and sync again: it is rebuilt from the vault and the server, and nothing is lost.";function dt(n){if(n===void 0)return;let e=a=>new Error(`the index cannot be trusted: ${a}. ${dc}`);if(!at(n))throw e("it is not an object");let t=n.cursor;if(!Ft(t))throw e(`cursor is ${te(t)}, not a non-negative integer`);let i=n.epoch;if(i!==void 0&&(typeof i!="string"||i===""))throw e(`epoch is ${te(i)}, not the server's epoch`);let r=n.entries;if(!at(r))throw e("entries is not an object");for(let[a,d]of Object.entries(r))cc(a,d,e);let s=n.remote;if(!at(s))throw e("remote is not an object");for(let[a,d]of Object.entries(s))lc(a,d,e);let o=n.pending;if(!Array.isArray(o))throw e("pending is not a list");o.forEach((a,d)=>{if(!Mn(a))throw e(`pending[${d}] is ${te(a)}, not a path`)});for(let a of o)if(!Object.hasOwn(s,a))throw e(`pending names ${JSON.stringify(a)}, which remote does not hold`);return{cursor:t,...i!==void 0?{epoch:i}:{},entries:r,remote:s,pending:o}}function cc(n,e,t){let i=`entries[${JSON.stringify(n)}]`;if(!Mn(n))throw t(`${i} has a key that is not a path`);if(!at(e))throw t(`${i} is not an object`);if("path"in e&&e.path!==n)throw t(`${i}.path is ${te(e.path)}, which is not its key`);for(let o of["size","syncuid","synctime"])if(o in e&&!Ft(e[o]))throw t(`${i}.${o} is ${te(e[o])}, not a non-negative integer`);for(let o of["ctime","mtime"])if(o in e&&!Ws(e[o]))throw t(`${i}.${o} is ${te(e[o])}, not a whole number of milliseconds`);if("folder"in e&&typeof e.folder!="boolean")throw t(`${i}.folder is ${te(e.folder)}, not a boolean`);for(let o of["hash","synchash","prev","changeId"])if(o in e&&typeof e[o]!="string")throw t(`${i}.${o} is ${te(e[o])}, not a string`);if("chunks"in e){let o=e.chunks;if(!Array.isArray(o)||!o.every(vt))throw t(`${i}.chunks is not a list of chunk names`)}if("unconfirmed"in e){let o=e.unconfirmed;if(!at(o)||typeof o.hash!="string"||!Ft(o.uid)||"load"in o&&typeof o.load!="string")throw t(`${i}.unconfirmed is ${te(o)}, not a hash, a uid and a load`)}let r=e.synchash,s=e.chunks;if(typeof r=="string"&&r!==""&&r!=="-empty-"&&e.folder!==!0&&Array.isArray(s)&&s.length===0&&e.hash===r)throw t(`${i} says it is synced as ${r.slice(0,16)}... but names no chunks`)}function lc(n,e,t){let i=`remote[${JSON.stringify(n)}]`;if(!Mn(n))throw t(`${i} has a key that is not a path`);if(!at(e))throw t(`${i} is not an object`);if(!Ft(e.uid)||e.uid===0)throw t(`${i}.uid is ${te(e.uid)}, not a positive integer`);for(let r of["folder","deleted"])if(typeof e[r]!="boolean")throw t(`${i}.${r} is ${te(e[r])}, not a boolean`);if(!Ws(e.mtime))throw t(`${i}.mtime is ${te(e.mtime)}, not a whole number of milliseconds`);if(!Ft(e.size))throw t(`${i}.size is ${te(e.size)}, not a non-negative integer`);if(typeof e.hash!="string")throw t(`${i}.hash is ${te(e.hash)}, not a string`);if(e.device!==void 0&&typeof e.device!="string")throw t(`${i}.device is ${te(e.device)}, not a string`);if(e.heads!==void 0&&(!at(e.heads)||!Object.entries(e.heads).every(([r,s])=>Mn(r)&&Ft(s))))throw t(`${i}.heads is not a map of path version numbers`)}function at(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)}function Ft(n){return typeof n=="number"&&Number.isSafeInteger(n)&&n>=0}function Ws(n){return typeof n=="number"&&Number.isSafeInteger(n)}function Mn(n){return typeof n=="string"&&n!==""&&!n.includes("\0")}function te(n){return n===void 0?"missing":n===null?"null":typeof n=="string"?JSON.stringify(n.length>40?`${n.slice(0,40)}...`:n):typeof n=="number"||typeof n=="boolean"?String(n):Array.isArray(n)?"a list":"an object"}function Nn(n){let e=n.split("/");e.pop();let t=[],i="";for(let r of e)i=i?`${i}/${r}`:r,t.push(i);return t}function hc(n){let e={...n};return n.hash===Z(n.chunks)&&delete e.hash,n.synchash===n.hash&&delete e.synchash,e}function uc(n,e){let t={...Et(n),...e};return e.hash===void 0&&(t.hash=Z(t.chunks)),e.synchash===void 0&&(t.synchash=t.hash),t}function Z(n){return n.length===0?"-empty-":n.join(",")}function fc(n,e){if(n<e)throw new C("cursor",`this server is at version ${n} and this device has already seen ${e}: refusing to sync, because a server behind its own clients is a restored backup or the wrong vault. ${zn}`)}var zn="A restore through trewd backup starts a new epoch and needs nothing from here; this is a data directory copied back behind the server's back. To rejoin it and keep what only this device holds, back the server up, then press Rejoin this server in the TrewSync panel, or unlink this device and pair it again with a new invite. Either resets the merge base, so the next edit made on two devices at once makes conflict copies instead of merging.",gc={perFileMax:1<<28,maxChunks:65536,maxBatchBytes:16<<20,maxFetchBytes:64<<20,chunkMax:1<<20};function pc(n,e){return n>0?Math.min(n,e):e}function _n(n){if(n.path==="")throw new Error(`version ${n.uid} has an empty path, and no file is called nothing`);for(let[e,t]of[["mtime",n.mtime],["ctime",n.ctime]])if(typeof t!="number"||!Number.isSafeInteger(t))throw new Error(`version ${n.uid} has ${e} ${JSON.stringify(t)}, which is not a time`);if(typeof n.folder!="boolean"||typeof n.deleted!="boolean")throw new Error(`version ${n.uid} does not say plainly whether it is a folder or a deletion`);if(n.folder&&n.deleted)throw new Error(`version ${n.uid} is both a folder and a deletion`);if(typeof n.size!="number"||!Number.isSafeInteger(n.size)||n.size<0)throw new Error(`version ${n.uid} declares ${JSON.stringify(n.size)} bytes, and there is no such file`);for(let e of n.chunks)if(!mc(e))throw new Error(`version ${n.uid} names ${JSON.stringify(e)}, which is not a chunk name`);if(!n.folder&&!n.deleted&&n.size>0&&n.chunks.length===0)throw new Error(`version ${n.uid} declares ${n.size} bytes and names no chunks, which cannot both be true`);if(!n.folder&&!n.deleted&&n.size===0&&n.chunks.length>0)throw new Error(`version ${n.uid} is a zero-byte file naming ${n.chunks.length} chunks`);if(n.chunks.length>0&&(n.folder||n.deleted)){let e=n.folder?"a folder":"a deletion";throw new Error(`version ${n.uid} is ${e} and names ${n.chunks.length} chunks`)}}function mc(n){return/^[0-9a-f]{64}$/.test(n)}function yc(n){return n===""||n==="-empty-"?[]:n.split(",")}var Ye=5,wc=3,vc=5e3,bc=1e3;function Ec(n){switch(n){case"toolarge":return"Make it smaller, or raise the server's -max-file and restart it.";case"badname":return"Rename it to something this server will take, on the device that made it.";case"neversync":return"Nothing syncs under that name here. Move it, or change what this device ignores.";case"badentry":return"The device that wrote it sent something malformed; its logs say what.";case"nochunk":return"The server no longer holds its content. Restore it from a backup, or write it again from a device that still has it.";case"cursor":return"The server has lost history this device applied without starting a new epoch. Back the server up, then unlink this device and pair it again.";case"badpath":return"Rename it on this device to a name the server takes; the rule it broke is named first.";case"collision":return"Another note already has this name in a different case or form. Rename one of the two.";default:return""}}function Kt(n,e){n.skipped++,n.skippedPaths.push(e)}function Ri(n,e){n.retrying++,n.retryingPaths.push(e)}function kc(n,e){let t=n??Li(),i=e??Li(),r={};for(let s of[t.filesystemMs,i.filesystemMs])for(let[o,a]of Object.entries(s)){let d=r[o]??={ms:0,calls:0};d.ms+=a.ms,d.calls+=a.calls}return{listMs:t.listMs+i.listMs,decideMs:t.decideMs+i.decideMs,transferMs:t.transferMs+i.transferMs,saveMs:t.saveMs+i.saveMs,journalCompareMs:t.journalCompareMs+i.journalCompareMs,filesystemMs:r,rounds:(n===void 0?0:t.rounds)+i.rounds}}function Li(){return{listMs:0,decideMs:0,transferMs:0,saveMs:0,journalCompareMs:0,filesystemMs:{},rounds:1}}function Js(){return{uploaded:0,downloaded:0,merged:0,conflicted:0,deletedLocally:0,deletedRemotely:0,restored:0,foldersCreated:0,foldersDeletedLocally:0,foldersDeletedRemotely:0,unchanged:0,waiting:0,retrying:0,skipped:0,skippedPaths:[],retryingPaths:[],heldBack:0,heldBackPaths:[],settingsHeld:0,settingsHeldPaths:[],ignored:0,blocked:0,inTheWay:[],needsAttention:[],chunksSent:0,reusedChunks:0,bytesSent:0}}function Zt(n,e,t,i){return t===e&&!n?.heads&&!n?.wire?{}:{...t!==e?{wire:t}:{},heads:{...n?.heads,...n?{[n.wire??e]:n.uid}:{},[t]:i}}}function js(n){return!n.folder&&!n.deleted&&typeof n.device=="string"&&n.device!==""?{device:n.device}:{}}function Ac(n,e,t){if(t!==void 0&&n&&n.uid!==t)throw new C("stale","The path changed while preparing this write.");if(!n?.wire)return t??0;let i=n.heads?.[e];return typeof i=="number"?i:0}var Ln=class{constructor(e){this.opts=e}opts;entries=new Map;remote=new Map;pending=new Set;retries=new Map;skipped=new Map;liveSetShrank=!1;refusedInbound=new Map;staleHeads=new Map;yieldedThisSync=!1;asked=new Map;ignoredPaths=new Map;heldSettings=new Set;applyingSettings=!1;applyOnly;toConfirm=new Set;ownLoad=crypto.randomUUID();get loadId(){return this.opts.loadId??this.ownLoad}firstChoiceSpent=!1;settingsHeldLast=0;settingsHeldLastPaths=[];unparsable=new Map;settingsUnsendable=new Set;resolved=new Map;blocked=new Set;nowBlocked=new Set;cannotStream=!1;outbox=[];outboxBudget=0;outboxFrame=0;inbox=[];inboxBytes=0;landing=new Set;limits;cursor=0;epoch;adoptedReplacedHistory=!1;syncing=!1;again=!1;started=!1;now(){return this.opts.now?.()??Date.now()}log(e,...t){this.opts.log?.(e,...t)}activity(e,t,i){try{this.opts.onActivity?.({at:this.now(),action:e,path:t,...i?{copy:i}:{}})}catch{}}mergeable(e){return(this.opts.mergeable??Ge)(e)}sizesFor(e,t){return Dr(e,t,this.limits?.chunkMax)}get coalesce(){return this.opts.coalesceWrites??!0}get merging(){return this.opts.merge??!0}get sending(){return this.opts.readOnly!==!0}heldBack(e,t,i){t.heldBack++,t.heldBackPaths.length<Ye&&t.heldBackPaths.push(e),this.log("held back",e,i)}serverHasOurs(e){let t=this.entries.get(e);return t===void 0||t.folder?!1:t.syncuid>0&&t.synchash!==""&&t.synchash===t.hash}inbound(){let e=new Set;if(this.syncing){for(let t of this.inbox)e.add(t.path);for(let t of this.landing)e.add(t)}for(let t of this.pending){let i=this.remote.get(t);i?.folder===!0||i?.deleted===!0||this.heldSettings.has(t)||this.settingsUnsendable.has(t)||this.retries.has(t)||e.add(t)}return e.size}status(){let e=0;for(let t of this.entries.values())t.folder||e++;return{cursor:this.cursor,files:e,pending:this.pending.size,retrying:this.retries.size,skipped:this.skipped.size+this.refusedInbound.size,ignored:this.ignoredPaths.size,settingsHeld:this.settingsHeldLast,syncing:this.syncing}}get firstChoiceDone(){return this.firstChoiceSpent}async start(){if(this.started)throw new Error("already started");this.started=!0;let e=dt(await this.opts.store.load());if(e){this.cursor=e.cursor,this.epoch=e.epoch;for(let[i,r]of Object.entries(e.entries))this.outOfScope(i)||this.opts.replayAll===!0&&pe(i)||this.entries.set(i,uc(i,r));for(let[i,r]of Object.entries(e.remote))this.remote.set(i,r);for(let i of e.pending)this.pending.add(i);for(let[i,r]of this.entries)r.unconfirmed!==void 0&&r.unconfirmed.load!==this.loadId&&this.toConfirm.add(i);this.log("index loaded",{cursor:this.cursor,entries:this.entries.size,pending:this.pending.size})}this.opts.replayAll===!0&&(this.cursor=0);let t=await this.opts.transport.hello({vault:this.opts.vaultId,deviceId:this.opts.deviceId,token:this.opts.token,device:this.opts.device,cursor:this.cursor,epoch:this.epoch});if(this.opts.transport.historyReplaced&&this.adoptReplacedHistory(t.epoch),this.epoch=t.epoch,fc(t.cursor,this.cursor),t.chunkMax<zt){let i=new C("protostate",`this server takes chunks of at most ${t.chunkMax} bytes, and this device cannot cut a chunk smaller than ${zt}, so every file it sent would be refused; the server's chunk limit has to be at least ${zt}`,{retryable:!1});throw this.opts.transport.close(),i}return this.limits=t,this.log("connected",t),t}adoptReplacedHistory(e){if(!this.adoptedReplacedHistory){this.adoptedReplacedHistory=!0,this.log("the server's history is not the one this device synced against; reading it as new",{was:this.epoch,now:e??this.opts.transport.serverLimits?.epoch,cursor:this.cursor}),this.cursor=0,this.remote.clear(),this.pending.clear(),this.staleHeads.clear(),this.asked.clear();for(let t of this.entries.values())t.synchash="",t.syncuid=0,t.synctime=0,delete t.unconfirmed;this.toConfirm.clear(),this.firstChoiceSpent=!0}}async acceptBatch(e){this.opts.transport.historyReplaced&&this.adoptReplacedHistory();for(let o of e.entries)_n(o);let t=e.entries.map(o=>o.path),i=t.map(se),r=e.entries.map(o=>o.prev?o.prev:void 0),s=new Map;for(let o=0;o<e.entries.length;o++){let a=e.entries[o],d=i[o],c=t[o];if(d===""||d.includes("\0")){let l=Hs(d)??"a path containing a NUL byte";this.refusedInbound.has(d)||this.log("refused a path from another device",d,l),this.refusedInbound.set(d,l);continue}if(s.set(d,{uid:a.uid,folder:a.folder,deleted:a.deleted,mtime:a.mtime,size:a.size,hash:Z(a.chunks),...js(a),...Zt(s.get(d)??this.remote.get(d),d,c,a.uid)}),a.prev){let l=se(r[o]);if(l!==d)s.set(l,{uid:a.uid,folder:!1,deleted:!0,mtime:a.mtime,size:0,hash:"",...Zt(s.get(l)??this.remote.get(l),l,r[o],a.uid)});else{let h=s.get(d);s.set(d,{...h,heads:{...h.heads,[r[o]]:a.uid}})}}}for(let[o,a]of s)this.remote.set(o,a),this.pending.add(o);e.entries.some(o=>o.deleted||o.prev!==void 0&&o.prev!=="")&&(this.liveSetShrank=!0),this.cursor=e.to}async sync(e={}){if(this.syncing)return this.again=!0,Js();this.syncing=!0,this.again=!1,this.yieldedThisSync=!1;try{if(e.retryFailures||e.verifyContents){let r=this.now();for(let s of this.retries.values())s.at=Math.min(s.at,r)}let t=await this.pass(e),i=1;for(;this.again&&i<8&&!this.opts.transport.isClosed;){this.again=!1,await this.opts.transport.drainReceived(),await this.refreshStaleHeads(t);let r=await this.pass(e);t=Ui(t,r),i++}return this.again&&(t.waiting=Math.max(t.waiting,1),t.nextUploadAt=this.now()+bc,delete t.appliedCursor),t}finally{this.opts.releaseUploadTransport?.(),this.syncing=!1}}outOfScope(e){if(!pe(e))return!1;let t=this.opts.settings?.root,i=this.opts.settings?.ownFolder;return t===void 0||!e.startsWith(t+"/")||i!==void 0&&nt(e).startsWith(nt(i)+"/")||bn(e,this.opts.settings?.plugins===!0)!==void 0}neverSyncsHere(e){return kn(e,new Set)&&(!pe(e)||this.outOfScope(e))}refusedName(e){let t=this.refusalOf.get(e);if(t!==void 0)return t.why;let i=Hs(e,this.opts.windows===!0);return this.refusalOf.set(e,{why:i}),i}refusalOf=new Map;async refreshStaleHeads(e){if(!(this.staleHeads.size===0||this.opts.transport.isClosed))for(let[t,i]of[...this.staleHeads]){this.staleHeads.delete(t),this.asked.set(t,i);let r=this.remote.get(t),s=r?.wire??t;try{let[o]=await this.opts.transport.history(s,{limit:1});if(o===void 0){this.remote.delete(t),this.pending.delete(t);continue}if(_n(o),o.path!==s)throw new Error(`the server answered a request for the newest version of ${t} with a version of another note, so the current version of this path is still not known here`);if(r!==void 0&&o.uid<=r.uid)continue;this.remote.set(t,{uid:o.uid,folder:o.folder,deleted:o.deleted,mtime:o.mtime,size:o.size,hash:Z(o.chunks),...js(o),...Zt(r,t,s,o.uid)}),this.pending.add(t),this.log("asked the server which version of a refused path it holds",t,{was:r?.uid??0,now:o.uid})}catch(o){this.recordFailure(t,o,e)}}}async preview(e){let t=new Map(this.remote),i={cursor:this.cursor,files:[]},r=new Map((e??await this.opts.vault.list()).map(o=>[o.path,o])),s=new Set([...this.entries].flatMap(([o,a])=>a.prev&&r.has(o)&&!r.has(a.prev)?[a.prev]:[]));for(let o of new Set([...r.keys(),...t.keys(),...this.entries.keys()])){if(s.has(o)||this.outOfScope(o))continue;let a=r.get(o),d=t.get(o);if(a?.folder||d?.folder||this.entries.get(o)?.folder)continue;let c=this.entries.get(o),l=c?{...c,chunks:[...c.chunks]}:Et(o),h;try{if(a){if(st(l,a),a.size>this.limitOn("perFileMax"))throw new Error("File too large");(this.dirty.has(o)||kt(l,Math.ceil(a.mtime),a.size,a.changeId))&&await this.rehash(l,o,a.size)}let u=a?{folder:!1,mtime:l.mtime,size:l.size,hash:l.hash}:void 0,{kind:f}=Bn({local:u,remote:d,index:l,mergeable:this.mergeable(o)});pe(o)&&(f=this.firstChoice(o,{kind:f},l,u!==void 0)?.kind??f),h=f==="nothing"?"unchanged":f==="conflict"?"copy":f==="deleteLocal"?"delete-local":f==="deleteRemote"?"delete-server":f==="restoreLocal"?"download":f==="upload"||f==="download"||f==="merge"?f:"blocked",!this.sending&&(h==="upload"||h==="delete-server")&&(h="held-back"),(this.ignoredPaths.has(o)||this.skipped.has(o)||this.refusedName(o)!==void 0)&&(h="blocked")}catch{h="blocked"}i.files.push({path:o,action:h})}return i}firstSyncConfirmed=!1;approvedDeletions=new Set;async confirmWork(e){let t=new Map(e.map(d=>[d.path,d])),i=!this.firstSyncConfirmed&&this.opts.confirmFirstSync&&![...this.entries.values()].some(d=>d.syncuid>0)&&e.some(d=>!d.folder)&&[...this.remote.values()].some(d=>!d.deleted&&!d.folder),r=this.opts.confirmDeletions?[...new Set([...this.entries.keys(),...this.remote.keys()])].filter(d=>this.remote.get(d)?.folder&&this.remote.get(d)?.deleted&&t.has(d)||this.sending&&this.entries.get(d)?.folder&&!t.has(d)&&!this.remote.get(d)?.deleted):[];if(!i&&!r.length)return;let s=await this.preview(e);if(i&&s.files.some(d=>d.action!=="unchanged"&&d.action!=="download")){if(!await this.opts.confirmFirstSync(s))throw new Error("First sync paused for review.");this.firstSyncConfirmed=!0}let o=s.files.filter(d=>d.action==="delete-local"||d.action==="delete-server");if(!r.some(d=>o.filter(c=>c.path.startsWith(`${d}/`)).length>1))return;let a=JSON.stringify(o.map(d=>[d.path,d.action,this.remote.get(d.path)?.uid]).sort());if(!this.approvedDeletions.has(a)){if(!await this.opts.confirmDeletions(s))throw new Error("Folder deletion paused for review.");if(this.cursor!==s.cursor)throw new Error("Server changes arrived during review. Review the updated deletion plan.");this.approvedDeletions.clear(),this.approvedDeletions.add(a)}}async pass(e={}){let t=Js();if(this.heldSettings=new Set,this.settingsUnsendable=new Set,this.applyingSettings=e.applySettings===!0,this.applyOnly=e.applyOnly,this.checkpointedAt=Date.now(),this.liveSetShrank){this.liveSetShrank=!1;for(let[p,B]of this.skipped)B.code==="collision"&&this.skipped.delete(p)}let i=this.opts.timing?Li():void 0,r=i===void 0?0:performance.now(),s=p=>{if(i===void 0)return;let B=performance.now();i[p]+=B-r,r=B},o=this.now(),a=e.coalesceWrites??this.coalesce;(this.outbox.length>0||this.inbox.length>0)&&(this.log("a pass ended early, discarding what it had queued",{writes:this.outbox.length,reads:this.inbox.length}),this.outbox=[],this.outboxBudget=0,this.outboxFrame=0,this.inbox=[],this.inboxBytes=0),this.landing=new Set,this.folderDeletes=[],this.folderRemovals=[],this.folderRespellings=[],this.liveFolderSpellings=void 0;let d=await this.opts.vault.list({forceFull:e.verifyContents===!0||e.forceFullScan===!0}),c=new Map(d.map(p=>[p.path,p])),l=new Map,h=[];for(let[p,B]of this.entries)if(!(c.has(p)||B.synchash===""&&B.synctime<=0)&&!this.outOfScope(p))try{await this.opts.vault.exists(p)&&h.push(p)}catch(T){let _=T?.code;if(_!=="ignored"&&_!=="neversync")throw T;l.set(p,T)}h.length>0&&(d=await this.opts.vault.list({forceFull:!0,present:h}),c=new Map(d.map(p=>[p.path,p]))),this.recordScannedRenames(c,l),s("listMs"),await this.confirmWork(d);let u=new Set(this.dirty);this.dirty.clear();for(let p of d){let B=this.entryFor(p.path);(u.has(p.path)||e.verifyContents)&&(B.hash="",B.chunks=[]),st(B,p)}let f=new Set;for(let[p,B]of this.entries){if(!B.prev)continue;let T=se(B.prev);T!==p&&(B.folder&&!Jt(T,p)||(c.has(T)?B.prev="":this.sending&&c.has(p)&&f.add(T)))}let g=new Set;for(let[p,B]of c)B.folder||g.add(p);let m=new Set;this.nowBlocked=m;let y=new Map;for(let p of this.opts.vault.ambiguous?.()??[])y.set(p.path,`${p.spellings.map(B=>`"${zr(B)}"`).join(" and ")} are one name here, and only one of them can sync.`);this.checkIdentityProbe(),this.localByIdentity=new Map;for(let p of c.keys())this.localByIdentity.set(this.identity(p),p);this.deletingThisPass=new Set;let w=new Set(c.keys());for(let p of this.entries.keys())w.add(p);for(let p of this.remote.keys())w.add(p);for(let p of y.keys())w.add(p);let b=this.opts.activePath?.(),k=p=>c.get(p)?.folder||this.remote.get(p)?.folder?0:Ge(p)?p===b?1:2:3,S=[[],[],[],[]];for(let p of w)S[k(p)].push(p);let v=[];S.forEach((p,B)=>{for(let T of p.sort())v.push({path:T,priority:B})});let A=0,F=!1,x;for(let{path:p,priority:B}of v){let T=b?this.remote.get(b)?.uid:void 0;if(b&&F&&!this.yieldedThisSync&&(this.dirty.has(b)||T!==void 0&&T!==x&&T>(this.entries.get(b)?.syncuid??0))){this.yieldedThisSync=!0,this.again=!0;break}if(p===b&&(F=!0,x=this.remote.get(p)?.uid),f.has(p))continue;if(this.outOfScope(p)&&(c.has(p)||!this.remote.has(p)||bn(p,!0)===void 0)){this.pending.delete(p);continue}let _=c.has(p)||!this.remote.has(p)?void 0:this.refusedName(p);if(_!==void 0){this.refusedInbound.get(p)!==_&&this.log("refused a path from another device",p,_),this.refusedInbound.set(p,_),this.pending.delete(p),Kt(t,p);continue}if(A>0&&B>A&&(s("decideMs"),await this.fill(t),await this.flush(t),s("transferMs")),A=B,l.has(p)){this.recordFailure(p,l.get(p),t);continue}if(this.ignoredPaths.has(p)){this.pending.delete(p),t.ignored++;continue}let fe=this.skipped.get(p);if(fe&&!c.has(p)&&!this.remote.has(p))this.skipped.delete(p),this.log("written-off file is gone, and the server never had it",p);else if(fe){if(Oi(this.entries.get(p),this.remote.get(p))===fe.fingerprint){Kt(t,p);continue}this.skipped.delete(p),this.log("skipped file changed, trying again",p)}let q=y.size===0?void 0:y.has(p)?p:Nn(p).find(R=>y.has(R));if(q!==void 0){let R=y.get(q);m.add(p),this.blocked.has(p)||this.log("cannot be both",p,R),t.blocked++,t.inTheWay.length<Ye&&t.inTheWay.push({path:p,blockedBy:q,why:R});continue}let V=c.has(p)?void 0:Nn(p).find(R=>g.has(R));if(V!==void 0){m.add(p),this.blocked.has(p)||this.log("cannot be both",p,`${V} is a file here and a folder elsewhere`),t.blocked++,t.inTheWay.length<Ye&&t.inTheWay.push({path:p,blockedBy:V});continue}let W=this.retries.get(p);if(W&&W.at>o){Ri(t,p),t.nextUploadAt=Math.min(t.nextUploadAt??1/0,W.at);continue}try{this.opts.onProgress?.(p),await this.reconcile(p,c.get(p),t,o,a),this.retries.delete(p)}catch(R){this.recordFailure(p,R,t)}}s("decideMs"),await this.fill(t),await this.applyDeletes(t),this.wroteThisPass=new Map,await this.flush(t),await this.settleFolders(t),s("transferMs"),this.opts.onProgress?.(void 0);for(let[p]of this.refusedInbound)this.remote.has(p)||Kt(t,p);return t.skippedPaths=[...new Set(t.skippedPaths)].sort().slice(0,Ye),t.retryingPaths=[...new Set(t.retryingPaths)].sort().slice(0,Ye),this.blocked=m,s("decideMs"),this.prune(c),await this.opts.vault.flush?.(),await this.save(),[...this.pending].every(p=>this.heldSettings.has(p)||this.settingsUnsendable.has(p))&&t.waiting===0&&t.retrying===0&&t.skipped===0&&t.blocked===0&&t.heldBack===0&&t.conflicted===0&&[...this.remote].every(([p,B])=>this.ignoredPaths.has(p)||this.outOfScope(p)||this.heldSettings.has(p)||this.settingsUnsendable.has(p)||(this.entries.get(p)?.syncuid??-1)>=B.uid)&&(t.appliedCursor=this.cursor),this.settingsHeldLast=this.heldSettings.size,this.settingsHeldLastPaths=[...this.heldSettings].sort(),this.opts.settings!==void 0&&!this.firstChoiceSpent&&this.heldSettings.size===0&&![...c.keys()].some(p=>pe(p)&&!this.outOfScope(p)&&this.remote.has(p)&&(this.entries.get(p)?.synchash??"")==="")&&(this.firstChoiceSpent=!0),t.needsAttention=this.attentionList(t),i!==void 0&&(s("saveMs"),t.phases=i),t}attentionList(e){let t=[],i=new Set,r=(s,o)=>{i.has(s)||(i.add(s),t.push({path:s,why:o}))};for(let s of e.inTheWay)r(s.path,s.why===void 0?`"${s.blockedBy}" is a file here and a folder on another device. Rename one of them, on whichever device meant the other thing.`:`${s.why} Rename one of them here; nothing syncs under that name until you do.`);for(let s of e.skippedPaths){let o=this.skipped.get(s)?.why??this.refusedInbound.get(s)??this.refusedName(s);o!==void 0&&r(s,o)}for(let s of this.settingsUnsendable)r(s,"This setting is not valid JSON, so it is not sent. It is sent once it is; fix the file, or remove it.");return t}entryFor(e){let t=this.entries.get(e);return t||(t=Et(e),this.entries.set(e,t)),t}dirty=new Set;settingResolved(e){let t=se(e),i=this.entries.get(t);i!==void 0&&this.resolved.set(t,{hash:i.synchash,uid:i.syncuid}),this.noteChanged(e)}noteChanged(e){let t=se(e);this.dirty.add(t);let i=this.retries.get(t);i&&(i.at=Math.min(i.at,this.now())),this.syncing&&(this.again=!0)}async reconcile(e,t,i,r,s){let o=this.entryFor(e),a=this.remote.get(e),d=this.limitOn("perFileMax");if(t&&!t.folder&&t.size>d){this.recordFailure(e,Rc(t.size,d),i);return}let c,l;if(t){if(!t.folder&&kt(o,Math.ceil(t.mtime),t.size,t.changeId))try{l=await this.rehash(o,e,t.size)}catch(g){if(!await this.goneSinceListed(e))throw g;this.log("gone before it could be read, so deciding it as deleted",e),t=void 0}t&&(c={folder:t.folder,mtime:o.mtime,size:o.size,hash:o.hash})}let h=o.creating;if(h!==void 0){if(c!==void 0&&!c.folder&&(c.hash===h.hash||await this.tornFrom(e,c.size,h))){let g=await this.opts.vault.stat(e);if(g?.size!==t?.size||g?.mtime!==t?.mtime)throw new Error(`${e} changed while a torn write was being checked`);await this.opts.vault.remove(e),this.log("removed what a crash left of a direct write",e),Object.assign(o,Et(e)),c=void 0,l=void 0}delete o.creating}this.toConfirm.delete(e)&&await this.confirmApplied(e,o,c);let u=Bn({local:c,remote:a,index:o,mergeable:this.mergeable(e)});if(u.kind==="deleteRemoteFolder"){let g=this.localByIdentity.get(this.identity(e));g!==void 0&&g!==e&&(u={kind:"nothing",why:`folder is here as ${g}, a spelling this disk folds together`})}else if(c?.folder&&a?.deleted){let g=this.liveFolderSpelledOtherwise(e);g!==void 0&&(u.kind==="removeLocalFolder"&&Ht(o,"",a.uid,r),u={kind:"nothing",why:`folder is live on the server as ${g}, a spelling this disk folds together`},this.onlyLiveSpelling(e)===g&&this.folderRespellings.push({from:e,to:g}))}let f=a?.wire;if(f!==void 0&&c!==void 0&&!c.folder&&(o.prev===""&&(o.prev=f),u.kind==="nothing"&&(u={kind:"upload",why:"the server spells this name in another normal form"})),pe(e)){let g=await this.settingsAction(e,u,o,c,l,i,r);if(g===void 0)return;u=g}if(s&&u.kind==="upload"&&this.sending&&c&&!t?.folder&&!Ge(e)&&!gs(o,r)){i.waiting++,i.nextUploadAt=Math.min(i.nextUploadAt??1/0,wi(o));return}await this.act(e,u,o,c,a,i,r,l),this.pending.delete(e)}async settingsAction(e,t,i,r,s,o,a){t=this.firstChoice(e,t,i,r!==void 0)??t;let d=this.remote.get(e),c=i.sameAs;if(c!==void 0&&(r?.hash!==c.local||i.synchash!==c.base))delete i.sameAs;else if(c!==void 0){if(d?.deleted===!0)t={kind:"deleteLocal",why:"deleted on another device, and only reordered here"};else if(t.kind==="upload")return;(t.kind==="merge"||t.kind==="conflict")&&(t={kind:"download",why:"changed on another device, and only reordered here"})}if(i.sameAs===void 0&&r!==void 0&&d!==void 0&&!d.deleted&&r.hash!==d.hash&&(t.kind==="upload"||t.kind==="download"||t.kind==="merge"||t.kind==="conflict")&&await this.sameJson(e,d.hash)){i.sameAs={local:r.hash,base:d.hash},i.synchash=d.hash,i.syncuid=d.uid,this.pending.delete(e),this.log("a setting holds the same values as the server's, in another order",e);return}if(r!==void 0&&i.synchash!==""&&d!==void 0&&!d.deleted&&(t.kind==="upload"||t.kind==="merge"||t.kind==="conflict")&&await this.emptiedHere(e,s)&&(this.log("a setting was emptied here, as Obsidian does with one it cannot read",e),t={kind:"download",why:"emptied here, as Obsidian does with a settings file it cannot read, so the synced version is offered back"}),(t.kind==="upload"||t.kind==="merge"||t.kind==="conflict")&&r!==void 0&&qe(e)){if(!await this.parsesHere(e,s)){let y=this.unparsable.get(e),w=y!==void 0&&y.hash===i.hash?y.since:a;this.unparsable.set(e,{since:w,hash:i.hash}),a-w<Nc?(o.waiting++,o.nextUploadAt=Math.min(o.nextUploadAt??1/0,a+Mc)):this.settingsUnsendable.add(e);return}this.unparsable.delete(e)}let h=t.kind==="download"||t.kind==="restoreLocal"||t.kind==="deleteLocal"||t.kind==="merge"||t.kind==="conflict",u=i.unconfirmed!==void 0&&i.unconfirmed.load===this.loadId,f=this.applyOnly===void 0||this.applyOnly.get(e)===this.remote.get(e)?.uid;if((h?!this.applyingSettings||!f:u)&&t.kind!=="nothing"){this.heldSettings.add(e),o.settingsHeld++,o.settingsHeldPaths.length<Ye&&o.settingsHeldPaths.push(e);return}h&&(i.unconfirmed??={hash:i.synchash,uid:i.syncuid,load:this.loadId});let m=this.resolved.get(e);return m!==void 0&&(this.resolved.delete(e),t.kind==="upload"&&(i.unconfirmed={hash:m.hash,uid:m.uid,load:this.loadId})),t}firstChoice(e,t,i,r){let s=this.firstChoiceSpent?void 0:this.opts.settings?.firstChoice;if(!(s===void 0||i.synchash!==""||!r)){if(t.kind==="conflict")return s==="server"?{kind:"download",why:"the server's settings were chosen for this device"}:{kind:"upload",why:"this device's settings were chosen over the server's"};if(s==="server"&&t.kind==="upload"&&this.remote.get(e)?.deleted)return{kind:"deleteLocal",why:"the server's settings were chosen for this device, and the server deleted this one"}}}async parsesHere(e,t){try{let i=t?.bytes??await this.opts.vault.read(e);return zi(new TextDecoder("utf-8",{fatal:!0}).decode(i))}catch{return!1}}async confirmApplied(e,t,i){let r=t.unconfirmed;if(r!==void 0&&i!==void 0&&i.hash!==t.synchash&&await this.sameJson(e,t.synchash)){delete t.unconfirmed,t.sameAs={local:i.hash,base:t.synchash},this.log("a setting applied here was saved again with the same values",e);return}if(delete t.unconfirmed,!(r===void 0||i?.hash===t.synchash)){if(i===void 0){t.synchash="",t.syncuid=0;return}if(this.log("a setting changed after it was applied, deciding against the base it replaced",e),r.hash===""){t.synchash=i?.hash??"",t.syncuid=0;return}t.synchash=r.hash,t.syncuid=r.uid}}async rehash(e,t,i){let r=await this.streamScan(e,t,i);if(r)return r;let s=await this.opts.vault.read(t),o=this.mergeable(t),a=[...Wt(s,this.sizesFor(s.length,o),o)];return e.chunks=await vn(a.map(d=>d.bytes)),e.hash=Z(e.chunks),e.size=s.length,{bytes:s,pieces:a,names:e.chunks}}async streamScan(e,t,i){let r=this.opts.vault;if(!(!r.readBlocks||!r.readRange||this.cannotStream)&&!(i===void 0||i<=Mi))try{return await this.streamed(e,t,i)}catch(s){this.cannotStream=!0,this.log("streaming is not available here, reading whole files instead",t,{why:s.message});return}}async streamed(e,t,i){let r=this.opts.vault,s=this.mergeable(t),o=[],a=[],d=0;for await(let c of En(r.readBlocks(t),this.sizesFor(i,s),s))o.push(await Je(c.bytes)),a.push({start:c.offset,end:c.offset+c.bytes.length}),d+=c.bytes.length;return e.chunks=o,e.hash=Z(o),e.size=d,{names:o,spans:a,path:t,size:d}}async act(e,t,i,r,s,o,a,d){switch(t.kind){case"nothing":o.unchanged++,this.staleHeads.delete(e),this.asked.delete(e),r&&s&&!s.deleted&&(r.folder&&s.folder?ot(i,"",[],s.uid,a):r.hash===s.hash&&ot(i,r.hash,i.chunks,s.uid,a)),r===void 0&&s?.deleted&&i.unconfirmed?.load!==this.loadId&&this.entries.delete(e);return;case"upload":await this.upload(e,i,o,s?.uid,!0,d);return;case"download":case"restoreLocal":{if(!s)return;await this.receive(e,i,s,t.kind,t.why,o,r);return}case"createLocalFolder":await this.opts.vault.mkdir(e),i.folder=!0,s&&ot(i,"",[],s.uid,a),o.foldersCreated++;return;case"deleteRemoteFolder":if(!this.sending){this.heldBack(e,o,"this device is read-only, so the folder was not deleted anywhere");return}this.folderDeletes.push(e);return;case"removeLocalFolder":this.folderRemovals.push(e);return;case"clash":this.skipped.set(e,{why:`${t.why}. Rename one of them, and it will sync.`,fingerprint:Oi(i,s)}),Kt(o,e),this.log("cannot be both",e,t.why);return;case"deleteLocal":if(this.deletingThisPass.add(e),this.pendingDeletes.push({path:e,why:t.why,based:r}),r!==void 0&&!r.folder){let c=await this.syncedDigestOf(e,r);c!==void 0&&this.deleteBaseline.set(e,c)}return;case"deleteRemote":{if(!this.sending){this.heldBack(e,o,"this device is read-only, so it was not deleted anywhere");return}let c=this.now(),l={path:s?.wire??e,meta:{size:0,ctime:0,mtime:c,deleted:!0},names:[]};await this.queue({path:e,size:0,entry:{...l,base:s?.uid??0},bodyOf:_i,commit:(h,u)=>{u||this.remote.set(e,{uid:h,folder:!1,deleted:!0,mtime:this.now(),size:0,hash:""}),this.entries.delete(e),o.deletedRemotely++,this.log("deleted on the server",e,t.why),this.activity("deleted-server",e)}},o);return}case"merge":await this.merge(e,i,s,o);return;case"conflict":await this.conflict(e,i,s,o,t.why);return}}async upload(e,t,i,r,s=!1,o){let a=Ac(this.remote.get(e),e,r);if(!this.sending){this.heldBack(e,i,"this device is read-only, so it was not sent");let y=Cc(r,this.remote.get(e));y&&Ht(t,y.hash,y.uid,this.now());return}if(t.folder){let y=t.prev!==""&&Jt(se(t.prev),e)?t.prev:"",w=y?this.entries.get(se(y))?.syncuid??0:0,b={path:e,meta:{size:0,ctime:0,mtime:0,folder:!0,...y?{prev:y}:{}},names:[]};await this.queue({path:e,size:0,entry:{...b,base:a,...y?{prevBase:w}:{}},bodyOf:_i,commit:(k,S)=>{ot(t,"",[],k,this.now()),S||this.remote.set(e,{uid:k,folder:!0,deleted:!1,mtime:0,size:0,hash:""}),y&&this.retireMovedSource(y,e,k,0),s&&i.uploaded++}},i);return}let d=await this.planUpload(t,e,o),c=t.hash,l=[...t.chunks],h=t.size,u=t.mtime,f=t.prev,g=f?this.entries.get(se(f))?.syncuid??0:0,m={path:e,meta:{size:h,ctime:t.ctime,mtime:u,...f?{prev:f}:{}},names:d.names};await this.queue({path:e,size:h,entry:{...m,base:a,prevBase:g},bodyOf:d.bodyOf,commit:(y,w)=>{ot(t,c,l,y,this.now()),w||this.remote.set(e,{uid:y,folder:!1,deleted:!1,mtime:u,size:h,hash:c,...Zt(this.remote.get(e),e,e,y)}),f&&this.retireMovedSource(f,e,y,u),s&&i.uploaded++,this.log("uploaded",e),this.activity("uploaded",e)}},i)}retireMovedSource(e,t,i,r){let s=se(e);if(s!==t)this.entries.delete(s),(this.remote.get(s)?.uid??0)<=i&&(this.remote.set(s,{uid:i,folder:!1,deleted:!0,mtime:r,size:0,hash:"",...Zt(this.remote.get(s),s,e,i)}),this.pending.delete(s));else if(s===t){let o=this.remote.get(t);this.remote.set(t,{...o,heads:{...o.heads,[e]:Math.max(o.heads?.[e]??0,i)}})}}async queue(e,t){let i=this.batchCap,r=e.size,s=zs(e.entry);this.outbox.length>0&&(r>i||this.outboxBudget+r>i||this.outboxFrame+s>i-Ii)&&await this.flush(t),this.outbox.push(e),this.outboxBudget+=r,this.outboxFrame+=s,(this.outbox.length>=Ct||this.outboxBudget>=i||this.outboxFrame>=i-Ii)&&await this.flush(t)}limitOn(e){return pc(this.limits?.[e]??0,gc[e])}get batchCap(){return Math.min(this.limitOn("maxBatchBytes"),this.opts.activePath?.()?2*1024*1024:1/0)}get fetchCap(){return Math.min(this.limitOn("maxFetchBytes"),this.opts.activePath?.()?2*1024*1024:1/0)}async flush(e){if(this.outbox.length===0)return;let t=this.outbox;this.outbox=[],this.outboxBudget=0,this.outboxFrame=0;let i=new Map;for(let o of t)for(let a of o.entry.names)i.has(a)||i.set(a,o.bodyOf);let r=async o=>{let a=i.get(o);if(!a)throw new Error(`server asked for ${o}, which no queued file contains`);return a(o)},s;try{s=await this.transferring("upload",t.filter(o=>o.entry.names.length>0).map(o=>o.path),async o=>{let a=t.length===1?t[0]:void 0;if(a!==void 0&&a.size>this.batchCap){let{entry:d}=a,c=h=>h.put(d.path,d.meta,d.names,r,{base:d.base??0,prevBase:d.prevBase??0},o,h===this.opts.transport?void 0:()=>this.sendInteractiveEdit(e,t.map(u=>u.path))),l=this.opts.withUploadTransport&&!this.servicingInteractive?await this.opts.withUploadTransport(c):await c(this.opts.transport);return{results:[{uid:l.uid}],uploaded:l.uploaded,bytes:l.bytes}}else return await this.opts.transport.putMany(t.map(d=>d.entry),r,o)})}catch(o){for(let a of t)this.recordFailure(a.path,o,e);return}e.chunksSent+=s.uploaded,e.bytesSent+=s.bytes;for(let o=0;o<t.length;o++){let a=t[o],d=s.results[o];if(d.error){this.recordFailure(a.path,d.error,e);continue}this.staleHeads.delete(a.path),this.asked.delete(a.path);let c=(this.remote.get(a.path)?.uid??0)>d.uid;a.commit(d.uid,c),(a.entry.meta.deleted===!0||(a.entry.meta.prev??"")!=="")&&(this.liveSetShrank=!0),c&&(e.waiting++,this.again=!0,this.log("another device wrote after this upload, reconciling next pass",a.path,{uploaded:d.uid,now:this.remote.get(a.path)?.uid}))}}servicingInteractive=!1;lastInteractive=0;async sendInteractiveEdit(e,t){if(this.servicingInteractive||this.dirty.size===0||!this.sending||this.opts.transport.isClosed)return;let i=Date.now();if(i-this.lastInteractive<Pc)return;this.lastInteractive=i;let r=this.opts.activePath?.(),s=r&&this.dirty.has(r)?r:[...this.dirty].find(g=>Ge(g));if(!s||!Ge(s)||!this.opts.vault.stat)return;let o=this.entries.get(s),a=this.remote.get(s),d=[...t,...this.outbox.map(g=>g.path),...this.inbox.map(g=>g.path),...this.pendingDeletes.map(g=>g.path)],c=this.identity(s);if(d.some(g=>{let m=this.identity(g);return m===c||m.startsWith(`${c}/`)||c.startsWith(`${m}/`)})||!o||o.folder||o.prev||a?.wire||a?.deleted||a?.folder||(a?.uid??0)!==o.syncuid||this.skipped.has(s)||this.ignoredPaths.has(s)||this.refusedName(s)!==void 0||this.nowBlocked.has(s)||this.pending.has(s)||[...this.entries.values()].some(g=>g.prev&&this.identity(g.prev)===c)||(this.opts.vault.ambiguous?.()??[]).some(g=>this.identity(g.path)===c||c.startsWith(`${this.identity(g.path)}/`)))return;let l=this.retries.get(s);if(l&&l.at>this.now())return;this.servicingInteractive=!0;let h=this.outbox,u=this.outboxBudget,f=this.outboxFrame;this.outbox=[],this.outboxBudget=0,this.outboxFrame=0;try{let g=await this.opts.vault.stat(s);if(!g||g.folder||g.size>Math.min(512*1024,this.limitOn("perFileMax")))return;this.dirty.delete(s),o.hash="",o.chunks=[],st(o,g);let m;try{m=await this.rehash(o,s,g.size)}catch(b){if(!await this.goneSinceListed(s))throw b;this.dirty.add(s),this.again=!0;return}if(o.size>Math.min(512*1024,this.limitOn("perFileMax"))){this.again=!0;return}let y=this.remote.get(s);if(Bn({local:{folder:!1,mtime:o.mtime,size:o.size,hash:o.hash},remote:y,index:o,mergeable:this.mergeable(s)}).kind!=="upload"){this.again=!0;return}await this.upload(s,o,e,y?.uid,!0,m),await this.flush(e)}catch(g){this.recordFailure(s,g,e)}finally{this.outbox=h,this.outboxBudget=u,this.outboxFrame=f,this.servicingInteractive=!1}}async repair(){let e={scanned:0,offered:0,stored:0,couldNotOffer:0,stillMissing:0,failed:[]},t=[];for(let[i,r]of[...this.entries]){if(r.folder||r.chunks.length===0)continue;e.scanned++;let s=r.chunks;if(r.hash!==r.synchash){e.couldNotOffer+=s.length;continue}let o=this.opts.vault.stat?await this.opts.vault.stat(i):void 0;if(o===void 0||o.folder||kt(r,Math.ceil(o.mtime),o.size,o.changeId)){e.couldNotOffer+=s.length;continue}t.push({path:i,entry:r,names:s})}for(let i=0;i<t.length;){let r=[],s=0;for(;i<t.length&&(r.length===0||s+t[i].names.length<=Bc);)s+=t[i].names.length,r.push(t[i]),i++;let o=new Map,a=[];for(let h of r)for(let u of h.names)o.has(u)||(o.set(u,h),a.push(u));let d=new Map,c,l=async h=>{let u=o.get(h);if(!u)throw new Error(`the server asked for ${h}, which this repair did not offer`);let f=d.get(u.path);if(f===void 0){if(f=await this.planUpload(u.entry,u.path),f.names.length!==u.names.length||f.names.some((g,m)=>g!==u.names[m]))throw c=u.path,new Error(`${u.path} has changed since the version the server acknowledged, so its chunks were not sent`);d.set(u.path,f)}return f.bodyOf(h)};try{let h=await this.opts.transport.resend(a,l);e.offered+=a.length,e.stored+=h.stored,e.stillMissing+=h.missing}catch(h){for(let u of r)u.path===c?e.couldNotOffer+=u.names.length:e.failed.push({path:u.path,why:h.message});if(this.opts.transport.isClosed)break}}return e}async planUpload(e,t,i){if(i===void 0&&e.chunks.length>0&&e.hash!==""){let a=[...e.chunks],d;return{names:a,bodyOf:async c=>{if(d===void 0){let l=await this.rehash(e,t);if(l.names.length!==a.length||l.names.some((h,u)=>h!==a[u]))throw new Error(`${t} changed while it was being sent, so it was not sent`);d=await this.planUpload(e,t,l)}return d.bodyOf(c)}}}let r=i??await this.rehash(e,t),s=this.opts.vault;if(r.spans){let a=new Map(r.names.map((d,c)=>[d,r.spans[c]]));return{names:r.names,bodyOf:async d=>{let c=a.get(d);if(!c)throw new Error(`no chunk named ${d} in ${t}`);let l=await s.readRange(r.path,c.start,c.end);if(await Je(l)!==d)throw new Error(`${t} changed while it was being sent, so it was not sent`);return l}}}let o=new Map;for(let a=0;a<r.names.length;a++)o.set(r.names[a],r.pieces[a].bytes);return{names:r.names,bodyOf:async a=>{let d=o.get(a);if(!d)throw new Error(`no chunk named ${a} in ${t}`);return d}}}async receive(e,t,i,r,s,o,a){let d=yc(i.hash);this.checkChunkCount(i.uid,d.length);let c=a===void 0?await this.respelledHere(e,i):void 0,l=c?.state??a,h=l===void 0||l.folder?void 0:await this.syncedDigestOf(c?.from??e,l);this.inbox.push({path:e,entry:t,remote:i,chunks:d,kind:r,why:s,based:l,baseDigest:h}),this.inboxBytes+=i.size,(this.inbox.length>=Ct||this.inboxBytes>=$c)&&await this.fill(o)}async respelledHere(e,t){let i=this.opts.vault;if(i.sameFile===void 0&&i.canonical===void 0)return;let r=this.localByIdentity.get(this.identity(e));if(r===void 0||r===e||!Jt(r,e))return;let s=this.remote.get(r);if(s===void 0||!s.deleted||s.uid!==t.uid)return;let o=this.entries.get(r);if(o===void 0||o.folder||o.synchash===""||o.hash!==o.synchash||i.sameFile!==void 0&&!await i.sameFile(e,r))return;let a=await i.stat(e);if(!(a===void 0||a.folder)&&!(a.size!==o.size||Math.ceil(a.mtime)!==o.mtime))return{from:r,state:{folder:!1,mtime:o.mtime,size:o.size,hash:o.hash}}}async fill(e){if(this.inbox.length===0)return;let t=this.refuseAliases(this.inbox,e);if(this.inbox=[],this.inboxBytes=0,t.length===0)return;this.landing=new Set(t.map(h=>h.path));let i=new Map,r=this.heldByContent();for(let h of t){let u=r.get(Z(h.chunks));u!==void 0&&u!==h.path&&i.set(h,u)}let s=this.reusableFrom(t,i),o=[],a=new Map;for(let h of t){if(i.has(h))continue;let u=s.get(h),f=Qt(h.remote.size,h.chunks.length);for(let g of h.chunks){if(u?.has(g))continue;let m=a.get(g);m===void 0&&o.push(g),(m===void 0||f>m)&&a.set(g,f)}}let d=new Map,c=!1;if(o.length>0)try{let h=await this.fetchAll(o,u=>a.get(u),t.filter(u=>!i.has(u)).map(u=>u.path),()=>this.sendInteractiveEdit(e,t.map(u=>u.path)));for(let u=0;u<o.length;u++)d.set(o[u],h[u])}catch(h){if(h instanceof C&&h.code==="nochunk"&&!this.opts.transport.isClosed)c=!0;else{for(let u of t)this.recordFailure(u.path,h,e);this.landing=new Set;return}}let l=await this.intendDirect(t,i);for(let h of t)try{let u=i.get(h),f=u===void 0?"ask":await this.landFromLocal(h,u,e);if(f!=="ask"&&this.writtenSinceSave++,f==="landed"){h.kind==="download"?(e.downloaded++,this.activity("downloaded",h.path)):e.restored++,this.log(h.kind,h.path,`${h.why}, from ${u} without asking`);continue}if(f==="kept")continue;let g=s.get(h),m=g===void 0?d:await this.withLocalChunks(h,g,d,e),y=u!==void 0||c?await this.land(h,await this.fetchFor(h),e):await this.land(h,m,e);if(this.writtenSinceSave++,!y)continue;h.kind==="download"?(e.downloaded++,this.activity("downloaded",h.path)):e.restored++,this.log(h.kind,h.path,h.why)}catch(u){this.recordFailure(h.path,u,e)}finally{this.landing.delete(h.path),l.has(h)&&!this.triedDirect.delete(h)&&delete h.entry.creating}await this.checkpoint()}triedDirect=new Set;async tornFrom(e,t,i){if(t>i.size)return!1;let r=await this.opts.vault.read(e);if(r.length>i.size)return!1;let s=await this.versionBytes(e,i.hash,i.size);if(s.length!==i.size)return!1;for(let o=0;o<r.length;o++)if(r[o]!==s[o]&&r[o]!==0)return!1;return!0}async emptiedHere(e,t){if(!qe(e))return!1;try{let i=t!==void 0&&t.spans===void 0?t.bytes:await this.opts.vault.read(e),r=JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(i));return r!==null&&typeof r=="object"&&Object.keys(r).length===0}catch{return!1}}async versionBytes(e,t,i){let r=t===Z([])?[]:t.split(","),s=Qt(i,r.length),o=await this.fetchAll(r,()=>s,[e]),a=new Uint8Array(o.reduce((c,l)=>c+l.length,0)),d=0;for(let c of o)a.set(c,d),d+=c.length;return a}async sameJson(e,t){if(!qe(e))return!1;let i=this.remote.get(e);if(i===void 0||i.hash!==t||i.deleted)return!1;try{let r=await this.opts.vault.read(e),s=await this.versionBytes(e,t,i.size),o=a=>JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(a));return Gs(o(r))===Gs(o(s))}catch{return!1}}async intendDirect(e,t){let i=this.opts.vault,r=new Set;if(i.createDirect===void 0)return r;for(let s of e)s.based!==void 0||t.has(s)||this.entries.get(s.path)!==s.entry||s.entry.synchash===""&&(s.entry.creating={hash:Z(s.chunks),uid:s.remote.uid,size:s.remote.size},r.add(s));if(r.size===0)return r;try{await i.flush?.(),await this.save()}catch(s){for(let o of r)delete o.entry.creating;return this.log("could not save the intent to write new files directly; writing them staged",{why:s.message}),new Set}return r}writtenSinceSave=0;checkpointedAt=0;async checkpoint(){if(this.writtenSinceSave!==0&&!(this.writtenSinceSave<Dc&&Date.now()-this.checkpointedAt<Tc))try{await this.opts.vault.flush?.(),await this.save()}catch(e){this.writtenSinceSave=0,this.checkpointedAt=Date.now(),this.log("could not save the index part way through the pass; the end of it will",{why:e.message})}}localByIdentity=new Map;deletingThisPass=new Set;identity(e){let t=this.identityOf.get(e);if(t!==void 0)return t;let i=this.opts.vault,r=i.canonical?i.canonical(e):ee(e);return this.identityOf.set(e,r),r}identityOf=new Map;identityProbe;checkIdentityProbe(){let e=this.opts.vault.canonical?.("Aa");e!==this.identityProbe&&(this.identityProbe=e,this.identityOf.clear())}refuseAliases(e,t){let i=new Map;for(let s of e){let o=this.identity(s.path),a=i.get(o)??[];a.push(s),i.set(o,a)}let r=[];for(let[s,o]of i){let a=this.localByIdentity.get(s),d=a!==void 0&&!this.deletingThisPass.has(a)&&o.some(c=>c.path!==a);if(!d&&o.length===1){r.push(o[0]);continue}for(let c of o){let l=d?a:o.find(h=>h.path!==c.path).path;t.blocked++,t.inTheWay.length<Ye&&t.inTheWay.push({path:c.path,blockedBy:l}),this.blocked.has(c.path)||this.log("cannot be both",c.path,`${l} is the same file on this disk`),this.nowBlocked.add(c.path)}}return r}pendingDeletes=[];deleteBaseline=new Map;wroteThisPass=new Map;async wouldUndoAWrite(e){let t=this.opts.vault;for(let i of this.wroteThisPass.get(Vs(e))??[])if(i!==e){if(t.sameFile){if(await t.sameFile(i,e))return{wrote:i,sure:!0};continue}if(Jt(i,e))return{wrote:i,sure:!1}}}async applyDeletes(e){let t=this.pendingDeletes;this.pendingDeletes=[];let i=this.deleteBaseline;this.deleteBaseline=new Map;for(let{path:r,why:s,based:o}of t)try{let a=await this.wouldUndoAWrite(r);if(a!==void 0){if(this.entries.delete(r),a.sure){this.log("kept",r,`deleting it would remove ${a.wrote}, which is the same file`);continue}e.blocked++,e.inTheWay.length<Ye&&e.inTheWay.push({path:r,blockedBy:a.wrote}),this.log("kept",r,`deleting it might remove ${a.wrote}, and this vault cannot say whether they are one file`);continue}if(!await this.unchangedSince(r,o)){e.waiting++,this.again=!0,this.log("kept",r,{why:"it changed after the pass decided to delete it",deletion:s});continue}let d=await this.removedSomethingElse(r,o,i);if(d!==void 0){this.log("kept what was about to be deleted",r,{why:"it changed after the pass decided to delete it",deletion:s,keptAt:d}),this.landed(d),this.activity("conflict",r,d),e.conflicted++,this.entries.delete(r);continue}let c=this.entries.get(r),l=c?.hash||c?.synchash||"";c?.unconfirmed!==void 0&&l!==""?this.entries.set(r,{...Et(r),synchash:l,syncuid:c.syncuid,unconfirmed:c.unconfirmed}):this.entries.delete(r),e.deletedLocally++,this.log("deleted locally",r,s),this.activity("deleted-local",r)}catch(a){this.recordFailure(r,a,e)}}folderDeletes=[];folderRemovals=[];folderKeptBy=new Map;liveFolderSpellings;liveFolderSpelledOtherwise(e){if(this.liveFolderSpellings===void 0){let t=new Map,i=r=>{let s=this.identity(r),o=t.get(s);o?o.add(r):t.set(s,new Set([r]))};for(let[r,s]of this.remote)if(!s.deleted){s.folder&&i(r);for(let o of Nn(r))i(o)}this.liveFolderSpellings=t}for(let t of this.liveFolderSpellings.get(this.identity(e))??[])if(t!==e)return t}onlyLiveSpelling(e){let t=this.liveFolderSpellings?.get(this.identity(e));return t?.size===1?[...t][0]:void 0}folderRespellings=[];async respellFolders(){let e=this.opts.vault.respellFolder?.bind(this.opts.vault),t=this.folderRespellings;if(this.folderRespellings=[],e===void 0)return;let i=new Map(t.map(r=>[r.from,r.to]));for(let r of Ni([...i.keys()])){let s=i.get(r),o=r.slice(0,r.lastIndexOf("/")+1)+s.slice(s.lastIndexOf("/")+1);if(o!==r)try{await e(r,o)&&this.log("respelled",r,`the server has this folder as ${i.get(r)} now`)}catch(a){this.log("could not respell",r,{to:o,why:a.message})}}}async settleFolders(e){let t=this.folderDeletes,i=this.folderRemovals;this.folderDeletes=[],this.folderRemovals=[],await this.respellFolders(),!(t.length===0&&i.length===0)&&(await this.sendFolderDeletions(t,e),await this.removeEmptiedFolders(i,e),await this.flush(e))}async sendFolderDeletions(e,t){let i=new Set;for(let r of Ni(e))try{let s=this.remote.get(r),o=this.entries.get(r);if(s===void 0||s.deleted||!s.folder||o===void 0||o.syncuid!==s.uid||await this.opts.vault.exists(r))continue;let a=this.liveBeneath(r,i);if(a!==void 0){this.folderKeptBy.get(r)!==a&&this.log("kept on the server",r,`folder removed here, and ${a} is live in it`),this.folderKeptBy.set(r,a);continue}this.folderKeptBy.delete(r),i.add(r);let d={path:s.wire??r,meta:{size:0,ctime:0,mtime:this.now(),deleted:!0},names:[]};await this.queue({path:r,size:0,entry:{...d,base:s.uid},bodyOf:_i,commit:(c,l)=>{l||this.remote.set(r,{uid:c,folder:!1,deleted:!0,mtime:this.now(),size:0,hash:""}),this.entries.delete(r),t.foldersDeletedRemotely++,this.log("deleted on the server",r,"folder removed here, with nothing left in it"),this.activity("deleted-server",r)}},t)}catch(s){this.recordFailure(r,s,t)}}liveBeneath(e,t){let i=`${e}/`;for(let[r,s]of this.remote)if(!s.deleted&&r.startsWith(i)&&!t.has(r))return r}async removeEmptiedFolders(e,t){let i=new Set,r;for(let s of Ni(e))try{let o=this.remote.get(s),a=this.entries.get(s);if(o===void 0||!o.deleted||a===void 0)continue;let d=await this.opts.vault.stat(s);if(d===void 0){this.entries.delete(s);continue}if(!d.folder)continue;if(await this.opts.vault.removeFolder(s)){this.entries.delete(s),r=void 0,t.foldersDeletedLocally++,this.log("deleted locally",s,"folder deleted on another device, and empty here"),this.activity("deleted-local",s);continue}r??=new Map((await this.opts.vault.list()).map(l=>[l.path,l]));let c=this.keepsFolder(s,o.uid,r,i);if(c===void 0){i.add(s),Ht(a,"",o.uid,this.now()),this.log("kept for now",s,"folder deleted on another device; what is left in it is going too");continue}this.log("kept",s,`folder deleted on another device, and ${c} is still in it here`),await this.upload(s,a,t,o.uid,!0)}catch(o){this.recordFailure(s,o,t)}}keepsFolder(e,t,i,r){let s=`${e}/`,o=!1;for(let[a,d]of i){if(!a.startsWith(s))continue;if(o=!0,d.folder){if(r.has(a))continue;return a}let c=this.remote.get(a),l=this.entries.get(a);if(c===void 0||l===void 0||!(l.synchash!==""&&l.hash===l.synchash&&!kt(l,Math.ceil(d.mtime),d.size,d.changeId)))return a;if(!c.deleted&&!(c.uid<t&&l.syncuid===c.uid))return a}return o?void 0:"something this device does not list"}landed(e){let t=Vs(e),i=this.wroteThisPass.get(t);i?i.push(e):this.wroteThisPass.set(t,[e]),this.localByIdentity.set(this.identity(e),e)}heldByContent(){let e=new Map;for(let[t,i]of this.entries)i.folder||i.hash===""||i.hash==="-empty-"||e.set(i.hash,t);return e}reusableFrom(e,t){let i=new Map;for(let r of e){if(t.has(r)||r.remote.size<xc)continue;let s=this.entries.get(r.path);if(!s||s.folder||s.chunks.length===0)continue;let o=new Set(s.chunks),a=new Set(r.chunks.filter(d=>o.has(d)));a.size*2<r.chunks.length||i.set(r,a)}return i}async withLocalChunks(e,t,i,r){let s=new Map(i),o=new Set([...t].filter(h=>!s.has(h)));if(o.size===0)return s;let a=this.entries.get(e.path),d=this.opts.vault,c=this.mergeable(e.path),l=0;try{let h=this.sizesFor(a?.size??e.remote.size,c),u=d.readBlocks&&!this.cannotStream?En(d.readBlocks(e.path),h,c):(a?.size??1/0)<=Mi?Wt(await d.read(e.path),h,c):[];for await(let f of u){if(o.size===0)break;let g=await Je(f.bytes);o.has(g)&&(s.set(g,f.bytes),o.delete(g),l++)}}catch(h){this.log("could not reuse this device's copy, fetching instead",e.path,{why:h.message})}if(o.size>0){let h=Qt(e.remote.size,e.chunks.length),u=[...o],f=await this.fetchAll(u,()=>h,[e.path]);u.forEach((g,m)=>s.set(g,f[m]))}return l>0&&(this.log("reused this device's own copy",e.path,{chunks:l,of:e.chunks.length,fetched:o.size}),r.reusedChunks+=l),s}async fetchFor(e){let t=Qt(e.remote.size,e.chunks.length),i=await this.fetchAll([...e.chunks],()=>t,[e.path]),r=new Map;return e.chunks.forEach((s,o)=>r.set(s,i[o])),r}async fetchAll(e,t,i=[],r){return this.transferring("download",i,async s=>{let o=async(l,h,u)=>{let f=[],g=0,m=async y=>{let w=0,b;try{b=await l.fetch(y,s===void 0?void 0:k=>{w=k,s(g+k)},u)}catch(k){if(!(k instanceof C)||k.code!=="toolarge")throw k;if(y.length>1&&!l.isClosed){let S=Math.ceil(y.length/2);await m(y.slice(0,S)),await m(y.slice(S));return}throw new Error(l.isClosed?`the download ended: ${k.message}`:`the server will not send even one chunk of this file in a fetch: ${k.message}`)}for(let k of b)f.push(k);g+=w};for(let y of Ic(e,t,h,Rn))await m(y);return f},a=this.limitOn("maxFetchBytes"),d=this.fetchCap,c=0;for(let l of e)c+=t(l);return this.syncing&&d<a&&c>d&&this.opts.withUploadTransport&&!this.servicingInteractive?await this.opts.withUploadTransport(l=>o(l,a,r)):await o(this.opts.transport,d)})}async transferring(e,t,i){if(t.length===0||this.opts.onTransfer===void 0)return i(void 0);let r={direction:e,files:t.length,...t.length===1?{path:t[0]}:{}},s=o=>Me(this.opts.onTransfer,{...r,bytes:o});s(0);try{return await i(s)}finally{Me(this.opts.onTransfer,void 0)}}async landFromLocal(e,t,i){let r;try{r=await this.opts.vault.read(t)}catch{return"ask"}if(r.length!==e.remote.size)return"ask";let s=this.mergeable(t),o=[...Wt(r,this.sizesFor(r.length,s),s)].map(d=>d.bytes),a=await vn(o);return Z(a)!==Z(e.chunks)?"ask":await this.createdWhereNothingWas(e,r)?"landed":await this.unchangedSince(e.path,e.based)?await this.writePreserving(e.path,this.expecting(e.baseDigest),r,{mtime:e.remote.mtime,ctime:e.remote.mtime},i,this.copyAuthor(e.remote))?"kept":(this.settled(e,r.length),"landed"):"ask"}settled(e,t){this.landed(e.path),st(e.entry,{folder:!1,mtime:e.remote.mtime,ctime:e.remote.mtime,size:t}),e.entry.chunks=[...e.chunks],e.entry.hash=Z(e.chunks),e.entry.size=t,ot(e.entry,e.entry.hash,e.entry.chunks,e.remote.uid,this.now())}async createdWhereNothingWas(e,t){let i=this.opts.vault;if(e.based!==void 0||i.create===void 0)return!1;let r={mtime:e.remote.mtime,ctime:e.remote.mtime},s=e.entry.creating;if(s!==void 0&&s.uid===e.remote.uid&&i.createDirect!==void 0){this.triedDirect.add(e);let o=await i.createDirect(e.path,t,r);return delete e.entry.creating,o?(this.settled(e,t.length),!0):!1}return await i.create(e.path,t,r)?(this.settled(e,t.length),!0):!1}async syncedDigestOf(e,t){if(t.folder||t.hash==="")return;let i=this.opts.vault,r=this.mergeable(e),s,o,a=i.contentDigest;if(i.readBlocks!==void 0&&a!==void 0&&!this.cannotStream&&t.size>Mi)try{o=await a(e);let d=[];for await(let c of En(i.readBlocks(e),this.sizesFor(t.size,r),r))d.push(await Je(c.bytes));if(o===void 0||await a(e)!==o)return;s=d}catch(d){this.cannotStream=!0,this.log("streaming is not available here, reading whole files instead",e,{why:d.message})}try{if(s===void 0){let d=await i.read(e),c=[...Wt(d,this.sizesFor(d.length,r),r)];s=await vn(c.map(l=>l.bytes)),o=await ke(d)}if(Z(s)!==t.hash){this.log("not the synced version",e,{why:"it changed without its length or timestamp moving, so what is displaced is kept"});return}return o}catch{return}}expecting(e){return e===void 0?void 0:{contentId:e,idOf:ke}}async writePreserving(e,t,i,r,s,o){let a=this.opts.vault;if(a.replace===void 0)return await a.write(e,i,r),!1;let d=await this.freeConflictPath(e,this.opts.device),c=await a.replace(e,t,i,r,d);if(c.keptAt!==void 0&&(this.log("kept what was already there",e,{why:"it changed while its next version was being fetched",keptAt:c.keptAt}),this.landed(c.keptAt),this.activity("conflict",e,c.keptAt),s.conflicted++),!c.landed){let l=await Un(()=>this.freeConflictPath(e,o),i,r,a);this.landed(l),this.log("kept the incoming version beside",e,{at:l}),this.activity("conflict",e,l),c.keptAt===void 0&&s.conflicted++}return c.keptAt!==void 0||!c.landed}async removedSomethingElse(e,t,i){let r=this.opts.vault,s=t===void 0||t.folder?void 0:i.get(e);if(r.removeExpecting===void 0){await r.remove(e);return}let o=await this.freeConflictPath(e,this.opts.device);return(await r.removeExpecting(e,this.expecting(s),o)).keptAt}async goneSinceListed(e){try{return await this.opts.vault.stat(e)===void 0}catch{return!1}}async unchangedSince(e,t){let i;try{i=await this.opts.vault.stat(e)}catch{return!1}if(t===void 0){if(i===void 0)return!0;let r=this.localByIdentity.get(this.identity(e));return r!==void 0&&this.deletingThisPass.has(r)}return i===void 0||i.folder!==t.folder?!1:i.folder?!0:i.size===t.size&&Math.ceil(i.mtime)===t.mtime}async landedOnAChangedFile(e,t,i){this.log("kept the local copy",e.path,{why:"it changed while its next version was being fetched",version:e.remote.uid});let r=this.entryFor(e.path);r.hash="",r.chunks=[],await this.conflict(e.path,r,e.remote,i,"changed during the fetch",t)}async land(e,t,i){let r=e.chunks.map(o=>{let a=t.get(o);if(!a)throw new Error(`the server did not send ${o}, which ${e.path} is made of`);return a}),s=await this.assemble(e.remote.uid,`version ${e.remote.uid} of ${e.path}`,r,e.remote.size);if(pe(e.path)&&qe(e.path)&&!_c(s)){let o=new Error("the version another device sent is not valid JSON, so it was not applied");throw o.code="badentry",o}return await this.createdWhereNothingWas(e,s)?!0:await this.unchangedSince(e.path,e.based)?await this.writePreserving(e.path,this.expecting(e.baseDigest),s,{mtime:e.remote.mtime,ctime:e.remote.mtime},i,this.copyAuthor(e.remote))?!1:(this.settled(e,s.length),!0):(await this.landedOnAChangedFile(e,s,i),!1)}settingsWaiting(){let e=[];for(let t of this.settingsHeldLastPaths){let i=this.remote.get(t);i!==void 0&&e.push({path:t,uid:i.uid,hash:i.hash,size:i.size,deleted:i.deleted,...i.device?{device:i.device}:{}})}return e}async contentOf(e,t,i){let r=await this.opts.transport.get(e);if(t!==void 0&&Z(r.chunks)!==t)throw new Error(`version ${e} is made of chunks this device did not record for it, so it is not the version it is being offered as`);if(i!==void 0&&i!==r.size)throw new Error(`version ${e} is offered as ${r.size} bytes and was listed as ${i} bytes`);let s=i??r.size;if(r.chunks.length===0){if(s!==0)throw new Error(`version ${e} declares ${s} bytes and names no chunks, which cannot both be true`);return new Uint8Array(0)}this.checkChunkCount(e,r.chunks.length);let o=Qt(r.size,r.chunks.length);return await this.assemble(e,`version ${e}`,await this.fetchAll(r.chunks,()=>o),s)}checkChunkCount(e,t){let i=this.limitOn("maxChunks");if(t>i)throw new Error(`version ${e} names ${t} chunks, and this server said it stores at most ${i}`)}async assemble(e,t,i,r){if(i.length===0){if(r!==0)throw new Error(`${t} assembled to 0 bytes, not the ${r} it declares`);return new Uint8Array(0)}let s=this.limitOn("perFileMax");if(r>s)throw new Error(`version ${e} is offered as ${r} bytes, and this server said it stores at most ${s}`);let o=new Uint8Array(r),a=0;for(let d=0;d<i.length;d++){let c=i[d];if(c===void 0)throw new Error(`version ${e} is missing one of its chunks`);if(i[d]=void 0,a+=c.length,a>s)throw new Error(`version ${e} is over ${a} bytes, and this server said it stores at most ${s}`);a<=r&&o.set(c,a-c.length)}if(a!==r)throw new Error(`${t} assembled to ${a} bytes, not the ${r} it declares`);return o}async merge(e,t,i,r){if(!i)return;if(!this.merging){await this.conflict(e,t,i,r,"merging is off on this device");return}let s;try{s=await this.contentOf(t.syncuid,t.synchash)}catch(b){if(!Oc(b))throw b;let k="the version both sides edited from has been purged from the server, so there is nothing to merge against";this.log("merge refused",e,k),await this.conflict(e,t,i,r,k);return}let o=await this.opts.vault.read(e),a=await this.opts.vault.stat(e),d=a&&{folder:a.folder,mtime:Math.ceil(a.mtime),size:a.size,hash:""},c=await this.contentOf(i.uid,i.hash,i.size),l=new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}),h,u,f;try{h=l.decode(s),u=l.decode(o),f=l.decode(c)}catch{let b="one side is not valid UTF-8, so merging it would rewrite bytes nobody edited";this.log("merge refused",e,b),await this.conflict(e,t,i,r,b);return}let g=Zr(h,u,f,Sc(e,h,u,f));if(g.kind==="conflict"){this.log("merge refused",e,g.why),await this.conflict(e,t,i,r,g.why);return}let m=g.text,y=o,w=t.mtime;if(m!==u){if(!await this.unchangedSince(e,d)){let b="it changed while the other side of the merge was being fetched";this.log("merge refused",e,b),t.hash="",t.chunks=[],await this.conflict(e,t,i,r,b,c);return}if(y=new TextEncoder().encode(m),w=this.now(),await this.writePreserving(e,{contentId:await ke(o),idOf:ke},y,{mtime:w,ctime:t.ctime},r,this.opts.device))return}Ht(t,i.hash,i.uid,this.now()),st(t,{folder:!1,mtime:w,ctime:t.ctime,size:y.length}),await this.upload(e,t,r,i.uid),r.merged++,this.log("merged",e,g.kind==="merged"?"three-way":g.why),this.activity("merged",e)}freeConflictPath(e,t){return Oe(Sn(e,t,new Date(this.now())),async i=>{let r=this.remote.get(i);return r!==void 0&&!r.deleted||await this.opts.vault.exists(i)})}copyAuthor(e){let t=e?.device;return t!==void 0&&gi(t)!==""?t:this.opts.device}async conflict(e,t,i,r,s,o){if(!i)return;let a=o??await this.contentOf(i.uid,i.hash,i.size),d=await Un(()=>this.freeConflictPath(e,this.copyAuthor(i)),a,{mtime:i.mtime,ctime:i.mtime},this.opts.vault),c=this.entryFor(d);st(c,{folder:!1,mtime:i.mtime,ctime:i.mtime,size:a.length}),await this.upload(d,c,r,this.remote.get(d)?.uid),await this.upload(e,t,r,i.uid),r.conflicted++,this.log("kept both",e,{copy:d,why:s}),this.activity("conflict",e,d)}recordFailure(e,t,i){let r=t instanceof Error?t.message:String(t),s=t?.code;if(s==="stale"){let d=this.entries.get(e);d?.prev&&se(d.prev)!==e&&(d.prev="");let c=(this.staleHeads.get(e)??this.asked.get(e)??0)+1;if(c<=wc){this.staleHeads.set(e,c),this.retries.delete(e),i.waiting++,this.again=!0,this.log("another device wrote first, reconciling next pass",e);return}this.staleHeads.delete(e),this.asked.delete(e),r=`${r} (refused as out of date ${c} times running, even after asking the server for this path's current version)`}if(t instanceof I){Ri(i,e),i.nextUploadAt=Math.min(i.nextUploadAt??1/0,this.now()+vc),this.log("will retry when the connection is back",e,r);return}if(s==="ignored"){this.ignoredPaths.has(e)||this.log("ignored here",e,r),this.ignoredPaths.set(e,r),this.pending.delete(e),i.ignored++;return}if(s!==void 0&&["badentry","badname","toolarge","neversync","badpath","collision"].includes(s)){let d=Ec(s);this.skipped.set(e,{why:d===""?r:`${/[.!?]$/.test(r)?r:`${r}.`} ${d}`,fingerprint:Oi(this.entries.get(e),this.remote.get(e)),code:s}),Kt(i,e),this.log("skipped for good",e,r),this.activity("error",e);return}let a=this.retries.get(e)??{count:0,error:"",at:0};a.count++,a.error=r,a.at=this.now()+Math.min(3e5,5e3*Math.pow(2,a.count)),this.retries.set(e,a),Ri(i,e),i.nextUploadAt=Math.min(i.nextUploadAt??1/0,a.at),this.log("will retry",e,{attempt:a.count,error:r}),this.activity("error",e)}prune(e){for(let i of this.entries.keys()){if(e.has(i))continue;let r=this.entries.get(i),s=this.remote.get(i);s&&!s.deleted||r.synchash===""&&r.hash===""&&this.entries.delete(i)}for(let i of this.remote.keys())this.remote.get(i).deleted&&(e.has(i)||this.entries.has(i)||this.pending.has(i)||(this.remote.delete(i),this.staleHeads.delete(i),this.asked.delete(i),this.refusedInbound.delete(i)));let t=e.size+this.entries.size+this.remote.size;if(this.refusalOf.size>t||this.identityOf.size>t){let i=new Set([...e.keys(),...this.entries.keys(),...this.remote.keys()]);for(let r of[this.refusalOf,this.identityOf])for(let s of r.keys())i.has(s)||r.delete(s)}}async save(){let e=Object.create(null);for(let[i,r]of this.entries)e[i]=hc(r);let t=Object.create(null);for(let[i,r]of this.remote)t[i]=r;await this.opts.store.save({cursor:this.cursor,...this.epoch!==void 0?{epoch:this.epoch}:{},entries:e,remote:t,pending:[...this.pending]}),this.writtenSinceSave=0,this.checkpointedAt=Date.now()}recordScannedRenames(e,t){if(!this.sending)return;let i=(a,d)=>{let c=ee(d),l=a.get(c);l?l.push(d):a.set(c,[d])},r=new Map;for(let[a,d]of this.entries){if(e.has(a)||t.has(a)||d.prev!=="")continue;let c=d.folder?d.synctime>0:d.synchash!=="",l=this.remote.get(a);!c||d.syncuid<=0||l===void 0||l.deleted||l.uid!==d.syncuid||l.folder!==d.folder||i(r,a)}if(r.size===0)return;let s=new Set;for(let a of this.entries.values())a.prev!==""&&s.add(se(a.prev));let o=new Map;for(let a of e.keys()){let d=ee(a);if(!r.has(d))continue;let c=this.entries.get(a);c&&(c.syncuid>0||c.synchash!==""||c.prev!=="")||i(o,a)}for(let[a,d]of o){let c=r.get(a);if(d.length!==1||c.length!==1)continue;let l=d[0],h=c[0];s.has(h)||this.neverSyncsHere(l)||e.get(l).folder===this.entries.get(h).folder&&(this.log("a rename that changed only case, found by the scan",h,l),this.skipped.delete(l),this.retries.delete(l),this.movePath(h,l))}}noteRename(e,t){if(this.neverSyncsHere(t)){this.log("rename into a path that never syncs, not recorded",e,t);return}this.movePath(e,t);let i=`${e}/`,r=new Set([...this.entries.keys(),...this.retries.keys(),...this.skipped.keys()]);for(let s of r)s.startsWith(i)&&this.movePath(s,t+s.slice(e.length))}movePath(e,t){this.moveEntry(e,t);let i=this.retries.get(e);i!==void 0&&(this.retries.delete(e),this.retries.set(t,i));let r=this.skipped.get(e);r!==void 0&&(this.skipped.delete(e),this.skipped.set(t,r))}moveEntry(e,t){let i=this.entries.get(e);if(!i)return;let r=this.entries.get(t),s={...i,chunks:[...i.chunks],synchash:r?.synchash??"",syncuid:r?.syncuid??0};fs(s,e,t),this.entries.set(t,s)}};function Ui(n,e){return{uploaded:n.uploaded+e.uploaded,downloaded:n.downloaded+e.downloaded,merged:n.merged+e.merged,conflicted:n.conflicted+e.conflicted,deletedLocally:n.deletedLocally+e.deletedLocally,deletedRemotely:n.deletedRemotely+e.deletedRemotely,restored:n.restored+e.restored,foldersCreated:n.foldersCreated+e.foldersCreated,foldersDeletedLocally:n.foldersDeletedLocally+e.foldersDeletedLocally,foldersDeletedRemotely:n.foldersDeletedRemotely+e.foldersDeletedRemotely,chunksSent:n.chunksSent+e.chunksSent,reusedChunks:n.reusedChunks+e.reusedChunks,...n.phases||e.phases?{phases:kc(n.phases,e.phases)}:{},bytesSent:n.bytesSent+e.bytesSent,unchanged:e.unchanged,waiting:e.waiting,...e.nextUploadAt!==void 0?{nextUploadAt:e.nextUploadAt}:{},...e.appliedCursor!==void 0?{appliedCursor:e.appliedCursor}:{},retrying:e.retrying,skipped:e.skipped,skippedPaths:e.skippedPaths,retryingPaths:e.retryingPaths,heldBack:e.heldBack,heldBackPaths:e.heldBackPaths,settingsHeld:e.settingsHeld,settingsHeldPaths:e.settingsHeldPaths,ignored:e.ignored,blocked:e.blocked,inTheWay:e.inTheWay,needsAttention:e.needsAttention}}function Cc(n,e){if(n!==void 0&&!(!e||e.uid!==n))return{uid:n,hash:e.hash}}function Sc(n,e,t,i){if(qe(n))return zi;if(os(n))return as(e,t,i);if(cs(n))return ds;if(Ir(n))return jt(e)&&jt(t)&&jt(i)?jt:void 0}function Hs(n,e=!1){let t=pe(n)?bn(n,!0):Fr(n);if(t===void 0){let i=e?ls(n):void 0;return i===void 0?void 0:hs(i)}if(t==="slash")return n.startsWith("/")?"a path starting with a slash is not canonical":"a path ending with a slash is not canonical";if(t==="dotsegment"){let i=n.split("/").find(r=>r==="."||r==="..")??".";return`a path with a ${JSON.stringify(i)} segment is not canonical`}return Fc[t]}var Fc={utf8:"a path that is not valid UTF-8",empty:"an empty path",toolong:"a path longer than the 1024 bytes the server holds",segmenttoolong:"a path with a name longer than the 255 bytes Android and Linux can hold",control:"a path with a control character in it",nfc:"a path that is not in Unicode NFC",nbsp:"a path with a no-break space in it, which Obsidian would turn into a space",backslash:"a path with a backslash in it, which Obsidian would turn into a slash",slash:"a path starting or ending with a slash is not canonical",emptysegment:"a path with an empty segment (//) is not canonical",dotsegment:"a path with a . or .. segment is not canonical",dotprefix:"a path under a dot-prefixed name never syncs",staging:"a path carrying the name the vaults give files they are staging",devicelocal:"a path holding one device's own state in its settings, which never syncs",configscope:"a path in a settings folder that settings sync does not carry"};function Oi(n,e){let t=e?.uid??0;return n?`${n.mtime}:${n.size}:${t}`:`gone:${t}`}var Mi=8*1024*1024,xc=1024*1024,Bc=4096,Pc=200,$c=8*1024*1024,Dc=Ct,Tc=3e4;function Qt(n,e){return Math.ceil(n/Math.max(1,e))}function Ic(n,e,t,i){let r=[],s=[],o=0;for(let a of n){let d=e(a);s.length>0&&(o+d>t||s.length>=i)&&(r.push(s),s=[],o=0),s.push(a),o+=d}return s.length>0&&r.push(s),r}async function Un(n,e,t,i){for(let r=0;r<100;r++){let s=await n();if(!i.create)return await i.write(s,e,t),s;if(await i.create(s,e,t))return s}throw new Error("could not find a name beside the note that stayed free long enough to use")}function Rc(n,e){let t=new Error(`${n} bytes, and this server said it stores at most ${e}, so it was not read`);return t.code="toolarge",t}function Vs(n){return ee(n).toUpperCase()}function Ni(n){let e=t=>t.split("/").length;return[...new Set(n)].sort((t,i)=>e(i)-e(t)||(t<i?-1:t>i?1:0))}async function _i(n){throw new Error(`this put has no bodies, and the server asked for ${n}`)}function Oc(n){let e=n?.code;return e==="nouid"||e==="nochunk"||e==="nocontent"}var Mc=1e3,Nc=1e4;function _c(n){try{return zi(new TextDecoder("utf-8",{fatal:!0}).decode(n))}catch{return!1}}function zi(n){try{return JSON.parse(n),!0}catch{return!1}}function Gs(n){return JSON.stringify(n,(e,t)=>t!==null&&typeof t=="object"&&!Array.isArray(t)?Object.fromEntries(Object.entries(t).sort(([i],[r])=>i<r?-1:i>r?1:0)):t)}Re();function Wn(n){let e=4294967295;for(let t of n){e^=t;for(let i=0;i<8;i++)e=e&1?e>>>1^3988292384:e>>>1}return(e^4294967295)>>>0}function Wi(n){let e=Wn(n);return new Uint8Array([e>>>24&255,e>>>16&255,e>>>8&255,e&255])}Re();var xt="trew1i_",Ji=1,ct=16,qs=64,ji=new TextEncoder,Lc=new TextDecoder("utf-8",{fatal:!0});function Xs(n){let e=n.startsWith("wss://")?n.slice(6):n.startsWith("ws://")?n.slice(5):void 0;if(e===void 0||e==="")throw new Error(`the server address ${JSON.stringify(n)} is not ws:// or wss://`);if(!/^[\x21-\x7e]+$/.test(n))throw new Error("the server address has a character outside printable ASCII");if(n.endsWith("/")||n.length>255)throw new Error(`the server address ${JSON.stringify(n)} is not in canonical form`)}function Ys(n){let e=ji.encode(n).length;if(n===""||e>qs||/[\x00-\x1f\x7f]/.test(n))throw new Error(`the vault name is empty, over ${qs} bytes, or has a control character`)}function Ks(n){if(n.token.length!==ct)throw new Error(`an invite token is ${ct} bytes, not ${n.token.length}`);Xs(n.url),Ys(n.vault);let e=ji.encode(n.url),t=ji.encode(n.vault),i=new Uint8Array(1+ct+1+e.length+1+t.length),r=0;i[r++]=Ji,i.set(n.token,r),r+=ct,i[r++]=e.length,i.set(e,r),r+=e.length,i[r++]=t.length,i.set(t,r);let s=new Uint8Array(i.length+4);return s.set(i,0),s.set(Wi(i),i.length),xt+je(s)}function Zs(n){let e=n.replace(/^[ \t\r\n]+|[ \t\r\n]+$/g,"");if(!e.startsWith(xt))throw new Error(`not an invite: it should start with ${xt}`);let t;try{t=He(e.slice(xt.length))}catch(c){throw new Error(`this invite is damaged: ${c.message}`)}if(t.length<1+ct+2+4)throw new Error("this invite is too short to be complete");let i=t.subarray(0,t.length-4),r=Wi(i);for(let c=0;c<4;c++)if(t[i.length+c]!==r[c])throw new Error("this invite is damaged: it did not survive being copied");if(i[0]!==Ji)throw new Error(`this invite is version ${i[0]}, and this device understands ${Ji}`);let s=1+ct,o=[];for(let c of["server address","vault name"]){if(s>=i.length)throw new Error(`this invite ends before its ${c}`);let l=i[s++];if(s+l>i.length)throw new Error(`this invite ends inside its ${c}`);try{o.push(Lc.decode(i.subarray(s,s+l)))}catch{throw new Error(`this invite's ${c} is not UTF-8`)}s+=l}if(s!==i.length)throw new Error("this invite has more in it than it should");let[a,d]=o;return Xs(a),Ys(d),{token:i.slice(1,1+ct),url:a,vault:d}}Re();var Uc=16,eo=32,zc=16;function Wc(){for(;;){let n=je(Lt(Uc));if(!n.startsWith("-"))return n}}function Jc(){return je(Lt(eo))}var jc=".obsidian",Hc=[jc,".obsidian-mobile",".obsidian-desktop"];function Vc(n){return Hc.includes(n)}function Ue(n){return typeof n.invite=="string"}function to(n,e,t={}){return{url:n.url,vaultId:n.vault,device:e,invite:je(n.token),deviceId:Wc(),deviceToken:Jc(),...t.readOnly===!0?{readOnly:!0}:{},...t.ignore?.length?{ignore:t.ignore}:{}}}function no(n){return{url:n.url,vaultId:n.vaultId,device:n.device,deviceId:n.deviceId,deviceToken:n.deviceToken,...n.readOnly===!0?{readOnly:!0}:{},...n.ignore?.length?{ignore:n.ignore}:{}}}var Le=class extends Error{};function io(n){if(Ue(n))throw new Le("this device's pairing has not finished: the invite was sent and no answer has been heard. Pairing again finishes it with the credential already saved here.");let e=[];if(n.deviceId||e.push("a device id"),n.deviceToken||e.push("a device token"),e.length>0||!n.deviceId||!n.deviceToken)throw new Le(`this device has no credential for the vault: it is missing ${e.join(" and ")}. Pair this vault again with an invite, from another device or from trewd invite on the server.`);return{deviceId:n.deviceId,deviceToken:n.deviceToken}}function en(n){return{url:n.url,vaultId:n.vaultId,device:n.device,...n.deviceId?{deviceId:n.deviceId}:{},...n.deviceToken?{deviceToken:n.deviceToken}:{},...Ue(n)?{invite:n.invite}:{},...n.readOnly===!0?{readOnly:"true"}:{},...n.ignore?.length?{ignore:JSON.stringify(n.ignore)}:{},...n.settings!==void 0?{settings:n.settings}:{},...n.settingsFirstChoice?{settingsFirstChoice:n.settingsFirstChoice}:{},...n.settingsReplay===!0?{settingsReplay:"true"}:{},...n.settingsPlugins===!0?{settingsPlugins:"true"}:{}}}function Gc(n){return n!==""&&n!=="."&&n!==".."&&!n.includes("/")}function qc(n){let e=n.ignore;if(typeof e!="string"||e==="")return{};let t;try{t=JSON.parse(e)}catch{return{}}if(!Array.isArray(t))return{};let i=t.filter(r=>typeof r=="string"&&Gc(r));return i.length>0?{ignore:[...new Set(i)]}:{}}function ro(n,e){if(typeof n!="object"||n===null)throw new Error(`${e} does not hold a configuration`);let t=n,i=s=>{let o=t[s];if(typeof o!="string"||o==="")throw new Error(`${e} has no ${s}`);return o},r={url:i("url"),vaultId:i("vaultId"),device:i("device"),...Xc(t,e),...Qs(t,"deviceToken",eo,"a device token",e),...Qs(t,"invite",zc,"an invite token",e),...t.readOnly==="true"?{readOnly:!0}:{},...qc(t),...Vc(t.settings)?{settings:t.settings}:{},...t.settingsFirstChoice==="server"||t.settingsFirstChoice==="device"?{settingsFirstChoice:t.settingsFirstChoice}:{},...t.settingsReplay==="true"?{settingsReplay:!0}:{},...t.settingsPlugins==="true"?{settingsPlugins:!0}:{}};if(r.deviceId===void 0)throw new Error(`${e} holds no device id, so there is nothing in it to connect with or to finish`);if(r.invite!==void 0&&r.deviceToken===void 0)throw new Error(`${e} holds a pairing in progress with no device token, so it cannot be finished`);return r}function Xc(n,e){let t=n.deviceId;if(t==null)return{};if(typeof t!="string"||!/^[A-Za-z0-9_-]{1,64}$/.test(t))throw new Error(`${e} holds a deviceId that is not base64url of at most 64 characters, which is not an id any server would answer to`);return{deviceId:t}}function Qs(n,e,t,i,r){let s=n[e];if(s==null)return{};if(typeof s!="string"||s==="")throw new Error(`${r} holds a ${e} that is not a string`);let o;try{o=He(s)}catch(a){throw new Error(`${r} holds a ${e} that is not base64url: ${a.message}`)}if(o.length!==t)throw new Error(`${r} holds a ${o.length} byte ${e}, and ${i} is ${t} bytes`);return{[e]:s}}function so(n){let e=n.trim();if(e.startsWith("basalt3_")||e.startsWith("basalt3i_"))throw new Error("that is a Basalt string, and TrewSync does not read them. Pair with a trew1i_ invite: trewd invite on the server makes one, and so does a paired device's panel.");return Zs(n)}var Yc=0,Se=class extends Error{constructor(t,i){super(i);this.code=t}code},tn=class{constructor(e){this.opts=e;let t;this.transport=new St(e.url,{onBatch:async i=>{this.lastBatchAt=Date.now(),this.backlogChanged(),await t.acceptBatch(i),this.reportCatchUp(),i.entries.length>0&&e.inspect!==!0&&this.soon()},onCaughtUp:()=>{this.caughtUp=!0,this.backlogChanged()},onClosed:i=>{this.uploadTransport?.close(),this.endedWith=i,this.backlogChanged(),this.notifyEnded?.(i)},...e.timeoutMs!==void 0?{timeoutMs:e.timeoutMs}:{},...e.log!==void 0?{log:e.log}:{},...e.socketFactory!==void 0?{socketFactory:e.socketFactory}:{}}),t=new Ln({vault:e.vault,store:e.store,transport:this.transport,withUploadTransport:i=>this.withUploadTransport(i),releaseUploadTransport:()=>this.releaseUploadTransport(),device:e.device,vaultId:e.vaultId,deviceId:e.deviceId,token:e.token,...e.coalesceWrites!==void 0?{coalesceWrites:e.coalesceWrites}:{},...e.timing!==void 0?{timing:e.timing}:{},...e.merge!==void 0?{merge:e.merge}:{},...e.readOnly!==void 0?{readOnly:e.readOnly}:{},...e.windows!==void 0?{windows:e.windows}:{},...e.settings!==void 0?{settings:e.settings}:{},...e.loadId!==void 0?{loadId:e.loadId}:{},...e.replayAll===!0?{replayAll:!0}:{},...e.log!==void 0?{log:e.log}:{},...e.confirmFirstSync?{confirmFirstSync:e.confirmFirstSync}:{},...e.confirmDeletions?{confirmDeletions:e.confirmDeletions}:{},...e.onActivity!==void 0?{onActivity:e.onActivity}:{},...e.onProgress!==void 0?{onProgress:e.onProgress}:{},...e.onTransfer!==void 0?{onTransfer:e.onTransfer}:{},...e.activePath!==void 0?{activePath:e.activePath}:{}}),this.engine=t}opts;engine;transport;uploadTransport;limits;soonTimer;uploadTimer;nextUploadAt;reportedCursor;confirmedPass=!1;watching=!1;caughtUp=!1;lastBatchAt=Date.now();backlogWaiters=new Set;endedWith;notifyEnded;get vault(){return this.opts.vault}async withUploadTransport(e){if(this.closing||this.transport.isClosed)throw new I("this client has closed");if(this.uploadTransport&&!this.uploadTransport.isClosed)try{return await this.completeUpload(e,this.uploadTransport)}catch(i){throw this.releaseUploadTransport(),i}let t=new St(this.opts.url,{onBatch:()=>{},...this.opts.timeoutMs!==void 0?{timeoutMs:this.opts.timeoutMs}:{},...this.opts.socketFactory?{socketFactory:this.opts.socketFactory}:{}});this.uploadTransport=t;try{await t.connect();let i=this.engine.status().cursor,r=await t.hello({vault:this.opts.vaultId,deviceId:this.opts.deviceId,token:this.opts.token,device:this.opts.device,cursor:i,epoch:this.limits?.epoch});if(t.historyReplaced||r.epoch!==this.limits?.epoch)throw new Error("the server's history changed under this connection; reconnect sync");if(r.cursor<i)throw new C("cursor","upload server is behind this device");for(let s of["perFileMax","chunkMax","maxChunks","maxBatchBytes","maxFetchBytes"])if(r[s]!==this.limits?.[s])throw new Error("upload server limits changed; reconnect sync");if(this.closing||this.transport.isClosed)throw new I("this client has closed");return await this.completeUpload(e,t)}catch(i){throw this.releaseUploadTransport(),i}}releaseUploadTransport(){this.uploadTransport?.close(),this.uploadTransport=void 0}async completeUpload(e,t){let i=await e(t);return await this.transport.ping(),await this.transport.drainReceived(),i}queue=Promise.resolve();serial(e){let t=this.queue.then(e,e);return this.queue=t.catch(()=>{}),t}initiallySettled=!1;pendingMutations=0;cancelMutations=new Set;get writeReady(){return this.initiallySettled&&this.limits!==void 0&&!this.closing&&!this.endedWith&&!this.transport.isClosed&&!this.opts.inspect&&!this.opts.readOnly}mutateLocal(e,t={}){let i=t.waitMs??5e3;if(!Number.isSafeInteger(i)||i<0||i>5e3||this.pendingMutations>=16)return Promise.reject(new Se("busy","the local mutation queue is full"));this.pendingMutations++;let r=Date.now()+i,s=new Set,o=!1,a,d,c,l,h=new Promise((w,b)=>{c=w,l=b}),u=()=>{clearTimeout(d),t.signal?.removeEventListener("abort",g),this.cancelMutations.delete(m)},f=w=>{o||a||(a=w,u(),l(w))},g=()=>f(new Se("cancelled","cancelled before the local write started")),m=()=>f(new Se("stopping","the client is stopping"));return this.cancelMutations.add(m),t.signal?.addEventListener("abort",g,{once:!0}),t.signal?.aborted&&g(),a||(d=setTimeout(()=>f(new Se("busy","the local write did not start before its queue deadline")),i)),this.serial(async()=>{if(a)throw a;if(this.closing)throw new Se("stopping","the client is stopping");if(this.opts.inspect||this.opts.readOnly)throw new Se("read_only","this client does not permit local agent writes");if(!this.writeReady)throw new Se("not_ready","wait for the initial sync and a live connection before editing");if(t.signal?.aborted)throw new Se("cancelled","cancelled before the local write started");if(Date.now()>=r)throw new Se("busy","the local write did not start before its queue deadline");o=!0,u();try{return await e({vault:this.opts.vault,changed:w=>{s.add(w)}})}finally{for(let w of s)this.noteChanged(w)}}).then(c,l).finally(()=>{u(),this.pendingMutations--,s.size>0&&!this.closing&&!this.endedWith&&!this.transport.isClosed&&this.sync()}),h}get serverCursor(){return Math.max(this.limits?.cursor??0,this.transport.appliedCursor)}get deliveryReady(){return!this.closing&&this.confirmedPass&&this.reportedCursor===this.serverCursor}get serverLimits(){return this.limits}async connect(e={}){return await this.transport.connect(),this.lastBatchAt=Date.now(),this.limits=await this.engine.start(),e.waitForBacklog===!1?this.limits:(this.reportCatchUp(),await this.waitForBacklog(),this.limits)}backlogChanged(){for(let e of this.backlogWaiters)e()}waitForBacklog(){let e=this.opts.timeoutMs??3e4;return new Promise((t,i)=>{let r,s=()=>{clearTimeout(r);let o=e-(Date.now()-this.lastBatchAt);if(!this.caughtUp&&!this.endedWith&&o>0){r=setTimeout(s,o);return}this.backlogWaiters.delete(s),this.endedWith?i(this.endedWith):this.caughtUp?t():i(new Error("the server never finished sending what it already had"))};this.backlogWaiters.add(s),s()})}reportCatchUp(){!this.limits||this.caughtUp||this.closing||this.transport.isClosed||this.opts.onCatchUp?.({local:this.engine.status().cursor,server:this.serverCursor})}async settle(e={},t=8){let i=await this.pass(e),r=i;for(let s=0;s<t&&Vi(i);s++)i=await this.pass(e),r=Ui(r,i);return this.initiallySettled=!0,r}pass(e,t){return this.serial(async()=>{if(t?.(),this.closing)throw new I("this client has been closed");this.confirmedPass=!1,this.opts.onSyncStart?.();let i=await this.engine.sync(e);return i.appliedCursor!==void 0&&i.appliedCursor!==this.reportedCursor&&(await this.transport.applied(i.appliedCursor),this.reportedCursor=i.appliedCursor),this.confirmedPass=i.appliedCursor!==void 0,this.nextUploadAt=i.nextUploadAt,this.scheduleUpload(),this.opts.onPass?.(i),i})}async drain(){let e;for(;this.queue!==e;)e=this.queue,await e}async runUntilClosed(e=3e4){if(this.endedWith)return this.endedWith;this.watching=!0,this.scheduleUpload();let t=this.opts.vault.watch?.(s=>{this.noteChanged(s),this.sync()}),i=setInterval(()=>{this.sync({forceFullScan:!0}).then(()=>this.keepalive())},e),r;try{r=await new Promise(s=>{this.notifyEnded=s})}finally{this.watching=!1,this.clearUploadTimer(),clearInterval(i),t?.()}return await this.drain(),r}async keepalive(){try{await this.serial(()=>this.transport.ping())}catch{}}probe(){return this.serial(()=>this.transport.probe())}soon(){!this.caughtUp||this.soonTimer!==void 0||(this.soonTimer=setTimeout(()=>{this.transport.drainReceived().then(()=>{this.soonTimer=void 0,this.closing||this.sync()},()=>{this.soonTimer=void 0})},Yc))}clearUploadTimer(){clearTimeout(this.uploadTimer),this.uploadTimer=void 0}scheduleUpload(){this.clearUploadTimer(),!(!this.watching||this.closing||this.transport.isClosed||this.nextUploadAt===void 0)&&(this.uploadTimer=setTimeout(()=>{this.uploadTimer=void 0,this.watching&&!this.closing&&!this.transport.isClosed&&this.sync()},Math.max(0,this.nextUploadAt-Date.now())))}queued;async sync(e={}){if(this.opts.inspect===!0)throw new Error("this client is connected to read, not to sync: an inspection command cannot write to the vault, because it does not hold the lock that makes writing safe");let t=JSON.stringify(e);if(this.queued!==void 0&&this.queuedKey===t)return this.queued;let i=(async()=>{try{return await this.pass(e,()=>{this.queued===i&&(this.queued=void 0,this.queuedKey=void 0)})}catch(r){this.opts.log?.("sync failed",r.message),this.opts.onSyncFailed?.(r);return}})();return this.queued=i,this.queuedKey=t,i}queuedKey;noteRename(e,t){return this.serial(async()=>this.engine.noteRename(e,t))}noteChanged(e){this.engine.noteChanged(e)}async history(e,t={}){let i=await this.serial(()=>this.transport.history(e,t));return this.recoveryIsWellFormed(i),this.recoveryIsAboutThisPath(i,e,t.before),i.map(r=>this.asVersion(r,e,r.prev))}recoveryIsAboutThisPath(e,t,i){let r;for(let s of e){if(s.path!==t)throw new Error(`the server answered a history request for ${t} with a version of some other note, and it is not shown`);if(i!==void 0&&s.uid>=i)throw new Error(`the server answered a history request for versions of ${t} older than ${i} with version ${s.uid}, and it is not shown`);if(r!==void 0&&s.uid>=r)throw new Error(`the server answered a history request for ${t} with versions out of order (${s.uid} after ${r}), and it is not shown`);r=s.uid}}recoveryIsWellFormed(e){for(let t of e)try{_n(t)}catch(i){throw new Error(`${i.message}, and it is not shown`)}}async repair(){return this.serial(()=>this.engine.repair())}async deleted(e,t){let i=await this.serial(()=>this.transport.deleted(e,t));this.recoveryIsWellFormed(i.entries);let r=[],s;for(let o of i.entries){if(t!==void 0&&t>0&&o.uid>=t)throw new Error(`the server answered a request for deletions older than ${t} with version ${o.uid}, and it is not shown`);if(s!==void 0&&o.uid>=s)throw new Error(`the server answered with deletions out of order (${o.uid} after ${s}), and they are not shown`);s=o.uid,r.push({...this.asVersion(o,o.path),restorable:o.restorable??0})}return{notes:r,more:i.more,...s!==void 0?{oldest:s}:{}}}async contentAt(e){return e.deleted||e.folder?new Uint8Array(0):this.serial(()=>this.engine.contentOf(e.uid,e.contentId,e.size))}preview(e){return this.serial(()=>this.engine.preview(e))}reviewConflict(e){return this.serial(()=>ns(this.opts.vault,e))}resolveConflict(e,t,i){return this.serial(async()=>{if(this.closing)throw new Error("This client is closed.");if(this.opts.readOnly)throw new Error("Turn off receive-only mode before resolving conflicts.");await is(this.opts.vault,this.opts.device,e,t,i),t!=="original"&&pe(e.original)&&this.engine.settingResolved(e.original),this.engine.noteChanged(e.original),this.engine.noteChanged(e.copy);try{this.opts.onActivity?.({at:Date.now(),action:"resolved",path:e.original,copy:e.copy})}catch{}})}async restore(e,t){return this.serial(async()=>{if(this.closing)throw new Error("this client is closed");if(e.deleted)throw new Error(`version ${e.uid} of ${e.path} is the deletion itself, not a version to restore`);if(e.folder){let c=t??e.path;return await this.opts.vault.mkdir(c),{path:c,bytes:0}}let i=await this.engine.contentOf(e.uid,e.contentId,e.size),r=t??e.path,s=this.opts.vault,o=c=>s.exists(c),a={mtime:e.mtime,ctime:e.ctime};return{path:await Un(async()=>await o(r)?Oe(Kc(r,e),o):r,i,a,s),bytes:i.length}})}async newestContentVersion(e){return this.findVersion(e,t=>!t.deleted)}async findVersion(e,t,i=100){let r;for(;;){let s=await this.history(e,r===void 0?{limit:i}:{before:r,limit:i}),o=s.find(t);if(o)return o;if(s.length<i)return;let a=s[s.length-1].uid;if(r!==void 0&&a>=r)throw new Error(`the server is not paging back through the versions of ${e}: it answered a request for versions older than ${r} with a page ending at ${a}`);r=a}}asVersion(e,t,i){return{uid:e.uid,path:t,...i!==void 0&&i!==t?{previousPath:i}:{},size:e.size,ctime:e.ctime,mtime:e.mtime,folder:e.folder,deleted:e.deleted,device:e.device,chunks:e.chunks.length,contentId:Z(e.chunks),...e.op!==void 0?{operation:e.op}:{}}}async invite(e={}){let t=await this.serial(()=>this.transport.invite({...e.ttlMs!==void 0?{ttlMs:e.ttlMs}:{},...e.label!==void 0?{label:e.label}:{}}));return{invite:Ks({token:He(t.token),url:this.opts.url,vault:this.opts.vaultId}),id:t.invite,expiresAt:t.expiresAt}}async undo(e,t={}){await this.settle({coalesceWrites:!1});let i=await this.serial(()=>this.transport.undo(e,t));return await this.settle({coalesceWrites:!1}),i}async search(e){return this.serial(()=>this.transport.search(e))}async devices(){return this.serial(()=>this.transport.devices())}async uninvite(e){return this.serial(()=>this.transport.uninvite(e))}async revoke(e){return this.serial(()=>this.transport.revoke({deviceId:e}))}async rename(e){return this.serial(()=>this.transport.rename(e))}get deviceId(){return this.opts.deviceId}closing=!1;async close(){this.closing=!0;for(let e of this.cancelMutations)e();this.clearUploadTimer(),this.soonTimer!==void 0&&(clearTimeout(this.soonTimer),this.soonTimer=void 0),this.transport.close(),this.uploadTransport?.close(),await this.drain()}};function Kc(n,e){let{stem:t,ext:i}=rt(n);return An(t,` (restored ${e.uid})`,i)}var Zc=3;async function oo(n,e={}){let t=new On(0,3e5,5e3,!0),i,r=!1,s=async d=>{if(e.keepGoing?.()??!0){if(r){r=!1;return}await new Promise(c=>{let l=!1,h,u=()=>{l||(l=!0,clearTimeout(h),r=!1,i=void 0,c())};i=u,e.sleep?e.sleep(d).then(u):h=setTimeout(u,d)})}};e.onWaiting?.(()=>{t.success(),r=!0,i?.()});let o="",a=0;for(;e.keepGoing?.()??!0;){let d,c,l=!1;try{if(d=new tn(n),e.onConnecting?.(d),await d.connect(),l=!0,!(e.keepGoing?.()??!0))return;e.onClient?.(d);let f=await d.settle();t.success(),e.onSynced?.(f,d.serverCursor),c=await d.runUntilClosed()}catch(f){c=f}finally{e.onClient?.(void 0),await d?.close()}if(c&&Qc(c)){e.onFatal?.(c);return}if(c&&!(c instanceof I)&&!(c instanceof C)){if(a=c.message===o?a+1:1,o=c.message,a>=Zc){e.onFatal?.(new Error(`${c.message}. This has failed ${a} times in a row with this device at cursor ${d?.engine.status().cursor??0}, so waiting will not help; docs/server.md says how to recover from an entry no device can apply`));return}}else a=0,o="";if(!(e.keepGoing?.()??!0))return;t.fail();let h=c??new Error("the connection ended"),u=el(h,t.delay());l?e.onDisconnected?.(h,u):e.onUnreachable?.(h,u),await s(u)}}function Qc(n){return n instanceof C&&n.fatal}function el(n,e,t=Math.random){let i=n instanceof C?n.retryAfterMs??0:0;return e>=i?e:Math.floor(i*(1+.5*t()))}var Hi=class extends I{constructor(t,i){super(t);this.pending=i;this.name="PairingInterrupted"}pending};async function ao(n,e,t={}){await e.save(n);let i=new St(n.url,{onBatch:()=>{},...t.timeoutMs!==void 0?{timeoutMs:t.timeoutMs}:{},...t.socketFactory!==void 0?{socketFactory:t.socketFactory}:{},...t.log!==void 0?{log:t.log}:{}}),r=!1;try{await i.connect(),r=!0,t.onSent?.(),await i.redeem({vault:n.vaultId,device:n.device,invite:n.invite,deviceId:n.deviceId,token:n.deviceToken})}catch(o){let a=o instanceof Error?o:new Error(String(o)),d=a instanceof C&&!a.retryable,c=!r&&t.resuming!==!0;if(!d&&!c){let l=a instanceof C?`the server could not take the pairing just now (${a.message})`:r?`the invite was sent and no answer came back (${a.message}), so whether the server registered this device is not known`:`the server could not be reached (${a.message}), and an earlier attempt may have registered this device`;throw new Hi(`${l}. The pairing is kept, and trying again finishes it with the same credential.`,n)}try{await e.forget()}catch(l){throw new Error(`${a.message}; and the pairing saved before it was sent could not be removed: `+l.message,{cause:a})}throw a}finally{i.close()}let s=no(n);return await e.save(s),t.log?.("paired",{deviceId:s.deviceId}),s}async function co(n){let e;try{e=await n()}catch(t){return{kind:"unreadable",why:t.message}}return e===void 0?{kind:"nothing"}:Ue(e)?{kind:"pending",config:e}:{kind:"credential",config:e}}function lo(n){let{remains:e,surface:t,where:i}=n,r=t==="cli";switch(e.kind){case"credential":return r?`This device is paired with the vault and ${i} holds its credential; run trew sync here to finish, or trew unlink to start again.`:"This device is paired with the vault; TrewSync will connect as it on the next attempt.";case"pending":return r?`The invite was sent and no answer came back, so whether the server registered this device is not known. ${i} holds the pairing: run trew pair here again to finish it with the same credential, which works even after the invite has expired if the server did register it.`:"The invite was sent and no answer came back, so whether the server registered this device is not known. TrewSync will finish the pairing with the same credential the next time it connects.";case"unreadable":return`${i} could not be read (${e.why}), so what this device holds is not known and nothing should be revoked on the strength of it: a credential that was written and cannot be read back is still the only copy of its row's token. Fix that first, `+(r?"then trew status here says whether this device has one.":"then reload the plugin, which says whether this device has one.");default:return"Nothing was registered and nothing is saved here, so the invite was not spent by this attempt. Pair again with it, or with a new one if it has expired."}}function ho(n){let{deviceId:e,deviceToken:t}=io(n);return{url:n.url,token:t,deviceId:e,vaultId:n.vaultId,device:n.device}}function Vi(n){return n.uploaded+n.downloaded+n.merged+n.conflicted+n.deletedLocally+n.deletedRemotely+n.restored+n.foldersCreated+n.foldersDeletedLocally+n.foldersDeletedRemotely>0}function nn(n){return n.skipped+n.blocked}function uo(n,e=""){let t=n.needsAttention??[],i=new Map;for(let{path:o,why:a}of t){let d=i.get(a);d?d.push(o):i.set(a,[o])}let r=[];for(let[o,a]of i)r.push(`${e}${a.sort().join(", ")}: ${o}`);let s=nn(n)-t.length;return s>0&&r.push(`${e}and ${s} more.`),r}import{mkdir as Wo,readFile as Jo,rm as cn,stat as jo}from"node:fs/promises";import{join as ve}from"node:path";var go=new TextEncoder;function po(n,e){if(!Number.isSafeInteger(n)||n<1)throw new Error(`a journal sequence must be a positive integer, not ${n}`);let t=JSON.stringify(e),i=Wn(go.encode(t)).toString(16).padStart(8,"0");return`${n} ${i} ${t}
18
+ `}function tl(n){if(n.includes("\0"))return{why:"torn"};let e=n.indexOf(" "),t=n.indexOf(" ",e+1);if(e<1||t<0)return{why:"unparsable"};let i=Number(n.slice(0,e));if(!Number.isSafeInteger(i)||i<1)return{why:"unparsable"};let r=n.slice(e+1,t),s=n.slice(t+1);if(!/^[0-9a-f]{8}$/.test(r))return{why:"unparsable"};if(Wn(go.encode(s)).toString(16).padStart(8,"0")!==r)return{why:"checksum"};let o;try{o=JSON.parse(s)}catch{return{why:"unparsable"}}return o===null||typeof o!="object"||Array.isArray(o)?{why:"unparsable"}:{seq:i,delta:o}}function nl(n){return n.why!==void 0}function mo(n,e){let t=n.state,i=n.seq,r=0,s={why:"end"},o=!0,a,d=e.split(`
19
+ `),c=d.slice(0,-1),l=d[d.length-1]??"";for(let u=0;u<c.length;u++){let f=c[u];if(f===""){s={why:"torn",at:u};break}let g=tl(f);if(nl(g)){s={why:g.why,at:u};break}if(!(g.seq<=n.seq)){if(g.seq<=i){s={why:"out-of-order",at:u,seq:g.seq};break}if(o&&g.seq!==n.seq+1){s={why:"gap",at:u,seq:g.seq,after:n.seq};break}o=!1,a??=il(t),rl(a,g.delta),i=g.seq,r++}}return s.why==="end"&&l!==""&&(s={why:"torn",at:c.length}),{state:a===void 0?t:a,seq:i,applied:r,stopped:s}}function il(n){let e=n??{};return{cursor:e.cursor,...e.epoch!==void 0?{epoch:e.epoch}:{},entries:Object.assign(Object.create(null),e.entries),remote:Object.assign(Object.create(null),e.remote),pending:Array.isArray(e.pending)?[...e.pending]:e.pending}}function rl(n,e){for(let[t,i]of Object.entries(e.set??{}))n.entries[t]=i;for(let t of e.del??[])delete n.entries[t];for(let[t,i]of Object.entries(e.remote??{}))n.remote[t]=i;for(let t of e.unremote??[])delete n.remote[t];e.cursor!==void 0&&(n.cursor=e.cursor),e.epoch!==void 0&&(n.epoch=e.epoch),e.pending!==void 0&&(n.pending=[...e.pending])}function Gi(n){return{cursor:n.cursor,epoch:n.epoch,entries:Jn(n.entries),remote:Jn(n.remote),pending:wo(n.pending)}}function yo(n,e){let t={cursor:e.cursor,epoch:e.epoch,entries:Jn(e.entries,n.entries),remote:Jn(e.remote,n.remote),pending:wo(e.pending)},i={};n.cursor!==e.cursor&&(i.cursor=e.cursor),e.epoch!==void 0&&n.epoch!==e.epoch&&(i.epoch=e.epoch);let r=fo(n.entries,t.entries,e.entries);Object.keys(r.set).length>0&&(i.set=r.set),r.del.length>0&&(i.del=r.del);let s=fo(n.remote,t.remote,e.remote);return Object.keys(s.set).length>0&&(i.remote=s.set),s.del.length>0&&(i.unremote=s.del),n.pending.length===t.pending.length&&n.pending.every((a,d)=>a===t.pending[d])||(i.pending=[...t.pending]),{delta:Object.keys(i).length===0?void 0:i,shape:t}}function fo(n,e,t){let i=Object.create(null),r=[];for(let[s,o]of e)n.get(s)!==o&&(i[s]=t[s]);for(let s of n.keys())e.has(s)||r.push(s);return{set:i,del:r}}function Jn(n,e){let t=new Map;if(typeof n!="object"||n===null||Array.isArray(n))return t;for(let i of Object.keys(n)){let r=n[i],s=e?.get(i);if(s&&jn(s.value,r))t.set(i,s);else{let o=JSON.stringify(r),a=o===void 0?void 0:JSON.parse(o);t.set(i,s&&jn(s.value,a)?s:{value:a})}}return t}function jn(n,e){if(n===e)return!0;if(n===null||e===null||typeof n!="object"||typeof e!="object"||typeof e.toJSON=="function")return!1;if(Array.isArray(n))return Array.isArray(e)&&n.length===e.length&&n.every((s,o)=>jn(s,e[o]));if(Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);if(t!==Object.prototype&&t!==null)return!1;let i=Object.keys(n),r=Object.keys(e);return i.length===r.length&&i.every((s,o)=>s===r[o]&&jn(n[s],e[s]))}function wo(n){return Array.isArray(n)?[...n]:[]}var Eo={fractionOfSnapshot:.25,maxRecords:1e3,minBytes:64*1024};function sl(n,e,t,i=Eo){return t>=i.maxRecords?!0:n<i.minBytes||e<=0?!1:n>e*i.fractionOfSnapshot}function Vn(n){return n.replace(/\.json$/i,"")+".log"}var Hn=class{files;policy;say;saved;seq=0;snapshotBytes=0;records=0;left={};mustSnapshot=!1;opts;constructor(e,t={}){this.files=e,this.opts=t,this.policy=t.policy??Eo,this.say=t.log??(()=>{})}async load(){let e=await this.files.readSnapshot(),t=await this.files.readLog();if(this.left=await this.files.stamps(),e===void 0){if(t!==void 0&&t!=="")throw new Error("the index has a journal but no snapshot to apply it to, so it cannot be trusted. Remove the journal to start from the server instead.");return}let i;try{i=JSON.parse(e)}catch(d){throw new Error(`the index snapshot is not valid JSON, so it cannot be trusted: ${d.message}`)}let r=al(i),s=ol(i);if(this.snapshotBytes=Bt(e),t===void 0||t==="")return this.settle(s,r??0,0),this.mustSnapshot=r===void 0,s;if(r===void 0)return this.say("the index journal sits beside a snapshot that does not say which records it holds, so something other than this client wrote one of them. Using the snapshot alone, which is older and consistent; the journal will be replaced on the next save."),this.settle(s,0,0),this.mustSnapshot=!0,s;let o={state:s,seq:r},a;try{a=mo(o,t)}catch(d){return this.say(`the index journal could not be replayed (${String(d)}); using the snapshot alone.`),this.settle(s,r,0),this.mustSnapshot=!0,s}return a.stopped.why!=="end"&&this.say(`the index journal stops at record ${a.stopped.at??0} (${a.stopped.why}); ${a.applied} of its records were applied. An older index is safe: anything past that point is work this device will do again.`),!vo(a.state)&&vo(s)?(this.say("the index journal replayed to a state that cannot be trusted; falling back to the snapshot, which is older and consistent."),this.settle(s,r,0),this.mustSnapshot=!0,s):(this.settle(a.state,a.seq,a.applied),a.stopped.why!=="end"&&(this.mustSnapshot=!0),a.state)}async save(e){let t=this.opts.onSave,i=t===void 0?0:performance.now(),r=i,s=(d,c)=>{if(t!==void 0)try{t({compareMs:r-i,writeMs:performance.now()-r,bytes:c,kind:d,records:this.records})}catch{}},o=await this.files.stamps(),a=this.foreignWrite(o);if(this.saved!==void 0&&a===void 0){let{delta:d,shape:c}=yo(this.saved,e);if(t!==void 0&&(r=performance.now()),d===void 0){s("unchanged",0);return}if(!this.mustSnapshot&&!sl(o.log?.size??0,this.snapshotBytes,this.records+1,this.policy)){let l=await this.append(d,c,o.log?.size??0);s("append",l);return}}a!==void 0&&this.say(`${a} is not what this session wrote, so something else is writing the index. Replacing both with a fresh snapshot, which is complete on its own. If two clients share this vault, stop one of them: their indexes will keep overwriting each other.`),s("snapshot",await this.snapshot(e))}foreignWrite(e){if(this.saved!==void 0){if(!bo(this.left.snapshot,e.snapshot))return"the index snapshot";if(!bo(this.left.log,e.log))return"the index journal"}}async append(e,t,i){let r=po(++this.seq,e);try{await this.files.appendLog(r);let s=await this.files.stamps(),o=(s.log?.size??0)-i;if(o!==Bt(r))throw new Error(`the index journal grew by ${o} bytes for a ${Bt(r)} byte record, so the append did not land whole`);return this.records++,this.saved=t,this.left=s,Bt(r)}catch(s){throw this.mustSnapshot=!0,this.left=await this.files.stamps().catch(()=>this.left),s}}async snapshot(e){let t=JSON.stringify({...e,seq:this.seq});try{return await this.files.writeSnapshot(t),this.snapshotBytes=Bt(t),await this.files.truncateLog(),this.records=0,this.mustSnapshot=!1,this.saved=Gi(e),Bt(t)}catch(i){throw this.mustSnapshot=!0,i}finally{this.left=await this.files.stamps().catch(()=>({}))}}settle(e,t,i){this.saved=Gi(e),this.seq=t,this.records=i,this.mustSnapshot=!1}};function ol(n){if(typeof n!="object"||n===null||Array.isArray(n))return n;let{seq:e,...t}=n;return t}function al(n){if(typeof n!="object"||n===null||Array.isArray(n))return;let e=n.seq;return typeof e=="number"&&Number.isSafeInteger(e)&&e>=0?e:void 0}function vo(n){try{return dt(n)!==void 0}catch{return!1}}function bo(n,e){return n===void 0||e===void 0?n===e:n.size===e.size&&n.mtime===e.mtime}function Bt(n){return new TextEncoder().encode(n).length}import{constants as De,watch as ll}from"node:fs";import{createHash as Oo,randomBytes as lt}from"node:crypto";import{access as rn,cp as hl,link as Fe,lstat as z,mkdir as oe,open as xe,readFile as Mo,readdir as ze,realpath as sn,rename as me,rm as J,rmdir as No,stat as ye}from"node:fs/promises";import{basename as ht,dirname as D,join as P,relative as K,resolve as Xn,sep as $t}from"node:path";function Gn(n){let e=0,t=[],i=()=>{e--,t.shift()?.()};return async r=>{e>=n&&await new Promise(s=>t.push(s)),e++;try{return await r()}finally{i()}}}var ko=new Map;function ne(n){if(ko.has(n))throw new Error(`two seams are called ${n}`);let e={name:n,pause:async()=>{},hold(t){let i=e.pause,r=async s=>{await i(s),await t(s)};return e.pause=r,()=>{e.pause===r&&(e.pause=i)}}};return ko.set(n,e),e}function Ke(n){let e={};for(let[t,i]of Object.entries(n))Object.defineProperty(e,t,{enumerable:!0,get:()=>i.pause,set:r=>{i.pause=r}});return e}var qn=class{files;say;now;constructor(e,t=()=>{},i=()=>Date.now()){this.files=e,this.say=t,this.now=i}gone=new Set;missing;async record(e){let t=JSON.stringify(e);try{await this.files.append(`
20
20
  ${t}
21
- `)}catch(r){return this.say(`could not write down that ${e.at} is waiting: ${r.message}`),this.missing=`${e.from} was displaced to ${e.at} and could not be written down`,!1}return await this.readableNow(t)?!0:(this.say(`wrote down that ${e.at} is waiting and could not read it back`),this.missing=`${e.from} was displaced to ${e.at} and the record cannot be read back`,!1)}async readableNow(e){try{let t=await this.files.read();return t===void 0?!1:t.split(`
22
- `).some(r=>r.trim()===e)}catch{return!1}}async waiting(e=!0){return(await this.inventory(e)).waiting}async inventory(e=!0){let t=await this.parse(),r=new Map;for(let c of t.records)r.set(c.at,c);let i=[],s=[],o=this.now();for(let c of r.values()){let l=JSON.stringify(c);this.gone.has(l)||(await this.files.stillThere(c.at).catch(()=>!0)?(i.push(c),s.push(c)):o-c.when<6e4?s.push(c):this.gone.add(l))}let a=t.records.length-s.length;e&&a>0&&(a>=32||s.length===0)&&await this.compact(s,t),i.sort((c,l)=>c.when-l.when);let d=t.why??this.missing;return d===void 0?{waiting:i,complete:!0}:{waiting:i,complete:!1,why:d}}async compact(e,t){let r=[...e.map(i=>JSON.stringify(i)),...t.unreadable].map(i=>`${i}
23
- `).join("");try{if(r===""&&this.files.clear!==void 0&&t.text!==void 0){await this.files.clear(t.text)&&this.gone.clear();return}let i=this.files.rewrite?.bind(this.files);if(i===void 0)return;await i(r),this.gone.clear()}catch(i){this.say(`could not tidy the displaced-version log: ${i.message}`)}}async parse(){let e;try{e=await this.files.read()}catch(i){let s=`the record of displaced versions could not be read (${i.message})`;return this.say(s),{records:[],unreadable:[],text:void 0,why:s}}if(e===void 0||e.length===0)return{records:[],unreadable:[],text:e};let t=[],r=[];for(let i of e.split(`
24
- `)){if(i.trim().length===0)continue;let s=Vc(i);s!==void 0?t.push(s):r.push(i)}return r.length===0?{records:t,unreadable:r,text:e}:{records:t,unreadable:r,text:e,why:"the record of displaced versions has a line that cannot be read"}}};function Vc(n){try{let e=JSON.parse(n);return typeof e.at!="string"||e.at.length===0?void 0:{at:e.at,from:typeof e.from=="string"?e.from:"an unknown note",why:typeof e.why=="string"?e.why:"it could not be placed",when:typeof e.when=="number"?e.when:0}}catch{return}}var po="displaced.log";var mo=/[\u0000-\u0008\u000a-\u001f\u007f-\u009f\u2028\u2029\u202a-\u202e\u2066-\u2069]/gu;function K(n){return n.replace(mo,e=>`\\u{${e.codePointAt(0).toString(16)}}`)}function U(n){return JSON.stringify(n).replace(/[\u007f-\u009f\u2028\u2029\u202a-\u202e\u2066-\u2069]/gu,e=>`\\u${e.codePointAt(0).toString(16).padStart(4,"0")}`)}var Be={match:"\x1B[1;31m",path:"\x1B[35m",line:"\x1B[32m",reset:"\x1B[0m"},Gc=new RegExp(`${Object.values(Be).map(n=>n.replace(/[[\]]/g,"\\$&")).join("|")}|${mo.source}`,"gu");function Jr(n,e){return e?n.replace(Gc,t=>t.length>1?t:`\\u{${t.codePointAt(0).toString(16)}}`):K(n)}var Vr=".trew",Kc=".trash";async function Gr(n){try{return await Qt(n,$e.F_OK),!0}catch(e){if(e.code==="ENOENT")return!1;throw e}}async function Yc(n){try{return!(await z(n)).isDirectory()}catch(e){if(e.code==="ENOENT")return!1;throw e}}var Zc=new Set(["node_modules"]),Zr=".obsidian";var V=class extends Error{constructor(t,r){super(r);this.code=t}code},Ft=class extends Error{constructor(t,r){super(t instanceof Error?t.message:"file preservation failed",{cause:t});this.preserved=r}preserved};function jn(n,e){return n.dev===e.dev&&n.ino===e.ino&&n.mode===e.mode}function Ct(n,e){return jn(n,e)&&n.size===e.size&&n.mtimeNs===e.mtimeNs&&n.ctimeNs===e.ctimeNs}function yo(n){return n.toLowerCase().toUpperCase().normalize("NFC")}function wo(n){return/^[ -~]*$/.test(n)?n.toLowerCase():Q(n)}var jr=qe({pause:ee("cli/vault:respell"),beforeGivingBack:ee("cli/vault:respell.beforeGivingBack"),parked:ee("cli/vault:respell.parked")}),Qr=qe({pause:ee("cli/vault:trash"),afterCompare:ee("cli/vault:trash.afterCompare"),parked:ee("cli/vault:trash.parked")}),Qc=qe({beforeClaim:ee("cli/vault:preserve.beforeClaim")}),el=qe({pause:ee("cli/vault:removeFolder")}),vo=qe({staged:ee("cli/vault:replace.staged"),nameFree:ee("cli/vault:replace.nameFree")});async function tl(n,e,t){await jr.pause(e),await he(n,{recursive:!0});let r=$(n,`preserved.${ot(8).toString("hex")}`);if(await z(e).catch(()=>{})===void 0)return;await pe(e,r),await jr.parked(r);let s=await z(r).catch(()=>{});if(s!==void 0&&s.dev===t.dev&&s.ino===t.ino){await J(r,{force:!0});return}await jr.beforeGivingBack(e);try{await Pe(r,e),await J(r,{force:!0});return}catch(a){if(a.code!=="EEXIST")throw a}let o=await Do(e,"kept");try{await Pe(r,o)}catch{await Io(r,o).catch(a=>{throw new Error(`two versions of ${e} were saved at once and the one this scan moved could not be put beside the other (${a.message}); it is at ${r}`)})}await J(r,{force:!0})}async function Hr(n,e){await Qc.beforeClaim(e);let t=e;for(let r=0;;r++)try{return await Pe(n,t),await J(n,{force:!0}),t}catch(i){if(i.code!=="EEXIST"||r>=64)throw i;t=await Do(e,"kept")}}async function Do(n,e){let t=D(n),r=at(n),i=r.lastIndexOf("."),s=i<=0?r:r.slice(0,i),o=i<=0?"":r.slice(i);for(let a=1;a<1e3;a++){let d=$(t,Hn(s,` (${e} ${a})${o}`));if(!await Gr(d))return d}throw new Error(`no free name beside ${n}`)}function Hn(n,e){let t=Ot-Buffer.byteLength(e);if(Buffer.byteLength(n)<=t)return n+e;let r="",i=0;for(let s of n){if(i+=Buffer.byteLength(s),i>t)break;r+=s}return r+e}function tn(n,e){return $(D(n),Hn(at(n),e))}async function To(n,e){let t=D(e);for(;;){let r=await en(t).catch(s=>{if(s.code!=="ENOENT")throw s});if(r!==void 0){if(r!==n&&!r.startsWith(n+St))throw new Error(`refusing a path that leaves the vault through a link: ${e}`);return}let i=D(t);if(i===t)return;t=i}}async function ye(n,e){let t=await en(n).catch(r=>{if(r.code!=="ENOENT")throw r});t!==void 0&&await To(t,e)}var xt=class{root;ignore;ignoreFolded;normal;reported;observeOnly;listingWatchers=new Set;cachedListing;listingChanges=new Set;listingGeneration=0;fullScanDue=0;invalidateListing(){this.cachedListing=void 0,this.listingChanges.clear(),this.listingGeneration++}ledger;displaced=[];recovery={waiting:[],complete:!1,why:"nothing has scanned this vault yet"};constructor(e,t={}){this.root=Jn(e),this.pairing=t.pairing,this.observeOnly=t.observeOnly??!1;let r=t.normalForm??de;this.normal=r,this.reported=s=>Ri(r(s));let i=this.reported(yn(t.configDir??Zr));this.ignore=new Set([...Zc,i,...(t.alsoIgnore??[]).map(s=>this.reported(s))]),this.ignoreFolded=new Set([...this.ignore].map(wo)),this.ledger=new Wn(new Yr(this.root),s=>console.warn(K(`trew: ${s}`)))}async noteDisplaced(e,t,r){this.invalidateListing(),await this.ledger.record({at:Y(this.root,e),from:this.normalPath(Y(this.root,t)),why:r,when:Date.now()})}normalPath(e){return e.split("/").map(t=>this.reported(t)).join("/")}realRootOnce;pairing;rootSeen;async sameVault(e){let t=s=>{throw new Error(`${this.root} is not the folder this trew opened as the vault: ${s}. Nothing was listed or changed, because a folder standing in for it would read as every note deleted. Put the vault back (mount its disk again, for example) and start trew again.`)},r;try{r=await me(this.root,{bigint:!0})}catch(s){return t(`it cannot be looked at (${s.message})`)}r.isDirectory()||t("it is not a folder");let i=this.rootSeen;i!==void 0&&(r.dev!==i.dev||r.ino!==i.ino)&&t("a different folder is at its path now, which is what an unmounted disk or a vault moved away leaves behind"),this.pairing!==void 0&&(e||i===void 0)&&!await Gr(this.pairing)&&t(`it no longer holds this device's pairing, ${Y(this.root,this.pairing)}`),this.rootSeen??={dev:r.dev,ino:r.ino}}unflushed=new Set;async flush(){let e=[...this.unflushed];this.unflushed.clear();let t=await Promise.allSettled(e.map(i=>ct(i))),r;if(t.forEach((i,s)=>{i.status==="rejected"&&(this.unflushed.add(e[s]),r??=i.reason)}),r!==void 0)throw r}dirty(e,t){this.invalidateListing();let r=D(e);for(this.unflushed.add(r);r!==t&&r.startsWith(this.root)&&r!==this.root;)r=D(r),this.unflushed.add(r)}async deepestExisting(e){let t=D(e);for(;;){try{return await Qt(t,$e.F_OK),t}catch(i){if(i.code!=="ENOENT")throw i}let r=D(t);if(r===t)return t;t=r}}async insideForReal(e){await To(await(this.realRootOnce??=en(this.root)),e)}async readableDir(e){let t=D(e);this.checkedDirs.has(t)||(await this.insideForReal(e),this.checkedDirs.add(t))}checkedDirs=new Set;assertPathPolicy(e,t="file"){if(typeof e!="string"||/[\\\0]/u.test(e)||new RegExp("\\p{Surrogate}","u").test(e)||/^[A-Za-z]:/u.test(e)||Buffer.byteLength(e)>4096||e!==this.normalPath(e)||e!==""&&e.split("/").some(s=>!s||s==="."||s==="..")||e===""&&t!=="directory")throw new V("invalid_path","expected a canonical vault-relative path");let r=e===""?[]:e.split("/"),i=new Set([...this.ignore].map(yo));if(r.some(s=>s.startsWith(".")||i.has(yo(s))))throw new V("excluded_path","the path is excluded from this vault")}async checkedLocation(e,{allowMissing:t=!1,kind:r="file"}={}){this.assertPathPolicy(e,r);let i=e===""?[]:e.split("/"),s=await(this.realRootOnce??=en(this.root)),o=await z(s,{bigint:!0}),a=[],d=[],c=async()=>{for(let l of a){let h=await z(l.full,{bigint:!0});if(!h.isDirectory()||!Ct(l.info,h))throw new V("changed_during_read","a path ancestor changed while checking it")}};for(let l=0;l<i.length;l++){if(!o.isDirectory())throw new V("not_regular_file","a path ancestor is not a regular directory");a.push({full:s,info:o});let h=i[l],u=(await Ue(s)).filter(m=>this.canonical(m)===this.canonical(h));if(u.length>1)throw new V("ambiguous_path","the path has ambiguous spellings on disk");let f=u[0]??h;d.push(this.reported(f));let g=s;s=$(s,f);try{o=await z(s,{bigint:!0})}catch(m){if(!t||m.code!=="ENOENT")throw m;let y=i.slice(l+1);return await c(),{path:[...d,...y].join("/"),full:$(s,...y),info:void 0,parents:a}}if(u.length===0)throw new V("ambiguous_path","the path uses an unlisted filesystem alias");if(o.isSymbolicLink())throw new V("symlink","refusing a path through a link");for(let m of this.ignore){if(m!==at(m))continue;let y=await z($(g,m),{bigint:!0}).catch(w=>{if(w.code!=="ENOENT")throw w});if(y!==void 0&&jn(y,o))throw new V("excluded_path","the path aliases an excluded name in this vault")}}if(r==="file"?!o.isFile():!o.isDirectory())throw new V("not_regular_file",`the path is not a regular ${r}`);return await c(),{path:d.join("/"),full:s,info:o,parents:a}}async checkPath(e,t={}){let r=await this.checkedLocation(e,t),i=await this.checkedLocation(e,t);if(r.full!==i.full||r.parents.length!==i.parents.length||r.parents.some((s,o)=>!jn(s.info,i.parents[o].info))||(r.info===void 0?i.info!==void 0:i.info===void 0||!Ct(r.info,i.info)))throw new V("changed_during_read","the path changed while checking it");return this.diskName.clear(),this.spellingsKnown.clear(),{path:r.path,exists:r.info!==void 0}}async readSnapshot(e,t,{flush:r=!1}={}){if(!Number.isSafeInteger(t)||t<1||t>1024*1024)throw new V("invalid_limit","snapshot byte limit must be between 1 and 1048576");let i=await this.checkedLocation(e),s=()=>{throw new V("note_too_large","the note is too large for this read")},o=()=>{throw new V("changed_during_read","the note changed during the read; read it again")};i.info.size>BigInt(t)&&s();let a;try{a=await Se(i.full,$e.O_RDONLY|$e.O_NOFOLLOW|$e.O_NONBLOCK)}catch(d){throw["ELOOP","EMLINK"].includes(d.code??"")?new V("symlink","refusing a path through a link"):d}try{let d=await a.stat({bigint:!0});(!d.isFile()||!Ct(i.info,d))&&o();let c=async()=>{let g=await this.checkedLocation(e);(g.full!==i.full||!Ct(d,g.info)||g.parents.length!==i.parents.length||g.parents.some((m,y)=>!jn(m.info,i.parents[y].info)))&&o()};await c();let l=Buffer.alloc(t+1),h=0;for(;h<l.length;){let{bytesRead:g}=await a.read(l,h,l.length-h,h);if(g===0)break;h+=g}h>t&&s(),r&&await a.sync();let u=await a.stat({bigint:!0});(!Ct(d,u)||BigInt(h)!==u.size)&&o(),await c();let f=new Uint8Array(l.buffer,l.byteOffset,h);return{path:i.path,bytes:f,base:Bo("sha256").update(f).digest("hex"),size:h,mtime:Number(d.mtimeNs)/1e6,ctime:Number(d.birthtimeNs)/1e6}}finally{await a.close()}}async absolute(e){await this.sameVault(!1);let t=Jn(this.root,e),r=Y(this.root,t);if(r===""||r===".."||r.startsWith(`..${St}`))throw new Error(`refusing a path outside the vault: ${e}`);let i=this.normalPath(r.split(St).join("/"));if(this.neverSynced(i)){let[s,o]=this.ignoreQuestion(i);throw Ni(s,o)?Mi(`not writing under a name this device is set to ignore: ${e}`):Oi(`refusing to write inside a folder that is never synced: ${e}`)}return Jn(this.root,await this.spelledOnDisk(i))}neverSynced(e){return _t(...this.ignoreQuestion(e))}ignoreQuestion(e){return this.foldsCaseSync?[wo(e),this.ignoreFolded]:[e,this.ignore]}diskName=new Map;spellingsKnown=new Set;async spelledOnDisk(e){let t="",r="";for(let i of e.split("/")){let s=t?`${t}/${i}`:i,o=this.diskName.get(s);o===void 0&&!this.spellingsKnown.has(t)&&(await this.readSpellings(t,r),o=this.diskName.get(s)),r=r?`${r}/${o??i}`:o??i,t=s}return r}async readSpellings(e,t){let r;try{r=await Ue(Jn(this.root,t))}catch(s){let o=s.code;if(o==="ENOENT"||o==="ENOTDIR")return;throw s}this.spellingsKnown.add(e);let i=new Map;for(let s of r){let o=this.reported(s),a=i.get(o);a?a.push(s):i.set(o,[s])}for(let[s,o]of i){let a=e?`${e}/${s}`:s;o.length>1?this.diskName.delete(a):o[0]!==s&&!this.diskName.has(a)&&this.diskName.set(a,o[0])}}ambiguousPaths=[];ambiguous(){return this.ambiguousPaths}normalized=new Set;async normalizeName(e,t,r){if(!this.normalized.has(r))try{let i=$(e,t.disk),s=$(e,t.spelled),o=await z(i),a=async()=>{let d=await z(s).catch(()=>{});return d===void 0?!0:d.dev===o.dev&&d.ino===o.ino};if(o.isDirectory()){if(!await a())return;await pe(i,s),this.finishNormalising(r,t,e)}else{try{await Pe(i,s)}catch(c){if(c.code!=="EEXIST"||!await a())throw c;await pe(i,s),this.finishNormalising(r,t,e);return}let d=t.disk;this.finishNormalising(r,t,e);try{await this.retireOldSpelling(i,o)}catch(c){this.ambiguousPaths.push({path:r,spellings:[t.spelled,d]})}}}catch{}}finishNormalising(e,t,r){this.normalized.add(e),t.disk=t.spelled,this.unflushed.add(r)}async retireOldSpelling(e,t){await this.checkStaging(),await tl(this.staging,e,t)}reaped=0;stranded=[];async reapStaleTemps(){this.stranded.length=0;try{await this.checkStaging()}catch(r){return`recovery staging could not be checked: ${r.message}`}let e;try{e=await Ue(this.staging)}catch(r){return r.code==="ENOENT"?void 0:`recovery staging could not be read: ${r.message}`}for(let r of e)!ko(r)&&!G.has($(this.staging,r))&&this.stranded.push(Y(this.root,$(this.staging,r)));if(this.observeOnly)return;let t=Date.now()-rl;for(let r of e){if(!ko(r))continue;let i=$(this.staging,r);if(!G.has(i))try{(await me(i)).mtimeMs<t&&(await J(i,{force:!0}),this.reaped++)}catch{}}}async list(e={}){if(e.checked&&!this.observeOnly)throw new Error("checked inventory requires an observe-only vault");await this.sameVault(!0),this.observeOnly||await this.refuseWithoutLinks(this.root);let t=await this.reapStaleTemps(),r=await this.listFiles(e.forceFull===!0,e.checked===!0),i=await this.ledger.inventory(!this.observeOnly);this.displaced=i.waiting,this.recovery=t===void 0?i:{...i,complete:!1,why:i.why?`${t}; ${i.why}`:t};let s=new Set(this.stranded);for(let o of this.displaced)!s.has(o.at)&&!G.has($(this.root,o.at))&&(this.stranded.push(o.at),s.add(o.at));return r}async listFiles(e,t=!1){if(!e&&!this.observeOnly&&this.listingWatchers.size>0&&Date.now()<this.fullScanDue){let c=this.cachedListing;if(c){let l=[...this.listingChanges];this.listingChanges.clear();let h=xo(Fo);try{await Promise.all(l.map(u=>h(async()=>{let f=await z(await this.absolute(u)).catch(g=>{if(!(g.code==="ENOENT"||g.code==="ENOTDIR"))throw g});if(!f?.isFile()){this.invalidateListing();return}c.set(u,{path:u,folder:!1,mtime:f.mtimeMs,ctime:f.birthtimeMs||f.ctimeMs,size:f.size,changeId:`${f.dev}:${f.ino}:${f.ctimeMs}`})})))}catch(u){throw this.invalidateListing(),u}if(this.cachedListing===c)return[...c.values()]}}this.invalidateListing();let r=this.listingGeneration;this.diskName.clear(),this.spellingsKnown.clear(),this.ambiguousPaths=[];let i=xo(Fo),s=async c=>{if(!t)return Promise.all(c);let l=await Promise.allSettled(c);for(let h of l)if(h.status==="rejected")throw h.reason;return l.map(h=>h.value)},o=async(c,l)=>{let h=t?await z(c,{bigint:!0}):void 0,u=async()=>{if(!h)return;let v=await z(c,{bigint:!0});if(!h.isDirectory()||!v.isDirectory()||!Ct(h,v))throw new V("changed_during_read","a directory changed during inventory")};await u();let f;try{f=await Ue(c,{withFileTypes:!0})}catch(v){throw new Error(`cannot read ${c}: ${v.message}`)}await u(),this.spellingsKnown.add(l);for(let v of f)if(v.isFile()&&Ao(v.name)){let A=$(c,v.name);G.has(A)||this.stranded.push(Y(this.root,A))}let g=f.map(v=>({item:v,name:this.reported(v.name),disk:v.name,spelled:this.normal(v.name)})).filter(({item:v,name:A})=>!this.neverSynced(l?`${l}/${A}`:A)&&!Co(v.name,$(c,v.name))&&(v.isDirectory()||v.isFile())).filter(({item:v,name:A})=>{if(!t)return!0;try{return this.assertPathPolicy(l?`${l}/${A}`:A,v.isDirectory()?"directory":"file"),!0}catch{return!1}}),m=new Map;for(let v of g){let A=m.get(v.name);A?A.push(v):m.set(v.name,[v])}let y=[],w=new Set(f.map(v=>v.name));for(let[v,A]of m){let F=l?`${l}/${v}`:v;if(A.length>1){this.ambiguousPaths.push({path:F,spellings:A.map(p=>l?`${l}/${p.disk}`:p.disk).sort()}),this.diskName.delete(F);continue}let x=A[0];!this.observeOnly&&x.disk!==x.spelled&&!w.has(x.spelled)&&await this.normalizeName(c,x,F),x.disk!==v&&this.diskName.set(F,x.disk),y.push(x)}let b=await s(y.map(({item:v,disk:A})=>t||v.isFile()?i(()=>(t?z($(c,A)):me($(c,A))).catch(F=>{if(F.code!=="ENOENT")throw F})):void 0));if(t)for(let v=0;v<y.length;v++){let A=b[v];if(A&&(y[v].item.isDirectory()?!A.isDirectory():!A.isFile()))throw new V("changed_during_read","a file type changed during inventory")}let k=await s(y.map(({item:v,name:A,disk:F},x)=>v.isDirectory()&&(!t||b[x]!==void 0)?o($(c,F),l?`${l}/${A}`:A):void 0));await u();let S=[];for(let v=0;v<y.length;v++){let{item:A,name:F}=y[v],x=l?`${l}/${F}`:F;if(A.isDirectory()){if(t&&b[v]===void 0)continue;S.push({path:x,folder:!0,mtime:0,ctime:0,size:0}),S.push(...k[v])}else{let p=b[v];if(p===void 0)continue;S.push({path:x,folder:!1,mtime:p.mtimeMs,ctime:p.birthtimeMs||p.ctimeMs,size:p.size,changeId:`${p.dev}:${p.ino}:${p.ctimeMs}`})}}return S},a=t?await(this.realRootOnce??=en(this.root)):this.root,d=await o(a,"");return await this.sameVault(!0),!this.observeOnly&&this.listingWatchers.size>0&&r===this.listingGeneration&&this.stranded.length===0&&this.ambiguousPaths.length===0&&(this.cachedListing=new Map(d.map(c=>[c.path,c])),this.fullScanDue=Date.now()+3e4),d}async read(e){let t=await this.openNote(e);try{return new Uint8Array(await t.readFile())}finally{await t.close()}}async openNote(e){let t=await this.absolute(e);await this.readableDir(t);try{return await Se(t,$e.O_RDONLY|$e.O_NOFOLLOW)}catch(r){let i=r.code;throw i==="ELOOP"||i==="EMLINK"?new Error(`refusing a path that leaves the vault through a link: ${t}`):r}}async stat(e){let t;try{t=await z(await this.absolute(e))}catch(r){let i=r.code;if(i==="ENOENT"||i==="ENOTDIR")return;throw r}if(t.isDirectory())return{path:e,folder:!0,mtime:0,ctime:0,size:0};if(t.isFile())return{path:e,folder:!1,mtime:t.mtimeMs,ctime:t.birthtimeMs||t.ctimeMs,size:t.size,changeId:`${t.dev}:${t.ino}:${t.ctimeMs}`}}async*readBlocks(e,t=1024*1024){let r=await this.openNote(e);try{let i=new Uint8Array(t);for(;;){let{bytesRead:s}=await r.read(i,0,t,null);if(s===0)return;yield i.slice(0,s)}}finally{await r.close()}}async readRange(e,t,r){let i=await this.openNote(e);try{let s=new Uint8Array(r-t),o=0;for(;o<s.length;){let{bytesRead:a}=await i.read(s,o,s.length-o,t+o);if(a===0)break;o+=a}return o===s.length?s:s.subarray(0,o)}finally{await i.close()}}async write(e,t,r){this.invalidateListing();let i=await this.absolute(e);await this.insideForReal(i);let s=await this.deepestExisting(i);await he(D(i),{recursive:!0}),await this.matchCase(i),await this.checkStaging(),await ze(i,t,!1,{mtime:r.mtime,stageIn:this.staging}),this.dirty(i,s)}get staging(){return $(this.root,Vr,"tmp")}stagingChecked;checkStaging(){return this.stagingChecked??=this.insideForReal($(this.staging,"x"))}async matchCase(e){if(!this.foldsCaseSync)return;let t;try{t=await me(e)}catch(d){if(d.code==="ENOENT")return;throw d}if(t.isDirectory())return;let r=D(e),i=at(e),s=await Ue(r);if(s.includes(i))return;let o=Q(i),a=s.find(d=>Q(d)===o);a!==void 0&&(await pe($(r,a),e),this.unflushed.add(r))}async replace(e,t,r,i,s){this.invalidateListing();let o=await this.absolute(e);await this.insideForReal(o);let a=await this.deepestExisting(o);await he(D(o),{recursive:!0}),await this.refuseWithoutLinks(D(o)),await this.matchCase(o),await this.checkStaging();let d=await this.absolute(s);await this.insideForReal(d);let c=$(this.staging,`replace.${ot(8).toString("hex")}`),l=tn(o,`.${Xr}${ot(4).toString("hex")}`),h,u=!1,f=g=>h===void 0?g:new Ft(g,[h]);try{let g=await al(o),m={mtime:i.mtime,...g===void 0?{}:{mode:g}};if(await ze(c,r,!1,{...m,stageIn:this.staging}),!await ol(c,D(o))){let k=tn(o,`.${nn}near${ot(4).toString("hex")}`);await ze(k,r,!1,m),await J(c,{force:!0}),c=k}let y=!0;G.add(l),await vo.staged(e);try{await pe(o,l),h=Y(this.root,l)}catch(k){if(k.code!=="ENOENT")throw k;y=!1}if(y&&await So(l))throw await this.putFolderBack(l,o,e),h=void 0,new Error(`refusing to write a file over the folder at ${e}`);let w=!0;await vo.nameFree(e);try{await Pe(c,o)}catch(k){if(k.code==="EEXIST")w=!1;else{if(y&&!await this.putBack(l,o)){let v=await Hr(l,d).catch(()=>l);throw h=Y(this.root,v),v===l&&await this.noteDisplaced(l,o,`${e} could not be written and its previous version could not be put back`),new Error(`${e} could not be written (${k.message}) and its previous version could not be put back; it is at ${Y(this.root,v)}`)}throw h=void 0,k}}if(this.dirty(o,a),this.unflushed.add(D(o)),!y)return{landed:w};if(w&&t!==void 0){let k=await dt(l).catch(()=>{});if(k!==void 0&&k===t.contentId)return await J(l,{force:!0}),h=void 0,{landed:!0}}let b;try{b=await Hr(l,d),h=Y(this.root,b)}catch(k){throw await this.noteDisplaced(l,o,`the version replaced at ${e} could not be placed at ${s} (${k.message})`),k}return this.dirty(b,a),this.unflushed.add(D(b)),{keptAt:Y(this.root,b),landed:w}}catch(g){throw u=!0,f(g)}finally{try{await J(c,{force:!0})}catch(g){if(!u)throw f(g)}finally{G.delete(l)}}}async putBack(e,t){try{await Pe(e,t)}catch{return!1}return await J(e,{force:!0}),this.unflushed.add(D(t)),!0}async putFolderBack(e,t,r){try{await pe(e,t)}catch(i){throw await this.noteDisplaced(e,t,`the folder at ${r} was taken aside in place of a note and could not be put back`),new Ft(new Error(`the folder at ${r} was taken aside in place of a note and could not be put back (${i.message}); it is at ${Y(this.root,e)}`),[Y(this.root,e)])}this.unflushed.add(D(t))}async removeExpecting(e,t,r){this.invalidateListing();let i=await this.absolute(e);if(await this.insideForReal(i),await z(i).catch(a=>{if(a.code!=="ENOENT")throw a})===void 0)return{landed:!0};await this.refuseWithoutLinks(D(i));let o=tn(i,`.${Xr}${ot(4).toString("hex")}`);G.add(o);try{await pe(i,o)}catch(a){if(G.delete(o),a.code!=="ENOENT")throw a;return{landed:!0}}if(this.unflushed.add(D(i)),await So(o)){try{await this.putFolderBack(o,i,e)}finally{G.delete(o)}throw new Error(`refusing to remove the folder at ${e} as if it were a note`)}await Qr.parked(o);try{let a=t===void 0?void 0:await dt(o).catch(()=>{});if(a!==void 0&&t!==void 0&&a===t.contentId)return await this.intoTrash(i,o),{landed:!0};let d=await this.absolute(r);await this.insideForReal(d);let c=await this.deepestExisting(d);await he(D(d),{recursive:!0});let l=await Hr(o,d);return this.dirty(l,c),this.unflushed.add(D(l)),{keptAt:Y(this.root,l),landed:!0}}catch(a){if(await this.putBack(o,i))throw a;try{await this.noteDisplaced(o,i,`${e} was taken off its name to be identified and could not be put back`)}catch(d){throw new Ft(d,[Y(this.root,o)])}throw new Ft(a,[Y(this.root,o)])}finally{G.delete(o)}}contentDigest=async e=>dt(await this.absolute(e)).catch(()=>{});async remove(e){this.invalidateListing();let t=await this.absolute(e);await this.insideForReal(t);try{await Qt(t,$e.F_OK)}catch(r){if(r.code==="ENOENT")return;throw r}await this.intoTrash(t,t)}async removeFolder(e){this.invalidateListing();let t=await this.absolute(e);await this.insideForReal(t);try{if(!(await z(t)).isDirectory())return!1}catch(r){if(r.code==="ENOENT")return!0;throw r}await el.pause(t);try{await Po(t)}catch(r){let i=r.code;if(i==="ENOENT")return!0;if(i==="ENOTEMPTY"||i==="EEXIST")return!1;throw r}for(let r of this.unflushed)(r===t||r.startsWith(`${t}${St}`))&&this.unflushed.delete(r);return this.unflushed.add(D(t)),!0}async respellFolder(e,t){if(e===t||Q(e)!==Q(t))return!1;this.invalidateListing();let r=await this.absolute(e);await this.insideForReal(r);let i=D(r),s=t.slice(t.lastIndexOf("/")+1),o=await Ue(i,{withFileTypes:!0});if(o.some(d=>d.name===s))return!1;let a=o.filter(d=>Q(d.name)===Q(s));return a.length!==1||!a[0].isDirectory()?!1:(await pe($(i,a[0].name),$(i,s)),this.unflushed.add(i),!0)}async intoTrash(e,t){let r=await this.freeTrashPath(Y(this.root,e).split(St).join("/"));await this.insideForReal(r);let i=await this.deepestExisting(r);await he(D(r),{recursive:!0});try{await pe(t,r),this.unflushed.add(D(t)),this.dirty(r,i);return}catch(s){if(s.code!=="EXDEV")throw s}await Io(t,r),this.unflushed.add(D(t)),this.dirty(r,i)}async freeTrashPath(e){let t=e.split("/"),r=t.pop(),i=$(this.root,Kc);for(let a of t){let d=i;i=await Ie($(d,a),Yc,c=>$(d,Hn(a,` (${c})`)))}let{stem:s,ext:o}=et(r);return Ie($(i,r),Gr,a=>$(i,Hn(s,` (${a})${o}`)))}async mkdir(e){this.invalidateListing();let t=await this.absolute(e);await this.insideForReal(t);let r=await this.deepestExisting($(t,"x"));await he(t,{recursive:!0}),this.dirty($(t,"x"),r)}async exists(e){try{return await Qt(await this.absolute(e),$e.F_OK),!0}catch(t){let r=t.code;if(r==="ENOENT"||r==="ENOTDIR")return!1;throw t}}canonical(e){let t=this.normalPath(e);return this.foldsCaseSync?t.toLowerCase():t}foldsCaseSync=!0;probed;probeCase(){return this.probed??=(async()=>{let e=$(this.root,`.trew-CaseProbe-${process.pid}`);try{await(await Se(e,"wx")).close();try{await Qt($(this.root,`.trew-caseprobe-${process.pid}`),$e.F_OK),this.foldsCaseSync=!0}catch{this.foldsCaseSync=!1}}catch{}finally{await J(e,{force:!0}).catch(()=>{})}})()}linksOn=new Map;async refuseWithoutLinks(e){let{dev:t}=await me(e),r=this.linksOn.get(t);if(r===void 0){if(r=await cl(e),r===void 0)return;this.linksOn.set(t,r)}if(r!==!0)throw new Error(`${e} is on a filesystem that cannot make hard links (link answered ${r}), and trew needs them to replace or remove a note without a moment in which the note could be lost, so nothing was changed. exFAT and FAT drives are like this. Keep the vault on a filesystem with hard links, such as APFS, ext4, btrfs or XFS.`)}async create(e,t,r){this.invalidateListing();let i=await this.absolute(e);await this.insideForReal(i),await this.checkStaging();let s=await this.deepestExisting(i);await he(D(i),{recursive:!0});let{tmp:o,handle:a}=await Ro(i,void 0,this.staging);try{try{await Vn(a,t),r.mtime>0&&await a.utimes(r.mtime/1e3,r.mtime/1e3),await a.sync()}finally{await a.close()}try{await Pe(o,i)}catch(d){let c=d.code;if(c==="EEXIST")return!1;if(c!=="EPERM"&&c!=="ENOTSUP"&&c!=="EOPNOTSUPP"&&c!=="EXDEV")throw d;if(c==="EXDEV"){let h=await Kr(i,t,{mtime:r.mtime},void 0);try{return await Pe(h,i),this.dirty(i,s),!0}catch(u){let f=u.code;if(f==="EEXIST")return!1;if(f!=="EPERM"&&f!=="ENOTSUP"&&f!=="EOPNOTSUPP"&&f!=="EXDEV")throw u}finally{await J(h,{force:!0}).catch(()=>{}),G.delete(h)}}let l;try{l=await Se(i,"wx")}catch(h){if(h.code==="EEXIST")return!1;throw h}try{await Vn(l,t),r.mtime>0&&await l.utimes(r.mtime/1e3,r.mtime/1e3),await l.sync()}finally{await l.close()}}return this.dirty(i,s),!0}finally{await J(o,{force:!0}).catch(()=>{}),G.delete(o)}}async sameFile(e,t){if(e===t)return!0;try{let[r,i]=await Promise.all([this.absolute(e),this.absolute(t)]),[s,o]=await Promise.all([me(r),me(i)]);return s.dev===o.dev&&s.ino===o.ino}catch(r){if(r.code==="ENOENT")return!1;throw r}}watch(e){let t,r=new Set,i,s=a=>{r.add(a),!t&&(t=setTimeout(()=>{t=void 0;let d=[...r];r.clear();for(let c of d)e(c)},0))},o=()=>{i&&this.listingWatchers.delete(i),this.invalidateListing()};try{this.invalidateListing(),i=qc(this.root,{recursive:!0,persistent:!0},(a,d)=>{if(!d){this.invalidateListing(),s("");return}let c=d.toString().split(St).join("/");Ao(at(c))&&this.invalidateListing();let l=this.normalPath(c);if(this.neverSynced(l)||Co(at(c),$(this.root,c)))return;let h=this.cachedListing?.get(l);a==="change"&&h&&!h.folder?this.listingChanges.add(l):this.invalidateListing(),s(c)}),this.listingWatchers.add(i),i.on("error",o),i.on("close",o)}catch{return o(),()=>{}}return()=>{t&&clearTimeout(t),o(),i?.close()}}},Bt=class{store;constructor(e,t={}){this.store=new Un(new qr(e),{log:(r,...i)=>console.warn(K(`trew: ${r}`),...i),...t})}load(){return this.store.load()}save(e){return this.store.save(e)}},qr=class{constructor(e){this.file=e;this.log=zn(e)}file;log;named=!1;async readSnapshot(){return Eo(this.file,`the index at ${this.file}`)}async writeSnapshot(e){await he(D(this.file),{recursive:!0}),await ze(this.file,new TextEncoder().encode(e),!0,{stageIn:$(D(this.file),"tmp")})}async readLog(){return Eo(this.log,`the index journal at ${this.log}`)}async appendLog(e){await he(D(this.log),{recursive:!0});let t=await Se(this.log,"a");try{await Vn(t,new TextEncoder().encode(e)),await t.sync()}finally{await t.close()}this.named||(await ct(D(this.log)),this.named=!0)}async truncateLog(){await he(D(this.log),{recursive:!0}),await ze(this.log,new Uint8Array(0),!0,{stageIn:$(D(this.log),"tmp")}),this.named=!0}async stamps(){let[e,t]=await Promise.all([bo(this.file),bo(this.log)]);return{...e?{snapshot:e}:{},...t?{log:t}:{}}}};async function bo(n){try{let e=await me(n);return e.isFile()?{size:e.size,mtime:e.mtimeMs}:void 0}catch{return}}async function Eo(n,e){try{return await $o(n,"utf8")}catch(t){if(t.code==="ENOENT")return;throw new Error(`cannot read ${e}: ${t.message}`)}}var nn=".trew-tmp-",nl=["replace."];function ko(n){return n.includes(nn)||nl.some(e=>n.startsWith(e))}var Xr=`${nn}keep`;function Ao(n){return n.includes(Xr)}var G=new Set,rl=3600*1e3;function Co(n,e){return e!==void 0&&G.has(e)?!0:/\.trew-tmp-[0-9a-z]+(-\d+)?$/.test(n)}var il=0;async function Ro(n,e,t){t!==void 0&&await he(t,{recursive:!0});let r=t!==void 0?$(t,at(n)):n;for(let i=0;i<64;i++){let s=tn(r,`${nn}${(il++).toString(36)}${i?`-${i}`:""}`);try{let o=await Se(s,"wx",e);return G.add(s),{tmp:s,handle:o}}catch(o){if(o.code!=="EEXIST")throw o}}throw new Error(`could not find an unused temporary name for ${n}`)}async function sl(n){for(let e=0;e<64;e++){let t=tn(n,`.${nn}${ot(4).toString("hex")}`);if(!await z(t).catch(()=>{}))return t}throw new Error(`no free temporary name beside ${n}`)}async function ol(n,e){let[t,r]=await Promise.all([z(n).catch(()=>{}),z(e).catch(()=>{})]);return t!==void 0&&r!==void 0&&t.dev===r.dev}async function al(n){let e=await z(n).catch(()=>{});return e?.isFile()?e.mode&511:void 0}async function So(n){return(await z(n).catch(()=>{}))?.isDirectory()===!0}var dl=new Set(["EPERM","ENOTSUP","EOPNOTSUPP"]);async function cl(n){let e=$(n,`.trew-linkprobe-${process.pid}-${ot(4).toString("hex")}`);try{await(await Se(e,"wx")).close()}catch{return}try{return await Pe(e,`${e}-link`),!0}catch(t){let r=t.code??"";return dl.has(r)?r:void 0}finally{await J(`${e}-link`,{force:!0}).catch(()=>{}),await J(e,{force:!0}).catch(()=>{})}}async function ze(n,e,t=!0,r={}){let i=await Kr(n,e,r,r.stageIn);try{await pe(i,n)}catch(s){if(await J(i,{force:!0}).catch(()=>{}),G.delete(i),s.code!=="EXDEV"||r.stageIn===void 0)throw s;let o=await Kr(n,e,r,void 0);try{await pe(o,n)}catch(a){throw await J(o,{force:!0}).catch(()=>{}),a}finally{G.delete(o)}}G.delete(i),t&&await ct(D(n))}async function Kr(n,e,t,r){let{tmp:i,handle:s}=await Ro(n,t.mode,r);try{try{await Vn(s,e),t.mode!==void 0&&await s.chmod(t.mode),t.mtime!==void 0&&t.mtime>0&&await s.utimes(t.mtime/1e3,t.mtime/1e3),await s.sync()}finally{await s.close()}return i}catch(o){throw await J(i,{force:!0}).catch(()=>{}),G.delete(i),o}}async function Io(n,e){await Xc(n,e,{recursive:!0,errorOnExist:!0,force:!1,preserveTimestamps:!0});try{await Oo(n,e)}catch(r){throw await J(e,{recursive:!0,force:!0}).catch(()=>{}),new Error(`refusing to remove ${n}: its copy at ${e} does not match: ${r.message}`)}try{await hl(e)}catch(r){throw new Error(`refusing to remove ${n}: its copy at ${e} could not be made durable: ${r.message}`)}await Qr.pause(n);let t=await ll(n,e);if(t.length>0)throw new Error(`moved ${n} to ${e}, and left ${t.length} ${t.length===1?"file":"files"} in place because ${t.length===1?"it changed":"they changed"} while the copy was being made: ${t.slice(0,3).join(", ")}`)}async function ll(n,e){let t=[],r=async(i,s)=>{let o=await me(i).catch(()=>{});if(o===void 0)return;if(o.isDirectory()){for(let l of await Ue(i))await r($(i,l),$(s,l));await Po(i).catch(()=>{t.push(i)});return}if(!o.isFile())return;let a=await sl(i);try{await pe(i,a)}catch(l){if(l.code==="ENOENT")return;t.push(i);return}let[d,c]=await Promise.all([dt(a).catch(()=>{}),dt(s).catch(()=>{})]);if(await Qr.afterCompare(i),d!==void 0&&c!==void 0&&d===c){await J(a,{force:!0});return}try{await Pe(a,i),await J(a,{force:!0}),t.push(i)}catch{t.push(a)}};return await r(n,e),t.filter(i=>!t.some(s=>s!==i&&s.startsWith(`${i}/`)))}async function hl(n){let e=new Set,t=async r=>{let i=await me(r);if(i.isDirectory()){e.add(r);for(let o of await Ue(r))await t($(r,o));return}if(!i.isFile())return;let s=await Se(r,"r");try{await s.sync()}finally{await s.close()}e.add(D(r))};await t(n),e.add(D(n));for(let r of[...e].sort((i,s)=>s.length-i.length))await ct(r)}async function Oo(n,e){let t=await me(n),r=await me(e).catch(()=>{});if(r===void 0)throw new Error(`${e} is missing`);if(t.isDirectory()){if(!r.isDirectory())throw new Error(`${e} is not a directory`);for(let o of await Ue(n))await Oo($(n,o),$(e,o));return}if(!t.isFile())return;if(!r.isFile()||r.size!==t.size)throw new Error(`${e} is ${r.size} bytes, not ${t.size}`);let[i,s]=await Promise.all([dt(n),dt(e)]);if(i!==s)throw new Error(`${e} does not have the same bytes as ${n}`)}async function dt(n){let e=await Se(n,"r"),t=Bo("sha256");for await(let r of e.createReadStream())t.update(r);return t.digest("hex")}async function Vn(n,e){let t=0;for(;t<e.length;){let{bytesWritten:r}=await n.write(e.subarray(t));if(r<=0)throw new Error(`wrote 0 of the ${e.length-t} bytes remaining, so the write is not progressing`);t+=r}}var Fo=64;function xo(n){let e=0,t=[],r=()=>{e--,t.shift()?.()};return async i=>{e>=n&&await new Promise(s=>t.push(s)),e++;try{return await i()}finally{r()}}}async function ct(n){let e=await Se(n,"r");try{await e.sync()}finally{await e.close()}}var ul=new Set(["ENOENT","ENOTSUP","EOPNOTSUPP","EINVAL","EPERM"]);async function Gn(n){try{return await ct(n),{synced:!0}}catch(e){let t=e.code??"";return ul.has(t)?{synced:!0}:{synced:!1,why:`${t||"the filesystem"}: ${e.message}`}}}var Yr=class{constructor(e){this.root=e;this.path=$(e,Vr,po)}root;path;async read(){try{return await $o(this.path,"utf8")}catch(e){if(e.code==="ENOENT")return;throw e}}async append(e){await he(D(this.path),{recursive:!0});let t=await Se(this.path,"a",384);try{await t.writeFile(e,"utf8"),await t.sync()}finally{await t.close()}}async rewrite(e){await he(D(this.path),{recursive:!0}),await ze(this.path,new TextEncoder().encode(e),!0,{stageIn:$(this.root,Vr)})}async stillThere(e){try{return await z($(this.root,e)),!0}catch(t){if(t.code==="ENOENT")return!1;throw t}}};var Z=".trew",ve=n=>we(n,Z,"config.json"),De=n=>we(n,Z,"index.json"),ei=n=>zn(De(n));async function lt(n){let e=ve(n),t;try{t=await No(e,"utf8")}catch(i){if(i.code==="ENOENT")return;throw new Error(`cannot read ${e}: ${i.message}`)}let r;try{r=JSON.parse(t)}catch(i){throw new Error(`${e} is not valid JSON, so it cannot be trusted: ${i.message}`)}return Ks(r,e)}async function ti(n,e){let t=we(n,Z),r=ve(n);await ye(n,r),await Mo(t,{recursive:!0}),await ye(n,we(t,"tmp","probe"));let i=JSON.stringify(Kt(e),null,2)+`
25
- `;await ze(r,new TextEncoder().encode(i),!0,{mode:384,stageIn:we(t,"tmp")}),await ct(n)}async function Lo(n){await ye(n,ve(n)),await rn($t(n),{force:!0}),await sn($t(n),"the record of what needs attention");let e=await fl(n);await rn(ve(n),{force:!0}),await sn(ve(n),"the config");let t=await Gn(we(n,Z));return e??(t.synced?void 0:t.why)}async function fl(n){await ye(n,De(n)),await rn(ei(n),{force:!0}),await sn(ei(n),"the index journal"),await rn(De(n),{force:!0}),await sn(De(n),"the index");let e=await Gn(we(n,Z));return e.synced?void 0:e.why}async function Uo(n){await ye(n,ve(n)),await rn(ve(n),{force:!0}),await sn(ve(n),"the config");let e=await Gn(we(n,Z));return e.synced?void 0:e.why}var $t=n=>we(n,Z,"attention.json");async function zo(n,e){let t=we(n,Z),r=$t(n);await ye(n,r),await Mo(t,{recursive:!0}),await ye(n,we(t,"tmp","probe"));let i=JSON.stringify(e)+`
26
- `;await ze(r,new TextEncoder().encode(i),!0,{mode:384,stageIn:we(t,"tmp")})}async function Wo(n){let e=$t(n),t;try{t=await No(e,"utf8")}catch(c){if(c.code==="ENOENT")return;throw new Error(`cannot read ${e}: ${c.message}`)}let r;try{r=JSON.parse(t)}catch(c){throw new Error(`${e} is not valid JSON: ${c.message}`)}let i=typeof r=="object"&&r!==null?r:{},{at:s,count:o,paths:a}=i,d=Array.isArray(a)?a:void 0;if(typeof s!="number"||!Number.isFinite(s)||typeof o!="number"||!Number.isSafeInteger(o)||d===void 0||o<d.length||!d.every(c=>typeof c=="object"&&c!==null&&typeof c.path=="string"&&typeof c.why=="string"))throw new Error(`${e} does not hold a record of what needs attention`);return{at:s,count:o,paths:d}}async function Jo(n){for(let e of[De(n),ei(n)])try{return await _o(e),!0}catch(t){if(t.code!=="ENOENT")throw t}return!1}async function sn(n,e){try{await _o(n)}catch(t){if(t.code==="ENOENT")return;throw t}throw new Error(`${e} at ${n} is still there after removing it`)}async function ni(n,e,t,r=!1){let i=new xt(e.dir,{configDir:e.configDir,alsoIgnore:e.ignore,observeOnly:r,pairing:ve(e.dir)});return await i.probeCase(),{vault:i,store:new Bt(De(e.dir)),...no(n),timeoutMs:e.timeout,coalesceWrites:e.watch,...e.merge?{}:{merge:!1},...e.readOnly||n.readOnly===!0?{readOnly:!0}:{},...process.platform==="win32"?{windows:!0}:{},...e.watch&&t?{onProgress:s=>{s!==void 0&&t.err(` ... ${s}`)}}:{},...e.verbose&&t?{log:(s,...o)=>t.err(` ${s} ${o.map(gl).join(" ")}`.trimEnd())}:{}}}function gl(n){return typeof n=="string"?n:JSON.stringify(n)}var pl={pair:1,history:1,search:1,rename:1,restore:1,revoke:1,uninvite:1};function ml(n){if(!(!n.force||n.command==="unlock"))throw new Error(`${n.command} does not take --force, so it would have been ignored. It is for trew unlock, and only for a lock held on another machine.`)}function yl(n){let e=pl[n.command??""]??0;if(n.rest.length<=e)return;let r=n.rest.slice(e).map(i=>JSON.stringify(i)).join(", ");throw new Error(e===0?`${n.command} takes no arguments, so ${r} was not used. The vault is chosen with --dir.`:`${n.command} takes one argument, so ${r} was not used.`)}function jo(n){yl(n);let e={"--before":["history","deleted"],"--limit":["history","deleted","search"],"--mode":["search"],"--folder":["search"],"--case-sensitive":["search"],"--context":["search"],"--all":["search"],"--after":["search"],"--uid":["restore"],"--to":["restore"],"--ttl":["invite"],"--watch":["sync"],"--verify":["sync"],"--device":["pair"],"--key-file":["pair"],"--no-merge":["sync","restore","preview"],"--read-only":["pair","sync","restore","preview"]};for(let i of n.provided??[]){let s=e[i];if(s&&!s.includes(n.command??""))throw new Error(`${i} is only for ${s.join(", ")}; it has no effect on ${n.command}`)}if(n.keyFile&&n.rest[0]&&n.rest[0]!=="-")throw new Error("give the invite as an argument or with --key-file, not both");if(ml(n),n.verify&&(n.command!=="sync"||n.watch))throw new Error("--verify is for a one-time sync, without --watch");if(n.before&&n.command!=="history"&&n.command!=="deleted")throw new Error("--before is only for history and deleted");if(n.command==="search"&&n.limitGiven&&n.limit>200)throw new Error(`--limit for search is at most 200 matches a page, not ${n.limit}`);let r={search:"something to search for",history:"the path of a note",restore:"the path of a note",rename:"a name for this device",revoke:"a device id",uninvite:"an invite id"}[n.command??""];if(r&&!n.rest[0])throw new Error(`${n.command} needs ${r}`)}function ri(n){let e={upload:0,download:0,merge:0,copy:0,"delete-local":0,"delete-server":0,unchanged:0,blocked:0,"held-back":0};for(let t of n.files)e[t.action]++;return e}Re();import{readFile as Ul,rm as zl}from"node:fs/promises";import{hostname as Wl}from"node:os";import{join as Jl,resolve as jl}from"node:path";import{link as ea,mkdir as ta,readFile as Fl,realpath as xl,rename as na,rm as Ke,writeFile as ra}from"node:fs/promises";import{randomBytes as si}from"node:crypto";import{hostname as Pt}from"node:os";import{join as Ye,resolve as Bl}from"node:path";import{createHash as Vo}from"node:crypto";import{constants as ii,open as wl,rm as vl}from"node:fs/promises";import bl from"node:net";import{platform as El}from"node:process";import{join as kl}from"node:path";var Al=32,Xe=Symbol("another process holds this vault"),qn=new Set,Go={how:"O_EXLOCK",async take(n,e){let t;try{t=await wl(e,ii.O_CREAT|ii.O_RDWR|Al|ii.O_NONBLOCK,384)}catch(r){let i=r.code;if(i==="EAGAIN"||i==="EWOULDBLOCK")return Xe;throw r}return qn.add(t),{how:Go.how,release:async()=>{qn.delete(t),await t.close().catch(()=>{})}}}},qo={how:"abstract socket",async take(n){let e=`\0trew.${Vo("sha256").update(n).digest("hex").slice(0,32)}`,t=bl.createServer();t.unref();let r=await new Promise(i=>{t.once("error",s=>i(s.code==="EADDRINUSE"?!1:s)),t.listen(e,()=>i(!0))});if(r instanceof Error)throw r;return r?(qn.add(t),{how:qo.how,release:async()=>{qn.delete(t),await new Promise(i=>{t.close(()=>i())})}}):Xe}};function Xo(n=El){if(!Cl.on){if(n==="darwin")return Go;if(n==="linux")return qo}}var Cl={on:!1};async function Sl(n,e){let t=Vo("sha256").update(`${process.pid}.${Math.random()}`).digest("hex").slice(0,16),r=kl(e,`exclusion-probe.${t}`),i=`${r}#probe`,s;try{s=await n.take(i,r)}catch{return!1}if(s===Xe)return!1;try{return await n.take(i,r).catch(()=>Xe)===Xe}finally{await s.release(),await vl(r,{force:!0}).catch(()=>{})}}var Ho=new Map;function Ko(n,e){let t=`${n.how}\0${e}`,r=Ho.get(t);return r===void 0&&(r=Sl(n,e),Ho.set(t,r)),r}var ia=n=>Ye(n,Z,"lock"),$l=n=>Ye(n,Z,"lock.recovering"),Pl=n=>Ye(n,Z,"lock.excl"),sa=ee("cli/lock:publish"),Yo=qe({beforeTaking:ee("cli/lock:break.beforeTaking"),taken:ee("cli/lock:break.taken")});async function oa(n,e){let t=ia(n),r=Ye(n,Z);await ye(n,t),await ta(r,{recursive:!0});let i={pid:process.pid,host:Pt(),command:e,since:Date.now(),token:si(16).toString("hex")},s=await aa(n);if(s===Xe){let o=await an(t);throw new Error(o===void 0?"another trew is using this vault. Wait for it to finish, or stop it.":`another trew is using this vault: ${o.command} (pid ${o.pid} on ${o.host}, since ${new Date(o.since).toISOString()}). Wait for it to finish, or stop it.`)}if(s!==void 0)try{return await Dl(s,t,i)}catch(o){throw await s.release(),o}for(let o=0;o<3;o++){if(await ca(r,t,i))return async()=>{(await an(t))?.token===i.token&&await Ke(t,{force:!0})};let a=await on(t);if(a.state!=="absent")throw new Error(Tl(a,t))}throw new Error(`could not take the lock at ${t}: it keeps being taken and released. Something else is running against this vault in a loop.`)}async function Dl(n,e,t){let r=await on(e);if(r.state==="held"){let s=r.holder;if(s.host!==Pt())throw new Error(`another trew is using this vault: ${s.command} (pid ${s.pid} on ${s.host}, since ${new Date(s.since).toISOString()}). That is a different machine, so this one cannot tell whether it is still running. Wait for it to finish, or if you know it is gone, run trew unlock --force.`);if(s.pid!==process.pid&&oi(s.pid))throw new Error(`this vault is locked by ${s.command} (pid ${s.pid} on ${s.host}), which is still running, but the ${n.how} exclusion for it was free. Either that process is not a trew, which is what a process id reused after a restart looks like, or something is wrong with locking on this filesystem; nothing was changed. If pid ${s.pid} is not a trew, trew unlock --force clears the record; if it is, stop it.`)}let i=`${e}.claiming.${t.token}`;try{await ra(i,JSON.stringify(t),{mode:384}),await sa.pause(""),await na(i,e)}catch(s){throw await Ke(i,{force:!0}).catch(()=>{}),s}return async()=>{(await an(e))?.token===t.token&&await Ke(e,{force:!0}).catch(()=>{}),await n.release()}}async function aa(n){let e=Xo();if(e===void 0)return;let t=await xl(n).catch(()=>Bl(n));if(!await Ko(e,Ye(t,Z))){process.stderr.write(`trew: ${e.how} does not lock on this filesystem, so a crashed trew will need trew unlock rather than clearing itself.
27
- `);return}return await e.take(t,Pl(t))}function Tl(n,e){if(n.state==="unreadable")return`something is at ${e} but it does not name a holder, so this vault cannot be locked and nobody can say who has it. Run trew unlock to clear it.`;let t=n.holder,r=new Date(t.since).toISOString(),i=`${t.command} (pid ${t.pid} on ${t.host}, since ${r})`;return t.host!==Pt()?`another trew is using this vault: ${i}. That is a different machine, so this one cannot tell whether it is still running. Wait for it to finish, or if you know it is gone, run trew unlock --force.`:oi(t.pid)?`another trew is using this vault: ${i}. Wait for it to finish, or stop it.`:`this vault is locked by ${i}, which is not running any more. This filesystem does not support the lock that would let trew clear that by itself, so run trew unlock.`}async function da(n,e=!1){let t=ia(n);await ye(n,t);let r=$l(n);await ye(n,r),await ta(Ye(n,Z),{recursive:!0});let i={pid:process.pid,host:Pt(),command:"unlock",since:Date.now(),token:si(16).toString("hex")};if(!await ca(Ye(n,Z),r,i)){let s=await an(r);return{did:"refused",was:s??i,why:"another trew unlock is already running against this vault"+(s===void 0?"":` (pid ${s.pid} on ${s.host})`)+`. Two of them at once can hand this vault to two writers, so this one stopped. If no trew is running, remove ${r} and try again`}}try{return await Il(t,e,await Rl(n))}finally{(await an(r))?.token===i.token&&await Ke(r,{force:!0}).catch(()=>{})}}async function Rl(n){let e=await aa(n);if(e!==void 0)return e===Xe?!1:(await e.release(),!0)}async function Il(n,e,t){let r=await on(n);if(r.state==="absent")return{did:"nothing",why:"nothing is holding this vault"};let i=c=>r.state==="held"&&c.token===r.holder.token?t:void 0;if(r.state==="held"&&!Zo(r.holder,e,t))return{did:"refused",was:r.holder,why:Qo(r.holder,t)};await Yo.beforeTaking(n);let s=`${n}.breaking.${si(8).toString("hex")}`;try{await na(n,s)}catch(c){if(c.code==="ENOENT")return{did:"nothing",why:"the lock was released while this was looking at it"};throw c}await Yo.taken(s);let o=await on(s);if(o.state==="unreadable")return await Ke(s,{force:!0}),{did:"removed",was:void 0,why:"the lock named nobody, so it was debris rather than a holder"};if(o.state==="absent")return{did:"removed",was:void 0,why:"the lock file vanished as it was moved aside"};let a=o.holder;if(Zo(a,e,i(a)))return await Ke(s,{force:!0}),{did:"removed",was:a,why:Ol(a)};let d=!0;try{await ea(s,n)}catch{d=!1}return await Ke(s,{force:!0}),d?{did:"refused",was:a,why:Qo(a,i(a))}:{did:"contested",was:a,why:`this vault was locked by ${a.command} (pid ${a.pid} on ${a.host}), which is still running, and another trew took the lock while that was being established. Two processes may both believe they hold this vault: stop both, then run unlock again`}}function Zo(n,e,t){return n.host!==Pt()?e:!oi(n.pid)||e&&t===!0}function Qo(n,e){return n.host!==Pt()?`it is held on ${n.host}, and this machine cannot tell whether that process is still running. Use --force if you know it is not.`:e===!0?`pid ${n.pid} is running, but it holds nothing: this machine's lock for the vault is free, which is what a process id reused after a restart looks like. Check what pid ${n.pid} is, and if it is not a trew, run trew unlock --force`:`pid ${n.pid} is still running, and --force does not break a lock this machine can see is held. Stop it instead.`}function Ol(n){let e=new Date(n.since).toISOString();return`it was held by ${n.command} (pid ${n.pid} on ${n.host}, since ${e}), which is not running`}async function ca(n,e,t){let r=Ye(n,`claiming.${t.token}`);await ra(r,JSON.stringify(t),{mode:384}),await sa.pause("");try{return await ea(r,e),!0}catch(i){if(i.code!=="EEXIST")throw i;return!1}finally{await Ke(r,{force:!0})}}async function on(n){let e;try{e=await Fl(n,"utf8")}catch(r){let i=r.code;if(i==="ENOENT")return{state:"absent"};if(i==="EISDIR"||i==="EACCES"||i==="EPERM")return{state:"unreadable"};throw r}let t=Ml(e);return t===void 0?{state:"unreadable"}:{state:"held",holder:t}}async function an(n){let e=await on(n).catch(()=>({state:"unreadable"}));return e.state==="held"?e.holder:void 0}function Ml(n){try{let e=JSON.parse(n);return typeof e.pid!="number"||typeof e.host!="string"?void 0:{pid:e.pid,host:e.host,command:typeof e.command=="string"?e.command:"unknown command",since:typeof e.since=="number"?e.since:0,token:typeof e.token=="string"?e.token:""}}catch{return}}function oi(n){try{return process.kill(n,0),!0}catch(e){return e.code!=="ESRCH"}}var ha=256,Nl=1024;function _l(n,e,t){if(n.kind==="filename"||n.line===0)return;let r=Math.max(0,n.column-1-ha),i=[n.column-1-r,n.column-2-r].filter(a=>a>=0&&a<n.text.length);if(i.length===0)return;let s=a=>{if(n.kind==="tag"||t==="tag"){let c=a+1;for(;c<n.text.length&&!/[\s,;:"'`()[\]{}<>|]/u.test(n.text[c]);)c++;return{start:a,end:c}}let d=a;for(let c=[...e].length;c>0&&d<n.text.length;c--)d+=n.text.codePointAt(d)>65535?2:1;return{start:a,end:d}},o=e.toLowerCase();for(let a of i){let d=s(a);if(n.kind==="tag"||t==="tag"){if(n.text[a]==="#"||n.text.slice(a).toLowerCase().startsWith(o))return d;continue}if(n.text.slice(d.start,d.end).toLowerCase()===o)return d}return s(i[0])}function Ll(n,e,t,r){let i=r?`${Be.path}${K(n.path)}${Be.reset}`:K(n.path);if(n.kind==="filename"||n.line===0)return`${i} (the file name matches)`;let s=`${n.line}:${n.column}`,o=r?`${Be.line}${s}${Be.reset}`:s,a=n.text.endsWith("\r")?n.text.slice(0,-1):n.text,d,c=r?_l({...n,text:a},e,t):void 0;c!==void 0?d=K(a.slice(0,c.start))+Be.match+K(a.slice(c.start,c.end))+Be.reset+K(a.slice(c.end)):d=K(a);let l=n.column-1>ha,h=n.clipped&&n.text.length>=Nl-1;return`${i}:${o}: ${l?"\u2026":""}${d}${h?"\u2026":""}`}function la(n,e,t,r){let i=r?`${Be.path}${K(n)}${Be.reset}`:K(n),s=t.endsWith("\r")?t.slice(0,-1):t;return s===""?`${i}-${e}-`:`${i}-${e}- ${K(s)}`}function ua(n,e,t,r){let i=[];return n.before.forEach((s,o)=>{i.push(la(n.path,n.line-n.before.length+o,s,r))}),i.push(Ll(n,e,t,r)),n.after.forEach((s,o)=>{i.push(la(n.path,n.line+1+o,s,r))}),i}function dn(n,e,t,r=[]){if(e!==void 0)return e.offline===!0?{kind:"offline",why:e.why}:{kind:"passFailed",why:e.why};if(n===void 0)return{kind:"passFailed",why:"the pass did not report a result"};if(n.retrying>0)return{kind:"retrying",paths:n.retryingPaths};if(n.skipped>0||n.blocked>0)return{kind:"refused",paths:[...n.skippedPaths,...n.inTheWay.map(s=>s.path)]};if(t!==void 0&&!t.complete)return{kind:"recoveryUnknown",why:t.why??"what is waiting to be recovered could not be established"};let i=[...new Set([...r,...(t?.waiting??[]).map(s=>s.at)])];return i.length>0?{kind:"recoveryNeeded",paths:i}:n.conflicted>0?{kind:"conflicted",count:n.conflicted}:{kind:"synced"}}function Xn(n){switch(n.kind){case"offline":case"passFailed":case"retrying":case"refused":case"recoveryUnknown":case"recoveryNeeded":return 1;case"conflicted":case"synced":return 0}}function ai(n){switch(n.kind){case"offline":return`cannot reach the server: ${n.why}`;case"passFailed":return`the pass did not finish: ${n.why}`;case"retrying":return n.paths.length===0?"some files could not be sent yet, and will be tried again":`${n.paths.length} not sent yet, and will be tried again: ${n.paths.join(", ")}`;case"refused":return n.paths.length===0?"some files need a person before they can sync":`${n.paths.length} need a person: ${n.paths.join(", ")}`;case"recoveryUnknown":return`everything sent and received, but ${n.why}, so a version may be waiting where nothing lists it`;case"recoveryNeeded":return n.paths.length===1?"1 preserved version needs recovery":`${n.paths.length} preserved versions need recovery`;case"conflicted":return`${n.count} kept both versions, which are both on this device`;case"synced":return"everything is where it should be"}}var fa="0.12.0",ga=`trew: the TrewSync command-line client, self-hosted sync for Obsidian
21
+ `)}catch(i){return this.say(`could not write down that ${e.at} is waiting: ${i.message}`),this.missing=`${e.from} was displaced to ${e.at} and could not be written down`,!1}return await this.readableNow(t)?!0:(this.say(`wrote down that ${e.at} is waiting and could not read it back`),this.missing=`${e.from} was displaced to ${e.at} and the record cannot be read back`,!1)}async readableNow(e){try{let t=await this.files.read();return t===void 0?!1:t.split(`
22
+ `).some(i=>i.trim()===e)}catch{return!1}}async waiting(e=!0){return(await this.inventory(e)).waiting}async inventory(e=!0){let t=await this.parse(),i=new Map;for(let c of t.records)i.set(c.at,c);let r=[],s=[],o=this.now();for(let c of i.values()){let l=JSON.stringify(c);this.gone.has(l)||(await this.files.stillThere(c.at).catch(()=>!0)?(r.push(c),s.push(c)):o-c.when<6e4?s.push(c):this.gone.add(l))}let a=t.records.length-s.length;e&&a>0&&(a>=32||s.length===0)&&await this.compact(s,t),r.sort((c,l)=>c.when-l.when);let d=t.why??this.missing;return d===void 0?{waiting:r,complete:!0}:{waiting:r,complete:!1,why:d}}async compact(e,t){let i=[...e.map(r=>JSON.stringify(r)),...t.unreadable].map(r=>`${r}
23
+ `).join("");try{if(i===""&&this.files.clear!==void 0&&t.text!==void 0){await this.files.clear(t.text)&&this.gone.clear();return}let r=this.files.rewrite?.bind(this.files);if(r===void 0)return;await r(i),this.gone.clear()}catch(r){this.say(`could not tidy the displaced-version log: ${r.message}`)}}async parse(){let e;try{e=await this.files.read()}catch(r){let s=`the record of displaced versions could not be read (${r.message})`;return this.say(s),{records:[],unreadable:[],text:void 0,why:s}}if(e===void 0||e.length===0)return{records:[],unreadable:[],text:e};let t=[],i=[];for(let r of e.split(`
24
+ `)){if(r.trim().length===0)continue;let s=dl(r);s!==void 0?t.push(s):i.push(r)}return i.length===0?{records:t,unreadable:i,text:e}:{records:t,unreadable:i,text:e,why:"the record of displaced versions has a line that cannot be read"}}};function dl(n){try{let e=JSON.parse(n);return typeof e.at!="string"||e.at.length===0?void 0:{at:e.at,from:typeof e.from=="string"?e.from:"an unknown note",why:typeof e.why=="string"?e.why:"it could not be placed",when:typeof e.when=="number"?e.when:0}}catch{return}}var Ao="displaced.log";var Co=/[\u0000-\u0008\u000a-\u001f\u007f-\u009f\u2028\u2029\u202a-\u202e\u2066-\u2069]/gu;function Y(n){return n.replace(Co,e=>`\\u{${e.codePointAt(0).toString(16)}}`)}function U(n){return JSON.stringify(n).replace(/[\u007f-\u009f\u2028\u2029\u202a-\u202e\u2066-\u2069]/gu,e=>`\\u${e.codePointAt(0).toString(16).padStart(4,"0")}`)}var $e={match:"\x1B[1;31m",path:"\x1B[35m",line:"\x1B[32m",reset:"\x1B[0m"},cl=new RegExp(`${Object.values($e).map(n=>n.replace(/[[\]]/g,"\\$&")).join("|")}|${Co.source}`,"gu");function qi(n,e){return e?n.replace(cl,t=>t.length>1?t:`\\u{${t.codePointAt(0).toString(16)}}`):Y(n)}var Ki=".trew",ul=".trash";async function Zi(n){try{return await rn(n,De.F_OK),!0}catch(e){if(e.code==="ENOENT")return!1;throw e}}async function fl(n){try{return!(await z(n)).isDirectory()}catch(e){if(e.code==="ENOENT")return!1;throw e}}var gl=new Set(["node_modules"]),rr=".obsidian";var G=class extends Error{constructor(t,i){super(i);this.code=t}code},Dt=class extends Error{constructor(t,i){super(t instanceof Error?t.message:"file preservation failed",{cause:t});this.preserved=i}preserved};function Yn(n,e){return n.dev===e.dev&&n.ino===e.ino&&n.mode===e.mode}function Pt(n,e){return Yn(n,e)&&n.size===e.size&&n.mtimeNs===e.mtimeNs&&n.ctimeNs===e.ctimeNs}function So(n){return n.toLowerCase().toUpperCase().normalize("NFC")}function Fo(n){return/^[ -~]*$/.test(n)?n.toLowerCase():ee(n)}var Xi=Ke({pause:ne("cli/vault:respell"),beforeGivingBack:ne("cli/vault:respell.beforeGivingBack"),parked:ne("cli/vault:respell.parked")}),sr=Ke({pause:ne("cli/vault:trash"),afterCompare:ne("cli/vault:trash.afterCompare"),parked:ne("cli/vault:trash.parked")}),pl=Ke({beforeClaim:ne("cli/vault:preserve.beforeClaim")}),ml=Ke({pause:ne("cli/vault:removeFolder")}),xo=Ke({staged:ne("cli/vault:replace.staged"),nameFree:ne("cli/vault:replace.nameFree")});async function yl(n,e,t){await Xi.pause(e),await oe(n,{recursive:!0});let i=P(n,`preserved.${lt(8).toString("hex")}`);if(await z(e).catch(()=>{})===void 0)return;await me(e,i),await Xi.parked(i);let s=await z(i).catch(()=>{});if(s!==void 0&&s.dev===t.dev&&s.ino===t.ino){await J(i,{force:!0});return}await Xi.beforeGivingBack(e);try{await Fe(i,e),await J(i,{force:!0});return}catch(a){if(a.code!=="EEXIST")throw a}let o=await _o(e,"kept");try{await Fe(i,o)}catch{await Uo(i,o).catch(a=>{throw new Error(`two versions of ${e} were saved at once and the one this scan moved could not be put beside the other (${a.message}); it is at ${i}`)})}await J(i,{force:!0})}async function Yi(n,e){await pl.beforeClaim(e);let t=e;for(let i=0;;i++)try{return await Fe(n,t),await J(n,{force:!0}),t}catch(r){if(r.code!=="EEXIST"||i>=64)throw r;t=await _o(e,"kept")}}async function _o(n,e){let t=D(n),i=ht(n),r=i.lastIndexOf("."),s=r<=0?i:i.slice(0,r),o=r<=0?"":i.slice(r);for(let a=1;a<1e3;a++){let d=P(t,Kn(s,` (${e} ${a})${o}`));if(!await Zi(d))return d}throw new Error(`no free name beside ${n}`)}function Kn(n,e){let t=Ut-Buffer.byteLength(e);if(Buffer.byteLength(n)<=t)return n+e;let i="",r=0;for(let s of n){if(r+=Buffer.byteLength(s),r>t)break;i+=s}return i+e}function on(n,e){return P(D(n),Kn(ht(n),e))}async function Lo(n,e){let t=D(e);for(;;){let i=await sn(t).catch(s=>{if(s.code!=="ENOENT")throw s});if(i!==void 0){if(i!==n&&!i.startsWith(n+$t))throw new Error(`refusing a path that leaves the vault through a link: ${e}`);return}let r=D(t);if(r===t)return;t=r}}async function we(n,e){let t=await sn(n).catch(i=>{if(i.code!=="ENOENT")throw i});t!==void 0&&await Lo(t,e)}var Tt=class{root;ignore;ignoreFolded;normal;reported;observeOnly;listingWatchers=new Set;cachedListing;listingChanges=new Set;listingGeneration=0;fullScanDue=0;invalidateListing(){this.cachedListing=void 0,this.listingChanges.clear(),this.listingGeneration++}ledger;displaced=[];recovery={waiting:[],complete:!1,why:"nothing has scanned this vault yet"};constructor(e,t={}){this.root=Xn(e),this.pairing=t.pairing,this.observeOnly=t.observeOnly??!1;let i=t.normalForm??se;this.normal=i,this.reported=s=>Ur(i(s));let r=this.reported(Cn(t.configDir??rr));this.ignore=new Set([...gl,r,...(t.alsoIgnore??[]).map(s=>this.reported(s))]),this.ignoreFolded=new Set([...this.ignore].map(Fo)),this.ledger=new qn(new ir(this.root),s=>console.warn(Y(`trew: ${s}`)))}async noteDisplaced(e,t,i){this.invalidateListing(),await this.ledger.record({at:K(this.root,e),from:this.normalPath(K(this.root,t)),why:i,when:Date.now()})}normalPath(e){return e.split("/").map(t=>this.reported(t)).join("/")}realRootOnce;pairing;rootSeen;async sameVault(e){let t=s=>{throw new Error(`${this.root} is not the folder this trew opened as the vault: ${s}. Nothing was listed or changed, because a folder standing in for it would read as every note deleted. Put the vault back (mount its disk again, for example) and start trew again.`)},i;try{i=await ye(this.root,{bigint:!0})}catch(s){return t(`it cannot be looked at (${s.message})`)}i.isDirectory()||t("it is not a folder");let r=this.rootSeen;r!==void 0&&(i.dev!==r.dev||i.ino!==r.ino)&&t("a different folder is at its path now, which is what an unmounted disk or a vault moved away leaves behind"),this.pairing!==void 0&&(e||r===void 0)&&!await Zi(this.pairing)&&t(`it no longer holds this device's pairing, ${K(this.root,this.pairing)}`),this.rootSeen??={dev:i.dev,ino:i.ino}}unflushed=new Set;unsyncedFiles=new Map;fsyncFailed;async flush(){await this.syncFiles();let e=[...this.unflushed];this.unflushed.clear();let t=await Promise.allSettled(e.map(r=>ft(r))),i;if(t.forEach((r,s)=>{r.status==="rejected"&&(this.unflushed.add(e[s]),i??=r.reason)}),i!==void 0)throw i}async syncFiles(){if(this.fsyncFailed!==void 0)throw this.fsyncFailed;if(this.unsyncedFiles.size===0)return;let e=[...this.unsyncedFiles.values()];this.unsyncedFiles.clear();let t=Gn(Pl),i=await Promise.allSettled(e.map(r=>t(async()=>{try{await r.sync()}finally{await r.close()}})));for(let r of i)r.status==="rejected"&&(this.fsyncFailed??=r.reason);if(this.fsyncFailed!==void 0)throw this.fsyncFailed}dirty(e,t){this.invalidateListing();let i=D(e);for(this.unflushed.add(i);i!==t&&i.startsWith(this.root)&&i!==this.root;)i=D(i),this.unflushed.add(i)}async deepestExisting(e){let t=D(e);for(;;){try{return await rn(t,De.F_OK),t}catch(r){if(r.code!=="ENOENT")throw r}let i=D(t);if(i===t)return t;t=i}}async insideForReal(e){await Lo(await(this.realRootOnce??=sn(this.root)),e)}async readableDir(e){let t=D(e);this.checkedDirs.has(t)||(await this.insideForReal(e),this.checkedDirs.add(t))}checkedDirs=new Set;assertPathPolicy(e,t="file"){if(typeof e!="string"||/[\\\0]/u.test(e)||new RegExp("\\p{Surrogate}","u").test(e)||/^[A-Za-z]:/u.test(e)||Buffer.byteLength(e)>4096||e!==this.normalPath(e)||e!==""&&e.split("/").some(s=>!s||s==="."||s==="..")||e===""&&t!=="directory")throw new G("invalid_path","expected a canonical vault-relative path");let i=e===""?[]:e.split("/"),r=new Set([...this.ignore].map(So));if(i.some(s=>s.startsWith(".")||r.has(So(s))))throw new G("excluded_path","the path is excluded from this vault")}async checkedLocation(e,{allowMissing:t=!1,kind:i="file"}={}){this.assertPathPolicy(e,i);let r=e===""?[]:e.split("/"),s=await(this.realRootOnce??=sn(this.root)),o=await z(s,{bigint:!0}),a=[],d=[],c=async()=>{for(let l of a){let h=await z(l.full,{bigint:!0});if(!h.isDirectory()||!Pt(l.info,h))throw new G("changed_during_read","a path ancestor changed while checking it")}};for(let l=0;l<r.length;l++){if(!o.isDirectory())throw new G("not_regular_file","a path ancestor is not a regular directory");a.push({full:s,info:o});let h=r[l],u=(await ze(s)).filter(m=>this.canonical(m)===this.canonical(h));if(u.length>1)throw new G("ambiguous_path","the path has ambiguous spellings on disk");let f=u[0]??h;d.push(this.reported(f));let g=s;s=P(s,f);try{o=await z(s,{bigint:!0})}catch(m){if(!t||m.code!=="ENOENT")throw m;let y=r.slice(l+1);return await c(),{path:[...d,...y].join("/"),full:P(s,...y),info:void 0,parents:a}}if(u.length===0)throw new G("ambiguous_path","the path uses an unlisted filesystem alias");if(o.isSymbolicLink())throw new G("symlink","refusing a path through a link");for(let m of this.ignore){if(m!==ht(m))continue;let y=await z(P(g,m),{bigint:!0}).catch(w=>{if(w.code!=="ENOENT")throw w});if(y!==void 0&&Yn(y,o))throw new G("excluded_path","the path aliases an excluded name in this vault")}}if(i==="file"?!o.isFile():!o.isDirectory())throw new G("not_regular_file",`the path is not a regular ${i}`);return await c(),{path:d.join("/"),full:s,info:o,parents:a}}async checkPath(e,t={}){let i=await this.checkedLocation(e,t),r=await this.checkedLocation(e,t);if(i.full!==r.full||i.parents.length!==r.parents.length||i.parents.some((s,o)=>!Yn(s.info,r.parents[o].info))||(i.info===void 0?r.info!==void 0:r.info===void 0||!Pt(i.info,r.info)))throw new G("changed_during_read","the path changed while checking it");return this.diskName.clear(),this.spellingsKnown.clear(),{path:i.path,exists:i.info!==void 0}}async readSnapshot(e,t,{flush:i=!1}={}){if(!Number.isSafeInteger(t)||t<1||t>1024*1024)throw new G("invalid_limit","snapshot byte limit must be between 1 and 1048576");let r=await this.checkedLocation(e),s=()=>{throw new G("note_too_large","the note is too large for this read")},o=()=>{throw new G("changed_during_read","the note changed during the read; read it again")};r.info.size>BigInt(t)&&s();let a;try{a=await xe(r.full,De.O_RDONLY|De.O_NOFOLLOW|De.O_NONBLOCK)}catch(d){throw["ELOOP","EMLINK"].includes(d.code??"")?new G("symlink","refusing a path through a link"):d}try{let d=await a.stat({bigint:!0});(!d.isFile()||!Pt(r.info,d))&&o();let c=async()=>{let g=await this.checkedLocation(e);(g.full!==r.full||!Pt(d,g.info)||g.parents.length!==r.parents.length||g.parents.some((m,y)=>!Yn(m.info,r.parents[y].info)))&&o()};await c();let l=Buffer.alloc(t+1),h=0;for(;h<l.length;){let{bytesRead:g}=await a.read(l,h,l.length-h,h);if(g===0)break;h+=g}h>t&&s(),i&&await a.sync();let u=await a.stat({bigint:!0});(!Pt(d,u)||BigInt(h)!==u.size)&&o(),await c();let f=new Uint8Array(l.buffer,l.byteOffset,h);return{path:r.path,bytes:f,base:Oo("sha256").update(f).digest("hex"),size:h,mtime:Number(d.mtimeNs)/1e6,ctime:Number(d.birthtimeNs)/1e6}}finally{await a.close()}}async absolute(e){await this.sameVault(!1);let t=Xn(this.root,e),i=K(this.root,t);if(i===""||i===".."||i.startsWith(`..${$t}`))throw new Error(`refusing a path outside the vault: ${e}`);let r=this.normalPath(i.split($t).join("/"));if(this.neverSynced(r)){let[s,o]=this.ignoreQuestion(r);throw jr(s,o)?Jr(`not writing under a name this device is set to ignore: ${e}`):Wr(`refusing to write inside a folder that is never synced: ${e}`)}return Xn(this.root,await this.spelledOnDisk(r))}neverSynced(e){return kn(...this.ignoreQuestion(e))}ignoreQuestion(e){return this.foldsCaseSync?[Fo(e),this.ignoreFolded]:[e,this.ignore]}diskName=new Map;spellingsKnown=new Set;async spelledOnDisk(e){let t="",i="";for(let r of e.split("/")){let s=t?`${t}/${r}`:r,o=this.diskName.get(s);o===void 0&&!this.spellingsKnown.has(t)&&(await this.readSpellings(t,i),o=this.diskName.get(s)),i=i?`${i}/${o??r}`:o??r,t=s}return i}async readSpellings(e,t){let i;try{i=await ze(Xn(this.root,t))}catch(s){let o=s.code;if(o==="ENOENT"||o==="ENOTDIR")return;throw s}this.spellingsKnown.add(e);let r=new Map;for(let s of i){let o=this.reported(s),a=r.get(o);a?a.push(s):r.set(o,[s])}for(let[s,o]of r){let a=e?`${e}/${s}`:s;o.length>1?this.diskName.delete(a):o[0]!==s&&!this.diskName.has(a)&&this.diskName.set(a,o[0])}}ambiguousPaths=[];ambiguous(){return this.ambiguousPaths}normalized=new Set;async normalizeName(e,t,i){if(!this.normalized.has(i))try{let r=P(e,t.disk),s=P(e,t.spelled),o=await z(r),a=async()=>{let d=await z(s).catch(()=>{});return d===void 0?!0:d.dev===o.dev&&d.ino===o.ino};if(o.isDirectory()){if(!await a())return;await me(r,s),this.finishNormalising(i,t,e)}else{try{await Fe(r,s)}catch(c){if(c.code!=="EEXIST"||!await a())throw c;await me(r,s),this.finishNormalising(i,t,e);return}let d=t.disk;this.finishNormalising(i,t,e);try{await this.retireOldSpelling(r,o)}catch(c){this.ambiguousPaths.push({path:i,spellings:[t.spelled,d]})}}}catch{}}finishNormalising(e,t,i){this.normalized.add(e),t.disk=t.spelled,this.unflushed.add(i)}async retireOldSpelling(e,t){await this.checkStaging(),await yl(this.staging,e,t)}reaped=0;stranded=[];async reapStaleTemps(){this.stranded.length=0;try{await this.checkStaging()}catch(i){return`recovery staging could not be checked: ${i.message}`}let e;try{e=await ze(this.staging)}catch(i){return i.code==="ENOENT"?void 0:`recovery staging could not be read: ${i.message}`}for(let i of e)!$o(i)&&!H.has(P(this.staging,i))&&this.stranded.push(K(this.root,P(this.staging,i)));if(this.observeOnly)return;let t=Date.now()-vl;for(let i of e){if(!$o(i))continue;let r=P(this.staging,i);if(!H.has(r))try{(await ye(r)).mtimeMs<t&&(await J(r,{force:!0}),this.reaped++)}catch{}}}async list(e={}){if(e.checked&&!this.observeOnly)throw new Error("checked inventory requires an observe-only vault");await this.sameVault(!0),this.observeOnly||await this.refuseWithoutLinks(this.root);let t=await this.reapStaleTemps(),i=await this.listFiles(e.forceFull===!0,e.checked===!0),r=await this.ledger.inventory(!this.observeOnly);this.displaced=r.waiting,this.recovery=t===void 0?r:{...r,complete:!1,why:r.why?`${t}; ${r.why}`:t};let s=new Set(this.stranded);for(let o of this.displaced)!s.has(o.at)&&!H.has(P(this.root,o.at))&&(this.stranded.push(o.at),s.add(o.at));return i}async listFiles(e,t=!1){if(!e&&!this.observeOnly&&this.listingWatchers.size>0&&Date.now()<this.fullScanDue){let c=this.cachedListing;if(c){let l=[...this.listingChanges];this.listingChanges.clear();let h=Gn(Ro);try{await Promise.all(l.map(u=>h(async()=>{let f=await z(await this.absolute(u)).catch(g=>{if(!(g.code==="ENOENT"||g.code==="ENOTDIR"))throw g});if(!f?.isFile()){this.invalidateListing();return}c.set(u,{path:u,folder:!1,mtime:f.mtimeMs,ctime:f.birthtimeMs||f.ctimeMs,size:f.size,changeId:`${f.dev}:${f.ino}:${f.ctimeMs}`})})))}catch(u){throw this.invalidateListing(),u}if(this.cachedListing===c)return[...c.values()]}}this.invalidateListing();let i=this.listingGeneration;this.diskName.clear(),this.spellingsKnown.clear(),this.ambiguousPaths=[];let r=Gn(Ro),s=async c=>{if(!t)return Promise.all(c);let l=await Promise.allSettled(c);for(let h of l)if(h.status==="rejected")throw h.reason;return l.map(h=>h.value)},o=async(c,l)=>{let h=t?await z(c,{bigint:!0}):void 0,u=async()=>{if(!h)return;let v=await z(c,{bigint:!0});if(!h.isDirectory()||!v.isDirectory()||!Pt(h,v))throw new G("changed_during_read","a directory changed during inventory")};await u();let f;try{f=await ze(c,{withFileTypes:!0})}catch(v){throw new Error(`cannot read ${c}: ${v.message}`)}await u(),this.spellingsKnown.add(l);for(let v of f)if(v.isFile()&&Do(v.name)){let A=P(c,v.name);H.has(A)||this.stranded.push(K(this.root,A))}let g=f.map(v=>({item:v,name:this.reported(v.name),disk:v.name,spelled:this.normal(v.name)})).filter(({item:v,name:A})=>!this.neverSynced(l?`${l}/${A}`:A)&&!To(v.name,P(c,v.name))&&(v.isDirectory()||v.isFile())).filter(({item:v,name:A})=>{if(!t)return!0;try{return this.assertPathPolicy(l?`${l}/${A}`:A,v.isDirectory()?"directory":"file"),!0}catch{return!1}}),m=new Map;for(let v of g){let A=m.get(v.name);A?A.push(v):m.set(v.name,[v])}let y=[],w=new Set(f.map(v=>v.name));for(let[v,A]of m){let F=l?`${l}/${v}`:v;if(A.length>1){this.ambiguousPaths.push({path:F,spellings:A.map(p=>l?`${l}/${p.disk}`:p.disk).sort()}),this.diskName.delete(F);continue}let x=A[0];!this.observeOnly&&x.disk!==x.spelled&&!w.has(x.spelled)&&await this.normalizeName(c,x,F),x.disk!==v&&this.diskName.set(F,x.disk),y.push(x)}let b=await s(y.map(({item:v,disk:A})=>t||v.isFile()?r(()=>(t?z(P(c,A)):ye(P(c,A))).catch(F=>{if(F.code!=="ENOENT")throw F})):void 0));if(t)for(let v=0;v<y.length;v++){let A=b[v];if(A&&(y[v].item.isDirectory()?!A.isDirectory():!A.isFile()))throw new G("changed_during_read","a file type changed during inventory")}let k=await s(y.map(({item:v,name:A,disk:F},x)=>v.isDirectory()&&(!t||b[x]!==void 0)?o(P(c,F),l?`${l}/${A}`:A):void 0));await u();let S=[];for(let v=0;v<y.length;v++){let{item:A,name:F}=y[v],x=l?`${l}/${F}`:F;if(A.isDirectory()){if(t&&b[v]===void 0)continue;S.push({path:x,folder:!0,mtime:0,ctime:0,size:0}),S.push(...k[v])}else{let p=b[v];if(p===void 0)continue;S.push({path:x,folder:!1,mtime:p.mtimeMs,ctime:p.birthtimeMs||p.ctimeMs,size:p.size,changeId:`${p.dev}:${p.ino}:${p.ctimeMs}`})}}return S},a=t?await(this.realRootOnce??=sn(this.root)):this.root,d=await o(a,"");return await this.sameVault(!0),!this.observeOnly&&this.listingWatchers.size>0&&i===this.listingGeneration&&this.stranded.length===0&&this.ambiguousPaths.length===0&&(this.cachedListing=new Map(d.map(c=>[c.path,c])),this.fullScanDue=Date.now()+3e4),d}async read(e){let t=await this.openNote(e);try{return new Uint8Array(await t.readFile())}finally{await t.close()}}async openNote(e){let t=await this.absolute(e);await this.readableDir(t);try{return await xe(t,De.O_RDONLY|De.O_NOFOLLOW)}catch(i){let r=i.code;throw r==="ELOOP"||r==="EMLINK"?new Error(`refusing a path that leaves the vault through a link: ${t}`):i}}async stat(e){let t;try{t=await z(await this.absolute(e))}catch(i){let r=i.code;if(r==="ENOENT"||r==="ENOTDIR")return;throw i}if(t.isDirectory())return{path:e,folder:!0,mtime:0,ctime:0,size:0};if(t.isFile())return{path:e,folder:!1,mtime:t.mtimeMs,ctime:t.birthtimeMs||t.ctimeMs,size:t.size,changeId:`${t.dev}:${t.ino}:${t.ctimeMs}`}}async*readBlocks(e,t=1024*1024){let i=await this.openNote(e);try{let r=new Uint8Array(t);for(;;){let{bytesRead:s}=await i.read(r,0,t,null);if(s===0)return;yield r.slice(0,s)}}finally{await i.close()}}async readRange(e,t,i){let r=await this.openNote(e);try{let s=new Uint8Array(i-t),o=0;for(;o<s.length;){let{bytesRead:a}=await r.read(s,o,s.length-o,t+o);if(a===0)break;o+=a}return o===s.length?s:s.subarray(0,o)}finally{await r.close()}}async write(e,t,i){this.invalidateListing();let r=await this.absolute(e);await this.insideForReal(r);let s=await this.deepestExisting(r);await oe(D(r),{recursive:!0}),await this.matchCase(r),await this.checkStaging(),await We(r,t,!1,{mtime:i.mtime,stageIn:this.staging}),this.dirty(r,s)}get staging(){return P(this.root,Ki,"tmp")}stagingChecked;checkStaging(){return this.stagingChecked??=this.insideForReal(P(this.staging,"x"))}async matchCase(e){if(!this.foldsCaseSync)return;let t;try{t=await ye(e)}catch(d){if(d.code==="ENOENT")return;throw d}if(t.isDirectory())return;let i=D(e),r=ht(e),s=await ze(i);if(s.includes(r))return;let o=ee(r),a=s.find(d=>ee(d)===o);a!==void 0&&(await me(P(i,a),e),this.unflushed.add(i))}async replace(e,t,i,r,s){this.invalidateListing();let o=await this.absolute(e);await this.insideForReal(o);let a=await this.deepestExisting(o);await oe(D(o),{recursive:!0}),await this.refuseWithoutLinks(D(o)),await this.matchCase(o),await this.checkStaging();let d=await this.absolute(s);await this.insideForReal(d);let c=P(this.staging,`replace.${lt(8).toString("hex")}`),l=on(o,`.${er}${lt(4).toString("hex")}`),h,u=!1,f=g=>h===void 0?g:new Dt(g,[h]);try{let g=await Al(o),m={mtime:r.mtime,...g===void 0?{}:{mode:g}};if(await We(c,i,!1,{...m,stageIn:this.staging}),!await kl(c,D(o))){let k=on(o,`.${dn}near${lt(4).toString("hex")}`);await We(k,i,!1,m),await J(c,{force:!0}),c=k}let y=!0;H.add(l),await xo.staged(e);try{await me(o,l),h=K(this.root,l)}catch(k){if(k.code!=="ENOENT")throw k;y=!1}if(y&&await Io(l))throw await this.putFolderBack(l,o,e),h=void 0,new Error(`refusing to write a file over the folder at ${e}`);let w=!0;await xo.nameFree(e);try{await Fe(c,o)}catch(k){if(k.code==="EEXIST")w=!1;else{if(y&&!await this.putBack(l,o)){let v=await Yi(l,d).catch(()=>l);throw h=K(this.root,v),v===l&&await this.noteDisplaced(l,o,`${e} could not be written and its previous version could not be put back`),new Error(`${e} could not be written (${k.message}) and its previous version could not be put back; it is at ${K(this.root,v)}`)}throw h=void 0,k}}if(this.dirty(o,a),this.unflushed.add(D(o)),!y)return{landed:w};if(w&&t!==void 0){let k=await ut(l).catch(()=>{});if(k!==void 0&&k===t.contentId)return await J(l,{force:!0}),h=void 0,{landed:!0}}let b;try{b=await Yi(l,d),h=K(this.root,b)}catch(k){throw await this.noteDisplaced(l,o,`the version replaced at ${e} could not be placed at ${s} (${k.message})`),k}return this.dirty(b,a),this.unflushed.add(D(b)),{keptAt:K(this.root,b),landed:w}}catch(g){throw u=!0,f(g)}finally{try{await J(c,{force:!0})}catch(g){if(!u)throw f(g)}finally{H.delete(l)}}}async putBack(e,t){try{await Fe(e,t)}catch{return!1}return await J(e,{force:!0}),this.unflushed.add(D(t)),!0}async putFolderBack(e,t,i){try{await me(e,t)}catch(r){throw await this.noteDisplaced(e,t,`the folder at ${i} was taken aside in place of a note and could not be put back`),new Dt(new Error(`the folder at ${i} was taken aside in place of a note and could not be put back (${r.message}); it is at ${K(this.root,e)}`),[K(this.root,e)])}this.unflushed.add(D(t))}async removeExpecting(e,t,i){this.invalidateListing();let r=await this.absolute(e);if(await this.insideForReal(r),await z(r).catch(a=>{if(a.code!=="ENOENT")throw a})===void 0)return{landed:!0};await this.refuseWithoutLinks(D(r));let o=on(r,`.${er}${lt(4).toString("hex")}`);H.add(o);try{await me(r,o)}catch(a){if(H.delete(o),a.code!=="ENOENT")throw a;return{landed:!0}}if(this.unflushed.add(D(r)),await Io(o)){try{await this.putFolderBack(o,r,e)}finally{H.delete(o)}throw new Error(`refusing to remove the folder at ${e} as if it were a note`)}await sr.parked(o);try{let a=t===void 0?void 0:await ut(o).catch(()=>{});if(a!==void 0&&t!==void 0&&a===t.contentId)return await this.intoTrash(r,o),{landed:!0};let d=await this.absolute(i);await this.insideForReal(d);let c=await this.deepestExisting(d);await oe(D(d),{recursive:!0});let l=await Yi(o,d);return this.dirty(l,c),this.unflushed.add(D(l)),{keptAt:K(this.root,l),landed:!0}}catch(a){if(await this.putBack(o,r))throw a;try{await this.noteDisplaced(o,r,`${e} was taken off its name to be identified and could not be put back`)}catch(d){throw new Dt(d,[K(this.root,o)])}throw new Dt(a,[K(this.root,o)])}finally{H.delete(o)}}contentDigest=async e=>ut(await this.absolute(e)).catch(()=>{});async remove(e){this.invalidateListing();let t=await this.absolute(e);await this.insideForReal(t);try{await rn(t,De.F_OK)}catch(i){if(i.code==="ENOENT")return;throw i}await this.intoTrash(t,t)}async removeFolder(e){this.invalidateListing();let t=await this.absolute(e);await this.insideForReal(t);try{if(!(await z(t)).isDirectory())return!1}catch(i){if(i.code==="ENOENT")return!0;throw i}await ml.pause(t);try{await No(t)}catch(i){let r=i.code;if(r==="ENOENT")return!0;if(r==="ENOTEMPTY"||r==="EEXIST")return!1;throw i}for(let i of this.unflushed)(i===t||i.startsWith(`${t}${$t}`))&&this.unflushed.delete(i);return this.unflushed.add(D(t)),!0}async respellFolder(e,t){if(e===t||ee(e)!==ee(t))return!1;this.invalidateListing();let i=await this.absolute(e);await this.insideForReal(i);let r=D(i),s=t.slice(t.lastIndexOf("/")+1),o=await ze(r,{withFileTypes:!0});if(o.some(d=>d.name===s))return!1;let a=o.filter(d=>ee(d.name)===ee(s));return a.length!==1||!a[0].isDirectory()?!1:(await me(P(r,a[0].name),P(r,s)),this.unflushed.add(r),!0)}async intoTrash(e,t){let i=await this.freeTrashPath(K(this.root,e).split($t).join("/"));await this.insideForReal(i);let r=await this.deepestExisting(i);await oe(D(i),{recursive:!0});try{await me(t,i),this.unflushed.add(D(t)),this.dirty(i,r);return}catch(s){if(s.code!=="EXDEV")throw s}await Uo(t,i),this.unflushed.add(D(t)),this.dirty(i,r)}async freeTrashPath(e){let t=e.split("/"),i=t.pop(),r=P(this.root,ul);for(let a of t){let d=r;r=await Oe(P(d,a),fl,c=>P(d,Kn(a,` (${c})`)))}let{stem:s,ext:o}=rt(i);return Oe(P(r,i),Zi,a=>P(r,Kn(s,` (${a})${o}`)))}async mkdir(e){this.invalidateListing();let t=await this.absolute(e);await this.insideForReal(t);let i=await this.deepestExisting(P(t,"x"));await oe(t,{recursive:!0}),this.dirty(P(t,"x"),i)}async exists(e){try{return await rn(await this.absolute(e),De.F_OK),!0}catch(t){let i=t.code;if(i==="ENOENT"||i==="ENOTDIR")return!1;throw t}}canonical(e){let t=this.normalPath(e);return this.foldsCaseSync?t.toLowerCase():t}foldsCaseSync=!0;probed;probeCase(){return this.probed??=(async()=>{let e=P(this.root,`.trew-CaseProbe-${process.pid}`);try{await(await xe(e,"wx")).close();try{await rn(P(this.root,`.trew-caseprobe-${process.pid}`),De.F_OK),this.foldsCaseSync=!0}catch{this.foldsCaseSync=!1}}catch{}finally{await J(e,{force:!0}).catch(()=>{})}})()}linksOn=new Map;async refuseWithoutLinks(e){let{dev:t}=await ye(e),i=this.linksOn.get(t);if(i===void 0){if(i=await Sl(e),i===void 0)return;this.linksOn.set(t,i)}if(i!==!0)throw new Error(`${e} is on a filesystem that cannot make hard links (link answered ${i}), and trew needs them to replace or remove a note without a moment in which the note could be lost, so nothing was changed. exFAT and FAT drives are like this. Keep the vault on a filesystem with hard links, such as APFS, ext4, btrfs or XFS.`)}async createDirect(e,t,i){this.unsyncedFiles.size>=$l&&await this.syncFiles(),this.invalidateListing();let r=await this.absolute(e);await this.insideForReal(r),await this.checkStaging();let s=await this.deepestExisting(r);await oe(D(r),{recursive:!0});let{tmp:o,handle:a}=await tr(r,void 0,this.staging),d=!1;try{await an(a,t),i.mtime>0&&await a.utimes(i.mtime/1e3,i.mtime/1e3);try{await Fe(o,r),d=!0}catch(c){let l=c.code;if(l==="EEXIST")return!1;if(l==="EPERM"||l==="ENOTSUP"||l==="EOPNOTSUPP"||l==="EXDEV")return await this.create(e,t,i);throw c}}finally{d||await a.close().catch(()=>{}),await J(o,{force:!0}).catch(()=>{}),H.delete(o)}return this.unsyncedFiles.set(r,a),this.dirty(r,s),!0}async create(e,t,i){this.invalidateListing();let r=await this.absolute(e);await this.insideForReal(r),await this.checkStaging();let s=await this.deepestExisting(r);await oe(D(r),{recursive:!0});let{tmp:o,handle:a}=await tr(r,void 0,this.staging);try{try{await an(a,t),i.mtime>0&&await a.utimes(i.mtime/1e3,i.mtime/1e3),await a.sync()}finally{await a.close()}try{await Fe(o,r)}catch(d){let c=d.code;if(c==="EEXIST")return!1;if(c!=="EPERM"&&c!=="ENOTSUP"&&c!=="EOPNOTSUPP"&&c!=="EXDEV")throw d;if(c==="EXDEV"){let h=await nr(r,t,{mtime:i.mtime},void 0);try{return await Fe(h,r),this.dirty(r,s),!0}catch(u){let f=u.code;if(f==="EEXIST")return!1;if(f!=="EPERM"&&f!=="ENOTSUP"&&f!=="EOPNOTSUPP"&&f!=="EXDEV")throw u}finally{await J(h,{force:!0}).catch(()=>{}),H.delete(h)}}let l;try{l=await xe(r,"wx")}catch(h){if(h.code==="EEXIST")return!1;throw h}try{await an(l,t),i.mtime>0&&await l.utimes(i.mtime/1e3,i.mtime/1e3),await l.sync()}finally{await l.close()}}return this.dirty(r,s),!0}finally{await J(o,{force:!0}).catch(()=>{}),H.delete(o)}}async sameFile(e,t){if(e===t)return!0;try{let[i,r]=await Promise.all([this.absolute(e),this.absolute(t)]),[s,o]=await Promise.all([ye(i),ye(r)]);return s.dev===o.dev&&s.ino===o.ino}catch(i){if(i.code==="ENOENT")return!1;throw i}}watch(e){let t,i=new Set,r,s=a=>{i.add(a),!t&&(t=setTimeout(()=>{t=void 0;let d=[...i];i.clear();for(let c of d)e(c)},0))},o=()=>{r&&this.listingWatchers.delete(r),this.invalidateListing()};try{this.invalidateListing(),r=ll(this.root,{recursive:!0,persistent:!0},(a,d)=>{if(!d){this.invalidateListing(),s("");return}let c=d.toString().split($t).join("/");Do(ht(c))&&this.invalidateListing();let l=this.normalPath(c);if(this.neverSynced(l)||To(ht(c),P(this.root,c)))return;let h=this.cachedListing?.get(l);a==="change"&&h&&!h.folder?this.listingChanges.add(l):this.invalidateListing(),s(c)}),this.listingWatchers.add(r),r.on("error",o),r.on("close",o)}catch{return o(),()=>{}}return()=>{t&&clearTimeout(t),o(),r?.close()}}},It=class{store;constructor(e,t={}){this.store=new Hn(new Qi(e),{log:(i,...r)=>console.warn(Y(`trew: ${i}`),...r),...t})}load(){return this.store.load()}save(e){return this.store.save(e)}},Qi=class{constructor(e){this.file=e;this.log=Vn(e)}file;log;named=!1;async readSnapshot(){return Po(this.file,`the index at ${this.file}`)}async writeSnapshot(e){await oe(D(this.file),{recursive:!0}),await We(this.file,new TextEncoder().encode(e),!0,{stageIn:P(D(this.file),"tmp")})}async readLog(){return Po(this.log,`the index journal at ${this.log}`)}async appendLog(e){await oe(D(this.log),{recursive:!0});let t=await xe(this.log,"a");try{await an(t,new TextEncoder().encode(e)),await t.sync()}finally{await t.close()}this.named||(await ft(D(this.log)),this.named=!0)}async truncateLog(){await oe(D(this.log),{recursive:!0}),await We(this.log,new Uint8Array(0),!0,{stageIn:P(D(this.log),"tmp")}),this.named=!0}async stamps(){let[e,t]=await Promise.all([Bo(this.file),Bo(this.log)]);return{...e?{snapshot:e}:{},...t?{log:t}:{}}}};async function Bo(n){try{let e=await ye(n);return e.isFile()?{size:e.size,mtime:e.mtimeMs}:void 0}catch{return}}async function Po(n,e){try{return await Mo(n,"utf8")}catch(t){if(t.code==="ENOENT")return;throw new Error(`cannot read ${e}: ${t.message}`)}}var dn=".trew-tmp-",wl=["replace."];function $o(n){return n.includes(dn)||wl.some(e=>n.startsWith(e))}var er=`${dn}keep`;function Do(n){return n.includes(er)}var H=new Set,vl=3600*1e3;function To(n,e){return e!==void 0&&H.has(e)?!0:/\.trew-tmp-[0-9a-z]+(-\d+)?$/.test(n)}var bl=0;async function tr(n,e,t){t!==void 0&&await oe(t,{recursive:!0});let i=t!==void 0?P(t,ht(n)):n;for(let r=0;r<64;r++){let s=on(i,`${dn}${(bl++).toString(36)}${r?`-${r}`:""}`);try{let o=await xe(s,"wx",e);return H.add(s),{tmp:s,handle:o}}catch(o){if(o.code!=="EEXIST")throw o}}throw new Error(`could not find an unused temporary name for ${n}`)}async function El(n){for(let e=0;e<64;e++){let t=on(n,`.${dn}${lt(4).toString("hex")}`);if(!await z(t).catch(()=>{}))return t}throw new Error(`no free temporary name beside ${n}`)}async function kl(n,e){let[t,i]=await Promise.all([z(n).catch(()=>{}),z(e).catch(()=>{})]);return t!==void 0&&i!==void 0&&t.dev===i.dev}async function Al(n){let e=await z(n).catch(()=>{});return e?.isFile()?e.mode&511:void 0}async function Io(n){return(await z(n).catch(()=>{}))?.isDirectory()===!0}var Cl=new Set(["EPERM","ENOTSUP","EOPNOTSUPP"]);async function Sl(n){let e=P(n,`.trew-linkprobe-${process.pid}-${lt(4).toString("hex")}`);try{await(await xe(e,"wx")).close()}catch{return}try{return await Fe(e,`${e}-link`),!0}catch(t){let i=t.code??"";return Cl.has(i)?i:void 0}finally{await J(`${e}-link`,{force:!0}).catch(()=>{}),await J(e,{force:!0}).catch(()=>{})}}async function We(n,e,t=!0,i={}){let r=await nr(n,e,i,i.stageIn);try{await me(r,n)}catch(s){if(await J(r,{force:!0}).catch(()=>{}),H.delete(r),s.code!=="EXDEV"||i.stageIn===void 0)throw s;let o=await nr(n,e,i,void 0);try{await me(o,n)}catch(a){throw await J(o,{force:!0}).catch(()=>{}),a}finally{H.delete(o)}}H.delete(r),t&&await ft(D(n))}async function nr(n,e,t,i){let{tmp:r,handle:s}=await tr(n,t.mode,i);try{try{await an(s,e),t.mode!==void 0&&await s.chmod(t.mode),t.mtime!==void 0&&t.mtime>0&&await s.utimes(t.mtime/1e3,t.mtime/1e3),await s.sync()}finally{await s.close()}return r}catch(o){throw await J(r,{force:!0}).catch(()=>{}),H.delete(r),o}}async function Uo(n,e){await hl(n,e,{recursive:!0,errorOnExist:!0,force:!1,preserveTimestamps:!0});try{await zo(n,e)}catch(i){throw await J(e,{recursive:!0,force:!0}).catch(()=>{}),new Error(`refusing to remove ${n}: its copy at ${e} does not match: ${i.message}`)}try{await xl(e)}catch(i){throw new Error(`refusing to remove ${n}: its copy at ${e} could not be made durable: ${i.message}`)}await sr.pause(n);let t=await Fl(n,e);if(t.length>0)throw new Error(`moved ${n} to ${e}, and left ${t.length} ${t.length===1?"file":"files"} in place because ${t.length===1?"it changed":"they changed"} while the copy was being made: ${t.slice(0,3).join(", ")}`)}async function Fl(n,e){let t=[],i=async(r,s)=>{let o=await ye(r).catch(()=>{});if(o===void 0)return;if(o.isDirectory()){for(let l of await ze(r))await i(P(r,l),P(s,l));await No(r).catch(()=>{t.push(r)});return}if(!o.isFile())return;let a=await El(r);try{await me(r,a)}catch(l){if(l.code==="ENOENT")return;t.push(r);return}let[d,c]=await Promise.all([ut(a).catch(()=>{}),ut(s).catch(()=>{})]);if(await sr.afterCompare(r),d!==void 0&&c!==void 0&&d===c){await J(a,{force:!0});return}try{await Fe(a,r),await J(a,{force:!0}),t.push(r)}catch{t.push(a)}};return await i(n,e),t.filter(r=>!t.some(s=>s!==r&&s.startsWith(`${r}/`)))}async function xl(n){let e=new Set,t=async i=>{let r=await ye(i);if(r.isDirectory()){e.add(i);for(let o of await ze(i))await t(P(i,o));return}if(!r.isFile())return;let s=await xe(i,"r");try{await s.sync()}finally{await s.close()}e.add(D(i))};await t(n),e.add(D(n));for(let i of[...e].sort((r,s)=>s.length-r.length))await ft(i)}async function zo(n,e){let t=await ye(n),i=await ye(e).catch(()=>{});if(i===void 0)throw new Error(`${e} is missing`);if(t.isDirectory()){if(!i.isDirectory())throw new Error(`${e} is not a directory`);for(let o of await ze(n))await zo(P(n,o),P(e,o));return}if(!t.isFile())return;if(!i.isFile()||i.size!==t.size)throw new Error(`${e} is ${i.size} bytes, not ${t.size}`);let[r,s]=await Promise.all([ut(n),ut(e)]);if(r!==s)throw new Error(`${e} does not have the same bytes as ${n}`)}async function ut(n){let e=await xe(n,"r"),t=Oo("sha256");for await(let i of e.createReadStream())t.update(i);return t.digest("hex")}async function an(n,e){let t=0;for(;t<e.length;){let{bytesWritten:i}=await n.write(e.subarray(t));if(i<=0)throw new Error(`wrote 0 of the ${e.length-t} bytes remaining, so the write is not progressing`);t+=i}}var Ro=64;async function ft(n){let e=await xe(n,"r");try{await e.sync()}finally{await e.close()}}var Bl=new Set(["ENOENT","ENOTSUP","EOPNOTSUPP","EINVAL","EPERM"]);async function Zn(n){try{return await ft(n),{synced:!0}}catch(e){let t=e.code??"";return Bl.has(t)?{synced:!0}:{synced:!1,why:`${t||"the filesystem"}: ${e.message}`}}}var ir=class{constructor(e){this.root=e;this.path=P(e,Ki,Ao)}root;path;async read(){try{return await Mo(this.path,"utf8")}catch(e){if(e.code==="ENOENT")return;throw e}}async append(e){await oe(D(this.path),{recursive:!0});let t=await xe(this.path,"a",384);try{await t.writeFile(e,"utf8"),await t.sync()}finally{await t.close()}}async rewrite(e){await oe(D(this.path),{recursive:!0}),await We(this.path,new TextEncoder().encode(e),!0,{stageIn:P(this.root,Ki)})}async stillThere(e){try{return await z(P(this.root,e)),!0}catch(t){if(t.code==="ENOENT")return!1;throw t}}},Pl=32,$l=256;var Q=".trew",be=n=>ve(n,Q,"config.json"),Te=n=>ve(n,Q,"index.json"),or=n=>Vn(Te(n));async function gt(n){let e=be(n),t;try{t=await Jo(e,"utf8")}catch(r){if(r.code==="ENOENT")return;throw new Error(`cannot read ${e}: ${r.message}`)}let i;try{i=JSON.parse(t)}catch(r){throw new Error(`${e} is not valid JSON, so it cannot be trusted: ${r.message}`)}return ro(i,e)}async function ar(n,e){let t=ve(n,Q),i=be(n);await we(n,i),await Wo(t,{recursive:!0}),await we(n,ve(t,"tmp","probe"));let r=JSON.stringify(en(e),null,2)+`
25
+ `;await We(i,new TextEncoder().encode(r),!0,{mode:384,stageIn:ve(t,"tmp")}),await ft(n)}async function Ho(n){await we(n,be(n)),await cn(Rt(n),{force:!0}),await ln(Rt(n),"the record of what needs attention");let e=await Dl(n);await cn(be(n),{force:!0}),await ln(be(n),"the config");let t=await Zn(ve(n,Q));return e??(t.synced?void 0:t.why)}async function Dl(n){await we(n,Te(n)),await cn(or(n),{force:!0}),await ln(or(n),"the index journal"),await cn(Te(n),{force:!0}),await ln(Te(n),"the index");let e=await Zn(ve(n,Q));return e.synced?void 0:e.why}async function Vo(n){await we(n,be(n)),await cn(be(n),{force:!0}),await ln(be(n),"the config");let e=await Zn(ve(n,Q));return e.synced?void 0:e.why}var Rt=n=>ve(n,Q,"attention.json");async function Go(n,e){let t=ve(n,Q),i=Rt(n);await we(n,i),await Wo(t,{recursive:!0}),await we(n,ve(t,"tmp","probe"));let r=JSON.stringify(e)+`
26
+ `;await We(i,new TextEncoder().encode(r),!0,{mode:384,stageIn:ve(t,"tmp")})}async function qo(n){let e=Rt(n),t;try{t=await Jo(e,"utf8")}catch(c){if(c.code==="ENOENT")return;throw new Error(`cannot read ${e}: ${c.message}`)}let i;try{i=JSON.parse(t)}catch(c){throw new Error(`${e} is not valid JSON: ${c.message}`)}let r=typeof i=="object"&&i!==null?i:{},{at:s,count:o,paths:a}=r,d=Array.isArray(a)?a:void 0;if(typeof s!="number"||!Number.isFinite(s)||typeof o!="number"||!Number.isSafeInteger(o)||d===void 0||o<d.length||!d.every(c=>typeof c=="object"&&c!==null&&typeof c.path=="string"&&typeof c.why=="string"))throw new Error(`${e} does not hold a record of what needs attention`);return{at:s,count:o,paths:d}}async function Xo(n){for(let e of[Te(n),or(n)])try{return await jo(e),!0}catch(t){if(t.code!=="ENOENT")throw t}return!1}async function ln(n,e){try{await jo(n)}catch(t){if(t.code==="ENOENT")return;throw t}throw new Error(`${e} at ${n} is still there after removing it`)}async function dr(n,e,t,i=!1){let r=new Tt(e.dir,{configDir:e.configDir,alsoIgnore:e.ignore,observeOnly:i,pairing:be(e.dir)});return await r.probeCase(),{vault:r,store:new It(Te(e.dir)),...ho(n),timeoutMs:e.timeout,coalesceWrites:e.watch,...e.merge?{}:{merge:!1},...e.readOnly||n.readOnly===!0?{readOnly:!0}:{},...process.platform==="win32"?{windows:!0}:{},...e.watch&&t?{onProgress:s=>{s!==void 0&&t.err(` ... ${s}`)}}:{},...e.verbose&&t?{log:(s,...o)=>t.err(` ${s} ${o.map(Tl).join(" ")}`.trimEnd())}:{}}}function Tl(n){return typeof n=="string"?n:JSON.stringify(n)}var Il={pair:1,history:1,search:1,rename:1,restore:1,revoke:1,uninvite:1};function Rl(n){if(!(!n.force||n.command==="unlock"))throw new Error(`${n.command} does not take --force, so it would have been ignored. It is for trew unlock, and only for a lock held on another machine.`)}function Ol(n){let e=Il[n.command??""]??0;if(n.rest.length<=e)return;let i=n.rest.slice(e).map(r=>JSON.stringify(r)).join(", ");throw new Error(e===0?`${n.command} takes no arguments, so ${i} was not used. The vault is chosen with --dir.`:`${n.command} takes one argument, so ${i} was not used.`)}function Yo(n){Ol(n);let e={"--before":["history","deleted"],"--limit":["history","deleted","search"],"--mode":["search"],"--folder":["search"],"--case-sensitive":["search"],"--context":["search"],"--all":["search"],"--after":["search"],"--uid":["restore"],"--to":["restore"],"--ttl":["invite"],"--watch":["sync"],"--verify":["sync"],"--device":["pair"],"--key-file":["pair"],"--no-merge":["sync","restore","preview"],"--read-only":["pair","sync","restore","preview"]};for(let r of n.provided??[]){let s=e[r];if(s&&!s.includes(n.command??""))throw new Error(`${r} is only for ${s.join(", ")}; it has no effect on ${n.command}`)}if(n.keyFile&&n.rest[0]&&n.rest[0]!=="-")throw new Error("give the invite as an argument or with --key-file, not both");if(Rl(n),n.verify&&(n.command!=="sync"||n.watch))throw new Error("--verify is for a one-time sync, without --watch");if(n.before&&n.command!=="history"&&n.command!=="deleted")throw new Error("--before is only for history and deleted");if(n.command==="search"&&n.limitGiven&&n.limit>200)throw new Error(`--limit for search is at most 200 matches a page, not ${n.limit}`);let i={search:"something to search for",history:"the path of a note",restore:"the path of a note",rename:"a name for this device",revoke:"a device id",uninvite:"an invite id"}[n.command??""];if(i&&!n.rest[0])throw new Error(`${n.command} needs ${i}`)}function cr(n){let e={upload:0,download:0,merge:0,copy:0,"delete-local":0,"delete-server":0,unchanged:0,blocked:0,"held-back":0};for(let t of n.files)e[t.action]++;return e}Re();import{readFile as rh,rm as sh}from"node:fs/promises";import{hostname as oh}from"node:os";import{join as ah,resolve as dh}from"node:path";import{link as oa,mkdir as aa,readFile as jl,realpath as Hl,rename as da,rm as Qe,writeFile as ca}from"node:fs/promises";import{randomBytes as hr}from"node:crypto";import{hostname as Ot}from"node:os";import{join as et,resolve as Vl}from"node:path";import{createHash as Zo}from"node:crypto";import{constants as lr,open as Ml,rm as Nl}from"node:fs/promises";import _l from"node:net";import{platform as Ll}from"node:process";import{join as Ul}from"node:path";var zl=32,Ze=Symbol("another process holds this vault"),Qn=new Set,Qo={how:"O_EXLOCK",async take(n,e){let t;try{t=await Ml(e,lr.O_CREAT|lr.O_RDWR|zl|lr.O_NONBLOCK,384)}catch(i){let r=i.code;if(r==="EAGAIN"||r==="EWOULDBLOCK")return Ze;throw i}return Qn.add(t),{how:Qo.how,release:async()=>{Qn.delete(t),await t.close().catch(()=>{})}}}},ea={how:"abstract socket",async take(n){let e=`\0trew.${Zo("sha256").update(n).digest("hex").slice(0,32)}`,t=_l.createServer();t.unref();let i=await new Promise(r=>{t.once("error",s=>r(s.code==="EADDRINUSE"?!1:s)),t.listen(e,()=>r(!0))});if(i instanceof Error)throw i;return i?(Qn.add(t),{how:ea.how,release:async()=>{Qn.delete(t),await new Promise(r=>{t.close(()=>r())})}}):Ze}};function ta(n=Ll){if(!Wl.on){if(n==="darwin")return Qo;if(n==="linux")return ea}}var Wl={on:!1};async function Jl(n,e){let t=Zo("sha256").update(`${process.pid}.${Math.random()}`).digest("hex").slice(0,16),i=Ul(e,`exclusion-probe.${t}`),r=`${i}#probe`,s;try{s=await n.take(r,i)}catch{return!1}if(s===Ze)return!1;try{return await n.take(r,i).catch(()=>Ze)===Ze}finally{await s.release(),await Nl(i,{force:!0}).catch(()=>{})}}var Ko=new Map;function na(n,e){let t=`${n.how}\0${e}`,i=Ko.get(t);return i===void 0&&(i=Jl(n,e),Ko.set(t,i)),i}var la=n=>et(n,Q,"lock"),Gl=n=>et(n,Q,"lock.recovering"),ql=n=>et(n,Q,"lock.excl"),ha=ne("cli/lock:publish"),ia=Ke({beforeTaking:ne("cli/lock:break.beforeTaking"),taken:ne("cli/lock:break.taken")});async function ua(n,e){let t=la(n),i=et(n,Q);await we(n,t),await aa(i,{recursive:!0});let r={pid:process.pid,host:Ot(),command:e,since:Date.now(),token:hr(16).toString("hex")},s=await fa(n);if(s===Ze){let o=await un(t);throw new Error(o===void 0?"another trew is using this vault. Wait for it to finish, or stop it.":`another trew is using this vault: ${o.command} (pid ${o.pid} on ${o.host}, since ${new Date(o.since).toISOString()}). Wait for it to finish, or stop it.`)}if(s!==void 0)try{return await Xl(s,t,r)}catch(o){throw await s.release(),o}for(let o=0;o<3;o++){if(await pa(i,t,r))return async()=>{(await un(t))?.token===r.token&&await Qe(t,{force:!0})};let a=await hn(t);if(a.state!=="absent")throw new Error(Yl(a,t))}throw new Error(`could not take the lock at ${t}: it keeps being taken and released. Something else is running against this vault in a loop.`)}async function Xl(n,e,t){let i=await hn(e);if(i.state==="held"){let s=i.holder;if(s.host!==Ot())throw new Error(`another trew is using this vault: ${s.command} (pid ${s.pid} on ${s.host}, since ${new Date(s.since).toISOString()}). That is a different machine, so this one cannot tell whether it is still running. Wait for it to finish, or if you know it is gone, run trew unlock --force.`);if(s.pid!==process.pid&&ur(s.pid))throw new Error(`this vault is locked by ${s.command} (pid ${s.pid} on ${s.host}), which is still running, but the ${n.how} exclusion for it was free. Either that process is not a trew, which is what a process id reused after a restart looks like, or something is wrong with locking on this filesystem; nothing was changed. If pid ${s.pid} is not a trew, trew unlock --force clears the record; if it is, stop it.`)}let r=`${e}.claiming.${t.token}`;try{await ca(r,JSON.stringify(t),{mode:384}),await ha.pause(""),await da(r,e)}catch(s){throw await Qe(r,{force:!0}).catch(()=>{}),s}return async()=>{(await un(e))?.token===t.token&&await Qe(e,{force:!0}).catch(()=>{}),await n.release()}}async function fa(n){let e=ta();if(e===void 0)return;let t=await Hl(n).catch(()=>Vl(n));if(!await na(e,et(t,Q))){process.stderr.write(`trew: ${e.how} does not lock on this filesystem, so a crashed trew will need trew unlock rather than clearing itself.
27
+ `);return}return await e.take(t,ql(t))}function Yl(n,e){if(n.state==="unreadable")return`something is at ${e} but it does not name a holder, so this vault cannot be locked and nobody can say who has it. Run trew unlock to clear it.`;let t=n.holder,i=new Date(t.since).toISOString(),r=`${t.command} (pid ${t.pid} on ${t.host}, since ${i})`;return t.host!==Ot()?`another trew is using this vault: ${r}. That is a different machine, so this one cannot tell whether it is still running. Wait for it to finish, or if you know it is gone, run trew unlock --force.`:ur(t.pid)?`another trew is using this vault: ${r}. Wait for it to finish, or stop it.`:`this vault is locked by ${r}, which is not running any more. This filesystem does not support the lock that would let trew clear that by itself, so run trew unlock.`}async function ga(n,e=!1){let t=la(n);await we(n,t);let i=Gl(n);await we(n,i),await aa(et(n,Q),{recursive:!0});let r={pid:process.pid,host:Ot(),command:"unlock",since:Date.now(),token:hr(16).toString("hex")};if(!await pa(et(n,Q),i,r)){let s=await un(i);return{did:"refused",was:s??r,why:"another trew unlock is already running against this vault"+(s===void 0?"":` (pid ${s.pid} on ${s.host})`)+`. Two of them at once can hand this vault to two writers, so this one stopped. If no trew is running, remove ${i} and try again`}}try{return await Zl(t,e,await Kl(n))}finally{(await un(i))?.token===r.token&&await Qe(i,{force:!0}).catch(()=>{})}}async function Kl(n){let e=await fa(n);if(e!==void 0)return e===Ze?!1:(await e.release(),!0)}async function Zl(n,e,t){let i=await hn(n);if(i.state==="absent")return{did:"nothing",why:"nothing is holding this vault"};let r=c=>i.state==="held"&&c.token===i.holder.token?t:void 0;if(i.state==="held"&&!ra(i.holder,e,t))return{did:"refused",was:i.holder,why:sa(i.holder,t)};await ia.beforeTaking(n);let s=`${n}.breaking.${hr(8).toString("hex")}`;try{await da(n,s)}catch(c){if(c.code==="ENOENT")return{did:"nothing",why:"the lock was released while this was looking at it"};throw c}await ia.taken(s);let o=await hn(s);if(o.state==="unreadable")return await Qe(s,{force:!0}),{did:"removed",was:void 0,why:"the lock named nobody, so it was debris rather than a holder"};if(o.state==="absent")return{did:"removed",was:void 0,why:"the lock file vanished as it was moved aside"};let a=o.holder;if(ra(a,e,r(a)))return await Qe(s,{force:!0}),{did:"removed",was:a,why:Ql(a)};let d=!0;try{await oa(s,n)}catch{d=!1}return await Qe(s,{force:!0}),d?{did:"refused",was:a,why:sa(a,r(a))}:{did:"contested",was:a,why:`this vault was locked by ${a.command} (pid ${a.pid} on ${a.host}), which is still running, and another trew took the lock while that was being established. Two processes may both believe they hold this vault: stop both, then run unlock again`}}function ra(n,e,t){return n.host!==Ot()?e:!ur(n.pid)||e&&t===!0}function sa(n,e){return n.host!==Ot()?`it is held on ${n.host}, and this machine cannot tell whether that process is still running. Use --force if you know it is not.`:e===!0?`pid ${n.pid} is running, but it holds nothing: this machine's lock for the vault is free, which is what a process id reused after a restart looks like. Check what pid ${n.pid} is, and if it is not a trew, run trew unlock --force`:`pid ${n.pid} is still running, and --force does not break a lock this machine can see is held. Stop it instead.`}function Ql(n){let e=new Date(n.since).toISOString();return`it was held by ${n.command} (pid ${n.pid} on ${n.host}, since ${e}), which is not running`}async function pa(n,e,t){let i=et(n,`claiming.${t.token}`);await ca(i,JSON.stringify(t),{mode:384}),await ha.pause("");try{return await oa(i,e),!0}catch(r){if(r.code!=="EEXIST")throw r;return!1}finally{await Qe(i,{force:!0})}}async function hn(n){let e;try{e=await jl(n,"utf8")}catch(i){let r=i.code;if(r==="ENOENT")return{state:"absent"};if(r==="EISDIR"||r==="EACCES"||r==="EPERM")return{state:"unreadable"};throw i}let t=eh(e);return t===void 0?{state:"unreadable"}:{state:"held",holder:t}}async function un(n){let e=await hn(n).catch(()=>({state:"unreadable"}));return e.state==="held"?e.holder:void 0}function eh(n){try{let e=JSON.parse(n);return typeof e.pid!="number"||typeof e.host!="string"?void 0:{pid:e.pid,host:e.host,command:typeof e.command=="string"?e.command:"unknown command",since:typeof e.since=="number"?e.since:0,token:typeof e.token=="string"?e.token:""}}catch{return}}function ur(n){try{return process.kill(n,0),!0}catch(e){return e.code!=="ESRCH"}}var ya=256,th=1024;function nh(n,e,t){if(n.kind==="filename"||n.line===0)return;let i=Math.max(0,n.column-1-ya),r=[n.column-1-i,n.column-2-i].filter(a=>a>=0&&a<n.text.length);if(r.length===0)return;let s=a=>{if(n.kind==="tag"||t==="tag"){let c=a+1;for(;c<n.text.length&&!/[\s,;:"'`()[\]{}<>|]/u.test(n.text[c]);)c++;return{start:a,end:c}}let d=a;for(let c=[...e].length;c>0&&d<n.text.length;c--)d+=n.text.codePointAt(d)>65535?2:1;return{start:a,end:d}},o=e.toLowerCase();for(let a of r){let d=s(a);if(n.kind==="tag"||t==="tag"){if(n.text[a]==="#"||n.text.slice(a).toLowerCase().startsWith(o))return d;continue}if(n.text.slice(d.start,d.end).toLowerCase()===o)return d}return s(r[0])}function ih(n,e,t,i){let r=i?`${$e.path}${Y(n.path)}${$e.reset}`:Y(n.path);if(n.kind==="filename"||n.line===0)return`${r} (the file name matches)`;let s=`${n.line}:${n.column}`,o=i?`${$e.line}${s}${$e.reset}`:s,a=n.text.endsWith("\r")?n.text.slice(0,-1):n.text,d,c=i?nh({...n,text:a},e,t):void 0;c!==void 0?d=Y(a.slice(0,c.start))+$e.match+Y(a.slice(c.start,c.end))+$e.reset+Y(a.slice(c.end)):d=Y(a);let l=n.column-1>ya,h=n.clipped&&n.text.length>=th-1;return`${r}:${o}: ${l?"\u2026":""}${d}${h?"\u2026":""}`}function ma(n,e,t,i){let r=i?`${$e.path}${Y(n)}${$e.reset}`:Y(n),s=t.endsWith("\r")?t.slice(0,-1):t;return s===""?`${r}-${e}-`:`${r}-${e}- ${Y(s)}`}function wa(n,e,t,i){let r=[];return n.before.forEach((s,o)=>{r.push(ma(n.path,n.line-n.before.length+o,s,i))}),r.push(ih(n,e,t,i)),n.after.forEach((s,o)=>{r.push(ma(n.path,n.line+1+o,s,i))}),r}function fn(n,e,t,i=[]){if(e!==void 0)return e.offline===!0?{kind:"offline",why:e.why}:{kind:"passFailed",why:e.why};if(n===void 0)return{kind:"passFailed",why:"the pass did not report a result"};if(n.retrying>0)return{kind:"retrying",paths:n.retryingPaths};if(n.skipped>0||n.blocked>0)return{kind:"refused",paths:[...n.skippedPaths,...n.inTheWay.map(s=>s.path)]};if(t!==void 0&&!t.complete)return{kind:"recoveryUnknown",why:t.why??"what is waiting to be recovered could not be established"};let r=[...new Set([...i,...(t?.waiting??[]).map(s=>s.at)])];return r.length>0?{kind:"recoveryNeeded",paths:r}:n.conflicted>0?{kind:"conflicted",count:n.conflicted}:{kind:"synced"}}function ei(n){switch(n.kind){case"offline":case"passFailed":case"retrying":case"refused":case"recoveryUnknown":case"recoveryNeeded":return 1;case"conflicted":case"synced":return 0}}function fr(n){switch(n.kind){case"offline":return`cannot reach the server: ${n.why}`;case"passFailed":return`the pass did not finish: ${n.why}`;case"retrying":return n.paths.length===0?"some files could not be sent yet, and will be tried again":`${n.paths.length} not sent yet, and will be tried again: ${n.paths.join(", ")}`;case"refused":return n.paths.length===0?"some files need a person before they can sync":`${n.paths.length} need a person: ${n.paths.join(", ")}`;case"recoveryUnknown":return`everything sent and received, but ${n.why}, so a version may be waiting where nothing lists it`;case"recoveryNeeded":return n.paths.length===1?"1 preserved version needs recovery":`${n.paths.length} preserved versions need recovery`;case"conflicted":return`${n.count} kept both versions, which are both on this device`;case"synced":return"everything is where it should be"}}var va="0.13.1",ba=`trew: the TrewSync command-line client, self-hosted sync for Obsidian
28
28
 
29
29
  trew pair INVITE add this device to a vault with an invite (- reads it
30
30
  from standard input); trew pair alone finishes a
@@ -85,8 +85,8 @@ Options
85
85
  --ignore NAME a folder or file name never to sync, at any depth, repeatable; local to this
86
86
  device. A path another device syncs and this one ignores is reported as
87
87
  ignored rather than failed, and does not affect the exit code
88
- `,pa=new Map([["mcp","trew mcp is gone: TrewSync serves MCP from the server now. Run trewd serve -mcp, and point the agent at the server's /mcp with a token from trewd mcp-token (see docs/agent.md)."],["mcp-token","trew mcp-token is gone: MCP tokens are made on the server now, with trewd mcp-token (see docs/agent.md)."]]),ue={asked:!1,clients:new Set,wake:void 0};function va(){ue.asked=!0,ue.wake?.();for(let n of ue.clients)n.close().catch(()=>{})}async function ba(n,e){ue.asked=!1,ue.clients.clear(),ue.wake=void 0;let t=e.color===!0,r={out:a=>e.out(Jr(a,t)),err:a=>e.err(Jr(a,!1)),...e.color===void 0?{}:{color:e.color}},i=pa.get(n[0]??"");if(i!==void 0)return r.err(`trew: ${i}`),2;let s;try{s=yh(n)}catch(a){return r.err(String(a.message)),2}let o=pa.get(s.command??"");if(o!==void 0)return r.err(`trew: ${o}`),2;if(s.version)return r.out(s.json?U({ok:!0,version:fa}):fa),0;if(s.help||s.command===void 0){for(let a of ga.split(`
89
- `))r.out(a);return s.command===void 0&&!s.help?2:0}try{jo(s)}catch(a){let d=a.message;return s.json?r.out(U({ok:!1,error:d})):r.err(`trew: ${d}`),2}try{switch(s.command){case"pair":return await cn(s,()=>Vl(s,r));case"devices":return await Yl(s,r);case"rename":return await cn(s,()=>Ql(s,r));case"revoke":return await eh(s,r);case"invite":return await Kl(s,r);case"uninvite":return await Zl(s,r);case"sync":return await cn(s,()=>th(s,r));case"status":return await sh(s,r);case"preview":return await dh(s,r);case"repair":return await oh(s,r);case"deleted":return await ah(s,r);case"history":return await ch(s,r);case"search":return await hh(s,r);case"restore":return await cn(s,()=>gh(s,r));case"unlink":return await cn(s,()=>mh(s,r));case"unlock":return await ph(s,r);default:r.err(`no such command: ${s.command}`);for(let a of ga.split(`
90
- `))r.err(a);return 2}}catch(a){let d=ci(a),c=ue.asked?`stopped, as asked (${d})`:d;return s.json?r.out(U({ok:!1,error:c})):r.err(`trew: ${c}`),1}}function ci(n){let e=n instanceof Error?n.message:String(n);return n instanceof C&&n.code==="cursor"&&!e.includes(Mn)?`${e}. ${Mn}`:e}function ln(n){let e=n?.recovery;if(!(e===void 0||e.complete))return e.why??"the record of displaced versions could not be established"}async function cn(n,e){let t=await oa(n.dir,`trew ${n.command??""}`.trim());try{return await e()}finally{await t().catch(()=>{})}}function Ea(n){if(n.deviceGiven)return n.device;let e=[...It(2)].map(t=>t.toString(16).padStart(2,"0")).join("");return`${Hl(n.device,xn-e.length-1)}-${e}`}function Hl(n,e){let t=new TextEncoder;if(t.encode(n).length<=e)return n;let r="";for(let i of n){if(t.encode(r+i).length>e)break;r+=i}return r===""?"device":r}async function Vl(n,e){let t=await nh(n.rest[0],n,"the invite"),i=(t?.split(/\r?\n/).filter(f=>f.trim()!=="")??[]).filter(f=>f.trim().startsWith(kt));if(i.length>1)throw new Error(`that holds ${i.length} invites, one per address of the server, all the same invite. Give trew pair the one line whose address this device can reach.`);let s=i.length===1?i[0].trim():t,o=s===void 0?void 0:Ys(s),a=await lt(n.dir),d,c=!1;if(a!==void 0&&Le(a))Gl(n,a,o),d=a,c=!0,n.json||e.err(`Finishing the pairing already started here, as "${a.device}".`);else{if(a!==void 0)throw new Error(`${n.dir} is already paired. Run trew unlink first if that is really what you want.`);if(await Jo(n.dir))throw new Error(`${n.dir} is not paired but still holds an index at ${De(n.dir)}, left by an unlink that did not finish. Run trew unlink to clear it, then pair again.`);if(o===void 0)throw new Error(`pair needs an invite. ${ka}`);d=Gs(o,Ea(n),{...n.readOnly?{readOnly:!0}:{}})}let l,h,u={timeoutMs:n.timeout,resuming:c,...n.verbose?{log:f=>e.err(` ${f}`)}:{}};try{h=await Qs(d,ql(n.dir,f=>l=f),u)}catch(f){let g=await eo(()=>lt(n.dir)),m=l===void 0?"":` The pairing saved before it was sent is gone from this disk, but flushing that removal failed (${l}); if the machine loses power first it may come back.`;throw new Error(`${f.message}. `+to({remains:g,surface:"cli",where:n.dir})+m)}try{await(await se(h,n,e,{waitForBacklog:!1,inspect:!0})).close()}catch(f){throw new Error(`${n.dir} is paired as "${h.device}" and holds its credential, and connecting as it afterwards failed: ${f.message}. Nothing needs undoing: trew sync connects again.`)}return n.json?e.out(U({ok:!0,paired:n.dir,device:h.device,deviceId:h.deviceId,url:h.url,vaultId:h.vaultId})):(e.out(`Paired ${n.dir} with ${h.url} as "${h.device}". Run trew sync.`),e.out(`This device has its own credential, and nothing else here opens the vault: trew revoke ${hn(h.deviceId)} on any device stops it connecting.`)),0}var ka="The first device pairs from the invite trewd serve writes to <data>/first-invite on the server, or from trewd invite run there; later devices pair from trew invite on any paired device, or from trewd invite on the server again.";function Gl(n,e,t){let r=t===void 0||Je(t.token)===e.invite&&t.url===e.url&&t.vault===e.vaultId,i=n.deviceGiven&&n.device!==e.device,s=n.readOnly&&e.readOnly!==!0;if(r&&!i&&!s)return;let o=r?i?`the name ${JSON.stringify(n.device)}`:"--read-only":"a different invite";throw new Error(`${n.dir} holds a pairing that has not finished, started with ${e.url} as "${e.device}"${e.readOnly===!0?" and read-only":""}, and this asked for ${o}. Run trew pair here with the same invite, or with none, to finish it as it was started; or run trew unlink here to abandon it, and then pair again.`)}function ql(n,e){return{save:async t=>{await ti(n,t),await Xl(n,t)},forget:async()=>{let t=await Uo(n);t!==void 0&&e(t)}}}async function Xl(n,e){let t=await lt(n),r=JSON.stringify(Kt(e));if(t===void 0||JSON.stringify(Kt(t))!==r)throw new Error(`${ve(n)} did not read back as what was just written`)}async function Kl(n,e){let t=await be(n.dir),r=await se(t,n,e,{waitForBacklog:!1,inspect:!0}),i;try{i=await r.invite(n.ttlMs!==void 0?{ttlMs:n.ttlMs}:{})}finally{await r.close()}return n.json?(e.out(U({ok:!0,invite:i.invite,id:i.id,expiresAt:i.expiresAt})),0):(e.out(i.invite),e.out(""),e.out("Paste it into trew pair, or into the TrewSync panel, on the new device."),e.out(i.expiresAt===null?`It works once and does not expire. trew uninvite ${hn(i.id)} cancels it.`:`It works once, until ${Ze(i.expiresAt)}. trew uninvite ${hn(i.id)} cancels it sooner.`),0)}async function Yl(n,e){let t=await be(n.dir),r=await se(t,n,e,{waitForBacklog:!1,inspect:!0}),i=r.deviceId,s,o;try{let d=await r.devices();s=d.devices,o=d.invites.map(c=>({id:c.invite,label:c.label,expiresAt:c.expiresAt}))}finally{await r.close()}if(n.json)return e.out(U({ok:!0,devices:s,invites:o,thisDevice:i})),0;for(let d of s){let c=d.id===i?" (this device)":"";e.out(`${d.id.padEnd(24)} ${d.name.padEnd(16)} added ${Ze(d.createdAt)} ${d.lastSeen===0?"never connected ":`last seen ${Ze(d.lastSeen)}`}${c}`)}e.out(""),e.out(`${s.length} ${s.length===1?"device":"devices"}. trew revoke ID stops one.`);let a=s.filter(d=>d.lastSeen===0);if(a.length>0&&e.out(`${a.length} of them ${a.length===1?"has":"have"} never connected. A pairing that was interrupted and never finished, or abandoned with trew unlink, leaves a row like that.`),e.out(Aa),e.out(""),o.length===0)e.out("No outstanding invites.");else{for(let d of o){let c=d.label===""?"":` ${JSON.stringify(d.label)}`;e.out(`${d.id.padEnd(24)} invite${c}, `+(d.expiresAt===null?"never expires":`expires ${Ze(d.expiresAt)}`))}e.out(""),e.out(`${o.length} outstanding ${o.length===1?"invite":"invites"}. Each one registers one device and then stops working. trew uninvite ID cancels one you did not mean to issue.`)}return 0}var Aa="Revoking stops a device connecting, receiving anything new and writing. It does not un-read what that device already read: every note it synced is still on its disk, in plaintext.";async function Zl(n,e){let t=n.rest[0];if(!t)throw new Error("uninvite needs an invite id, from trew devices");let r=await be(n.dir),i=await se(r,n,e,{waitForBacklog:!1,inspect:!0});try{await i.uninvite(t)}catch(s){throw s instanceof C&&s.code==="badentry"?new Error(`this vault has no outstanding invite ${t}: it may have expired, been cancelled, or been redeemed, in which case it is a device row now. trew devices shows both.`):s}finally{await i.close()}return n.json?(e.out(U({ok:!0,cancelled:t})),0):(e.out(`Cancelled ${t}. That string no longer adds a device.`),e.out("It does not touch a device already added with it. If it was redeemed before this, the device it added is a row in trew devices, and trew revoke ID is what stops that."),0)}async function Ql(n,e){let t=n.rest[0];if(!t)throw new Error("rename needs a name: trew rename laptop");let r=Ea({...n,device:t,deviceGiven:!0}),i=await be(n.dir),s=await se(i,n,e),o;try{o=await s.rename(r)}finally{await s.close()}try{await ti(n.dir,{...i,device:o})}catch(a){return e.err(`The device list now says ${o}, and this device could not write it down: ${a.message}. Conflict copies made here will still say ${JSON.stringify(i.device)} until this runs again.`),n.json&&e.out(U({ok:!1,renamed:!0,name:o,saved:!1})),1}return n.json?(e.out(U({ok:!0,renamed:!0,name:o,saved:!0})),0):(e.out(`This device is now ${o} in the device list.`),e.out("Conflict copies made before now keep the old name; they are notes, not labels."),0)}async function eh(n,e){let t=n.rest[0];if(!t)throw new Error("revoke needs a device id, from trew devices");let r=await be(n.dir),i=await se(r,n,e,{waitForBacklog:!1,inspect:!0}),s;try{({self:s}=await i.revoke(t))}catch(o){throw o instanceof C&&o.code==="nodevice"?new Error(`this vault has no device with id ${t}, so the list you were reading is stale. Run trew devices again.`):o}finally{await i.close()}return n.json?(e.out(U({ok:!0,revoked:t,self:s})),0):(e.out(`Revoked ${t}. Its sessions are closed and it cannot connect again.`),e.out(Aa),s&&(e.out(""),e.out("That was this device. It has stopped syncing; run trew unlink here to forget the pairing, then trew pair with a new invite to add it again: from trew invite on another device, or, if no device is left, from trewd invite on the server.")),0)}async function th(n,e){let t=await be(n.dir);if(n.watch)return await rh(t,n,e);let r=await se(t,n,e);try{let i=await r.settle({verifyContents:n.verify});return Kn(i,n,e,r.serverCursor,r.vault.stranded??[],r.vault.displaced??[],ln(r.vault)),await li(n,e,i),di(i,r.vault)}finally{await r.close()}}async function li(n,e,t){try{await zo(n.dir,{at:Date.now(),count:Zt(t),paths:t.needsAttention??[]})}catch(r){let i=await zl($t(n.dir),{force:!0}).then(()=>"",s=>` The older record could not be removed either: ${s.message}.`);e.err(`trew: could not write down what needs attention, for trew status: ${r.message}.${i}`)}}async function nh(n,e,t){if(e.keyFile!==void 0){if(n!==void 0&&n!=="-")throw new Error(`give ${t} as an argument or with --key-file, not both`);let i=(await Ul(e.keyFile,"utf8")).trim();if(i==="")throw new Error(`${e.keyFile} is empty, so it holds no ${t}`);return i}if(n==="-"){let r=[];for await(let s of process.stdin)r.push(s);let i=Buffer.concat(r).toString("utf8").trim();if(i==="")throw new Error(`nothing arrived on standard input, so there is no ${t}`);return i}return n}function di(n,e){return Xn(dn(n,void 0,e?.recovery,e?.stranded))}async function rh(n,e,t){let r,i=!1,s,o,a=Promise.resolve(),d=c=>{let l=JSON.stringify([Zt(c),c.needsAttention??[]]);l!==o&&(o=l,a=a.then(()=>li(e,t,c)))};return await Zs({...await ni(n,e,t),onPass:c=>{d(c),!(!i||!zr(c))&&Kn(c,e,t,s?.serverCursor??0,s?.vault.stranded??[],s?.vault.displaced??[],ln(s?.vault))},onSyncFailed:c=>{t.err(`trew: a sync failed: ${c.message}. It will try again.`)}},{keepGoing:()=>!ue.asked,onWaiting:c=>{ue.wake=c},onConnecting:c=>{ue.clients.add(c),ue.asked&&c.close().catch(()=>{})},onClient:c=>{s=c,i=!1},onSynced:(c,l)=>{Kn(c,e,t,l,s?.vault.stranded??[],s?.vault.displaced??[],ln(s?.vault)),i=!0,e.json||t.err("Watching for changes. Ctrl-C to stop.")},onDisconnected:(c,l)=>{t.err(`Disconnected: ${c.message}. Trying again in ${wa(l)}.`)},onUnreachable:(c,l)=>{t.err(`Cannot reach the server: ${c.message}. Trying again in ${wa(l)}.`)},onFatal:c=>{r=c}}),await a,r?(t.err(`trew: ${ci(r)}`),t.err("That will not fix itself by trying again."),1):0}async function ih(n,e,t,r,i){try{let s=new xt(n.dir,{configDir:n.configDir,alsoIgnore:n.ignore,observeOnly:!0}),o=await s.list();t?.push(...s.stranded),r?.push(...s.displaced),i!==void 0&&(i.at=s.recovery);let a=new Map(Object.entries(e?.entries??{})),d=0,c=new Set;for(let l of o){if(c.add(l.path),l.folder)continue;let h=a.get(l.path);if(h===void 0){d++;continue}(h.size!==l.size||h.mtime!==Math.ceil(l.mtime))&&d++}for(let[l,h]of a)h.folder||c.has(l)||d++;return d}catch{return"unknown"}}async function sh(n,e){let t=await lt(n.dir);if(!t)throw new Error(Ca(n.dir));let r=Le(t),i=rt(await new Bt(De(n.dir)).load()),s,o;try{s=await Wo(n.dir)}catch(g){o=g.message}let a=[],d=[],c={at:void 0},l={vault:n.dir,device:t.device,server:t.url,vaultId:t.vaultId,cursor:i?.cursor??0,tracked:i?Object.keys(i.entries).length:0,pending:i?.pending.length??0,ignore:[...n.ignore],unsent:await ih(n,i,a,d,c),unsentFrom:"size and timestamp",stranded:a,displaced:d,recoveryComplete:c.at?.complete??!1,recoveryUnknown:c.at===void 0?"this vault could not be scanned, so what is waiting is unknown":c.at.complete?void 0:c.at.why??"the record of displaced versions could not be established",attention:s??null,attentionUnknown:o},h,u=!1;try{if(r)throw new _e(Sa(n.dir));let g=await se(t,n,e,{waitForBacklog:!1,inspect:!0});h={reachable:!0,refused:!1,cursor:g.serverCursor,behind:g.serverCursor-l.cursor},await g.close()}catch(g){let m=!(g instanceof R)&&!(g instanceof _e);u=g instanceof _e,h={reachable:m,refused:m,error:g.message}}let f=!h.reachable||h.refused||l.unsent==="unknown"||l.stranded.length>0||!l.recoveryComplete||(s?.count??0)>0||o!==void 0;if(n.json)return e.out(U({ok:!f,...l,server:h})),f?1:0;if(e.out(`vault ${l.vault}`),e.out(`device ${l.device}`),e.out(`server ${l.server} (vault "${l.vaultId}")`),e.out(`tracked ${l.tracked} files`),e.out(`ignore ${l.ignore.length===0?"nothing beyond the dot rule and the config folder":l.ignore.join(", ")} (this device only)`),e.out(`local cursor ${l.cursor}`),h.cursor!==void 0&&e.out(`server cursor ${h.cursor}`),l.pending>0&&e.out(`pending ${l.pending} files with work outstanding`),l.recoveryUnknown!==void 0&&e.out(`unknown ${l.recoveryUnknown}. There may be versions waiting that are not listed.`),l.stranded.length>0){e.out(`kept ${l.stranded.length} version(s) this client could not put back:`);let g=new Map(l.displaced.map(m=>[m.at,m]));for(let m of l.stranded){e.out(` ${Jl(n.dir,m)}`);let y=g.get(m);y!==void 0&&e.out(` from ${y.from}: ${y.why}`)}}if(o!==void 0)e.out(`unknown what the last sync left needing attention could not be read: ${o}. trew sync writes it again.`);else if(s!==void 0&&s.count>0){e.out(`attention ${s.count} ${s.count===1?"path needs":"paths need"} a person, as the sync at ${Ze(s.at).trim()} found them:`);for(let{path:m,why:y}of s.paths)e.out(` ${wh(m)}: ${y}`);let g=s.count-s.paths.length;g>0&&e.out(` and ${g} more.`)}return u?(e.out(r?`state not connected: ${h.error}`:`state nothing to connect with: ${h.error}`),1):h.refused?(e.out(`state the server is up and refused this device: ${h.error}`),1):h.reachable?(e.out(h.behind!==0?`state ${h.behind} changes behind`:l.pending>0?`state caught up with the server, with ${l.pending} still not applied here`:l.unsent==="unknown"?"state caught up with the server; this vault could not be read, so what is unsent from here is unknown":l.unsent>0?`state caught up with the server, with ${l.unsent} not yet sent from here`:"state caught up with the server; nothing here looks changed (sizes and timestamps only)"),f?1:0):(e.out(`state cannot reach the server: ${h.error}`),1)}async function oh(n,e){let t=await be(n.dir),r=await se(t,n,e,{inspect:!0});try{let i=await r.repair(),s=i.failed.length>0||i.stillMissing>0;if(n.json)return e.out(U({ok:!s,...i})),s?1:0;i.stored>0?e.out(`Sent ${i.stored} ${i.stored===1?"body":"bodies"} the server was missing.`):e.out(`The server has every body this device can offer, from ${i.scanned} ${i.scanned===1?"note":"notes"}.`);for(let o of i.failed)e.err(`${o.path}: ${o.why}`);return i.stillMissing>0&&e.err(`${i.stillMissing} ${i.stillMissing===1?"body was":"bodies were"} asked for, sent, and the server still does not have them. Check its disk.`),i.couldNotOffer>0&&e.out(`${i.couldNotOffer} ${i.couldNotOffer===1?"chunk belongs":"chunks belong"} to notes this device has edited since they were last synced, so it cannot supply them.`),e.out(""),e.out("This repairs what this device holds. Run it on your other devices too, then `trewd verify` on the server for what is still missing: history this device never had is not visible from here."),s?1:0}finally{await r.close()}}async function ah(n,e){let t=await be(n.dir),r=await se(t,n,e,{inspect:!0});try{let i=await r.deleted(n.limitGiven?n.limit:void 0,n.before>0?n.before:void 0);if(n.json)return e.out(U({ok:!0,deleted:i.notes,more:i.more})),0;if(i.notes.length===0)return e.out("Nothing has been deleted from this vault."),0;let s=0;for(let a of i.notes){let d=a.restorable===0?" (content purged)":"";a.restorable===0&&s++,e.out(`${Ze(a.mtime)} ${a.device.padEnd(12)} ${a.path}${d}`)}e.out("");let o=i.notes.length-s;return s===0?e.out(`${o} deleted, all still recoverable. trew restore PATH brings one back.`):e.out(`${i.notes.length} deleted. ${o} can be restored; ${s} had their history purged and cannot be.`),i.more&&i.oldest!==void 0&&e.out(`There are older deletions than these. trew deleted --before ${i.oldest} shows the page before this one.`),0}finally{await r.close()}}var ma=500;async function dh(n,e){let t=await se(await be(n.dir),n,e,{inspect:!0});try{let r=await t.preview(),i=!r.files.some(s=>s.action==="blocked");if(n.json)e.out(U({ok:i,...r,counts:ri(r)}));else{e.out("Preview only. Files are checked again during sync.");for(let s of r.files)s.action!=="unchanged"&&e.out(`${s.action}: ${s.path}`);e.out(JSON.stringify(ri(r)))}return i?0:1}finally{await t.close()}}async function ch(n,e){let t=n.rest[0];if(!t)throw new Error("history needs the path of a note");let r=await be(n.dir),i=await se(r,n,e,{inspect:!0});try{let s=Math.min(n.limit,ma),o=await i.history(t,{limit:s,...n.before?{before:n.before}:{}}),a=o.length===s?o.at(-1).uid:null;if(n.json)return e.out(U({ok:!0,path:t,versions:o,limit:s,nextBefore:a})),0;if(o.length===0)return e.out(`The server holds no versions of ${t}.`),0;for(let d of o){let c=d.deleted?"deleted":d.folder?"folder":`${hi(d.size)}`;e.out(`${String(d.uid).padStart(7)} ${Ze(d.mtime)} ${d.device.padEnd(12)} ${c}`)}return e.out(""),n.limit>s&&e.out(`Showing the newest ${s}: the server lists at most ${ma} versions at a time, so --limit ${n.limit} was capped there.`),e.out("trew restore PATH --uid N brings one of these back."),a!==null&&e.out(`Older versions: trew history PATH --before ${a}`),0}finally{await i.close()}}var ya=3,lh=5;async function hh(n,e){let t=n.rest[0],r=n.mode??"content",i=await se(await be(n.dir),n,e,{inspect:!0}),s=e.color===!0&&!n.json,o=[],a=n.after,d=!1;try{for(;;){let g=await uh(i,n,t,r,a);if(o.push(g),!n.json)for(let m of g.matches){n.context>0&&d&&e.out("--");for(let y of ua(m,t,r,s))e.out(y);d=!0}if(!n.all||g.nextAfter===null)break;a=g.nextAfter}}finally{await i.close()}let c=o.at(-1),l=o.flatMap(g=>g.matches),h=o.flatMap(g=>g.skipped),u=o.reduce((g,m)=>g+m.scanned,0),f=h.length===0;if(n.json)return e.out(U({ok:f,query:t,mode:r,matches:l,skipped:h,complete:f&&c.nextAfter===null,nextAfter:c.nextAfter,head:c.head,indexedHead:c.indexedHead,index:c.index,pages:o.length,scanned:u,scannedBytes:o.reduce((g,m)=>g+m.scannedBytes,0)})),f?0:1;if(l.length===0&&e.err(c.nextAfter===null?"No matches.":"No matches on this page."),r!=="filename"&&(c.index.usable?c.indexedHead<c.head&&e.err(`The server's search index is still catching up (version ${c.indexedHead} of ${c.head}); notes it has not reached were read in full, so nothing is missed.`):e.err(`The server's search index was not used (${c.index.why??"no reason given"}), so every note was read: nothing is missed, it is only slower.`)),l.some(g=>g.clipped)&&e.err("Long lines are shortened; --json has each match's line as the server sent it."),c.nextAfter!==null&&e.err(`More matches may follow: this is ${o.length===1?"the first page":`${o.length} pages`}. trew search --all shows every page, or --after ${c.nextAfter} the next one.`),!f){e.err(`${h.length} ${h.length===1?"note":"notes"} could not be searched, so a match may be missing:`);for(let g of h)e.err(` ${K(g.path)}: ${K(g.why)}`)}return f?0:1}async function uh(n,e,t,r,i){for(let s=0;;s++)try{return await n.search({query:t,mode:r,...e.folder!==void 0?{folder:e.folder}:{},...e.caseSensitive?{caseSensitive:!0}:{},...e.context>0?{contextLines:e.context}:{},...e.limitGiven?{limit:e.limit}:{},...i!==void 0?{after:i}:{}})}catch(o){if(!(o instanceof C)||o.code!=="toomany"||s>=lh)throw fh(o);let a=Math.min(Math.max(o.retryAfterMs??1e3,50),3e4);await new Promise(d=>setTimeout(d,a))}}function fh(n){return n instanceof C?n.code==="proto"||n.code==="protostate"&&n.message.includes('"search"')?new Error("this server does not search for devices: it is older than this client. Upgrade the server (docs/server.md, Upgrade order)."):n.code==="stale"&&n.message.startsWith("expired:")?new Error("that --after cursor belongs to another search, or to the vault's history before a restore or a purge changed it; search again without it."):n.code==="toomany"?new Error(`the server is busy with searches: ${n.message}. Try again in a moment.`):n:n}async function gh(n,e){let t=n.rest[0];if(!t)throw new Error("restore needs the path of a note");let r=await be(n.dir),i=await se(r,n,e);try{let s;if(n.uid!==void 0){if(s=await i.findVersion(t,l=>l.uid===n.uid),!s)throw new Error(`the server has no version ${n.uid} of ${t}`)}else if(s=await i.newestContentVersion(t),!s)throw new Error(`the server holds no version of ${t} with any content in it`);let o=await i.restore(s,n.to),a=()=>{e.out(`Restored version ${s.uid} of ${t} to ${o.path} (${hi(o.bytes)}, from ${Ze(s.mtime)}).`),o.path!==(n.to??t)&&e.out(`Written to ${o.path}, because something is already at ${n.to??t}.`)},d;try{d=await i.settle({coalesceWrites:!1})}catch(l){let h=ci(l),u=dn(void 0,{why:h,offline:l instanceof R}),f=i.engine.serverHasOurs(o.path);return n.json?e.out(U({ok:!1,restored:!0,path:o.path,uid:s.uid,bytes:o.bytes,sent:f,outcome:u,error:h})):(a(),e.err(`The restored copy is on this device, but sync did not finish: ${h}. Run trew sync to retry.`)),1}let c=i.engine.serverHasOurs(o.path);if(await li(n,e,d),n.json){let l=dn(d,void 0,i.vault.recovery,i.vault.stranded),h=Xn(l);return e.out(U({ok:h===0,restored:!0,sent:c,outcome:l,path:o.path,uid:s.uid,bytes:o.bytes,sync:d,recoveryUnknown:ln(i.vault)??null})),h}return a(),c?e.out("Sent to the server, so your other devices will pick it up."):n.readOnly||r.readOnly===!0?e.out("The restored copy stays on this device because it is read-only."):e.out("The restored copy has not been acknowledged by the server. Run trew sync to retry."),di(d,i.vault)!==0&&Kn(d,n,e,i.serverCursor,i.vault.stranded??[],i.vault.displaced??[],ln(i.vault)),di(d,i.vault)}finally{await i.close()}}async function ph(n,e){let t=await da(n.dir,n.force);if(n.json){let r=t.did==="nothing"||t.did==="removed";return e.out(U({ok:r,did:t.did,why:t.why,...t.did==="nothing"?{}:{holder:t.was??null}})),r?0:1}switch(t.did){case"nothing":return e.out(t.why),0;case"removed":return e.out(`the lock is clear: ${t.why}.`),0;case"refused":return e.err(`trew: the lock was not cleared, because ${t.why}.`),1;case"contested":return e.err(`trew: ${t.why}.`),1}}async function mh(n,e){let t=await lt(n.dir).catch(()=>{}),r=await Lo(n.dir),i=t!==void 0&&Le(t);return n.json?(e.out(U({ok:!0,unlinked:n.dir,wasPaired:t!==void 0&&!i,...i?{unfinished:!0}:{},...r!==void 0?{notDurable:r}:{},...t?.deviceId!==void 0?{deviceId:t.deviceId}:{}})),0):(e.out(`Forgot the pairing for ${n.dir}. Every note is where it was.`),r!==void 0&&(e.out(""),e.out(`The pairing is gone from this disk, but flushing that removal failed: ${r}`),e.out("If the machine loses power before the filesystem catches up, the pairing may come back. Check the disk, and run `trew unlink` again if it does.")),e.out("Nothing was removed from the server."),i?(e.out(""),e.out(`The pairing here had not finished. If the server registered it, the vault's device list has a row ${t.deviceId} that has never connected, and nothing here can remove it now: run trew revoke ${hn(t.deviceId)} on a device that still syncs.`)):t?.deviceId!==void 0&&(e.out(""),e.out(`This device is still in the vault's device list as ${t.deviceId}. Nothing here can remove it now, because the credential for it has just been forgotten: run trew revoke ${hn(t.deviceId)} on a device that still syncs.`)),0)}async function se(n,e,t,r={}){let i=new Yt({...await ni(n,e,t,r.inspect),...r.inspect===!0?{inspect:!0}:{}});ue.clients.add(i);try{if(ue.asked)throw new Error("stopped before connecting, as asked");await i.connect(r)}catch(s){throw await i.close(),s}return i}function Kn(n,e,t,r,i=[],s=[],o=void 0){let a=dn(n,void 0,{complete:o===void 0,...o!==void 0?{why:o}:{},waiting:s},i);if(e.json){t.out(U({ok:Xn(a)===0,outcome:a,...n,serverCursor:r,stranded:i,displaced:s,recoveryUnknown:o??null}));return}let d=[],c=(l,h)=>{l>0&&d.push(`${String(l).padStart(5)} ${h}`)};if(c(n.uploaded,"uploaded"),c(n.downloaded,"downloaded"),c(n.merged,"merged"),c(n.conflicted,"kept both versions"),c(n.deletedLocally,"deleted here"),c(n.deletedRemotely,"deleted on the server"),c(n.restored,"brought back, having been edited elsewhere"),c(n.foldersCreated,"folders created"),c(n.foldersDeletedLocally,"folders removed here, deleted elsewhere"),c(n.foldersDeletedRemotely,"folders deleted on the server"),c(n.waiting,"waiting for a write to settle"),c(n.retrying,"failed, will try again"),c(Zt(n),"need attention"),c(n.heldBack,"changed here and not sent, because this device is read-only"),c(n.ignored,"ignored here, and synced by another device"),d.length===0)t.out(a.kind==="synced"?"Nothing to do. Everything here matches the server.":ai(a));else{for(let l of d)t.out(l);a.kind!=="synced"&&t.out(` ${ai(a)}`)}if(n.needsAttention.length>0){t.out("");for(let l of ro(n," "))t.out(l)}if(o!==void 0&&(t.out(""),t.out(` ${o}. There may be versions waiting that are not listed.`)),i.length>0){t.out(""),t.out(` ${i.length} version(s) this client could not put back:`);let l=new Map(s.map(h=>[h.at,h]));for(let h of i){t.out(` ${h}`);let u=l.get(h);u!==void 0&&t.out(` from ${u.from}: ${u.why}`)}}n.chunksSent>0&&t.out(`${String(n.chunksSent).padStart(5)} chunks sent, ${hi(n.bytesSent)}`),n.conflicted>0&&t.err('Look for files with "Conflicted copy" in the name. Both versions are kept.')}function yh(n){let e={provided:new Set,verify:!1,rest:[],dir:process.cwd(),device:Wl().split(".")[0]||"device",deviceGiven:!1,json:!1,watch:!1,limit:20,limitGiven:!1,before:0,keyFile:void 0,verbose:!1,help:!1,version:!1,force:!1,merge:!0,readOnly:!1,timeout:3e4,configDir:Zr,ignore:[],caseSensitive:!1,context:0,all:!1},t=new Set(["--dir","--device","--timeout","--uid","--to","--limit","--before","--key-file","--config-dir","--ignore","--ttl","--mode","--folder","--context","--after"]),r=!1;for(let i=0;i<n.length;i++){let s=n[i];if(r){e.command===void 0?e.command=s:e.rest.push(s);continue}if(s==="--"){r=!0;continue}s.startsWith("-")&&e.provided.add(s);let o;if(t.has(s)&&(o=n[++i],o===void 0||o.startsWith("--")))throw new Error(`${s} needs a value`);switch(s){case"--dir":e.dir=jl(o);break;case"--device":e.device=o,e.deviceGiven=!0;break;case"--timeout":{let a=Number(o);if(!Number.isFinite(a)||a<=0)throw new Error(`--timeout wants a number of milliseconds, not ${o}`);e.timeout=a;break}case"--uid":{let a=Number(o);if(!Number.isSafeInteger(a)||a<=0)throw new Error(`--uid wants a version number, not ${o}`);e.uid=a;break}case"--to":e.to=o;break;case"--ttl":e.ttlMs=vh(o);break;case"--config-dir":e.configDir=yn(o);break;case"--ignore":if(o===""||o==="."||o===".."||o.includes("/"))throw new Error(`--ignore wants one folder or file name, not ${JSON.stringify(o)}: it is matched against each part of a path on its own, so a name with a slash in it matches nothing, and . and .. are never a part`);e.ignore.push(o);break;case"--limit":{let a=Number(o);if(!Number.isSafeInteger(a)||a<=0)throw new Error(`--limit wants a count, not ${o}`);e.limit=a,e.limitGiven=!0;break}case"--key-file":e.keyFile=o;break;case"--before":{let a=Number(o);if(!Number.isSafeInteger(a)||a<=0)throw new Error(`--before wants a version number, not ${o}`);e.before=a;break}case"--mode":if(!["content","filename","both","tag"].includes(o))throw new Error(`--mode is content, filename, both or tag, not ${o}`);e.mode=o;break;case"--folder":e.folder=o;break;case"--context":{let a=Number(o);if(!Number.isSafeInteger(a)||a<0||a>ya)throw new Error(`--context wants 0 to ${ya} lines, not ${o}`);e.context=a;break}case"--after":e.after=o;break;case"--case-sensitive":e.caseSensitive=!0;break;case"--all":e.all=!0;break;case"--verify":e.verify=!0;break;case"--force":e.force=!0;break;case"--no-merge":e.merge=!1;break;case"--read-only":e.readOnly=!0;break;case"--json":e.json=!0;break;case"--version":case"-V":e.version=!0;break;case"--watch":e.watch=!0;break;case"--verbose":case"-v":e.verbose=!0;break;case"--help":case"-h":e.help=!0;break;default:if(s!=="-"&&s.startsWith("-"))throw new Error(`no such option: ${s}`);e.command===void 0?e.command=s:e.rest.push(s)}}return e}async function be(n){let e=await lt(n);if(!e)throw new Error(Ca(n));if(Le(e))throw new _e(Sa(n));return e}function hn(n){return n.startsWith("-")?`-- ${n}`:n}function Ca(n){return`${n} is not paired. Run trew pair with an invite. ${ka}`}function Sa(n){return`the pairing in ${n} has not finished: an invite was being redeemed and no answer was heard, so whether the server registered this device is not known. Run trew pair here to finish it with the credential already saved, which works even after the invite has expired if the server did register it.`}function wh(n){let e="";for(let t of n){let r=t.codePointAt(0);e+=r<32||r>=127&&r<=159?`\\u{${r.toString(16)}}`:t}return e}function vh(n){let e=/^(\d+)\s*(ms|s|m|h)?$/.exec(n.trim());if(!e)throw new Error(`--ttl wants a duration like 10m, 90s or 1h, not ${n}`);let t=Number(e[1]),r=e[2]??"s",i=t*(r==="ms"?1:r==="s"?1e3:r==="m"?6e4:36e5);if(i<=0)throw new Error("--ttl must be more than nothing");if(i>36e5)throw new Error("--ttl can be at most 1h, which is the most the server allows");return i}function Ze(n){if(!Number.isFinite(n)||n<=0)return"unknown ";let e=new Date(n),t=r=>String(r).padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())} ${t(e.getHours())}:${t(e.getMinutes())}`}function wa(n){return`${Math.max(1,Math.round(n/1e3))}s`}function hi(n){return n<1024?`${n} B`:n<1024*1024?`${(n/1024).toFixed(1)} KiB`:`${(n/(1024*1024)).toFixed(1)} MiB`}var ui;for(let n of["SIGINT","SIGTERM"])process.once(n,()=>{ui??=n,va(),process.stdin.destroy(),setTimeout(()=>process.kill(process.pid,n),5e3).unref()});var bh=await ba(process.argv.slice(2),{out:n=>process.stdout.write(n+`
88
+ `,Ea=new Map([["mcp","trew mcp is gone: TrewSync serves MCP from the server now. Run trewd serve -mcp, and point the agent at the server's /mcp with a token from trewd mcp-token (see docs/agent.md)."],["mcp-token","trew mcp-token is gone: MCP tokens are made on the server now, with trewd mcp-token (see docs/agent.md)."]]),ue={asked:!1,clients:new Set,wake:void 0};function Sa(){ue.asked=!0,ue.wake?.();for(let n of ue.clients)n.close().catch(()=>{})}async function Fa(n,e){ue.asked=!1,ue.clients.clear(),ue.wake=void 0;let t=e.color===!0,i={out:a=>e.out(qi(a,t)),err:a=>e.err(qi(a,!1)),...e.color===void 0?{}:{color:e.color}},r=Ea.get(n[0]??"");if(r!==void 0)return i.err(`trew: ${r}`),2;let s;try{s=Oh(n)}catch(a){return i.err(String(a.message)),2}let o=Ea.get(s.command??"");if(o!==void 0)return i.err(`trew: ${o}`),2;if(s.version)return i.out(s.json?U({ok:!0,version:va}):va),0;if(s.help||s.command===void 0){for(let a of ba.split(`
89
+ `))i.out(a);return s.command===void 0&&!s.help?2:0}try{Yo(s)}catch(a){let d=a.message;return s.json?i.out(U({ok:!1,error:d})):i.err(`trew: ${d}`),2}try{switch(s.command){case"pair":return await gn(s,()=>lh(s,i));case"devices":return await ph(s,i);case"rename":return await gn(s,()=>yh(s,i));case"revoke":return await wh(s,i);case"invite":return await gh(s,i);case"uninvite":return await mh(s,i);case"sync":return await gn(s,()=>vh(s,i));case"status":return await Ah(s,i);case"preview":return await Fh(s,i);case"repair":return await Ch(s,i);case"deleted":return await Sh(s,i);case"history":return await xh(s,i);case"search":return await Ph(s,i);case"restore":return await gn(s,()=>Th(s,i));case"unlink":return await gn(s,()=>Rh(s,i));case"unlock":return await Ih(s,i);default:i.err(`no such command: ${s.command}`);for(let a of ba.split(`
90
+ `))i.err(a);return 2}}catch(a){let d=pr(a),c=ue.asked?`stopped, as asked (${d})`:d;return s.json?i.out(U({ok:!1,error:c})):i.err(`trew: ${c}`),1}}function pr(n){let e=n instanceof Error?n.message:String(n);return n instanceof C&&n.code==="cursor"&&!e.includes(zn)?`${e}. ${zn}`:e}function pn(n){let e=n?.recovery;if(!(e===void 0||e.complete))return e.why??"the record of displaced versions could not be established"}async function gn(n,e){let t=await ua(n.dir,`trew ${n.command??""}`.trim());try{return await e()}finally{await t().catch(()=>{})}}function xa(n){if(n.deviceGiven)return n.device;let e=[...Lt(2)].map(t=>t.toString(16).padStart(2,"0")).join("");return`${ch(n.device,In-e.length-1)}-${e}`}function ch(n,e){let t=new TextEncoder;if(t.encode(n).length<=e)return n;let i="";for(let r of n){if(t.encode(i+r).length>e)break;i+=r}return i===""?"device":i}async function lh(n,e){let t=await bh(n.rest[0],n,"the invite"),r=(t?.split(/\r?\n/).filter(f=>f.trim()!=="")??[]).filter(f=>f.trim().startsWith(xt));if(r.length>1)throw new Error(`that holds ${r.length} invites, one per address of the server, all the same invite. Give trew pair the one line whose address this device can reach.`);let s=r.length===1?r[0].trim():t,o=s===void 0?void 0:so(s),a=await gt(n.dir),d,c=!1;if(a!==void 0&&Ue(a))hh(n,a,o),d=a,c=!0,n.json||e.err(`Finishing the pairing already started here, as "${a.device}".`);else{if(a!==void 0)throw new Error(`${n.dir} is already paired. Run trew unlink first if that is really what you want.`);if(await Xo(n.dir))throw new Error(`${n.dir} is not paired but still holds an index at ${Te(n.dir)}, left by an unlink that did not finish. Run trew unlink to clear it, then pair again.`);if(o===void 0)throw new Error(`pair needs an invite. ${Ba}`);d=to(o,xa(n),{...n.readOnly?{readOnly:!0}:{}})}let l,h,u={timeoutMs:n.timeout,resuming:c,...n.verbose?{log:f=>e.err(` ${f}`)}:{}};try{h=await ao(d,uh(n.dir,f=>l=f),u)}catch(f){let g=await co(()=>gt(n.dir)),m=l===void 0?"":` The pairing saved before it was sent is gone from this disk, but flushing that removal failed (${l}); if the machine loses power first it may come back.`;throw new Error(`${f.message}. `+lo({remains:g,surface:"cli",where:n.dir})+m)}try{await(await ae(h,n,e,{waitForBacklog:!1,inspect:!0})).close()}catch(f){throw new Error(`${n.dir} is paired as "${h.device}" and holds its credential, and connecting as it afterwards failed: ${f.message}. Nothing needs undoing: trew sync connects again.`)}return n.json?e.out(U({ok:!0,paired:n.dir,device:h.device,deviceId:h.deviceId,url:h.url,vaultId:h.vaultId})):(e.out(`Paired ${n.dir} with ${h.url} as "${h.device}". Run trew sync.`),e.out(`This device has its own credential, and nothing else here opens the vault: trew revoke ${mn(h.deviceId)} on any device stops it connecting.`)),0}var Ba="The first device pairs from the invite trewd serve writes to <data>/first-invite on the server, or from trewd invite run there; later devices pair from trew invite on any paired device, or from trewd invite on the server again.";function hh(n,e,t){let i=t===void 0||je(t.token)===e.invite&&t.url===e.url&&t.vault===e.vaultId,r=n.deviceGiven&&n.device!==e.device,s=n.readOnly&&e.readOnly!==!0;if(i&&!r&&!s)return;let o=i?r?`the name ${JSON.stringify(n.device)}`:"--read-only":"a different invite";throw new Error(`${n.dir} holds a pairing that has not finished, started with ${e.url} as "${e.device}"${e.readOnly===!0?" and read-only":""}, and this asked for ${o}. Run trew pair here with the same invite, or with none, to finish it as it was started; or run trew unlink here to abandon it, and then pair again.`)}function uh(n,e){return{save:async t=>{await ar(n,t),await fh(n,t)},forget:async()=>{let t=await Vo(n);t!==void 0&&e(t)}}}async function fh(n,e){let t=await gt(n),i=JSON.stringify(en(e));if(t===void 0||JSON.stringify(en(t))!==i)throw new Error(`${be(n)} did not read back as what was just written`)}async function gh(n,e){let t=await Ee(n.dir),i=await ae(t,n,e,{waitForBacklog:!1,inspect:!0}),r;try{r=await i.invite(n.ttlMs!==void 0?{ttlMs:n.ttlMs}:{})}finally{await i.close()}return n.json?(e.out(U({ok:!0,invite:r.invite,id:r.id,expiresAt:r.expiresAt})),0):(e.out(r.invite),e.out(""),e.out("Paste it into trew pair, or into the TrewSync panel, on the new device."),e.out(r.expiresAt===null?`It works once and does not expire. trew uninvite ${mn(r.id)} cancels it.`:`It works once, until ${tt(r.expiresAt)}. trew uninvite ${mn(r.id)} cancels it sooner.`),0)}async function ph(n,e){let t=await Ee(n.dir),i=await ae(t,n,e,{waitForBacklog:!1,inspect:!0}),r=i.deviceId,s,o;try{let d=await i.devices();s=d.devices,o=d.invites.map(c=>({id:c.invite,label:c.label,expiresAt:c.expiresAt}))}finally{await i.close()}if(n.json)return e.out(U({ok:!0,devices:s,invites:o,thisDevice:r})),0;for(let d of s){let c=d.id===r?" (this device)":"";e.out(`${d.id.padEnd(24)} ${d.name.padEnd(16)} added ${tt(d.createdAt)} ${d.lastSeen===0?"never connected ":`last seen ${tt(d.lastSeen)}`}${c}`)}e.out(""),e.out(`${s.length} ${s.length===1?"device":"devices"}. trew revoke ID stops one.`);let a=s.filter(d=>d.lastSeen===0);if(a.length>0&&e.out(`${a.length} of them ${a.length===1?"has":"have"} never connected. A pairing that was interrupted and never finished, or abandoned with trew unlink, leaves a row like that.`),e.out(Pa),e.out(""),o.length===0)e.out("No outstanding invites.");else{for(let d of o){let c=d.label===""?"":` ${JSON.stringify(d.label)}`;e.out(`${d.id.padEnd(24)} invite${c}, `+(d.expiresAt===null?"never expires":`expires ${tt(d.expiresAt)}`))}e.out(""),e.out(`${o.length} outstanding ${o.length===1?"invite":"invites"}. Each one registers one device and then stops working. trew uninvite ID cancels one you did not mean to issue.`)}return 0}var Pa="Revoking stops a device connecting, receiving anything new and writing. It does not un-read what that device already read: every note it synced is still on its disk, in plaintext.";async function mh(n,e){let t=n.rest[0];if(!t)throw new Error("uninvite needs an invite id, from trew devices");let i=await Ee(n.dir),r=await ae(i,n,e,{waitForBacklog:!1,inspect:!0});try{await r.uninvite(t)}catch(s){throw s instanceof C&&s.code==="badentry"?new Error(`this vault has no outstanding invite ${t}: it may have expired, been cancelled, or been redeemed, in which case it is a device row now. trew devices shows both.`):s}finally{await r.close()}return n.json?(e.out(U({ok:!0,cancelled:t})),0):(e.out(`Cancelled ${t}. That string no longer adds a device.`),e.out("It does not touch a device already added with it. If it was redeemed before this, the device it added is a row in trew devices, and trew revoke ID is what stops that."),0)}async function yh(n,e){let t=n.rest[0];if(!t)throw new Error("rename needs a name: trew rename laptop");let i=xa({...n,device:t,deviceGiven:!0}),r=await Ee(n.dir),s=await ae(r,n,e),o;try{o=await s.rename(i)}finally{await s.close()}try{await ar(n.dir,{...r,device:o})}catch(a){return e.err(`The device list now says ${o}, and this device could not write it down: ${a.message}. Conflict copies made here will still say ${JSON.stringify(r.device)} until this runs again.`),n.json&&e.out(U({ok:!1,renamed:!0,name:o,saved:!1})),1}return n.json?(e.out(U({ok:!0,renamed:!0,name:o,saved:!0})),0):(e.out(`This device is now ${o} in the device list.`),e.out("Conflict copies made before now keep the old name; they are notes, not labels."),0)}async function wh(n,e){let t=n.rest[0];if(!t)throw new Error("revoke needs a device id, from trew devices");let i=await Ee(n.dir),r=await ae(i,n,e,{waitForBacklog:!1,inspect:!0}),s;try{({self:s}=await r.revoke(t))}catch(o){throw o instanceof C&&o.code==="nodevice"?new Error(`this vault has no device with id ${t}, so the list you were reading is stale. Run trew devices again.`):o}finally{await r.close()}return n.json?(e.out(U({ok:!0,revoked:t,self:s})),0):(e.out(`Revoked ${t}. Its sessions are closed and it cannot connect again.`),e.out(Pa),s&&(e.out(""),e.out("That was this device. It has stopped syncing; run trew unlink here to forget the pairing, then trew pair with a new invite to add it again: from trew invite on another device, or, if no device is left, from trewd invite on the server.")),0)}async function vh(n,e){let t=await Ee(n.dir);if(n.watch)return await Eh(t,n,e);let i=await ae(t,n,e);try{let r=await i.settle({verifyContents:n.verify});return ti(r,n,e,i.serverCursor,i.vault.stranded??[],i.vault.displaced??[],pn(i.vault)),await mr(n,e,r),gr(r,i.vault)}finally{await i.close()}}async function mr(n,e,t){try{await Go(n.dir,{at:Date.now(),count:nn(t),paths:t.needsAttention??[]})}catch(i){let r=await sh(Rt(n.dir),{force:!0}).then(()=>"",s=>` The older record could not be removed either: ${s.message}.`);e.err(`trew: could not write down what needs attention, for trew status: ${i.message}.${r}`)}}async function bh(n,e,t){if(e.keyFile!==void 0){if(n!==void 0&&n!=="-")throw new Error(`give ${t} as an argument or with --key-file, not both`);let r=(await rh(e.keyFile,"utf8")).trim();if(r==="")throw new Error(`${e.keyFile} is empty, so it holds no ${t}`);return r}if(n==="-"){let i=[];for await(let s of process.stdin)i.push(s);let r=Buffer.concat(i).toString("utf8").trim();if(r==="")throw new Error(`nothing arrived on standard input, so there is no ${t}`);return r}return n}function gr(n,e){return ei(fn(n,void 0,e?.recovery,e?.stranded))}async function Eh(n,e,t){let i,r=!1,s,o,a=Promise.resolve(),d=c=>{let l=JSON.stringify([nn(c),c.needsAttention??[]]);l!==o&&(o=l,a=a.then(()=>mr(e,t,c)))};return await oo({...await dr(n,e,t),onPass:c=>{d(c),!(!r||!Vi(c))&&ti(c,e,t,s?.serverCursor??0,s?.vault.stranded??[],s?.vault.displaced??[],pn(s?.vault))},onSyncFailed:c=>{t.err(`trew: a sync failed: ${c.message}. It will try again.`)}},{keepGoing:()=>!ue.asked,onWaiting:c=>{ue.wake=c},onConnecting:c=>{ue.clients.add(c),ue.asked&&c.close().catch(()=>{})},onClient:c=>{s=c,r=!1},onSynced:(c,l)=>{ti(c,e,t,l,s?.vault.stranded??[],s?.vault.displaced??[],pn(s?.vault)),r=!0,e.json||t.err("Watching for changes. Ctrl-C to stop.")},onDisconnected:(c,l)=>{t.err(`Disconnected: ${c.message}. Trying again in ${Ca(l)}.`)},onUnreachable:(c,l)=>{t.err(`Cannot reach the server: ${c.message}. Trying again in ${Ca(l)}.`)},onFatal:c=>{i=c}}),await a,i?(t.err(`trew: ${pr(i)}`),t.err("That will not fix itself by trying again."),1):0}async function kh(n,e,t,i,r){try{let s=new Tt(n.dir,{configDir:n.configDir,alsoIgnore:n.ignore,observeOnly:!0}),o=await s.list();t?.push(...s.stranded),i?.push(...s.displaced),r!==void 0&&(r.at=s.recovery);let a=new Map(Object.entries(e?.entries??{})),d=0,c=new Set;for(let l of o){if(c.add(l.path),l.folder)continue;let h=a.get(l.path);if(h===void 0){d++;continue}(h.size!==l.size||h.mtime!==Math.ceil(l.mtime))&&d++}for(let[l,h]of a)h.folder||c.has(l)||d++;return d}catch{return"unknown"}}async function Ah(n,e){let t=await gt(n.dir);if(!t)throw new Error($a(n.dir));let i=Ue(t),r=dt(await new It(Te(n.dir)).load()),s,o;try{s=await qo(n.dir)}catch(g){o=g.message}let a=[],d=[],c={at:void 0},l={vault:n.dir,device:t.device,server:t.url,vaultId:t.vaultId,cursor:r?.cursor??0,tracked:r?Object.keys(r.entries).length:0,pending:r?.pending.length??0,ignore:[...n.ignore],unsent:await kh(n,r,a,d,c),unsentFrom:"size and timestamp",stranded:a,displaced:d,recoveryComplete:c.at?.complete??!1,recoveryUnknown:c.at===void 0?"this vault could not be scanned, so what is waiting is unknown":c.at.complete?void 0:c.at.why??"the record of displaced versions could not be established",attention:s??null,attentionUnknown:o},h,u=!1;try{if(i)throw new Le(Da(n.dir));let g=await ae(t,n,e,{waitForBacklog:!1,inspect:!0});h={reachable:!0,refused:!1,cursor:g.serverCursor,behind:g.serverCursor-l.cursor},await g.close()}catch(g){let m=!(g instanceof I)&&!(g instanceof Le);u=g instanceof Le,h={reachable:m,refused:m,error:g.message}}let f=!h.reachable||h.refused||l.unsent==="unknown"||l.stranded.length>0||!l.recoveryComplete||(s?.count??0)>0||o!==void 0;if(n.json)return e.out(U({ok:!f,...l,server:h})),f?1:0;if(e.out(`vault ${l.vault}`),e.out(`device ${l.device}`),e.out(`server ${l.server} (vault "${l.vaultId}")`),e.out(`tracked ${l.tracked} files`),e.out(`ignore ${l.ignore.length===0?"nothing beyond the dot rule and the config folder":l.ignore.join(", ")} (this device only)`),e.out(`local cursor ${l.cursor}`),h.cursor!==void 0&&e.out(`server cursor ${h.cursor}`),l.pending>0&&e.out(`pending ${l.pending} files with work outstanding`),l.recoveryUnknown!==void 0&&e.out(`unknown ${l.recoveryUnknown}. There may be versions waiting that are not listed.`),l.stranded.length>0){e.out(`kept ${l.stranded.length} version(s) this client could not put back:`);let g=new Map(l.displaced.map(m=>[m.at,m]));for(let m of l.stranded){e.out(` ${ah(n.dir,m)}`);let y=g.get(m);y!==void 0&&e.out(` from ${y.from}: ${y.why}`)}}if(o!==void 0)e.out(`unknown what the last sync left needing attention could not be read: ${o}. trew sync writes it again.`);else if(s!==void 0&&s.count>0){e.out(`attention ${s.count} ${s.count===1?"path needs":"paths need"} a person, as the sync at ${tt(s.at).trim()} found them:`);for(let{path:m,why:y}of s.paths)e.out(` ${Mh(m)}: ${y}`);let g=s.count-s.paths.length;g>0&&e.out(` and ${g} more.`)}return u?(e.out(i?`state not connected: ${h.error}`:`state nothing to connect with: ${h.error}`),1):h.refused?(e.out(`state the server is up and refused this device: ${h.error}`),1):h.reachable?(e.out(h.behind!==0?`state ${h.behind} changes behind`:l.pending>0?`state caught up with the server, with ${l.pending} still not applied here`:l.unsent==="unknown"?"state caught up with the server; this vault could not be read, so what is unsent from here is unknown":l.unsent>0?`state caught up with the server, with ${l.unsent} not yet sent from here`:"state caught up with the server; nothing here looks changed (sizes and timestamps only)"),f?1:0):(e.out(`state cannot reach the server: ${h.error}`),1)}async function Ch(n,e){let t=await Ee(n.dir),i=await ae(t,n,e,{inspect:!0});try{let r=await i.repair(),s=r.failed.length>0||r.stillMissing>0;if(n.json)return e.out(U({ok:!s,...r})),s?1:0;r.stored>0?e.out(`Sent ${r.stored} ${r.stored===1?"body":"bodies"} the server was missing.`):e.out(`The server has every body this device can offer, from ${r.scanned} ${r.scanned===1?"note":"notes"}.`);for(let o of r.failed)e.err(`${o.path}: ${o.why}`);return r.stillMissing>0&&e.err(`${r.stillMissing} ${r.stillMissing===1?"body was":"bodies were"} asked for, sent, and the server still does not have them. Check its disk.`),r.couldNotOffer>0&&e.out(`${r.couldNotOffer} ${r.couldNotOffer===1?"chunk belongs":"chunks belong"} to notes this device has edited since they were last synced, so it cannot supply them.`),e.out(""),e.out("This repairs what this device holds. Run it on your other devices too, then `trewd verify` on the server for what is still missing: history this device never had is not visible from here."),s?1:0}finally{await i.close()}}async function Sh(n,e){let t=await Ee(n.dir),i=await ae(t,n,e,{inspect:!0});try{let r=await i.deleted(n.limitGiven?n.limit:void 0,n.before>0?n.before:void 0);if(n.json)return e.out(U({ok:!0,deleted:r.notes,more:r.more})),0;if(r.notes.length===0)return e.out("Nothing has been deleted from this vault."),0;let s=0;for(let a of r.notes){let d=a.restorable===0?" (content purged)":"";a.restorable===0&&s++,e.out(`${tt(a.mtime)} ${a.device.padEnd(12)} ${a.path}${d}`)}e.out("");let o=r.notes.length-s;return s===0?e.out(`${o} deleted, all still recoverable. trew restore PATH brings one back.`):e.out(`${r.notes.length} deleted. ${o} can be restored; ${s} had their history purged and cannot be.`),r.more&&r.oldest!==void 0&&e.out(`There are older deletions than these. trew deleted --before ${r.oldest} shows the page before this one.`),0}finally{await i.close()}}var ka=500;async function Fh(n,e){let t=await ae(await Ee(n.dir),n,e,{inspect:!0});try{let i=await t.preview(),r=!i.files.some(s=>s.action==="blocked");if(n.json)e.out(U({ok:r,...i,counts:cr(i)}));else{e.out("Preview only. Files are checked again during sync.");for(let s of i.files)s.action!=="unchanged"&&e.out(`${s.action}: ${s.path}`);e.out(JSON.stringify(cr(i)))}return r?0:1}finally{await t.close()}}async function xh(n,e){let t=n.rest[0];if(!t)throw new Error("history needs the path of a note");let i=await Ee(n.dir),r=await ae(i,n,e,{inspect:!0});try{let s=Math.min(n.limit,ka),o=await r.history(t,{limit:s,...n.before?{before:n.before}:{}}),a=o.length===s?o.at(-1).uid:null;if(n.json)return e.out(U({ok:!0,path:t,versions:o,limit:s,nextBefore:a})),0;if(o.length===0)return e.out(`The server holds no versions of ${t}.`),0;for(let d of o){let c=d.deleted?"deleted":d.folder?"folder":`${yr(d.size)}`;e.out(`${String(d.uid).padStart(7)} ${tt(d.mtime)} ${d.device.padEnd(12)} ${c}`)}return e.out(""),n.limit>s&&e.out(`Showing the newest ${s}: the server lists at most ${ka} versions at a time, so --limit ${n.limit} was capped there.`),e.out("trew restore PATH --uid N brings one of these back."),a!==null&&e.out(`Older versions: trew history PATH --before ${a}`),0}finally{await r.close()}}var Aa=3,Bh=5;async function Ph(n,e){let t=n.rest[0],i=n.mode??"content",r=await ae(await Ee(n.dir),n,e,{inspect:!0}),s=e.color===!0&&!n.json,o=[],a=n.after,d=!1;try{for(;;){let g=await $h(r,n,t,i,a);if(o.push(g),!n.json)for(let m of g.matches){n.context>0&&d&&e.out("--");for(let y of wa(m,t,i,s))e.out(y);d=!0}if(!n.all||g.nextAfter===null)break;a=g.nextAfter}}finally{await r.close()}let c=o.at(-1),l=o.flatMap(g=>g.matches),h=o.flatMap(g=>g.skipped),u=o.reduce((g,m)=>g+m.scanned,0),f=h.length===0;if(n.json)return e.out(U({ok:f,query:t,mode:i,matches:l,skipped:h,complete:f&&c.nextAfter===null,nextAfter:c.nextAfter,head:c.head,indexedHead:c.indexedHead,index:c.index,pages:o.length,scanned:u,scannedBytes:o.reduce((g,m)=>g+m.scannedBytes,0)})),f?0:1;if(l.length===0&&e.err(c.nextAfter===null?"No matches.":"No matches on this page."),i!=="filename"&&(c.index.usable?c.indexedHead<c.head&&e.err(`The server's search index is still catching up (version ${c.indexedHead} of ${c.head}); notes it has not reached were read in full, so nothing is missed.`):e.err(`The server's search index was not used (${c.index.why??"no reason given"}), so every note was read: nothing is missed, it is only slower.`)),l.some(g=>g.clipped)&&e.err("Long lines are shortened; --json has each match's line as the server sent it."),c.nextAfter!==null&&e.err(`More matches may follow: this is ${o.length===1?"the first page":`${o.length} pages`}. trew search --all shows every page, or --after ${c.nextAfter} the next one.`),!f){e.err(`${h.length} ${h.length===1?"note":"notes"} could not be searched, so a match may be missing:`);for(let g of h)e.err(` ${Y(g.path)}: ${Y(g.why)}`)}return f?0:1}async function $h(n,e,t,i,r){for(let s=0;;s++)try{return await n.search({query:t,mode:i,...e.folder!==void 0?{folder:e.folder}:{},...e.caseSensitive?{caseSensitive:!0}:{},...e.context>0?{contextLines:e.context}:{},...e.limitGiven?{limit:e.limit}:{},...r!==void 0?{after:r}:{}})}catch(o){if(!(o instanceof C)||o.code!=="toomany"||s>=Bh)throw Dh(o);let a=Math.min(Math.max(o.retryAfterMs??1e3,50),3e4);await new Promise(d=>setTimeout(d,a))}}function Dh(n){return n instanceof C?n.code==="proto"||n.code==="protostate"&&n.message.includes('"search"')?new Error("this server does not search for devices: it is older than this client. Upgrade the server (docs/server.md, Upgrade order)."):n.code==="stale"&&n.message.startsWith("expired:")?new Error("that --after cursor belongs to another search, or to the vault's history before a restore or a purge changed it; search again without it."):n.code==="toomany"?new Error(`the server is busy with searches: ${n.message}. Try again in a moment.`):n:n}async function Th(n,e){let t=n.rest[0];if(!t)throw new Error("restore needs the path of a note");let i=await Ee(n.dir),r=await ae(i,n,e);try{let s;if(n.uid!==void 0){if(s=await r.findVersion(t,l=>l.uid===n.uid),!s)throw new Error(`the server has no version ${n.uid} of ${t}`)}else if(s=await r.newestContentVersion(t),!s)throw new Error(`the server holds no version of ${t} with any content in it`);let o=await r.restore(s,n.to),a=()=>{e.out(`Restored version ${s.uid} of ${t} to ${o.path} (${yr(o.bytes)}, from ${tt(s.mtime)}).`),o.path!==(n.to??t)&&e.out(`Written to ${o.path}, because something is already at ${n.to??t}.`)},d;try{d=await r.settle({coalesceWrites:!1})}catch(l){let h=pr(l),u=fn(void 0,{why:h,offline:l instanceof I}),f=r.engine.serverHasOurs(o.path);return n.json?e.out(U({ok:!1,restored:!0,path:o.path,uid:s.uid,bytes:o.bytes,sent:f,outcome:u,error:h})):(a(),e.err(`The restored copy is on this device, but sync did not finish: ${h}. Run trew sync to retry.`)),1}let c=r.engine.serverHasOurs(o.path);if(await mr(n,e,d),n.json){let l=fn(d,void 0,r.vault.recovery,r.vault.stranded),h=ei(l);return e.out(U({ok:h===0,restored:!0,sent:c,outcome:l,path:o.path,uid:s.uid,bytes:o.bytes,sync:d,recoveryUnknown:pn(r.vault)??null})),h}return a(),c?e.out("Sent to the server, so your other devices will pick it up."):n.readOnly||i.readOnly===!0?e.out("The restored copy stays on this device because it is read-only."):e.out("The restored copy has not been acknowledged by the server. Run trew sync to retry."),gr(d,r.vault)!==0&&ti(d,n,e,r.serverCursor,r.vault.stranded??[],r.vault.displaced??[],pn(r.vault)),gr(d,r.vault)}finally{await r.close()}}async function Ih(n,e){let t=await ga(n.dir,n.force);if(n.json){let i=t.did==="nothing"||t.did==="removed";return e.out(U({ok:i,did:t.did,why:t.why,...t.did==="nothing"?{}:{holder:t.was??null}})),i?0:1}switch(t.did){case"nothing":return e.out(t.why),0;case"removed":return e.out(`the lock is clear: ${t.why}.`),0;case"refused":return e.err(`trew: the lock was not cleared, because ${t.why}.`),1;case"contested":return e.err(`trew: ${t.why}.`),1}}async function Rh(n,e){let t=await gt(n.dir).catch(()=>{}),i=await Ho(n.dir),r=t!==void 0&&Ue(t);return n.json?(e.out(U({ok:!0,unlinked:n.dir,wasPaired:t!==void 0&&!r,...r?{unfinished:!0}:{},...i!==void 0?{notDurable:i}:{},...t?.deviceId!==void 0?{deviceId:t.deviceId}:{}})),0):(e.out(`Forgot the pairing for ${n.dir}. Every note is where it was.`),i!==void 0&&(e.out(""),e.out(`The pairing is gone from this disk, but flushing that removal failed: ${i}`),e.out("If the machine loses power before the filesystem catches up, the pairing may come back. Check the disk, and run `trew unlink` again if it does.")),e.out("Nothing was removed from the server."),r?(e.out(""),e.out(`The pairing here had not finished. If the server registered it, the vault's device list has a row ${t.deviceId} that has never connected, and nothing here can remove it now: run trew revoke ${mn(t.deviceId)} on a device that still syncs.`)):t?.deviceId!==void 0&&(e.out(""),e.out(`This device is still in the vault's device list as ${t.deviceId}. Nothing here can remove it now, because the credential for it has just been forgotten: run trew revoke ${mn(t.deviceId)} on a device that still syncs.`)),0)}async function ae(n,e,t,i={}){let r=new tn({...await dr(n,e,t,i.inspect),...i.inspect===!0?{inspect:!0}:{}});ue.clients.add(r);try{if(ue.asked)throw new Error("stopped before connecting, as asked");await r.connect(i)}catch(s){throw await r.close(),s}return r}function ti(n,e,t,i,r=[],s=[],o=void 0){let a=fn(n,void 0,{complete:o===void 0,...o!==void 0?{why:o}:{},waiting:s},r);if(e.json){t.out(U({ok:ei(a)===0,outcome:a,...n,serverCursor:i,stranded:r,displaced:s,recoveryUnknown:o??null}));return}let d=[],c=(l,h)=>{l>0&&d.push(`${String(l).padStart(5)} ${h}`)};if(c(n.uploaded,"uploaded"),c(n.downloaded,"downloaded"),c(n.merged,"merged"),c(n.conflicted,"kept both versions"),c(n.deletedLocally,"deleted here"),c(n.deletedRemotely,"deleted on the server"),c(n.restored,"brought back, having been edited elsewhere"),c(n.foldersCreated,"folders created"),c(n.foldersDeletedLocally,"folders removed here, deleted elsewhere"),c(n.foldersDeletedRemotely,"folders deleted on the server"),c(n.waiting,"waiting for a write to settle"),c(n.retrying,"failed, will try again"),c(nn(n),"need attention"),c(n.heldBack,"changed here and not sent, because this device is read-only"),c(n.ignored,"ignored here, and synced by another device"),d.length===0)t.out(a.kind==="synced"?"Nothing to do. Everything here matches the server.":fr(a));else{for(let l of d)t.out(l);a.kind!=="synced"&&t.out(` ${fr(a)}`)}if(n.needsAttention.length>0){t.out("");for(let l of uo(n," "))t.out(l)}if(o!==void 0&&(t.out(""),t.out(` ${o}. There may be versions waiting that are not listed.`)),r.length>0){t.out(""),t.out(` ${r.length} version(s) this client could not put back:`);let l=new Map(s.map(h=>[h.at,h]));for(let h of r){t.out(` ${h}`);let u=l.get(h);u!==void 0&&t.out(` from ${u.from}: ${u.why}`)}}n.chunksSent>0&&t.out(`${String(n.chunksSent).padStart(5)} chunks sent, ${yr(n.bytesSent)}`),n.conflicted>0&&t.err('Look for files with "Conflicted copy" in the name. Both versions are kept.')}function Oh(n){let e={provided:new Set,verify:!1,rest:[],dir:process.cwd(),device:oh().split(".")[0]||"device",deviceGiven:!1,json:!1,watch:!1,limit:20,limitGiven:!1,before:0,keyFile:void 0,verbose:!1,help:!1,version:!1,force:!1,merge:!0,readOnly:!1,timeout:3e4,configDir:rr,ignore:[],caseSensitive:!1,context:0,all:!1},t=new Set(["--dir","--device","--timeout","--uid","--to","--limit","--before","--key-file","--config-dir","--ignore","--ttl","--mode","--folder","--context","--after"]),i=!1;for(let r=0;r<n.length;r++){let s=n[r];if(i){e.command===void 0?e.command=s:e.rest.push(s);continue}if(s==="--"){i=!0;continue}s.startsWith("-")&&e.provided.add(s);let o;if(t.has(s)&&(o=n[++r],o===void 0||o.startsWith("--")))throw new Error(`${s} needs a value`);switch(s){case"--dir":e.dir=dh(o);break;case"--device":e.device=o,e.deviceGiven=!0;break;case"--timeout":{let a=Number(o);if(!Number.isFinite(a)||a<=0)throw new Error(`--timeout wants a number of milliseconds, not ${o}`);e.timeout=a;break}case"--uid":{let a=Number(o);if(!Number.isSafeInteger(a)||a<=0)throw new Error(`--uid wants a version number, not ${o}`);e.uid=a;break}case"--to":e.to=o;break;case"--ttl":e.ttlMs=Nh(o);break;case"--config-dir":e.configDir=Cn(o);break;case"--ignore":if(o===""||o==="."||o===".."||o.includes("/"))throw new Error(`--ignore wants one folder or file name, not ${JSON.stringify(o)}: it is matched against each part of a path on its own, so a name with a slash in it matches nothing, and . and .. are never a part`);e.ignore.push(o);break;case"--limit":{let a=Number(o);if(!Number.isSafeInteger(a)||a<=0)throw new Error(`--limit wants a count, not ${o}`);e.limit=a,e.limitGiven=!0;break}case"--key-file":e.keyFile=o;break;case"--before":{let a=Number(o);if(!Number.isSafeInteger(a)||a<=0)throw new Error(`--before wants a version number, not ${o}`);e.before=a;break}case"--mode":if(!["content","filename","both","tag"].includes(o))throw new Error(`--mode is content, filename, both or tag, not ${o}`);e.mode=o;break;case"--folder":e.folder=o;break;case"--context":{let a=Number(o);if(!Number.isSafeInteger(a)||a<0||a>Aa)throw new Error(`--context wants 0 to ${Aa} lines, not ${o}`);e.context=a;break}case"--after":e.after=o;break;case"--case-sensitive":e.caseSensitive=!0;break;case"--all":e.all=!0;break;case"--verify":e.verify=!0;break;case"--force":e.force=!0;break;case"--no-merge":e.merge=!1;break;case"--read-only":e.readOnly=!0;break;case"--json":e.json=!0;break;case"--version":case"-V":e.version=!0;break;case"--watch":e.watch=!0;break;case"--verbose":case"-v":e.verbose=!0;break;case"--help":case"-h":e.help=!0;break;default:if(s!=="-"&&s.startsWith("-"))throw new Error(`no such option: ${s}`);e.command===void 0?e.command=s:e.rest.push(s)}}return e}async function Ee(n){let e=await gt(n);if(!e)throw new Error($a(n));if(Ue(e))throw new Le(Da(n));return e}function mn(n){return n.startsWith("-")?`-- ${n}`:n}function $a(n){return`${n} is not paired. Run trew pair with an invite. ${Ba}`}function Da(n){return`the pairing in ${n} has not finished: an invite was being redeemed and no answer was heard, so whether the server registered this device is not known. Run trew pair here to finish it with the credential already saved, which works even after the invite has expired if the server did register it.`}function Mh(n){let e="";for(let t of n){let i=t.codePointAt(0);e+=i<32||i>=127&&i<=159?`\\u{${i.toString(16)}}`:t}return e}function Nh(n){let e=/^(\d+)\s*(ms|s|m|h)?$/.exec(n.trim());if(!e)throw new Error(`--ttl wants a duration like 10m, 90s or 1h, not ${n}`);let t=Number(e[1]),i=e[2]??"s",r=t*(i==="ms"?1:i==="s"?1e3:i==="m"?6e4:36e5);if(r<=0)throw new Error("--ttl must be more than nothing");if(r>36e5)throw new Error("--ttl can be at most 1h, which is the most the server allows");return r}function tt(n){if(!Number.isFinite(n)||n<=0)return"unknown ";let e=new Date(n),t=i=>String(i).padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())} ${t(e.getHours())}:${t(e.getMinutes())}`}function Ca(n){return`${Math.max(1,Math.round(n/1e3))}s`}function yr(n){return n<1024?`${n} B`:n<1024*1024?`${(n/1024).toFixed(1)} KiB`:`${(n/(1024*1024)).toFixed(1)} MiB`}var wr;for(let n of["SIGINT","SIGTERM"])process.once(n,()=>{wr??=n,Sa(),process.stdin.destroy(),setTimeout(()=>process.kill(process.pid,n),5e3).unref()});var _h=await Fa(process.argv.slice(2),{out:n=>process.stdout.write(n+`
91
91
  `),err:n=>process.stderr.write(n+`
92
- `),color:process.stdout.isTTY===!0&&(process.env.NO_COLOR??"")===""});ui!==void 0?process.kill(process.pid,ui):process.exitCode=bh;
92
+ `),color:process.stdout.isTTY===!0&&(process.env.NO_COLOR??"")===""});wr!==void 0?process.kill(process.pid,wr):process.exitCode=_h;