basalt-sync 0.1.7 → 0.2.0

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.
package/README.md CHANGED
@@ -24,10 +24,15 @@ Any sync decision that appears in a shell is in the wrong file.
24
24
  bun install
25
25
  bun run test # everything, including against a real server
26
26
  bun run typecheck
27
+ bun run format # prettier, and CI fails on anything it would change
27
28
  bun run bench # throughput and bandwidth, reported not asserted
28
29
  bun run bench:sync # a whole vault, timed and checked
29
30
  ```
30
31
 
32
+ The benchmarks run under bun and the shipped CLI runs under node, which is not a
33
+ detail: two of the largest wins in `docs/benchmark.md` were each invisible under
34
+ one of the two engines. Anything measuring the chunker should be run under both.
35
+
31
36
  The tests need a Go toolchain. `src/core/server-harness.test.ts` builds
32
37
  `cmd/basaltd`, runs it on a loopback port, and talks to it with the real
33
38
  transport. Nothing is mocked, and its assertions are checked by asking the
@@ -37,7 +42,7 @@ correct server never would.
37
42
 
38
43
  ## The headless client
39
44
 
40
- `bun run build` produces `dist/basalt.mjs`: one 85 KB file with nothing to
45
+ `bun run build` produces `dist/basalt.mjs`: one 91 KB file with nothing to
41
46
  install beside it, because everything is bundled and the only imports that
42
47
  survive are `node:` builtins. The npm package declares no dependencies at all. The command is `basalt`; the server's is `basaltd`, so a homelab can run both.
43
48
 
@@ -56,6 +61,19 @@ command gives machine-readable output. State lives in `.basalt/` inside the
56
61
  vault, which is never synced: `config.json` (0600, holds the root secret) and
57
62
  `index.json`.
58
63
 
64
+ `--config-dir` names Obsidian's config folder when it is not `.obsidian`. The
65
+ plugin asks Obsidian for this and always gets it right; a headless client has
66
+ nothing to ask, so it assumes `.obsidian` and has to be told otherwise. Until
67
+ this flag existed there was no way to tell it, and a vault whose config folder
68
+ had been renamed in the app had it synced here and refused by the plugin, which
69
+ is one vault disagreeing with itself about the one thing this project will not
70
+ sync. Naming a different folder also makes `.obsidian` ordinary content again,
71
+ since by then it is just a folder.
72
+
73
+ `--ignore NAME` leaves one more top-level name alone, and can be repeated. One
74
+ name per flag rather than a separated list, because a filename may contain a
75
+ comma and a vault is the wrong place to discover which separator was assumed.
76
+
59
77
  `cli.ts` takes an argv and two output functions and returns an exit code, so
60
78
  `cli.test.ts` drives the whole client against a real server with no subprocess.
61
79
  `bin.ts` is the six lines connecting that to a terminal, and the only part no
package/dist/basalt.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- var jn=Object.create;var Mt=Object.defineProperty;var Gn=Object.getOwnPropertyDescriptor;var qn=Object.getOwnPropertyNames;var Zn=Object.getPrototypeOf,Xn=Object.prototype.hasOwnProperty;var Yn=(n,e)=>()=>{try{return e||n((e={exports:{}}).exports,e),e.exports}catch(t){throw e=0,t}};var Qn=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of qn(e))!Xn.call(n,i)&&i!==t&&Mt(n,i,{get:()=>e[i],enumerable:!(r=Gn(e,i))||r.enumerable});return n};var er=(n,e,t)=>(t=n!=null?jn(Zn(n)):{},Qn(e||!n||!n.__esModule?Mt(t,"default",{value:n,enumerable:!0}):t,n));var on=Yn((Bi,me)=>{var d=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},C=-1,T=1,k=0;d.Diff=function(n,e){return[n,e]};d.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 d.Diff(k,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 l=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 d.Diff(k,a)),l&&c.push(new d.Diff(k,l)),this.diff_cleanupMerge(c),c};d.prototype.diff_compute_=function(n,e,t,r){var i;if(!n)return[new d.Diff(T,e)];if(!e)return[new d.Diff(C,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 d.Diff(T,s.substring(0,a)),new d.Diff(k,o),new d.Diff(T,s.substring(a+o.length))],n.length>e.length&&(i[0][0]=i[2][0]=C),i;if(o.length==1)return[new d.Diff(C,n),new d.Diff(T,e)];var l=this.diff_halfMatch_(n,e);if(l){var c=l[0],h=l[1],u=l[2],f=l[3],g=l[4],m=this.diff_main(c,u,t,r),v=this.diff_main(h,f,t,r);return m.concat([new d.Diff(k,g)],v)}return t&&n.length>100&&e.length>100?this.diff_lineMode_(n,e,r):this.diff_bisect_(n,e,r)};d.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 d.Diff(k,""));for(var o=0,a=0,l=0,c="",h="";o<s.length;){switch(s[o][0]){case T:l++,h+=s[o][1];break;case C:a++,c+=s[o][1];break;case k:if(a>=1&&l>=1){s.splice(o-a-l,a+l),o=o-a-l;for(var u=this.diff_main(c,h,!1,t),f=u.length-1;f>=0;f--)s.splice(o,0,u[f]);o=o+u.length}l=0,a=0,c="",h="";break}o++}return s.pop(),s};d.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,l=new Array(a),c=new Array(a),h=0;h<a;h++)l[h]=-1,c[h]=-1;l[o+1]=0,c[o+1]=0;for(var u=r-i,f=u%2!=0,g=0,m=0,v=0,x=0,w=0;w<s&&!(new Date().getTime()>t);w++){for(var A=-w+g;A<=w-m;A+=2){var b=o+A,S;A==-w||A!=w&&l[b-1]<l[b+1]?S=l[b+1]:S=l[b-1]+1;for(var M=S-A;S<r&&M<i&&n.charAt(S)==e.charAt(M);)S++,M++;if(l[b]=S,S>r)m+=2;else if(M>i)g+=2;else if(f){var $=o+u-A;if($>=0&&$<a&&c[$]!=-1){var E=r-c[$];if(S>=E)return this.diff_bisectSplit_(n,e,S,M,t)}}}for(var y=-w+v;y<=w-x;y+=2){var $=o+y,E;y==-w||y!=w&&c[$-1]<c[$+1]?E=c[$+1]:E=c[$-1]+1;for(var p=E-y;E<r&&p<i&&n.charAt(r-E-1)==e.charAt(i-p-1);)E++,p++;if(c[$]=E,E>r)x+=2;else if(p>i)v+=2;else if(!f){var b=o+u-y;if(b>=0&&b<a&&l[b]!=-1){var S=l[b],M=o+S-b;if(E=r-E,S>=E)return this.diff_bisectSplit_(n,e,S,M,t)}}}}return[new d.Diff(C,n),new d.Diff(T,e)]};d.prototype.diff_bisectSplit_=function(n,e,t,r,i){var s=n.substring(0,t),o=e.substring(0,r),a=n.substring(t),l=e.substring(r),c=this.diff_main(s,o,!1,i),h=this.diff_main(a,l,!1,i);return c.concat(h)};d.prototype.diff_linesToChars_=function(n,e){var t=[],r={};t[0]="";function i(l){for(var c="",h=0,u=-1,f=t.length;u<l.length-1;){u=l.indexOf(`
3
- `,h),u==-1&&(u=l.length-1);var g=l.substring(h,u+1);(r.hasOwnProperty?r.hasOwnProperty(g):r[g]!==void 0)?c+=String.fromCharCode(r[g]):(f==s&&(g=l.substring(h),u=l.length),c+=String.fromCharCode(f),r[g]=f,t[f++]=g),h=u+1}return c}var s=4e4,o=i(n);s=65535;var a=i(e);return{chars1:o,chars2:a,lineArray:t}};d.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("")}};d.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};d.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};d.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),l=e.indexOf(a);if(l==-1)return s;o+=l,(l==0||n.substring(i-o)==e.substring(0,o))&&(s=o,o++)}};d.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(m,v,x){for(var w=m.substring(x,x+Math.floor(m.length/4)),A=-1,b="",S,M,$,E;(A=v.indexOf(w,A+1))!=-1;){var y=i.diff_commonPrefix(m.substring(x),v.substring(A)),p=i.diff_commonSuffix(m.substring(0,x),v.substring(0,A));b.length<p+y&&(b=v.substring(A-p,A)+v.substring(A,A+y),S=m.substring(0,x-p),M=m.substring(x+y),$=v.substring(0,A-p),E=v.substring(A+y))}return b.length*2>=m.length?[S,M,$,E,b]:null}var o=s(t,r,Math.ceil(t.length/4)),a=s(t,r,Math.ceil(t.length/2)),l;if(!o&&!a)return null;a?o?l=o[4].length>a[4].length?o:a:l=a:l=o;var c,h,u,f;n.length>e.length?(c=l[0],h=l[1],u=l[2],f=l[3]):(u=l[0],f=l[1],c=l[2],h=l[3]);var g=l[4];return[c,h,u,f,g]};d.prototype.diff_cleanupSemantic=function(n){for(var e=!1,t=[],r=0,i=null,s=0,o=0,a=0,l=0,c=0;s<n.length;)n[s][0]==k?(t[r++]=s,o=l,a=c,l=0,c=0,i=n[s][1]):(n[s][0]==T?l+=n[s][1].length:c+=n[s][1].length,i&&i.length<=Math.max(o,a)&&i.length<=Math.max(l,c)&&(n.splice(t[r-1],0,new d.Diff(C,i)),n[t[r-1]+1][0]=T,r--,r--,s=r>0?t[r-1]:-1,o=0,a=0,l=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]==C&&n[s][0]==T){var h=n[s-1][1],u=n[s][1],f=this.diff_commonOverlap_(h,u),g=this.diff_commonOverlap_(u,h);f>=g?(f>=h.length/2||f>=u.length/2)&&(n.splice(s,0,new d.Diff(k,u.substring(0,f))),n[s-1][1]=h.substring(0,h.length-f),n[s+1][1]=u.substring(f),s++):(g>=h.length/2||g>=u.length/2)&&(n.splice(s,0,new d.Diff(k,h.substring(0,g))),n[s-1][0]=T,n[s-1][1]=u.substring(0,u.length-g),n[s+1][0]=C,n[s+1][1]=h.substring(g),s++),s++}s++}};d.prototype.diff_cleanupSemanticLossless=function(n){function e(g,m){if(!g||!m)return 6;var v=g.charAt(g.length-1),x=m.charAt(0),w=v.match(d.nonAlphaNumericRegex_),A=x.match(d.nonAlphaNumericRegex_),b=w&&v.match(d.whitespaceRegex_),S=A&&x.match(d.whitespaceRegex_),M=b&&v.match(d.linebreakRegex_),$=S&&x.match(d.linebreakRegex_),E=M&&g.match(d.blanklineEndRegex_),y=$&&m.match(d.blanklineStartRegex_);return E||y?5:M||$?4:w&&!b&&S?3:b||S?2:w||A?1:0}for(var t=1;t<n.length-1;){if(n[t-1][0]==k&&n[t+1][0]==k){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 l=r,c=i,h=s,u=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 f=e(r,i)+e(i,s);f>=u&&(u=f,l=r,c=i,h=s)}n[t-1][1]!=l&&(l?n[t-1][1]=l:(n.splice(t-1,1),t--),n[t][1]=c,h?n[t+1][1]=h:(n.splice(t+1,1),t--))}t++}};d.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;d.whitespaceRegex_=/\s/;d.linebreakRegex_=/[\r\n]/;d.blanklineEndRegex_=/\n\r?\n$/;d.blanklineStartRegex_=/^\r?\n\r?\n/;d.prototype.diff_cleanupEfficiency=function(n){for(var e=!1,t=[],r=0,i=null,s=0,o=!1,a=!1,l=!1,c=!1;s<n.length;)n[s][0]==k?(n[s][1].length<this.Diff_EditCost&&(l||c)?(t[r++]=s,o=l,a=c,i=n[s][1]):(r=0,i=null),l=c=!1):(n[s][0]==C?c=!0:l=!0,i&&(o&&a&&l&&c||i.length<this.Diff_EditCost/2&&o+a+l+c==3)&&(n.splice(t[r-1],0,new d.Diff(C,i)),n[t[r-1]+1][0]=T,r--,i=null,o&&a?(l=c=!0,r=0):(r--,s=r>0?t[r-1]:-1,l=c=!1),e=!0)),s++;e&&this.diff_cleanupMerge(n)};d.prototype.diff_cleanupMerge=function(n){n.push(new d.Diff(k,""));for(var e=0,t=0,r=0,i="",s="",o;e<n.length;)switch(n[e][0]){case T:r++,s+=n[e][1],e++;break;case C:t++,i+=n[e][1],e++;break;case k: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]==k?n[e-t-r-1][1]+=s.substring(0,o):(n.splice(0,0,new d.Diff(k,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 d.Diff(C,i)),e++),s.length&&(n.splice(e,0,new d.Diff(T,s)),e++),e++):e!==0&&n[e-1][0]==k?(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]==k&&n[e+1][0]==k&&(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)};d.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]!==T&&(t+=n[o][1].length),n[o][0]!==C&&(r+=n[o][1].length),!(t>e));o++)i=t,s=r;return n.length!=o&&n[o][0]===C?s:s+(e-i)};d.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],l=n[o][1],c=l.replace(t,"&amp;").replace(r,"&lt;").replace(i,"&gt;").replace(s,"&para;<br>");switch(a){case T:e[o]='<ins style="background:#e6ffe6;">'+c+"</ins>";break;case C:e[o]='<del style="background:#ffe6e6;">'+c+"</del>";break;case k:e[o]="<span>"+c+"</span>";break}}return e.join("")};d.prototype.diff_text1=function(n){for(var e=[],t=0;t<n.length;t++)n[t][0]!==T&&(e[t]=n[t][1]);return e.join("")};d.prototype.diff_text2=function(n){for(var e=[],t=0;t<n.length;t++)n[t][0]!==C&&(e[t]=n[t][1]);return e.join("")};d.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 T:t+=o.length;break;case C:r+=o.length;break;case k:e+=Math.max(t,r),t=0,r=0;break}}return e+=Math.max(t,r),e};d.prototype.diff_toDelta=function(n){for(var e=[],t=0;t<n.length;t++)switch(n[t][0]){case T:e[t]="+"+encodeURI(n[t][1]);break;case C:e[t]="-"+n[t][1].length;break;case k:e[t]="="+n[t][1].length;break}return e.join(" ").replace(/%20/g," ")};d.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 d.Diff(T,decodeURI(a))}catch{throw new Error("Illegal escape in diff_fromDelta: "+a)}break;case"-":case"=":var l=parseInt(a,10);if(isNaN(l)||l<0)throw new Error("Invalid number in diff_fromDelta: "+a);var c=n.substring(i,i+=l);s[o].charAt(0)=="="?t[r++]=new d.Diff(k,c):t[r++]=new d.Diff(C,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};d.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};d.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,M){var $=S/e.length,E=Math.abs(t-M);return i.Match_Distance?$+E/i.Match_Distance:E?1:$}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 l=1<<e.length-1;a=-1;for(var c,h,u=e.length+n.length,f,g=0;g<e.length;g++){for(c=0,h=u;c<h;)s(g,t+h)<=o?c=h:u=h,h=Math.floor((u-c)/2+c);u=h;var m=Math.max(1,t-h+1),v=Math.min(t+h,n.length)+e.length,x=Array(v+2);x[v+1]=(1<<g)-1;for(var w=v;w>=m;w--){var A=r[n.charAt(w-1)];if(g===0?x[w]=(x[w+1]<<1|1)&A:x[w]=(x[w+1]<<1|1)&A|((f[w+1]|f[w])<<1|1)|f[w+1],x[w]&l){var b=s(g,w-1);if(b<=o)if(o=b,a=w-1,a>t)m=Math.max(1,2*t-a);else break}}if(s(g+1,t)>o)break;f=x}return a};d.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};d.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 d.Diff(k,i));var s=e.substring(n.start2+n.length1,n.start2+n.length1+r);s&&n.diffs.push(new d.Diff(k,s)),n.start1-=i.length,n.start2-=i.length,n.length1+=i.length+s.length,n.length2+=i.length+s.length}};d.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 d.patch_obj,a=0,l=0,c=0,h=r,u=r,f=0;f<i.length;f++){var g=i[f][0],m=i[f][1];switch(!a&&g!==k&&(o.start1=l,o.start2=c),g){case T:o.diffs[a++]=i[f],o.length2+=m.length,u=u.substring(0,c)+m+u.substring(c);break;case C:o.length1+=m.length,o.diffs[a++]=i[f],u=u.substring(0,c)+u.substring(c+m.length);break;case k:m.length<=2*this.Patch_Margin&&a&&i.length!=f+1?(o.diffs[a++]=i[f],o.length1+=m.length,o.length2+=m.length):m.length>=2*this.Patch_Margin&&a&&(this.patch_addContext_(o,h),s.push(o),o=new d.patch_obj,a=0,h=u,l=c);break}g!==T&&(l+=m.length),g!==C&&(c+=m.length)}return a&&(this.patch_addContext_(o,h),s.push(o)),s};d.prototype.patch_deepCopy=function(n){for(var e=[],t=0;t<n.length;t++){var r=n[t],i=new d.patch_obj;i.diffs=[];for(var s=0;s<r.diffs.length;s++)i.diffs[s]=new d.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};d.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),l,c=-1;if(a.length>this.Match_MaxBits?(l=this.match_main(e,a.substring(0,this.Match_MaxBits),o),l!=-1&&(c=this.match_main(e,a.substring(a.length-this.Match_MaxBits),o+a.length-this.Match_MaxBits),(c==-1||l>=c)&&(l=-1))):l=this.match_main(e,a,o),l==-1)i[s]=!1,r-=n[s].length2-n[s].length1;else{i[s]=!0,r=l-o;var h;if(c==-1?h=e.substring(l,l+a.length):h=e.substring(l,c+this.Match_MaxBits),a==h)e=e.substring(0,l)+this.diff_text2(n[s].diffs)+e.substring(l+a.length);else{var u=this.diff_main(a,h,!1);if(a.length>this.Match_MaxBits&&this.diff_levenshtein(u)/a.length>this.Patch_DeleteThreshold)i[s]=!1;else{this.diff_cleanupSemanticLossless(u);for(var f=0,g,m=0;m<n[s].diffs.length;m++){var v=n[s].diffs[m];v[0]!==k&&(g=this.diff_xIndex(u,f)),v[0]===T?e=e.substring(0,l+g)+v[1]+e.substring(l+g):v[0]===C&&(e=e.substring(0,l+g)+e.substring(l+this.diff_xIndex(u,f+v[1].length))),v[0]!==C&&(f+=v[1].length)}}}}}return e=e.substring(t.length,e.length-t.length),[e,i]};d.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]!=k)s.unshift(new d.Diff(k,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]!=k)s.push(new d.Diff(k,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};d.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 d.patch_obj,l=!0;for(a.start1=i-o.length,a.start2=s-o.length,o!==""&&(a.length1=a.length2=o.length,a.diffs.push(new d.Diff(k,o)));r.diffs.length!==0&&a.length1<e-this.Patch_Margin;){var c=r.diffs[0][0],h=r.diffs[0][1];c===T?(a.length2+=h.length,s+=h.length,a.diffs.push(r.diffs.shift()),l=!1):c===C&&a.diffs.length==1&&a.diffs[0][0]==k&&h.length>2*e?(a.length1+=h.length,i+=h.length,l=!1,a.diffs.push(new d.Diff(c,h)),r.diffs.shift()):(h=h.substring(0,e-a.length1-this.Patch_Margin),a.length1+=h.length,i+=h.length,c===k?(a.length2+=h.length,s+=h.length):l=!1,a.diffs.push(new d.Diff(c,h)),h==r.diffs[0][1]?r.diffs.shift():r.diffs[0][1]=r.diffs[0][1].substring(h.length))}o=this.diff_text2(a.diffs),o=o.substring(o.length-this.Patch_Margin);var u=this.diff_text1(r.diffs).substring(0,this.Patch_Margin);u!==""&&(a.length1+=u.length,a.length2+=u.length,a.diffs.length!==0&&a.diffs[a.diffs.length-1][0]===k?a.diffs[a.diffs.length-1][1]+=u:a.diffs.push(new d.Diff(k,u))),l||n.splice(++t,0,a)}}};d.prototype.patch_toText=function(n){for(var e=[],t=0;t<n.length;t++)e[t]=n[t];return e.join("")};d.prototype.patch_fromText=function(n){var e=[];if(!n)return e;for(var t=n.split(`
4
- `),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 d.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 l=decodeURI(t[r].substring(1))}catch{throw new Error("Illegal escape in patch_fromText: "+l)}if(a=="-")o.diffs.push(new d.Diff(C,l));else if(a=="+")o.diffs.push(new d.Diff(T,l));else if(a==" ")o.diffs.push(new d.Diff(k,l));else{if(a=="@")break;if(a!=="")throw new Error('Invalid patch mode "'+a+'" in: '+l)}r++}}return e};d.patch_obj=function(){this.diffs=[],this.start1=null,this.start2=null,this.length1=0,this.length2=0};d.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+` @@
5
- `],r,i=0;i<this.diffs.length;i++){switch(this.diffs[i][0]){case T:r="+";break;case C:r="-";break;case k:r=" ";break}t[i+1]=r+encodeURI(this.diffs[i][1])+`
6
- `}return t.join("").replace(/%20/g," ")};me.exports=d;me.exports.diff_match_patch=d;me.exports.DIFF_DELETE=C;me.exports.DIFF_INSERT=T;me.exports.DIFF_EQUAL=k});import{hostname as yi}from"node:os";import{resolve as wi}from"node:path";import{createRequire as tr}from"module";var nr=tr("/"),fe,rr,ir;try{fe=nr("worker_threads"),rr=fe.Worker,ir=fe.isMarkedAsUntransferable}catch{}var N=Uint8Array,K=Uint16Array,at=Int32Array,De=new N([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]),Oe=new N([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]),rt=new N([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Rt=function(n,e){for(var t=new K(31),r=0;r<31;++r)t[r]=e+=1<<n[r-1];for(var i=new at(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}},fe=Rt(De,2),It=fe.b,it=fe.r;It[28]=258,it[258]=28;var zt=Rt(Oe,0),sr=zt.b,_t=zt.r,st=new K(32768);for(_=0;_<32768;++_)ee=(_&43690)>>1|(_&21845)<<1,ee=(ee&52428)>>2|(ee&13107)<<2,ee=(ee&61680)>>4|(ee&3855)<<4,st[_]=((ee&65280)>>8|(ee&255)<<8)>>1;var ee,_,Y=(function(n,e,t){for(var r=n.length,i=0,s=new K(e);i<r;++i)n[i]&&++s[n[i]-1];var o=new K(e);for(i=1;i<e;++i)o[i]=o[i-1]+s[i-1]<<1;var a;if(t){a=new K(1<<e);var l=15-e;for(i=0;i<r;++i)if(n[i])for(var c=i<<4|n[i],h=e-n[i],u=o[n[i]-1]++<<h,f=u|(1<<h)-1;u<=f;++u)a[st[u]>>l]=c}else for(a=new K(r),i=0;i<r;++i)n[i]&&(a[i]=st[o[n[i]-1]++]>>15-n[i]);return a}),ie=new N(288);for(_=0;_<144;++_)ie[_]=8;var _;for(_=144;_<256;++_)ie[_]=9;var _;for(_=256;_<280;++_)ie[_]=7;var _;for(_=280;_<288;++_)ie[_]=8;var _,Ee=new N(32);for(_=0;_<32;++_)Ee[_]=5;var _,or=Y(ie,9,0),ar=Y(ie,9,1),lr=Y(Ee,5,0),hr=Y(Ee,5,1),et=function(n){for(var e=n[0],t=1;t<n.length;++t)n[t]>e&&(e=n[t]);return e},q=function(n,e,t){var r=e/8|0;return(n[r]|n[r+1]<<8)>>(e&7)&t},tt=function(n,e){var t=e/8|0;return(n[t]|n[t+1]<<8|n[t+2]<<16)>>(e&7)},lt=function(n){return(n+7)/8|0},Ut=function(n,e,t){return(e==null||e<0)&&(e=0),(t==null||t>n.length)&&(t=n.length),new N(n.subarray(e,t))};var cr=["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"],ne=function(n,e,t){var r=new Error(e||cr[n]);if(r.code=n,Error.captureStackTrace&&Error.captureStackTrace(r,ne),!t)throw r;return r},ur=function(n,e,t,r){var i=n.length,s=r?r.length:0;if(!i||e.f&&!e.l)return t||new N(0);var o=!t,a=o||e.i!=2,l=e.i;o&&(t=new N(i*3));var c=function(we){var be=t.length;if(we>be){var ue=new N(Math.max(be*2,we));ue.set(t),t=ue}},h=e.f||0,u=e.p||0,f=e.b||0,g=e.l,m=e.d,v=e.m,x=e.n,w=i*8;do{if(!g){h=q(n,u,1);var A=q(n,u+1,3);if(u+=3,A)if(A==1)g=ar,m=hr,v=9,x=5;else if(A==2){var $=q(n,u,31)+257,E=q(n,u+10,15)+4,y=$+q(n,u+5,31)+1;u+=14;for(var p=new N(y),U=new N(19),z=0;z<E;++z)U[rt[z]]=q(n,u+z*3,7);u+=E*3;for(var F=et(U),re=(1<<F)-1,W=Y(U,F,1),z=0;z<y;){var B=W[q(n,u,re)];u+=B&15;var b=B>>4;if(b<16)p[z++]=b;else{var D=0,R=0;for(b==16?(R=3+q(n,u,3),u+=2,D=p[z-1]):b==17?(R=3+q(n,u,7),u+=3):b==18&&(R=11+q(n,u,127),u+=7);R--;)p[z++]=D}}var L=p.subarray(0,$),O=p.subarray($);v=et(L),x=et(O),g=Y(L,v,1),m=Y(O,x,1)}else ne(1);else{var b=lt(u)+4,S=n[b-4]|n[b-3]<<8,M=b+S;if(M>i){l&&ne(0);break}a&&c(f+S),t.set(n.subarray(b,M),f),e.b=f+=S,e.p=u=M*8,e.f=h;continue}if(u>w){l&&ne(0);break}}a&&c(f+131072);for(var ye=(1<<v)-1,G=(1<<x)-1,Q=u;;Q=u){var D=g[tt(n,u)&ye],V=D>>4;if(u+=D&15,u>w){l&&ne(0);break}if(D||ne(2),V<256)t[f++]=V;else if(V==256){Q=u,g=null;break}else{var J=V-254;if(V>264){var z=V-257,I=De[z];J=q(n,u,(1<<I)-1)+It[z],u+=I}var X=m[tt(n,u)&G],he=X>>4;X||ne(3),u+=X&15;var O=sr[he];if(he>3){var I=Oe[he];O+=tt(n,u)&(1<<I)-1,u+=I}if(u>w){l&&ne(0);break}a&&c(f+131072);var ce=f+J;if(f<O){var ze=s-O,Ue=Math.min(O,ce);for(ze+f<0&&ne(3);f<Ue;++f)t[f]=r[ze+f]}for(;f<ce;++f)t[f]=t[f-O]}}e.l=g,e.p=Q,e.b=f,e.f=h,g&&(h=1,e.m=v,e.d=m,e.n=x)}while(!h);return f!=t.length&&o?Ut(t,0,f):t.subarray(0,f)},te=function(n,e,t){t<<=e&7;var r=e/8|0;n[r]|=t,n[r+1]|=t>>8},ke=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},nt=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:Ot,l:0};if(i==1){var o=new N(t[0].s+1);return o[t[0].s]=1,{t:o,l:1}}t.sort(function(M,$){return M.f-$.f}),t.push({s:-1,f:25001});var a=t[0],l=t[1],c=0,h=1,u=2;for(t[0]={s:-1,f:a.f+l.f,l:a,r:l};h!=i-1;)a=t[t[c].f<t[u].f?c++:u++],l=t[c!=h&&t[c].f<t[u].f?c++:u++],t[h++]={s:-1,f:a.f+l.f,l:a,r:l};for(var f=s[0].s,r=1;r<i;++r)s[r].s>f&&(f=s[r].s);var g=new K(f+1),m=ot(t[h-1],g,0);if(m>e){var r=0,v=0,x=m-e,w=1<<x;for(s.sort(function($,E){return g[E.s]-g[$.s]||$.f-E.f});r<i;++r){var A=s[r].s;if(g[A]>e)v+=w-(1<<m-g[A]),g[A]=e;else break}for(v>>=x;v>0;){var b=s[r].s;g[b]<e?v-=1<<e-g[b]++-1:++r}for(;r>=0&&v;--r){var S=s[r].s;g[S]==e&&(--g[S],++v)}m=e}return{t:new N(g),l:m}},ot=function(n,e,t){return n.s==-1?Math.max(ot(n.l,e,t+1),ot(n.r,e,t+1)):e[n.s]=t},Ct=function(n){for(var e=n.length;e&&!n[--e];);for(var t=new K(++e),r=0,i=n[0],s=1,o=function(l){t[r++]=l},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}},Se=function(n,e){for(var t=0,r=0;r<e.length;++r)t+=n[r]*e[r];return t},Dt=function(n,e,t){var r=t.length,i=lt(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},Tt=function(n,e,t,r,i,s,o,a,l,c,h){te(e,h++,t),++i[256];for(var u=nt(i,15),f=u.t,g=u.l,m=nt(s,15),v=m.t,x=m.l,w=Ct(f),A=w.c,b=w.n,S=Ct(v),M=S.c,$=S.n,E=new K(19),y=0;y<A.length;++y)++E[A[y]&31];for(var y=0;y<M.length;++y)++E[M[y]&31];for(var p=nt(E,7),U=p.t,z=p.l,F=19;F>4&&!U[rt[F-1]];--F);var re=c+5<<3,W=Se(i,ie)+Se(s,Ee)+o,B=Se(i,f)+Se(s,v)+o+14+3*F+Se(E,U)+2*E[16]+3*E[17]+7*E[18];if(l>=0&&re<=W&&re<=B)return Dt(e,h,n.subarray(l,l+c));var D,R,L,O;if(te(e,h,1+(B<W)),h+=2,B<W){D=Y(f,g,0),R=f,L=Y(v,x,0),O=v;var ye=Y(U,z,0);te(e,h,b-257),te(e,h+5,$-1),te(e,h+10,F-4),h+=14;for(var y=0;y<F;++y)te(e,h+3*y,U[rt[y]]);h+=3*F;for(var G=[A,M],Q=0;Q<2;++Q)for(var V=G[Q],y=0;y<V.length;++y){var J=V[y]&31;te(e,h,ye[J]),h+=U[J],J>15&&(te(e,h,V[y]>>5&127),h+=V[y]>>12)}}else D=or,R=ie,L=lr,O=Ee;for(var y=0;y<a;++y){var I=r[y];if(I>255){var J=I>>18&31;ke(e,h,D[J+257]),h+=R[J+257],J>7&&(te(e,h,I>>23&31),h+=De[J]);var X=I&31;ke(e,h,L[X]),h+=O[X],X>3&&(ke(e,h,I>>5&8191),h+=Oe[X])}else ke(e,h,D[I]),h+=R[I]}return ke(e,h,D[256]),h+R[256]},fr=new at([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),Ot=new N(0),dr=function(n,e,t,r,i,s){var o=s.z||n.length,a=new N(r+o+5*(1+Math.ceil(o/7e3))+i),l=a.subarray(r,a.length-i),c=s.l,h=(s.r||0)&7;if(e){h&&(l[0]=s.r>>3);for(var u=fr[e-1],f=u>>13,g=u&8191,m=(1<<t)-1,v=s.p||new K(32768),x=s.h||new K(m+1),w=Math.ceil(t/3),A=2*w,b=function(Qe){return(n[Qe]^n[Qe+1]<<w^n[Qe+2]<<A)&m},S=new at(25e3),M=new K(288),$=new K(32),E=0,y=0,p=s.i||0,U=0,z=s.w||0,F=0;p+2<o;++p){var re=b(p),W=p&32767,B=x[re];if(v[W]=B,x[re]=W,z<=p){var D=o-p;if((E>7e3||U>24576)&&(D>423||!c)){h=Tt(n,l,0,S,M,$,y,U,F,p-F,h),U=E=y=0,F=p;for(var R=0;R<286;++R)M[R]=0;for(var R=0;R<30;++R)$[R]=0}var L=2,O=0,ye=g,G=W-B&32767;if(D>2&&re==b(p-G))for(var Q=Math.min(f,D)-1,V=Math.min(32767,p),J=Math.min(258,D);G<=V&&--ye&&W!=B;){if(n[p+L]==n[p+L-G]){for(var I=0;I<J&&n[p+I]==n[p+I-G];++I);if(I>L){if(L=I,O=G,I>Q)break;for(var X=Math.min(G,I-2),he=0,R=0;R<X;++R){var ce=p-G+R&32767,ze=v[ce],Ue=ce-ze&32767;Ue>he&&(he=Ue,B=ce)}}}W=B,B=v[W],G+=W-B&32767}if(O){S[U++]=268435456|it[L]<<18|_t[O];var we=it[L]&31,be=_t[O]&31;y+=De[we]+Oe[be],++M[257+we],++$[be],z=p+L,++E}else S[U++]=n[p],++M[n[p]]}}for(p=Math.max(p,z);p<o;++p)S[U++]=n[p],++M[n[p]];h=Tt(n,l,c,S,M,$,y,U,F,p-F,h),c||(s.r=h&7|l[h/8|0]<<3,h-=7,s.h=x,s.p=v,s.i=p,s.w=z)}else{for(var p=s.w||0;p<o+c;p+=65535){var ue=p+65535;ue>=o&&(l[h/8|0]=c,ue=o),h=Dt(l,h+1,n.subarray(p,ue))}s.i=o}return Ut(a,0,r+lt(h)+i)};var gr=function(n,e,t,r,i){if(!i&&(i={l:1},e.dictionary)){var s=e.dictionary.subarray(-32768),o=new N(s.length+n.length);o.set(s),o.set(n,s.length),n=o,i.w=s.length}return dr(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 ht(n,e){return gr(n,e||{},0,0)}function Ft(n,e){return ur(n,{i:2},e&&e.out,e&&e.dictionary)}var mr=typeof TextDecoder<"u"&&new TextDecoder,vr=0;try{mr.decode(Ot,{stream:!0}),vr=1}catch{}var Bt="basalt/hkdf-aes-gcm/1",oe=12,Ne=128,Lt=oe+Ne/8+1,Z=20,Wt=new TextEncoder,pr=new TextDecoder,Fe={auth:"basalt/auth/1",path:"basalt/path/1",content:"basalt/content/1",nonce:"basalt/nonce/1"};function Ae(){let n=globalThis.crypto;if(!n?.subtle)throw new Error("WebCrypto is unavailable, so this vault cannot be opened");return n.subtle}function Vt(){let n=globalThis.crypto;if(!n?.getRandomValues)throw new Error("no secure random source is available, so a vault cannot be created here");return n.getRandomValues(new Uint8Array(Z))}async function Jt(n){if(n.length<16)throw new Error(`root secret is ${n.length} bytes, need at least 16`);let e=Ae(),t=await e.importKey("raw",ae(n),"HKDF",!1,["deriveKey","deriveBits"]),r=l=>({name:"HKDF",hash:"SHA-256",salt:new Uint8Array(0),info:Wt.encode(l)}),[i,s,o,a]=await Promise.all([e.deriveBits(r(Fe.auth),t,256),e.deriveKey(r(Fe.path),t,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"]),e.deriveKey(r(Fe.content),t,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"]),e.deriveKey(r(Fe.nonce),t,{name:"HMAC",hash:"SHA-256"},!1,["sign"])]);return{auth:new Uint8Array(i),path:s,content:o,nonce:a}}async function Kt(n,e,t){let r=Ae(),i=await yr(e,t),s=await r.encrypt({name:"AES-GCM",iv:ae(i),tagLength:Ne},n,ae(t)),o=new Uint8Array(oe+s.byteLength);return o.set(i,0),o.set(new Uint8Array(s),oe),o}async function Ht(n,e){if(e.length<oe+Ne/8)throw new Error(`sealed value is ${e.length} bytes, too short to contain a nonce and a tag`);let t=Ae(),r=e.subarray(0,oe),i=e.subarray(oe);try{let s=await t.decrypt({name:"AES-GCM",iv:ae(r),tagLength:Ne},n,ae(i));return new Uint8Array(s)}catch(s){throw new Error("sealed value failed authentication, so it is not what was stored",{cause:s})}}async function yr(n,e){let t=await Ae().sign("HMAC",n,ae(e));return new Uint8Array(t,0,oe)}async function Be(n,e){return xe(await Kt(n.path,n.nonce,Wt.encode(e)))}async function Le(n,e){let t=await Ht(n.path,We(e));return pr.decode(t)}var jt=0,Gt=1;async function wr(n,e){let t=br(e)?ht(e,{level:6}):void 0,r=t!==void 0&&t.length<e.length,i=r?t:e,s=new Uint8Array(1+i.length);return s[0]=r?Gt:jt,s.set(i,1),Kt(n.content,n.nonce,s)}function br(n){if(n.length===0)return!1;if(n.length<=Nt*2)return!0;let e=n.subarray(0,Nt);return ht(e,{level:6}).length<e.length}var Nt=4096;async function ge(n,e){return Promise.all([...e].map(async t=>{let r=await wr(n,t);return{name:await ct(r),bytes:r}}))}async function qt(n,e){let t=await Ht(n.content,e);if(t.length===0)throw new Error("sealed chunk carries no marker byte");let r=t[0],i=t.subarray(1);if(r===jt)return i;if(r===Gt)try{return Ft(i)}catch(s){throw new Error("sealed chunk claims to be deflated and is not",{cause:s})}throw new Error(`sealed chunk has an unknown marker byte ${r}`)}async function ct(n){let e=await Ae().digest("SHA-256",ae(n));return kr(new Uint8Array(e))}function Zt(n){return xe(n.auth)}function ae(n){return n.slice().buffer}function kr(n){let e="";for(let t of n)e+=t.toString(16).padStart(2,"0");return e}var de="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";function xe(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+=de[r>>2],e+=de[(r&3)<<4|(i??0)>>4],i===void 0||(e+=de[(i&15)<<2|(s??0)>>6],s===void 0))break;e+=de[s&63]}return e}var Sr=(()=>{let n=new Int16Array(128).fill(-1);for(let e=0;e<de.length;e++)n[de.charCodeAt(e)]=e;return n})();function We(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),l=a<128?Sr[a]:-1;if(l<0)throw new Error(`invalid base64url character ${JSON.stringify(n[o])} at position ${o}`);i=i<<6|l,s+=6,s>=8&&(s-=8,t[r++]=i>>s&255)}return t.subarray(0,r)}var se=48,le=31,Xt=1,Yt={min:512,avg:1024,max:4096},Er=64,Ar=Yt.avg,xr=64*1024;function Pr(n){let e=Math.sqrt(Er*Math.max(n,1)),t=Math.min(xr,Math.max(Ar,Math.round(e/512)*512));return{min:Math.max(Yt.min,t/2),avg:t,max:t*4}}var ut={min:128*1024,avg:256*1024,max:1024*1024},$r=4*1024*1024;function Qt(n,e,t=ut.max){(!Number.isFinite(t)||t<=0)&&(t=ut.max);let r=e&&n<$r?Pr(n):ut,i=Math.min(r.max,t-Lt),s=Math.max(i,se*4);return{min:Math.min(r.min,s),avg:Math.min(r.avg,s),max:s}}function en(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*tn(n,e,t){let{min:r,avg:i,max:s}=e,o=n.length,a=1;for(let h=0;h<se-1;h++)a=Math.imul(a,le);let l=0,c=0;for(let h=0;h<o;h++){let u=n[h];h>=l+se?(c=c-Math.imul(n[h-se],a)|0,c=Math.imul(c,le),c=c+u|0):(c=Math.imul(c,le),c=c+u|0);let f=h-l+1,g=f>=r&&(c>>>0)%i===Xt;if(f>=s&&(g=!0),g){let m=t?en(n,l,h+1):h+1;yield{offset:l,bytes:n.subarray(l,m)},l=m,c=0,h=m-1}}l<o&&(yield{offset:l,bytes:n.subarray(l,o)})}async function*nn(n,e,t){let{min:r,avg:i,max:s}=e,o=1;for(let f=0;f<se-1;f++)o=Math.imul(o,le);let a=new Uint8Array(Math.max(s,se*2)),l=0,c=0,h=0,u=()=>{let f=t?en(a,0,l):l,g={offset:h,bytes:a.slice(0,f)};h+=f;let m=l-f;a.copyWithin(0,f,l),l=m,c=0;for(let v=0;v<m;v++)c=Math.imul(c,le),c=c+a[v]|0;return g};for await(let f of n)for(let g=0;g<f.length;g++){let m=f[g];a[l++]=m,l>=se+1?(c=c-Math.imul(a[l-1-se],o)|0,c=Math.imul(c,le),c=c+m|0):(c=Math.imul(c,le),c=c+m|0),(l>=s||l>=r&&(c>>>0)%i===Xt)&&(yield u())}if(l>0){let f={offset:h,bytes:a.slice(0,l)};h+=l,l=0,yield f}}var Mr=new Set(["md","txt","canvas","json","csv","yml","yaml","xml","html","css","js","ts","svg","bib","tex"]);function rn(n){let e=n.lastIndexOf(".");return e<0?!1:Mr.has(n.slice(e+1).toLowerCase())}var _r=new Set(["canvas","json"]);function sn(n){let e=n.lastIndexOf(".");return e<0?!1:_r.has(n.slice(e+1).toLowerCase())}var hn=er(on(),1),Cr=-1,Tr=0,Rr=1;function an(n){let e=[],t=0;for(let[r,i]of n)r===Tr?t+=i.length:r===Cr?(e.push({start:t,end:t+i.length}),t+=i.length):e.push({start:t,end:t});return e}function Ir(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 cn(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=new hn.diff_match_patch,s=i.diff_main(n,e,!0,0);s.length>2&&(i.diff_cleanupSemantic(s),i.diff_cleanupEfficiency(s));let o=i.diff_main(n,t,!0,0);o.length>2&&(i.diff_cleanupSemantic(o),i.diff_cleanupEfficiency(o));let a=Ir(an(s),an(o));if(a!==void 0)return{kind:"conflict",why:`both devices changed the same text, at characters ${a.start} to ${a.end} of the last synced version`};let l=ln(i,n,s,t),c=ln(i,n,o,e);if(l.failed>0||c.failed>0){let u=Math.max(l.failed,c.failed),f=Math.max(l.total,c.total);return{kind:"conflict",why:`${u} of ${f} changes could not be placed in the other version`}}if(!zr(l.text,c.text))return{kind:"conflict",why:"merging the two versions in either order gives different content, so at least one change was placed wrongly"};let h=Ur(s,l.text);return h!==void 0?{kind:"conflict",why:`the merge reported success but ${Dr(h)} is not in the result`}:r(l.text)?{kind:"merged",text:l.text}:{kind:"conflict",why:"both sides merged cleanly and the result is no longer a valid file of its kind"}}function zr(n,e){if(n===e)return!0;let t=n.split(`
2
+ var ar=Object.create;var Bt=Object.defineProperty;var lr=Object.getOwnPropertyDescriptor;var hr=Object.getOwnPropertyNames;var cr=Object.getPrototypeOf,ur=Object.prototype.hasOwnProperty;var fr=(t,e)=>()=>{try{return e||t((e={exports:{}}).exports,e),e.exports}catch(n){throw e=0,n}};var dr=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of hr(e))!ur.call(t,i)&&i!==n&&Bt(t,i,{get:()=>e[i],enumerable:!(r=lr(e,i))||r.enumerable});return t};var gr=(t,e,n)=>(n=t!=null?ar(cr(t)):{},dr(e||!t||!t.__esModule?Bt(n,"default",{value:t,enumerable:!0}):n,t));var vn=fr((ns,we)=>{var d=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},T=-1,_=1,k=0;d.Diff=function(t,e){return[t,e]};d.prototype.diff_main=function(t,e,n,r){typeof r>"u"&&(this.Diff_Timeout<=0?r=Number.MAX_VALUE:r=new Date().getTime()+this.Diff_Timeout*1e3);var i=r;if(t==null||e==null)throw new Error("Null input. (diff_main)");if(t==e)return t?[new d.Diff(k,t)]:[];typeof n>"u"&&(n=!0);var s=n,o=this.diff_commonPrefix(t,e),a=t.substring(0,o);t=t.substring(o),e=e.substring(o),o=this.diff_commonSuffix(t,e);var l=t.substring(t.length-o);t=t.substring(0,t.length-o),e=e.substring(0,e.length-o);var h=this.diff_compute_(t,e,s,i);return a&&h.unshift(new d.Diff(k,a)),l&&h.push(new d.Diff(k,l)),this.diff_cleanupMerge(h),h};d.prototype.diff_compute_=function(t,e,n,r){var i;if(!t)return[new d.Diff(_,e)];if(!e)return[new d.Diff(T,t)];var s=t.length>e.length?t:e,o=t.length>e.length?e:t,a=s.indexOf(o);if(a!=-1)return i=[new d.Diff(_,s.substring(0,a)),new d.Diff(k,o),new d.Diff(_,s.substring(a+o.length))],t.length>e.length&&(i[0][0]=i[2][0]=T),i;if(o.length==1)return[new d.Diff(T,t),new d.Diff(_,e)];var l=this.diff_halfMatch_(t,e);if(l){var h=l[0],c=l[1],u=l[2],f=l[3],g=l[4],m=this.diff_main(h,u,n,r),p=this.diff_main(c,f,n,r);return m.concat([new d.Diff(k,g)],p)}return n&&t.length>100&&e.length>100?this.diff_lineMode_(t,e,r):this.diff_bisect_(t,e,r)};d.prototype.diff_lineMode_=function(t,e,n){var r=this.diff_linesToChars_(t,e);t=r.chars1,e=r.chars2;var i=r.lineArray,s=this.diff_main(t,e,!1,n);this.diff_charsToLines_(s,i),this.diff_cleanupSemantic(s),s.push(new d.Diff(k,""));for(var o=0,a=0,l=0,h="",c="";o<s.length;){switch(s[o][0]){case _:l++,c+=s[o][1];break;case T:a++,h+=s[o][1];break;case k:if(a>=1&&l>=1){s.splice(o-a-l,a+l),o=o-a-l;for(var u=this.diff_main(h,c,!1,n),f=u.length-1;f>=0;f--)s.splice(o,0,u[f]);o=o+u.length}l=0,a=0,h="",c="";break}o++}return s.pop(),s};d.prototype.diff_bisect_=function(t,e,n){for(var r=t.length,i=e.length,s=Math.ceil((r+i)/2),o=s,a=2*s,l=new Array(a),h=new Array(a),c=0;c<a;c++)l[c]=-1,h[c]=-1;l[o+1]=0,h[o+1]=0;for(var u=r-i,f=u%2!=0,g=0,m=0,p=0,x=0,w=0;w<s&&!(new Date().getTime()>n);w++){for(var A=-w+g;A<=w-m;A+=2){var b=o+A,S;A==-w||A!=w&&l[b-1]<l[b+1]?S=l[b+1]:S=l[b-1]+1;for(var M=S-A;S<r&&M<i&&t.charAt(S)==e.charAt(M);)S++,M++;if(l[b]=S,S>r)m+=2;else if(M>i)g+=2;else if(f){var $=o+u-A;if($>=0&&$<a&&h[$]!=-1){var E=r-h[$];if(S>=E)return this.diff_bisectSplit_(t,e,S,M,n)}}}for(var v=-w+p;v<=w-x;v+=2){var $=o+v,E;v==-w||v!=w&&h[$-1]<h[$+1]?E=h[$+1]:E=h[$-1]+1;for(var y=E-v;E<r&&y<i&&t.charAt(r-E-1)==e.charAt(i-y-1);)E++,y++;if(h[$]=E,E>r)x+=2;else if(y>i)p+=2;else if(!f){var b=o+u-v;if(b>=0&&b<a&&l[b]!=-1){var S=l[b],M=o+S-b;if(E=r-E,S>=E)return this.diff_bisectSplit_(t,e,S,M,n)}}}}return[new d.Diff(T,t),new d.Diff(_,e)]};d.prototype.diff_bisectSplit_=function(t,e,n,r,i){var s=t.substring(0,n),o=e.substring(0,r),a=t.substring(n),l=e.substring(r),h=this.diff_main(s,o,!1,i),c=this.diff_main(a,l,!1,i);return h.concat(c)};d.prototype.diff_linesToChars_=function(t,e){var n=[],r={};n[0]="";function i(l){for(var h="",c=0,u=-1,f=n.length;u<l.length-1;){u=l.indexOf(`
3
+ `,c),u==-1&&(u=l.length-1);var g=l.substring(c,u+1);(r.hasOwnProperty?r.hasOwnProperty(g):r[g]!==void 0)?h+=String.fromCharCode(r[g]):(f==s&&(g=l.substring(c),u=l.length),h+=String.fromCharCode(f),r[g]=f,n[f++]=g),c=u+1}return h}var s=4e4,o=i(t);s=65535;var a=i(e);return{chars1:o,chars2:a,lineArray:n}};d.prototype.diff_charsToLines_=function(t,e){for(var n=0;n<t.length;n++){for(var r=t[n][1],i=[],s=0;s<r.length;s++)i[s]=e[r.charCodeAt(s)];t[n][1]=i.join("")}};d.prototype.diff_commonPrefix=function(t,e){if(!t||!e||t.charAt(0)!=e.charAt(0))return 0;for(var n=0,r=Math.min(t.length,e.length),i=r,s=0;n<i;)t.substring(s,i)==e.substring(s,i)?(n=i,s=n):r=i,i=Math.floor((r-n)/2+n);return i};d.prototype.diff_commonSuffix=function(t,e){if(!t||!e||t.charAt(t.length-1)!=e.charAt(e.length-1))return 0;for(var n=0,r=Math.min(t.length,e.length),i=r,s=0;n<i;)t.substring(t.length-i,t.length-s)==e.substring(e.length-i,e.length-s)?(n=i,s=n):r=i,i=Math.floor((r-n)/2+n);return i};d.prototype.diff_commonOverlap_=function(t,e){var n=t.length,r=e.length;if(n==0||r==0)return 0;n>r?t=t.substring(n-r):n<r&&(e=e.substring(0,n));var i=Math.min(n,r);if(t==e)return i;for(var s=0,o=1;;){var a=t.substring(i-o),l=e.indexOf(a);if(l==-1)return s;o+=l,(l==0||t.substring(i-o)==e.substring(0,o))&&(s=o,o++)}};d.prototype.diff_halfMatch_=function(t,e){if(this.Diff_Timeout<=0)return null;var n=t.length>e.length?t:e,r=t.length>e.length?e:t;if(n.length<4||r.length*2<n.length)return null;var i=this;function s(m,p,x){for(var w=m.substring(x,x+Math.floor(m.length/4)),A=-1,b="",S,M,$,E;(A=p.indexOf(w,A+1))!=-1;){var v=i.diff_commonPrefix(m.substring(x),p.substring(A)),y=i.diff_commonSuffix(m.substring(0,x),p.substring(0,A));b.length<y+v&&(b=p.substring(A-y,A)+p.substring(A,A+v),S=m.substring(0,x-y),M=m.substring(x+v),$=p.substring(0,A-y),E=p.substring(A+v))}return b.length*2>=m.length?[S,M,$,E,b]:null}var o=s(n,r,Math.ceil(n.length/4)),a=s(n,r,Math.ceil(n.length/2)),l;if(!o&&!a)return null;a?o?l=o[4].length>a[4].length?o:a:l=a:l=o;var h,c,u,f;t.length>e.length?(h=l[0],c=l[1],u=l[2],f=l[3]):(u=l[0],f=l[1],h=l[2],c=l[3]);var g=l[4];return[h,c,u,f,g]};d.prototype.diff_cleanupSemantic=function(t){for(var e=!1,n=[],r=0,i=null,s=0,o=0,a=0,l=0,h=0;s<t.length;)t[s][0]==k?(n[r++]=s,o=l,a=h,l=0,h=0,i=t[s][1]):(t[s][0]==_?l+=t[s][1].length:h+=t[s][1].length,i&&i.length<=Math.max(o,a)&&i.length<=Math.max(l,h)&&(t.splice(n[r-1],0,new d.Diff(T,i)),t[n[r-1]+1][0]=_,r--,r--,s=r>0?n[r-1]:-1,o=0,a=0,l=0,h=0,i=null,e=!0)),s++;for(e&&this.diff_cleanupMerge(t),this.diff_cleanupSemanticLossless(t),s=1;s<t.length;){if(t[s-1][0]==T&&t[s][0]==_){var c=t[s-1][1],u=t[s][1],f=this.diff_commonOverlap_(c,u),g=this.diff_commonOverlap_(u,c);f>=g?(f>=c.length/2||f>=u.length/2)&&(t.splice(s,0,new d.Diff(k,u.substring(0,f))),t[s-1][1]=c.substring(0,c.length-f),t[s+1][1]=u.substring(f),s++):(g>=c.length/2||g>=u.length/2)&&(t.splice(s,0,new d.Diff(k,c.substring(0,g))),t[s-1][0]=_,t[s-1][1]=u.substring(0,u.length-g),t[s+1][0]=T,t[s+1][1]=c.substring(g),s++),s++}s++}};d.prototype.diff_cleanupSemanticLossless=function(t){function e(g,m){if(!g||!m)return 6;var p=g.charAt(g.length-1),x=m.charAt(0),w=p.match(d.nonAlphaNumericRegex_),A=x.match(d.nonAlphaNumericRegex_),b=w&&p.match(d.whitespaceRegex_),S=A&&x.match(d.whitespaceRegex_),M=b&&p.match(d.linebreakRegex_),$=S&&x.match(d.linebreakRegex_),E=M&&g.match(d.blanklineEndRegex_),v=$&&m.match(d.blanklineStartRegex_);return E||v?5:M||$?4:w&&!b&&S?3:b||S?2:w||A?1:0}for(var n=1;n<t.length-1;){if(t[n-1][0]==k&&t[n+1][0]==k){var r=t[n-1][1],i=t[n][1],s=t[n+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 l=r,h=i,c=s,u=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 f=e(r,i)+e(i,s);f>=u&&(u=f,l=r,h=i,c=s)}t[n-1][1]!=l&&(l?t[n-1][1]=l:(t.splice(n-1,1),n--),t[n][1]=h,c?t[n+1][1]=c:(t.splice(n+1,1),n--))}n++}};d.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;d.whitespaceRegex_=/\s/;d.linebreakRegex_=/[\r\n]/;d.blanklineEndRegex_=/\n\r?\n$/;d.blanklineStartRegex_=/^\r?\n\r?\n/;d.prototype.diff_cleanupEfficiency=function(t){for(var e=!1,n=[],r=0,i=null,s=0,o=!1,a=!1,l=!1,h=!1;s<t.length;)t[s][0]==k?(t[s][1].length<this.Diff_EditCost&&(l||h)?(n[r++]=s,o=l,a=h,i=t[s][1]):(r=0,i=null),l=h=!1):(t[s][0]==T?h=!0:l=!0,i&&(o&&a&&l&&h||i.length<this.Diff_EditCost/2&&o+a+l+h==3)&&(t.splice(n[r-1],0,new d.Diff(T,i)),t[n[r-1]+1][0]=_,r--,i=null,o&&a?(l=h=!0,r=0):(r--,s=r>0?n[r-1]:-1,l=h=!1),e=!0)),s++;e&&this.diff_cleanupMerge(t)};d.prototype.diff_cleanupMerge=function(t){t.push(new d.Diff(k,""));for(var e=0,n=0,r=0,i="",s="",o;e<t.length;)switch(t[e][0]){case _:r++,s+=t[e][1],e++;break;case T:n++,i+=t[e][1],e++;break;case k:n+r>1?(n!==0&&r!==0&&(o=this.diff_commonPrefix(s,i),o!==0&&(e-n-r>0&&t[e-n-r-1][0]==k?t[e-n-r-1][1]+=s.substring(0,o):(t.splice(0,0,new d.Diff(k,s.substring(0,o))),e++),s=s.substring(o),i=i.substring(o)),o=this.diff_commonSuffix(s,i),o!==0&&(t[e][1]=s.substring(s.length-o)+t[e][1],s=s.substring(0,s.length-o),i=i.substring(0,i.length-o))),e-=n+r,t.splice(e,n+r),i.length&&(t.splice(e,0,new d.Diff(T,i)),e++),s.length&&(t.splice(e,0,new d.Diff(_,s)),e++),e++):e!==0&&t[e-1][0]==k?(t[e-1][1]+=t[e][1],t.splice(e,1)):e++,r=0,n=0,i="",s="";break}t[t.length-1][1]===""&&t.pop();var a=!1;for(e=1;e<t.length-1;)t[e-1][0]==k&&t[e+1][0]==k&&(t[e][1].substring(t[e][1].length-t[e-1][1].length)==t[e-1][1]?(t[e][1]=t[e-1][1]+t[e][1].substring(0,t[e][1].length-t[e-1][1].length),t[e+1][1]=t[e-1][1]+t[e+1][1],t.splice(e-1,1),a=!0):t[e][1].substring(0,t[e+1][1].length)==t[e+1][1]&&(t[e-1][1]+=t[e+1][1],t[e][1]=t[e][1].substring(t[e+1][1].length)+t[e+1][1],t.splice(e+1,1),a=!0)),e++;a&&this.diff_cleanupMerge(t)};d.prototype.diff_xIndex=function(t,e){var n=0,r=0,i=0,s=0,o;for(o=0;o<t.length&&(t[o][0]!==_&&(n+=t[o][1].length),t[o][0]!==T&&(r+=t[o][1].length),!(n>e));o++)i=n,s=r;return t.length!=o&&t[o][0]===T?s:s+(e-i)};d.prototype.diff_prettyHtml=function(t){for(var e=[],n=/&/g,r=/</g,i=/>/g,s=/\n/g,o=0;o<t.length;o++){var a=t[o][0],l=t[o][1],h=l.replace(n,"&amp;").replace(r,"&lt;").replace(i,"&gt;").replace(s,"&para;<br>");switch(a){case _:e[o]='<ins style="background:#e6ffe6;">'+h+"</ins>";break;case T:e[o]='<del style="background:#ffe6e6;">'+h+"</del>";break;case k:e[o]="<span>"+h+"</span>";break}}return e.join("")};d.prototype.diff_text1=function(t){for(var e=[],n=0;n<t.length;n++)t[n][0]!==_&&(e[n]=t[n][1]);return e.join("")};d.prototype.diff_text2=function(t){for(var e=[],n=0;n<t.length;n++)t[n][0]!==T&&(e[n]=t[n][1]);return e.join("")};d.prototype.diff_levenshtein=function(t){for(var e=0,n=0,r=0,i=0;i<t.length;i++){var s=t[i][0],o=t[i][1];switch(s){case _:n+=o.length;break;case T:r+=o.length;break;case k:e+=Math.max(n,r),n=0,r=0;break}}return e+=Math.max(n,r),e};d.prototype.diff_toDelta=function(t){for(var e=[],n=0;n<t.length;n++)switch(t[n][0]){case _:e[n]="+"+encodeURI(t[n][1]);break;case T:e[n]="-"+t[n][1].length;break;case k:e[n]="="+t[n][1].length;break}return e.join(" ").replace(/%20/g," ")};d.prototype.diff_fromDelta=function(t,e){for(var n=[],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{n[r++]=new d.Diff(_,decodeURI(a))}catch{throw new Error("Illegal escape in diff_fromDelta: "+a)}break;case"-":case"=":var l=parseInt(a,10);if(isNaN(l)||l<0)throw new Error("Invalid number in diff_fromDelta: "+a);var h=t.substring(i,i+=l);s[o].charAt(0)=="="?n[r++]=new d.Diff(k,h):n[r++]=new d.Diff(T,h);break;default:if(s[o])throw new Error("Invalid diff operation in diff_fromDelta: "+s[o])}}if(i!=t.length)throw new Error("Delta length ("+i+") does not equal source text length ("+t.length+").");return n};d.prototype.match_main=function(t,e,n){if(t==null||e==null||n==null)throw new Error("Null input. (match_main)");return n=Math.max(0,Math.min(n,t.length)),t==e?0:t.length?t.substring(n,n+e.length)==e?n:this.match_bitap_(t,e,n):-1};d.prototype.match_bitap_=function(t,e,n){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,M){var $=S/e.length,E=Math.abs(n-M);return i.Match_Distance?$+E/i.Match_Distance:E?1:$}var o=this.Match_Threshold,a=t.indexOf(e,n);a!=-1&&(o=Math.min(s(0,a),o),a=t.lastIndexOf(e,n+e.length),a!=-1&&(o=Math.min(s(0,a),o)));var l=1<<e.length-1;a=-1;for(var h,c,u=e.length+t.length,f,g=0;g<e.length;g++){for(h=0,c=u;h<c;)s(g,n+c)<=o?h=c:u=c,c=Math.floor((u-h)/2+h);u=c;var m=Math.max(1,n-c+1),p=Math.min(n+c,t.length)+e.length,x=Array(p+2);x[p+1]=(1<<g)-1;for(var w=p;w>=m;w--){var A=r[t.charAt(w-1)];if(g===0?x[w]=(x[w+1]<<1|1)&A:x[w]=(x[w+1]<<1|1)&A|((f[w+1]|f[w])<<1|1)|f[w+1],x[w]&l){var b=s(g,w-1);if(b<=o)if(o=b,a=w-1,a>n)m=Math.max(1,2*n-a);else break}}if(s(g+1,n)>o)break;f=x}return a};d.prototype.match_alphabet_=function(t){for(var e={},n=0;n<t.length;n++)e[t.charAt(n)]=0;for(var n=0;n<t.length;n++)e[t.charAt(n)]|=1<<t.length-n-1;return e};d.prototype.patch_addContext_=function(t,e){if(e.length!=0){if(t.start2===null)throw Error("patch not initialized");for(var n=e.substring(t.start2,t.start2+t.length1),r=0;e.indexOf(n)!=e.lastIndexOf(n)&&n.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)r+=this.Patch_Margin,n=e.substring(t.start2-r,t.start2+t.length1+r);r+=this.Patch_Margin;var i=e.substring(t.start2-r,t.start2);i&&t.diffs.unshift(new d.Diff(k,i));var s=e.substring(t.start2+t.length1,t.start2+t.length1+r);s&&t.diffs.push(new d.Diff(k,s)),t.start1-=i.length,t.start2-=i.length,t.length1+=i.length+s.length,t.length2+=i.length+s.length}};d.prototype.patch_make=function(t,e,n){var r,i;if(typeof t=="string"&&typeof e=="string"&&typeof n>"u")r=t,i=this.diff_main(r,e,!0),i.length>2&&(this.diff_cleanupSemantic(i),this.diff_cleanupEfficiency(i));else if(t&&typeof t=="object"&&typeof e>"u"&&typeof n>"u")i=t,r=this.diff_text1(i);else if(typeof t=="string"&&e&&typeof e=="object"&&typeof n>"u")r=t,i=e;else if(typeof t=="string"&&typeof e=="string"&&n&&typeof n=="object")r=t,i=n;else throw new Error("Unknown call format to patch_make.");if(i.length===0)return[];for(var s=[],o=new d.patch_obj,a=0,l=0,h=0,c=r,u=r,f=0;f<i.length;f++){var g=i[f][0],m=i[f][1];switch(!a&&g!==k&&(o.start1=l,o.start2=h),g){case _:o.diffs[a++]=i[f],o.length2+=m.length,u=u.substring(0,h)+m+u.substring(h);break;case T:o.length1+=m.length,o.diffs[a++]=i[f],u=u.substring(0,h)+u.substring(h+m.length);break;case k:m.length<=2*this.Patch_Margin&&a&&i.length!=f+1?(o.diffs[a++]=i[f],o.length1+=m.length,o.length2+=m.length):m.length>=2*this.Patch_Margin&&a&&(this.patch_addContext_(o,c),s.push(o),o=new d.patch_obj,a=0,c=u,l=h);break}g!==_&&(l+=m.length),g!==T&&(h+=m.length)}return a&&(this.patch_addContext_(o,c),s.push(o)),s};d.prototype.patch_deepCopy=function(t){for(var e=[],n=0;n<t.length;n++){var r=t[n],i=new d.patch_obj;i.diffs=[];for(var s=0;s<r.diffs.length;s++)i.diffs[s]=new d.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[n]=i}return e};d.prototype.patch_apply=function(t,e){if(t.length==0)return[e,[]];t=this.patch_deepCopy(t);var n=this.patch_addPadding(t);e=n+e+n,this.patch_splitMax(t);for(var r=0,i=[],s=0;s<t.length;s++){var o=t[s].start2+r,a=this.diff_text1(t[s].diffs),l,h=-1;if(a.length>this.Match_MaxBits?(l=this.match_main(e,a.substring(0,this.Match_MaxBits),o),l!=-1&&(h=this.match_main(e,a.substring(a.length-this.Match_MaxBits),o+a.length-this.Match_MaxBits),(h==-1||l>=h)&&(l=-1))):l=this.match_main(e,a,o),l==-1)i[s]=!1,r-=t[s].length2-t[s].length1;else{i[s]=!0,r=l-o;var c;if(h==-1?c=e.substring(l,l+a.length):c=e.substring(l,h+this.Match_MaxBits),a==c)e=e.substring(0,l)+this.diff_text2(t[s].diffs)+e.substring(l+a.length);else{var u=this.diff_main(a,c,!1);if(a.length>this.Match_MaxBits&&this.diff_levenshtein(u)/a.length>this.Patch_DeleteThreshold)i[s]=!1;else{this.diff_cleanupSemanticLossless(u);for(var f=0,g,m=0;m<t[s].diffs.length;m++){var p=t[s].diffs[m];p[0]!==k&&(g=this.diff_xIndex(u,f)),p[0]===_?e=e.substring(0,l+g)+p[1]+e.substring(l+g):p[0]===T&&(e=e.substring(0,l+g)+e.substring(l+this.diff_xIndex(u,f+p[1].length))),p[0]!==T&&(f+=p[1].length)}}}}}return e=e.substring(n.length,e.length-n.length),[e,i]};d.prototype.patch_addPadding=function(t){for(var e=this.Patch_Margin,n="",r=1;r<=e;r++)n+=String.fromCharCode(r);for(var r=0;r<t.length;r++)t[r].start1+=e,t[r].start2+=e;var i=t[0],s=i.diffs;if(s.length==0||s[0][0]!=k)s.unshift(new d.Diff(k,n)),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]=n.substring(s[0][1].length)+s[0][1],i.start1-=o,i.start2-=o,i.length1+=o,i.length2+=o}if(i=t[t.length-1],s=i.diffs,s.length==0||s[s.length-1][0]!=k)s.push(new d.Diff(k,n)),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]+=n.substring(0,o),i.length1+=o,i.length2+=o}return n};d.prototype.patch_splitMax=function(t){for(var e=this.Match_MaxBits,n=0;n<t.length;n++)if(!(t[n].length1<=e)){var r=t[n];t.splice(n--,1);for(var i=r.start1,s=r.start2,o="";r.diffs.length!==0;){var a=new d.patch_obj,l=!0;for(a.start1=i-o.length,a.start2=s-o.length,o!==""&&(a.length1=a.length2=o.length,a.diffs.push(new d.Diff(k,o)));r.diffs.length!==0&&a.length1<e-this.Patch_Margin;){var h=r.diffs[0][0],c=r.diffs[0][1];h===_?(a.length2+=c.length,s+=c.length,a.diffs.push(r.diffs.shift()),l=!1):h===T&&a.diffs.length==1&&a.diffs[0][0]==k&&c.length>2*e?(a.length1+=c.length,i+=c.length,l=!1,a.diffs.push(new d.Diff(h,c)),r.diffs.shift()):(c=c.substring(0,e-a.length1-this.Patch_Margin),a.length1+=c.length,i+=c.length,h===k?(a.length2+=c.length,s+=c.length):l=!1,a.diffs.push(new d.Diff(h,c)),c==r.diffs[0][1]?r.diffs.shift():r.diffs[0][1]=r.diffs[0][1].substring(c.length))}o=this.diff_text2(a.diffs),o=o.substring(o.length-this.Patch_Margin);var u=this.diff_text1(r.diffs).substring(0,this.Patch_Margin);u!==""&&(a.length1+=u.length,a.length2+=u.length,a.diffs.length!==0&&a.diffs[a.diffs.length-1][0]===k?a.diffs[a.diffs.length-1][1]+=u:a.diffs.push(new d.Diff(k,u))),l||t.splice(++n,0,a)}}};d.prototype.patch_toText=function(t){for(var e=[],n=0;n<t.length;n++)e[n]=t[n];return e.join("")};d.prototype.patch_fromText=function(t){var e=[];if(!t)return e;for(var n=t.split(`
4
+ `),r=0,i=/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/;r<n.length;){var s=n[r].match(i);if(!s)throw new Error("Invalid patch string: "+n[r]);var o=new d.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<n.length;){var a=n[r].charAt(0);try{var l=decodeURI(n[r].substring(1))}catch{throw new Error("Illegal escape in patch_fromText: "+l)}if(a=="-")o.diffs.push(new d.Diff(T,l));else if(a=="+")o.diffs.push(new d.Diff(_,l));else if(a==" ")o.diffs.push(new d.Diff(k,l));else{if(a=="@")break;if(a!=="")throw new Error('Invalid patch mode "'+a+'" in: '+l)}r++}}return e};d.patch_obj=function(){this.diffs=[],this.start1=null,this.start2=null,this.length1=0,this.length2=0};d.patch_obj.prototype.toString=function(){var t,e;this.length1===0?t=this.start1+",0":this.length1==1?t=this.start1+1:t=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 n=["@@ -"+t+" +"+e+` @@
5
+ `],r,i=0;i<this.diffs.length;i++){switch(this.diffs[i][0]){case _:r="+";break;case T:r="-";break;case k:r=" ";break}n[i+1]=r+encodeURI(this.diffs[i][1])+`
6
+ `}return n.join("").replace(/%20/g," ")};we.exports=d;we.exports.diff_match_patch=d;we.exports.DIFF_DELETE=T;we.exports.DIFF_INSERT=_;we.exports.DIFF_EQUAL=k});import{hostname as zi}from"node:os";import{resolve as Di}from"node:path";import{createRequire as mr}from"module";var pr=mr("/"),ye,yr,vr;try{ye=pr("worker_threads"),yr=ye.Worker,vr=ye.isMarkedAsUntransferable}catch{}var N=Uint8Array,K=Uint16Array,ft=Int32Array,Oe=new N([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]),Ne=new N([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]),lt=new N([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Jt=function(t,e){for(var n=new K(31),r=0;r<31;++r)n[r]=e+=1<<t[r-1];for(var i=new ft(n[30]),r=1;r<30;++r)for(var s=n[r];s<n[r+1];++s)i[s]=s-n[r]<<5|r;return{b:n,r:i}},ye=Jt(Oe,2),Kt=ye.b,ht=ye.r;Kt[28]=258,ht[258]=28;var Ht=Jt(Ne,0),wr=Ht.b,Lt=Ht.r,ct=new K(32768);for(C=0;C<32768;++C)te=(C&43690)>>1|(C&21845)<<1,te=(te&52428)>>2|(te&13107)<<2,te=(te&61680)>>4|(te&3855)<<4,ct[C]=((te&65280)>>8|(te&255)<<8)>>1;var te,C,Q=(function(t,e,n){for(var r=t.length,i=0,s=new K(e);i<r;++i)t[i]&&++s[t[i]-1];var o=new K(e);for(i=1;i<e;++i)o[i]=o[i-1]+s[i-1]<<1;var a;if(n){a=new K(1<<e);var l=15-e;for(i=0;i<r;++i)if(t[i])for(var h=i<<4|t[i],c=e-t[i],u=o[t[i]-1]++<<c,f=u|(1<<c)-1;u<=f;++u)a[ct[u]>>l]=h}else for(a=new K(r),i=0;i<r;++i)t[i]&&(a[i]=ct[o[t[i]-1]++]>>15-t[i]);return a}),oe=new N(288);for(C=0;C<144;++C)oe[C]=8;var C;for(C=144;C<256;++C)oe[C]=9;var C;for(C=256;C<280;++C)oe[C]=7;var C;for(C=280;C<288;++C)oe[C]=8;var C,Me=new N(32);for(C=0;C<32;++C)Me[C]=5;var C,br=Q(oe,9,0),kr=Q(oe,9,1),Sr=Q(Me,5,0),Er=Q(Me,5,1),st=function(t){for(var e=t[0],n=1;n<t.length;++n)t[n]>e&&(e=t[n]);return e},Z=function(t,e,n){var r=e/8|0;return(t[r]|t[r+1]<<8)>>(e&7)&n},ot=function(t,e){var n=e/8|0;return(t[n]|t[n+1]<<8|t[n+2]<<16)>>(e&7)},dt=function(t){return(t+7)/8|0},jt=function(t,e,n){return(e==null||e<0)&&(e=0),(n==null||n>t.length)&&(n=t.length),new N(t.subarray(e,n))};var Ar=["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"],re=function(t,e,n){var r=new Error(e||Ar[t]);if(r.code=t,Error.captureStackTrace&&Error.captureStackTrace(r,re),!n)throw r;return r},xr=function(t,e,n,r){var i=t.length,s=r?r.length:0;if(!i||e.f&&!e.l)return n||new N(0);var o=!n,a=o||e.i!=2,l=e.i;o&&(n=new N(i*3));var h=function(Ae){var xe=n.length;if(Ae>xe){var pe=new N(Math.max(xe*2,Ae));pe.set(n),n=pe}},c=e.f||0,u=e.p||0,f=e.b||0,g=e.l,m=e.d,p=e.m,x=e.n,w=i*8;do{if(!g){c=Z(t,u,1);var A=Z(t,u+1,3);if(u+=3,A)if(A==1)g=kr,m=Er,p=9,x=5;else if(A==2){var $=Z(t,u,31)+257,E=Z(t,u+10,15)+4,v=$+Z(t,u+5,31)+1;u+=14;for(var y=new N(v),D=new N(19),z=0;z<E;++z)D[lt[z]]=Z(t,u+z*3,7);u+=E*3;for(var O=st(D),se=(1<<O)-1,W=Q(D,O,1),z=0;z<v;){var B=W[Z(t,u,se)];u+=B&15;var b=B>>4;if(b<16)y[z++]=b;else{var U=0,R=0;for(b==16?(R=3+Z(t,u,3),u+=2,U=y[z-1]):b==17?(R=3+Z(t,u,7),u+=3):b==18&&(R=11+Z(t,u,127),u+=7);R--;)y[z++]=U}}var L=y.subarray(0,$),F=y.subarray($);p=st(L),x=st(F),g=Q(L,p,1),m=Q(F,x,1)}else re(1);else{var b=dt(u)+4,S=t[b-4]|t[b-3]<<8,M=b+S;if(M>i){l&&re(0);break}a&&h(f+S),n.set(t.subarray(b,M),f),e.b=f+=S,e.p=u=M*8,e.f=c;continue}if(u>w){l&&re(0);break}}a&&h(f+131072);for(var Ee=(1<<p)-1,G=(1<<x)-1,ee=u;;ee=u){var U=g[ot(t,u)&Ee],V=U>>4;if(u+=U&15,u>w){l&&re(0);break}if(U||re(2),V<256)n[f++]=V;else if(V==256){ee=u,g=null;break}else{var J=V-254;if(V>264){var z=V-257,I=Oe[z];J=Z(t,u,(1<<I)-1)+Kt[z],u+=I}var Y=m[ot(t,u)&G],ge=Y>>4;Y||re(3),u+=Y&15;var F=wr[ge];if(ge>3){var I=Ne[ge];F+=ot(t,u)&(1<<I)-1,u+=I}if(u>w){l&&re(0);break}a&&h(f+131072);var me=f+J;if(f<F){var Ue=s-F,Fe=Math.min(F,me);for(Ue+f<0&&re(3);f<Fe;++f)n[f]=r[Ue+f]}for(;f<me;++f)n[f]=n[f-F]}}e.l=g,e.p=ee,e.b=f,e.f=c,g&&(c=1,e.m=p,e.d=m,e.n=x)}while(!c);return f!=n.length&&o?jt(n,0,f):n.subarray(0,f)},ne=function(t,e,n){n<<=e&7;var r=e/8|0;t[r]|=n,t[r+1]|=n>>8},Pe=function(t,e,n){n<<=e&7;var r=e/8|0;t[r]|=n,t[r+1]|=n>>8,t[r+2]|=n>>16},at=function(t,e){for(var n=[],r=0;r<t.length;++r)t[r]&&n.push({s:r,f:t[r]});var i=n.length,s=n.slice();if(!i)return{t:qt,l:0};if(i==1){var o=new N(n[0].s+1);return o[n[0].s]=1,{t:o,l:1}}n.sort(function(M,$){return M.f-$.f}),n.push({s:-1,f:25001});var a=n[0],l=n[1],h=0,c=1,u=2;for(n[0]={s:-1,f:a.f+l.f,l:a,r:l};c!=i-1;)a=n[n[h].f<n[u].f?h++:u++],l=n[h!=c&&n[h].f<n[u].f?h++:u++],n[c++]={s:-1,f:a.f+l.f,l:a,r:l};for(var f=s[0].s,r=1;r<i;++r)s[r].s>f&&(f=s[r].s);var g=new K(f+1),m=ut(n[c-1],g,0);if(m>e){var r=0,p=0,x=m-e,w=1<<x;for(s.sort(function($,E){return g[E.s]-g[$.s]||$.f-E.f});r<i;++r){var A=s[r].s;if(g[A]>e)p+=w-(1<<m-g[A]),g[A]=e;else break}for(p>>=x;p>0;){var b=s[r].s;g[b]<e?p-=1<<e-g[b]++-1:++r}for(;r>=0&&p;--r){var S=s[r].s;g[S]==e&&(--g[S],++p)}m=e}return{t:new N(g),l:m}},ut=function(t,e,n){return t.s==-1?Math.max(ut(t.l,e,n+1),ut(t.r,e,n+1)):e[t.s]=n},Wt=function(t){for(var e=t.length;e&&!t[--e];);for(var n=new K(++e),r=0,i=t[0],s=1,o=function(l){n[r++]=l},a=1;a<=e;++a)if(t[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=t[a]}return{c:n.subarray(0,r),n:e}},$e=function(t,e){for(var n=0,r=0;r<e.length;++r)n+=t[r]*e[r];return n},Gt=function(t,e,n){var r=n.length,i=dt(e+2);t[i]=r&255,t[i+1]=r>>8,t[i+2]=t[i]^255,t[i+3]=t[i+1]^255;for(var s=0;s<r;++s)t[i+s+4]=n[s];return(i+4+r)*8},Vt=function(t,e,n,r,i,s,o,a,l,h,c){ne(e,c++,n),++i[256];for(var u=at(i,15),f=u.t,g=u.l,m=at(s,15),p=m.t,x=m.l,w=Wt(f),A=w.c,b=w.n,S=Wt(p),M=S.c,$=S.n,E=new K(19),v=0;v<A.length;++v)++E[A[v]&31];for(var v=0;v<M.length;++v)++E[M[v]&31];for(var y=at(E,7),D=y.t,z=y.l,O=19;O>4&&!D[lt[O-1]];--O);var se=h+5<<3,W=$e(i,oe)+$e(s,Me)+o,B=$e(i,f)+$e(s,p)+o+14+3*O+$e(E,D)+2*E[16]+3*E[17]+7*E[18];if(l>=0&&se<=W&&se<=B)return Gt(e,c,t.subarray(l,l+h));var U,R,L,F;if(ne(e,c,1+(B<W)),c+=2,B<W){U=Q(f,g,0),R=f,L=Q(p,x,0),F=p;var Ee=Q(D,z,0);ne(e,c,b-257),ne(e,c+5,$-1),ne(e,c+10,O-4),c+=14;for(var v=0;v<O;++v)ne(e,c+3*v,D[lt[v]]);c+=3*O;for(var G=[A,M],ee=0;ee<2;++ee)for(var V=G[ee],v=0;v<V.length;++v){var J=V[v]&31;ne(e,c,Ee[J]),c+=D[J],J>15&&(ne(e,c,V[v]>>5&127),c+=V[v]>>12)}}else U=br,R=oe,L=Sr,F=Me;for(var v=0;v<a;++v){var I=r[v];if(I>255){var J=I>>18&31;Pe(e,c,U[J+257]),c+=R[J+257],J>7&&(ne(e,c,I>>23&31),c+=Oe[J]);var Y=I&31;Pe(e,c,L[Y]),c+=F[Y],Y>3&&(Pe(e,c,I>>5&8191),c+=Ne[Y])}else Pe(e,c,U[I]),c+=R[I]}return Pe(e,c,U[256]),c+R[256]},Pr=new ft([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),qt=new N(0),$r=function(t,e,n,r,i,s){var o=s.z||t.length,a=new N(r+o+5*(1+Math.ceil(o/7e3))+i),l=a.subarray(r,a.length-i),h=s.l,c=(s.r||0)&7;if(e){c&&(l[0]=s.r>>3);for(var u=Pr[e-1],f=u>>13,g=u&8191,m=(1<<n)-1,p=s.p||new K(32768),x=s.h||new K(m+1),w=Math.ceil(n/3),A=2*w,b=function(it){return(t[it]^t[it+1]<<w^t[it+2]<<A)&m},S=new ft(25e3),M=new K(288),$=new K(32),E=0,v=0,y=s.i||0,D=0,z=s.w||0,O=0;y+2<o;++y){var se=b(y),W=y&32767,B=x[se];if(p[W]=B,x[se]=W,z<=y){var U=o-y;if((E>7e3||D>24576)&&(U>423||!h)){c=Vt(t,l,0,S,M,$,v,D,O,y-O,c),D=E=v=0,O=y;for(var R=0;R<286;++R)M[R]=0;for(var R=0;R<30;++R)$[R]=0}var L=2,F=0,Ee=g,G=W-B&32767;if(U>2&&se==b(y-G))for(var ee=Math.min(f,U)-1,V=Math.min(32767,y),J=Math.min(258,U);G<=V&&--Ee&&W!=B;){if(t[y+L]==t[y+L-G]){for(var I=0;I<J&&t[y+I]==t[y+I-G];++I);if(I>L){if(L=I,F=G,I>ee)break;for(var Y=Math.min(G,I-2),ge=0,R=0;R<Y;++R){var me=y-G+R&32767,Ue=p[me],Fe=me-Ue&32767;Fe>ge&&(ge=Fe,B=me)}}}W=B,B=p[W],G+=W-B&32767}if(F){S[D++]=268435456|ht[L]<<18|Lt[F];var Ae=ht[L]&31,xe=Lt[F]&31;v+=Oe[Ae]+Ne[xe],++M[257+Ae],++$[xe],z=y+L,++E}else S[D++]=t[y],++M[t[y]]}}for(y=Math.max(y,z);y<o;++y)S[D++]=t[y],++M[t[y]];c=Vt(t,l,h,S,M,$,v,D,O,y-O,c),h||(s.r=c&7|l[c/8|0]<<3,c-=7,s.h=x,s.p=p,s.i=y,s.w=z)}else{for(var y=s.w||0;y<o+h;y+=65535){var pe=y+65535;pe>=o&&(l[c/8|0]=h,pe=o),c=Gt(l,c+1,t.subarray(y,pe))}s.i=o}return jt(a,0,r+dt(c)+i)};var Mr=function(t,e,n,r,i){if(!i&&(i={l:1},e.dictionary)){var s=e.dictionary.subarray(-32768),o=new N(s.length+t.length);o.set(s),o.set(t,s.length),t=o,i.w=s.length}return $r(t,e.level==null?6:e.level,e.mem==null?i.l?Math.ceil(Math.max(8,Math.min(13,Math.log(t.length)))*1.5):20:12+e.mem,n,r,i)};function gt(t,e){return Mr(t,e||{},0,0)}function Zt(t,e){return xr(t,{i:2},e&&e.out,e&&e.dictionary)}var Cr=typeof TextDecoder<"u"&&new TextDecoder,Tr=0;try{Cr.decode(qt,{stream:!0}),Tr=1}catch{}var Yt="basalt/hkdf-aes-gcm/1",he=12,Be=128,Qt=he+Be/8+1,X=20,Le=new TextEncoder,_r=new TextDecoder,Ce={auth:"basalt/auth/1",path:"basalt/path/1",content:"basalt/content/1",nonce:"basalt/nonce/1",meta:"basalt/meta/1"};function ce(){let t=globalThis.crypto;if(!t?.subtle)throw new Error("WebCrypto is unavailable, so this vault cannot be opened");return t.subtle}function en(){let t=globalThis.crypto;if(!t?.getRandomValues)throw new Error("no secure random source is available, so a vault cannot be created here");return t.getRandomValues(new Uint8Array(X))}async function tn(t){if(t.length<16)throw new Error(`root secret is ${t.length} bytes, need at least 16`);let e=ce(),n=await e.importKey("raw",ie(t),"HKDF",!1,["deriveKey","deriveBits"]),r=h=>({name:"HKDF",hash:"SHA-256",salt:new Uint8Array(0),info:Le.encode(h)}),[i,s,o,a,l]=await Promise.all([e.deriveBits(r(Ce.auth),n,256),e.deriveKey(r(Ce.path),n,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"]),e.deriveKey(r(Ce.content),n,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"]),e.deriveKey(r(Ce.nonce),n,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),e.deriveKey(r(Ce.meta),n,{name:"HMAC",hash:"SHA-256"},!1,["sign"])]);return{auth:new Uint8Array(i),path:s,content:o,nonce:a,meta:l}}async function nn(t,e,n){let r=ce(),i=await Rr(e,n),s=await r.encrypt({name:"AES-GCM",iv:ie(i),tagLength:Be},t,ie(n)),o=new Uint8Array(he+s.byteLength);return o.set(i,0),o.set(new Uint8Array(s),he),o}async function rn(t,e){if(e.length<he+Be/8)throw new Error(`sealed value is ${e.length} bytes, too short to contain a nonce and a tag`);let n=ce(),r=e.subarray(0,he),i=e.subarray(he);try{let s=await n.decrypt({name:"AES-GCM",iv:ie(r),tagLength:Be},t,ie(i));return new Uint8Array(s)}catch(s){throw new Error("sealed value failed authentication, so it is not what was stored",{cause:s})}}async function Rr(t,e){let n=await ce().sign("HMAC",t,ie(e));return new Uint8Array(n,0,he)}async function We(t,e){return Te(await nn(t.path,t.nonce,Le.encode(e)))}async function Ve(t,e){let n=await rn(t.path,Je(e));return _r.decode(n)}var sn=0,on=1;async function Ir(t,e){let n=zr(e)?gt(e,{level:6}):void 0,r=n!==void 0&&n.length<e.length,i=r?n:e,s=new Uint8Array(1+i.length);return s[0]=r?on:sn,s.set(i,1),nn(t.content,t.nonce,s)}function zr(t){if(t.length===0)return!1;if(t.length<=Xt*2)return!0;let e=t.subarray(0,Xt);return gt(e,{level:6}).length<e.length}var Xt=4096;async function ue(t,e){return Promise.all([...e].map(async n=>{let r=await Ir(t,n);return{name:await mt(r),bytes:r}}))}async function an(t,e){let n=await rn(t.content,e);if(n.length===0)throw new Error("sealed chunk carries no marker byte");let r=n[0],i=n.subarray(1);if(r===sn)return i;if(r===on)try{return Zt(i)}catch(s){throw new Error("sealed chunk claims to be deflated and is not",{cause:s})}throw new Error(`sealed chunk has an unknown marker byte ${r}`)}async function mt(t){let e=await ce().digest("SHA-256",ie(t));return pt(new Uint8Array(e))}function ln(t){return Te(t.auth)}function ie(t){return t.byteOffset===0&&t.byteLength===t.buffer.byteLength?t.buffer:t.slice().buffer}function pt(t){let e="";for(let n of t)e+=n.toString(16).padStart(2,"0");return e}var ve="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";function Te(t){let e="";for(let n=0;n<t.length;n+=3){let r=t[n],i=n+1<t.length?t[n+1]:void 0,s=n+2<t.length?t[n+2]:void 0;if(e+=ve[r>>2],e+=ve[(r&3)<<4|(i??0)>>4],i===void 0||(e+=ve[(i&15)<<2|(s??0)>>6],s===void 0))break;e+=ve[s&63]}return e}var Dr=(()=>{let t=new Int16Array(128).fill(-1);for(let e=0;e<ve.length;e++)t[ve.charCodeAt(e)]=e;return t})();function Je(t){let e=t.length,n=new Uint8Array(Math.floor(e*3/4)),r=0,i=0,s=0;for(let o=0;o<e;o++){let a=t.charCodeAt(o),l=a<128?Dr[a]:-1;if(l<0)throw new Error(`invalid base64url character ${JSON.stringify(t[o])} at position ${o}`);i=i<<6|l,s+=6,s>=8&&(s-=8,n[r++]=i>>s&255)}return n.subarray(0,r)}function Ur(t){let e=[t.path,String(t.size),String(t.ctime),String(t.mtime),t.folder?"1":"0",t.deleted?"1":"0",t.prev??"",t.parent,String(t.chunks.length),...t.chunks];return Le.encode(e.map(n=>`${n.length}:${n}`).join(""))}async function yt(t,e){let n=await ce().sign("HMAC",t.meta,ie(Ur(e)));return pt(new Uint8Array(n))}async function hn(t,e,n){let r=await yt(t,e);if(r.length!==n.length)return!1;let i=0;for(let s=0;s<r.length;s++)i|=r.charCodeAt(s)^n.charCodeAt(s);return i===0}async function cn(t){if(t==="")return"";let e=await ce().digest("SHA-256",ie(Le.encode(t)));return pt(new Uint8Array(e))}var ae=48,fe=31,Fr=1;function un(t,e){let n=t>>>0;return Math.floor(n/e)*e===n-Fr}var fn={min:512,avg:1024,max:4096},Or=64,Nr=fn.avg,Br=64*1024;function Lr(t){let e=Math.sqrt(Or*Math.max(t,1)),n=Math.min(Br,Math.max(Nr,Math.round(e/512)*512));return{min:Math.max(fn.min,n/2),avg:n,max:n*4}}var vt={min:128*1024,avg:256*1024,max:1024*1024},Wr=4*1024*1024;function dn(t,e,n=vt.max){(!Number.isFinite(n)||n<=0)&&(n=vt.max);let r=e&&t<Wr?Lr(t):vt,i=Math.min(r.max,n-Qt),s=Math.max(i,ae*4);return{min:Math.min(r.min,s),avg:Math.min(r.avg,s),max:s}}function gn(t,e,n){let r=n-1;for(;r>e&&(t[r]&192)===128;)r--;if(r<e)return n;let i=t[r],s=i<128?1:(i&224)===192?2:(i&240)===224?3:(i&248)===240?4:1;return n-r>=s?n:r>e?r:n}function*bt(t,e,n){let{min:r,avg:i,max:s}=e,o=t.length,a=1;for(let c=0;c<ae-1;c++)a=Math.imul(a,fe);let l=0,h=0;for(let c=0;c<o;c++){let u=t[c];c>=l+ae?(h=h-Math.imul(t[c-ae],a)|0,h=Math.imul(h,fe),h=h+u|0):(h=Math.imul(h,fe),h=h+u|0);let f=c-l+1,g=f>=r&&un(h,i);if(f>=s&&(g=!0),g){let m=n?gn(t,l,c+1):c+1;yield{offset:l,bytes:t.subarray(l,m)},l=m,h=0,c=m-1}}l<o&&(yield{offset:l,bytes:t.subarray(l,o)})}var wt=class{constructor(e,n,r){this.buf=e;this.sizes=n;this.pPowW=r}buf;sizes;pPowW;used=0;hash=0;scanTo(e,n){let{min:r,avg:i,max:s}=this.sizes,o=this.buf,a=this.pPowW,l=this.used,h=this.hash;for(let c=n;c<e.length;c++){let u=e[c];if(o[l++]=u,l>=ae+1?(h=h-Math.imul(o[l-1-ae],a)|0,h=Math.imul(h,fe),h=h+u|0):(h=Math.imul(h,fe),h=h+u|0),l>=s||l>=r&&un(h,i))return this.used=l,this.hash=h,c+1}return this.used=l,this.hash=h,-1}};async function*mn(t,e,n){let{max:r}=e,i=1;for(let u=0;u<ae-1;u++)i=Math.imul(i,fe);let s=new Uint8Array(Math.max(r,ae*2)),o=0,a=0,l=0,h=()=>{let u=n?gn(s,0,o):o,f={offset:l,bytes:s.slice(0,u)};l+=u;let g=o-u;s.copyWithin(0,u,o),o=g,a=0;for(let m=0;m<g;m++)a=Math.imul(a,fe),a=a+s[m]|0;return f},c=new wt(s,e,i);for await(let u of t){let f=0;for(;;){let g=c.scanTo(u,f);if(g<0)break;o=c.used,yield h(),c.used=o,c.hash=a,f=g}o=c.used}if(o>0){let u={offset:l,bytes:s.slice(0,o)};l+=o,o=0,yield u}}var Vr=new Set(["md","txt","canvas","json","csv","yml","yaml","xml","html","css","js","ts","svg","bib","tex"]);function pn(t){let e=t.lastIndexOf(".");return e<0?!1:Vr.has(t.slice(e+1).toLowerCase())}var Jr=new Set(["canvas","json"]);function yn(t){let e=t.lastIndexOf(".");return e<0?!1:Jr.has(t.slice(e+1).toLowerCase())}var kn=gr(vn(),1),Kr=-1,Hr=0,jr=1;function wn(t){let e=[],n=0;for(let[r,i]of t)r===Hr?n+=i.length:r===Kr?(e.push({start:n,end:n+i.length}),n+=i.length):e.push({start:n,end:n});return e}function Gr(t,e){for(let n of t)for(let r of e){let i=n.start===n.end,s=r.start===r.end;if(!(i&&s)){if(i){if(r.start<n.start&&n.start<r.end)return n;continue}if(s){if(n.start<r.start&&r.start<n.end)return r;continue}if(n.start<r.end&&r.start<n.end)return n}}}function Sn(t,e,n,r=()=>!0){if(e===n)return{kind:"take",text:e,why:"both sides already agree"};if(t===e)return{kind:"take",text:n,why:"no local change since the last sync"};if(t===n)return{kind:"take",text:e,why:"no remote change since the last sync"};let i=new kn.diff_match_patch,s=i.diff_main(t,e,!0,0);s.length>2&&(i.diff_cleanupSemantic(s),i.diff_cleanupEfficiency(s));let o=i.diff_main(t,n,!0,0);o.length>2&&(i.diff_cleanupSemantic(o),i.diff_cleanupEfficiency(o));let a=Gr(wn(s),wn(o));if(a!==void 0)return{kind:"conflict",why:`both devices changed the same text, at characters ${a.start} to ${a.end} of the last synced version`};let l=bn(i,t,s,n),h=bn(i,t,o,e);if(l.failed>0||h.failed>0){let u=Math.max(l.failed,h.failed),f=Math.max(l.total,h.total);return{kind:"conflict",why:`${u} of ${f} changes could not be placed in the other version`}}if(!qr(l.text,h.text))return{kind:"conflict",why:"merging the two versions in either order gives different content, so at least one change was placed wrongly"};let c=Zr(s,l.text);return c!==void 0?{kind:"conflict",why:`the merge reported success but ${Xr(c)} is not in the result`}:r(l.text)?{kind:"merged",text:l.text}:{kind:"conflict",why:"both sides merged cleanly and the result is no longer a valid file of its kind"}}function qr(t,e){if(t===e)return!0;let n=t.split(`
7
7
  `).sort(),r=e.split(`
8
- `).sort();if(t.length!==r.length)return!1;for(let i=0;i<t.length;i++)if(t[i]!==r[i])return!1;return!0}function ln(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 Ur(n,e){for(let[t,r]of n)if(t===Rr&&!e.includes(r))return r}function Dr(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 un(n,e,t){let r=n.lastIndexOf("."),i=n.lastIndexOf("/"),s=r>i,o=s?n.slice(0,r):n,a=s?n.slice(r):"",l=(h,u=2)=>String(h).padStart(u,"0"),c=`${t.getFullYear()}${l(t.getMonth()+1)}${l(t.getDate())}${l(t.getHours())}${l(t.getMinutes())}`;return`${o} (Conflicted copy ${Or(e)} ${c})${a}`}function Or(n){return n.replace(/[-\\/:*?"<>|\s]/g,"-").replace(/-{2,}/g,"-").replace(/^[.\-\s]+|[.\-\s]+$/g,"").slice(0,32)||"device"}function ft(n){return{path:n,prev:"",folder:!1,ctime:0,mtime:0,size:0,hash:"",chunks:[],synchash:"",syncuid:0,synctime:0}}function fn(n){let{local:e,remote:t,index:r,mergeable:i}=n,s=r.synchash;return e?.folder||t?.folder?Fr(e,t):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?Nr(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 Fr(n,e){return n!==void 0&&n.folder?e===void 0?{kind:"upload",why:"new folder, the server has never held this path"}:e.deleted?{kind:"nothing",why:"folder deleted elsewhere; its files decide"}: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"}:{kind:"createLocalFolder",why:"folder exists on the server and not here"}:{kind:"nothing",why:"folder absent on both sides"}}function Nr(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?{kind:"deleteRemote",why:"deleted here and unchanged on the server"}:{kind:"restoreLocal",why:"deleted here but changed on another device, so the newer content is restored"}}function dt(n,e,t){return n.hash===""||n.chunks.length===0?!0:n.mtime!==e||n.size!==t}function Pe(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}dt(n,t,Br(e))&&(n.hash="",n.chunks=[]),n.folder=!1,n.mtime=t,n.ctime=r,n.size=e.size}function Br(n){return n.size}function dn(n,e,t){n.path=t,n.prev===""&&(n.prev=e),n.prev===t&&(n.prev=""),n.synctime=0}function ve(n,e,t,r,i){n.hash=e,n.chunks=[...t],n.synchash=e,n.syncuid=r,n.synctime=i,n.prev=""}function gn(n,e){if(!n.synctime)return!0;let t=n.size>102400?30:n.size>10240?20:10;return e-n.synctime>t*1e3}var gt=1,mn=6e4,$e=256;function vn(n){return{size:n.size,ctime:n.ctime,mtime:n.mtime,folder:n.folder??!1,deleted:n.deleted??!1,...n.prev?{prev:n.prev}:{}}}var P=class extends Error{constructor(t,r){super(r);this.code=t;this.name="ProtocolError"}code;get fatal(){return["proto","auth","cursor","busy","protostate","badchunk","internal"].includes(this.code)}};function Lr(n){return n.startsWith("wss://")?`. If that server has no TLS in front of it, pair with ws://${n.slice(6)} instead`:""}var j=class extends Error{constructor(e){super(e),this.name="ConnectionError"}},Ve=class{constructor(e,t){this.url=e;this.opts=t}url;opts;socket;replyWaiter;replyTimer;bodyWaiter;bodyQueue=[];expecting=0;requestsSent=0;closed=!1;closeReason;cursor=0;notifying=Promise.resolve();log(e,...t){this.opts.log?.(e,...t)}get appliedCursor(){return this.cursor}async connect(){if(this.socket)throw new Error("already connected");let t=(this.opts.socketFactory??Wr)(this.url);t.binaryType="arraybuffer",this.socket=t,await new Promise((r,i)=>{t.onopen=()=>r(),t.onerror=()=>i(new j(`could not connect to ${this.url}${Lr(this.url)}`)),t.onclose=s=>i(new j(`connection closed before opening: ${pn(s)}`))}),t.onerror=()=>this.die(new j("the connection failed")),t.onclose=r=>this.die(new j(`the connection closed: ${pn(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),this.disarmReply();let t=this.replyWaiter,r=this.bodyWaiter;this.replyWaiter=void 0,this.bodyWaiter=void 0,t?.reject(e),r?.reject(e);try{this.socket?.close()}catch{}try{this.opts.onClosed?.(e)}catch{}}disarmReply(){this.replyTimer!==void 0&&(clearTimeout(this.replyTimer),this.replyTimer=void 0)}close(){this.die(new j("closed by this device"))}get isClosed(){return this.closed}onFrame(e){if(typeof e=="string"){let i;try{i=JSON.parse(e)}catch{this.die(new P("protostate",`server sent a frame that is not JSON: ${e.slice(0,120)}`));return}this.onTextFrame(i);return}let t=Vr(e);if(t===void 0){this.die(new P("protostate","server sent a frame of an unexpected type"));return}let r=this.bodyWaiter;if(r){this.bodyWaiter=void 0,r.resolve(t);return}if(this.bodyQueue.length>=this.expecting){this.die(new P("protostate",`server sent a ${t.length} byte body with nothing outstanding to receive it`));return}this.bodyQueue.push(t)}onTextFrame(e){if(e.op==="batch"){this.queueNotification(()=>this.onBatchFrame(e));return}if(e.op==="caught-up"){let r=H(e.cursor);this.queueNotification(async()=>{if(r!==this.cursor){this.die(new P("protostate",`server says caught up at ${r}, this device reached ${this.cursor}`));return}this.opts.onCaughtUp?.(r)});return}let t=this.replyWaiter;if(!t){this.die(new P("protostate",`server sent an unexpected reply: ${JSON.stringify(e)}`));return}this.replyWaiter=void 0,t.resolve(e)}queueNotification(e){this.notifying=this.notifying.then(e).catch(t=>{this.die(t instanceof Error?t:new Error(String(t)))})}async onBatchFrame(e){let t=H(e.from),r=H(e.to),i=e.entries;if(!Array.isArray(i))throw new P("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 P("protostate",`batch covers ${t} to ${r} but this device has applied up to ${this.cursor}, so something was skipped`);if(r<t)throw new P("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 P("protostate",`batch ${t}..${r} contains an entry with no uid`);if(typeof o.path!="string"||o.path==="")throw new P("protostate",`batch ${t}..${r} contains uid ${o.uid} with no path`);if(!Array.isArray(o.chunks))throw new P("protostate",`batch ${t}..${r} contains uid ${o.uid} with no chunks array`);if(o.uid<t||o.uid>r)throw new P("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 j("not connected");this.socket.send(JSON.stringify(e))}sendBody(e){if(this.closed||!this.socket)throw this.closeReason??new j("not connected");this.socket.send(e)}async request(e){if(this.replyWaiter)throw new Error("a request is already in flight");this.requestsSent++;let t=this.opts.timeoutMs??mn,r=await new Promise((i,s)=>{let o=setTimeout(()=>{this.die(new j(`no reply within ${t}ms`))},t);this.replyTimer=o,this.replyWaiter={resolve:a=>{this.disarmReply(),i(a)},reject:a=>{this.disarmReply(),s(a)}};try{this.send(e)}catch(a){this.disarmReply(),this.replyWaiter=void 0,s(a instanceof Error?a:new Error(String(a)))}});if(r.res==="err"){let i=new P(String(r.code??"unknown"),String(r.msg??"no message"));throw i.fatal&&this.die(i),i}return r}async body(){let e=this.bodyQueue.shift();if(e)return e;if(this.closed)throw this.closeReason??new j("not connected");return new Promise((t,r)=>{this.bodyWaiter={resolve:t,reject:r}})}async hello(e){this.cursor=e.cursor;let t=await this.request({op:"hello",proto:gt,crypto:Bt,vault:e.vault,token:e.token,device:e.device,cursor:e.cursor,...e.claim!==void 0?{claim:e.claim}:{}});if(t.res!=="ready")throw new P("protostate",`expected ready, got ${JSON.stringify(t)}`);let r={proto:H(t.proto),cursor:H(t.cursor),perFileMax:H(t.perFileMax),chunkMax:H(t.chunkMax),maxChunks:H(t.maxChunks)};if(r.proto!==gt)throw new P("proto",`server speaks protocol ${r.proto}, this client speaks ${gt}`);return this.log("ready",r),r}async put(e,t,r,i){let s=await this.request({op:"put",path:e,meta:vn(t),chunks:[...r]});if(s.res==="have")return{uid:H(s.uid),uploaded:0,bytes:0};if(s.res!=="want")throw new P("protostate",`expected want or have, got ${JSON.stringify(s)}`);let o=mt(s.chunks),a=new Set(r),l=0;for(let h of o){if(!a.has(h))throw new P("badchunk",`server asked for ${h}, which this put does not contain`);let u=await i(h);this.sendBody(u),l+=u.length}return{uid:await this.awaitAck(),uploaded:o.length,bytes:l}}async putMany(e,t){if(e.length===0)return{results:[],uploaded:0,bytes:0};if(e.length>$e)throw new P("toolarge",`${e.length} entries in one batch, the limit is ${$e}`);let r=await this.request({op:"putmany",entries:e.map(c=>({path:c.path,meta:vn(c.meta),chunks:[...c.names]}))}),i=r,s=0,o=0;if(r.res==="want"){let c=mt(r.chunks),h=new Set;for(let u of e)for(let f of u.names)h.add(f);for(let u of c){if(!h.has(u))throw new P("badchunk",`server asked for ${u}, which this batch does not contain`);let f=await t(u);this.sendBody(f),o+=f.length}s=c.length,i=await this.awaitReply()}if(i.res!=="acks")throw new P("protostate",`expected acks, got ${JSON.stringify(i)}`);let a=i.results;if(!Array.isArray(a)||a.length!==e.length)throw new P("protostate",`${e.length} entries went up and ${Array.isArray(a)?a.length:"no"} results came back`);let l=a.map(c=>{let h=c??{};return h.code!==void 0?{uid:0,error:new P(String(h.code),String(h.msg??"no message"))}:{uid:H(h.uid)}});for(let c of l)c.error?.fatal&&this.die(c.error);return{results:l,uploaded:s,bytes:o}}async awaitAck(){let e=await this.awaitReply();if(e.res!=="ack")throw new P("protostate",`expected ack, got ${JSON.stringify(e)}`);return H(e.uid)}async awaitReply(){let e=await new Promise((t,r)=>{if(this.closed){r(this.closeReason??new j("not connected"));return}let i=this.opts.timeoutMs??mn,s=setTimeout(()=>{this.die(new j(`no acknowledgement within ${i}ms`))},i);this.replyWaiter={resolve:o=>{clearTimeout(s),t(o)},reject:o=>{clearTimeout(s),r(o)}}});if(e.res==="err"){let t=new P(String(e.code??"unknown"),String(e.msg??"no message"));throw t.fatal&&this.die(t),t}return e}async get(e){let t=await this.request({op:"get",uid:e});if(t.res!=="chunks")throw new P("protostate",`expected chunks, got ${JSON.stringify(t)}`);return{uid:H(t.uid),size:H(t.size),chunks:mt(t.chunks)}}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}:{}});if(r.res!=="history")throw new P("protostate",`expected history, got ${JSON.stringify(r)}`);return yn(r.entries,"history")}async deleted(e){let t=await this.request({op:"deleted",...e!==void 0?{limit:e}:{}});if(t.res!=="deleted")throw new P("protostate",`expected deleted, got ${JSON.stringify(t)}`);return{entries:yn(t.entries,"deleted"),more:t.more===!0}}async fetch(e){if(e.length===0)return[];this.expecting+=e.length;let t=this.request({op:"fetch",chunks:[...e]}),r=[];try{for(let i=0;i<e.length;i++){let s=await Promise.race([this.body(),t.then(a=>{throw new P("protostate",`expected a chunk body, got ${JSON.stringify(a)}`)})]),o=await ct(s);if(o!==e[i])throw new P("badchunk",`asked for ${e[i]} and received ${s.length} bytes that hash to ${o}`);r.push(s)}}catch(i){throw this.expecting=0,this.disarmReply(),this.replyWaiter=void 0,i instanceof P&&i.code==="badchunk"&&this.die(i),i}return this.expecting=Math.max(0,this.expecting-e.length),this.disarmReply(),this.replyWaiter=void 0,r}async ping(){let e=await this.request({op:"ping"});if(e.res!=="pong")throw new P("protostate",`expected pong, got ${JSON.stringify(e)}`)}},Je=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;nextAt=0;success(e){this.count=0,this.nextAt=e+this.delay()}fail(e){this.count++,this.nextAt=e+this.delay()}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))}readyAt(){return this.nextAt}isReady(e){return e>=this.nextAt}get failures(){return this.count}};function Wr(n){let e=globalThis.WebSocket;if(!e)throw new Error("no WebSocket available in this environment");return new e(n)}function Vr(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 H(n){return typeof n=="number"&&Number.isFinite(n)?n:0}function mt(n){return Array.isArray(n)?n.filter(e=>typeof e=="string"):[]}function pn(n){let e=n.code??0,t=n.reason?`, ${n.reason}`:"";return`code ${e}${t}`}function yn(n,e){if(!Array.isArray(n))throw new P("protostate",`${e} came back without a list of entries`);return n}function wn(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 Me(n){return n.length===0?"-empty-":n.join(",")}function Jr(n){return n===""||n==="-empty-"?[]:n.split(",")}function bn(){return{uploaded:0,downloaded:0,merged:0,conflicted:0,deletedLocally:0,deletedRemotely:0,restored:0,foldersCreated:0,unchanged:0,waiting:0,retrying:0,skipped:0,blocked:0,chunksSent:0,bytesSent:0}}var Ke=class{constructor(e){this.opts=e}opts;entries=new Map;remote=new Map;pending=new Set;retries=new Map;skipped=new Map;blocked=new Set;cannotStream=!1;outbox=[];outboxBytes=0;inbox=[];inboxBytes=0;limits;unsealed=new Map;cursor=0;syncing=!1;again=!1;started=!1;now(){return this.opts.now?.()??Date.now()}log(e,...t){this.opts.log?.(e,...t)}mergeable(e){return(this.opts.mergeable??rn)(e)}sizesFor(e,t){return Qt(e,t,this.limits?.chunkMax)}get coalesce(){return this.opts.coalesceWrites??!0}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,syncing:this.syncing}}async start(){if(this.started)throw new Error("already started");this.started=!0;let e=await this.opts.store.load();if(e){this.cursor=e.cursor;for(let[r,i]of Object.entries(e.entries))this.entries.set(r,{...ft(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,token:this.opts.token,device:this.opts.device,cursor:this.cursor,...this.opts.claim!==void 0?{claim:this.opts.claim}:{}});return this.limits=t,this.log("connected",t),t}async acceptBatch(e){for(let t of e.entries){let r=await this.plaintextPath(t.path);if(this.remote.set(r,{uid:t.uid,folder:t.folder,deleted:t.deleted,mtime:t.mtime,size:t.size,hash:Me(t.chunks)}),this.pending.add(r),t.prev){let i=await this.plaintextPath(t.prev);this.remote.set(i,{uid:t.uid,folder:!1,deleted:!0,mtime:t.mtime,size:0,hash:""}),this.pending.add(i)}}this.cursor=e.to}async plaintextPath(e){let t=this.unsealed.get(e);if(t!==void 0)return t;let r=await Le(this.opts.keys,e);return this.unsealed.set(e,r),r}async sync(e={}){if(this.syncing)return this.again=!0,bn();this.syncing=!0;try{let t=await this.pass(e);for(;this.again;){this.again=!1;let r=await this.pass(e);t=Kr(t,r)}return t}finally{this.syncing=!1}}async pass(e={}){let t=bn(),r=this.now(),i=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.outboxBytes=0,this.inbox=[],this.inboxBytes=0);let s=await this.opts.vault.list(),o=new Map(s.map(h=>[h.path,h]));for(let h of s){let u=this.entryFor(h.path);Pe(u,h)}let a=new Set;for(let[h,u]of o)u.folder||a.add(h);let l=new Set,c=new Set([...o.keys(),...this.entries.keys(),...this.remote.keys()]);for(let h of[...c].sort()){let u=this.skipped.get(h);if(u){if(vt(this.entries.get(h))===u.fingerprint){t.skipped++;continue}this.skipped.delete(h),this.log("skipped file changed, trying again",h)}let f=wn(h).find(m=>a.has(m));if(f!==void 0&&!o.has(h)){l.add(h),this.blocked.has(h)||this.log("cannot be both",h,`${f} is a file here and a folder elsewhere`),t.blocked++;continue}let g=this.retries.get(h);if(g&&g.at>r){t.retrying++;continue}try{this.opts.onProgress?.(h),await this.reconcile(h,o.get(h),t,r,i),this.retries.delete(h)}catch(m){this.recordFailure(h,m,t)}}return await this.fill(t),await this.flush(t),this.opts.onProgress?.(void 0),this.blocked=l,this.prune(o),await this.save(),t}entryFor(e){let t=this.entries.get(e);return t||(t=ft(e),this.entries.set(e,t)),t}async reconcile(e,t,r,i,s){let o=this.entryFor(e),a=this.remote.get(e),l=this.limits?.perFileMax??0;if(t&&!t.folder&&l>0&&t.size>l){this.recordFailure(e,qr(t.size,l),r);return}let c,h;t&&(!t.folder&&dt(o,Math.ceil(t.mtime),t.size)&&(h=await this.rehash(o,e,t.size)),c={folder:t.folder,mtime:o.mtime,size:o.size,hash:o.hash});let u=fn({local:c,remote:a,index:o,mergeable:this.mergeable(e)});if(s&&u.kind!=="nothing"&&c&&!t?.folder&&!gn(o,i)){r.waiting++;return}await this.act(e,u,o,c,a,r,h),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=[...tn(s,this.sizesFor(s.length,o),o)],l=a.map(c=>c.bytes);if(s.length<=kn){let c=await ge(this.opts.keys,l);return e.chunks=c.map(h=>h.name),e.hash=Me(e.chunks),e.size=s.length,{bytes:s,pieces:a,names:e.chunks,sealed:c}}return e.chunks=await this.namesOf(l),e.hash=Me(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<=kn))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=[],l=0;for await(let c of nn(i.readBlocks(t),this.sizesFor(r,s),s)){let h=await ge(this.opts.keys,[c.bytes]);o.push(h[0].name),a.push({start:c.offset,end:c.offset+c.bytes.length}),l+=c.bytes.length}return e.chunks=o,e.hash=Me(o),e.size=l,{names:o,spans:a,path:t,size:l}}namesOf(e){return jr(this.opts.keys,e)}async act(e,t,r,i,s,o,a){switch(t.kind){case"nothing":o.unchanged++,i&&s&&!s.deleted&&i.hash===s.hash&&ve(r,i.hash,r.chunks,s.uid,this.now());return;case"upload":await this.upload(e,r,o,!0,a);return;case"download":case"restoreLocal":{if(!s)return;await this.receive(e,r,s,t.kind,t.why,o);return}case"createLocalFolder":await this.opts.vault.mkdir(e),r.folder=!0,s&&ve(r,"",[],s.uid,this.now()),o.foldersCreated++;return;case"clash":this.skipped.set(e,{why:`${t.why}. Rename one of them, and it will sync.`,fingerprint:vt(r)}),o.skipped++,this.log("cannot be both",e,t.why);return;case"deleteLocal":await this.opts.vault.remove(e),this.entries.delete(e),o.deletedLocally++,this.log("deleted locally",e,t.why);return;case"deleteRemote":await this.queue({path:e,size:0,entry:{path:await this.sealedPath(e),meta:{size:0,ctime:0,mtime:this.now(),deleted:!0},names:[]},bodyOf:En,commit:l=>{this.remote.set(e,{uid:l,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)}},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=!1,s){if(t.folder){await this.queue({path:e,size:0,entry:{path:await this.sealedPath(e),meta:{size:0,ctime:0,mtime:0,folder:!0},names:[]},bodyOf:En,commit:u=>{ve(t,"",[],u,this.now()),this.remote.set(e,{uid:u,folder:!0,deleted:!1,mtime:0,size:0,hash:""}),i&&r.uploaded++}},r);return}let o=await this.planUpload(t,e,s),a=t.hash,l=[...t.chunks],c=t.size,h=t.mtime;await this.queue({path:e,size:c,entry:{path:await this.sealedPath(e),meta:{size:c,ctime:t.ctime,mtime:h,...t.prev?{prev:await this.sealedPath(t.prev)}:{}},names:o.names},bodyOf:o.bodyOf,commit:u=>{ve(t,a,l,u,this.now()),this.remote.set(e,{uid:u,folder:!1,deleted:!1,mtime:h,size:c,hash:a}),i&&r.uploaded++,this.log("uploaded",e)}},r)}async queue(e,t){this.outbox.push(e),this.outboxBytes+=e.size,(this.outbox.length>=$e||this.outboxBytes>=Sn)&&await this.flush(t)}async flush(e){if(this.outbox.length===0)return;let t=this.outbox;this.outbox=[],this.outboxBytes=0;let r=new Map;for(let s of t)for(let o of s.entry.names)r.has(o)||r.set(o,s.bodyOf);let i;try{i=await this.opts.transport.putMany(t.map(s=>s.entry),async s=>{let o=r.get(s);if(!o)throw new Error(`server asked for ${s}, which no queued file contains`);return o(s)})}catch(s){for(let o of t)this.recordFailure(o.path,s,e);return}e.chunksSent+=i.uploaded,e.bytesSent+=i.bytes;for(let s=0;s<t.length;s++){let o=t[s],a=i.results[s];if(a.error){this.recordFailure(o.path,a.error,e);continue}o.commit(a.uid)}}async planUpload(e,t,r){let i=r??await this.scan(e,t);if(i.sealed){let c=new Map(i.sealed.map(h=>[h.name,h.bytes]));return{names:i.names,bodyOf:async h=>{let u=c.get(h);if(!u)throw new Error(`no sealed body for ${h} of ${t}`);return u}}}let s=this.opts.keys,o=this.opts.vault;if(i.spans){let c=new Map(i.names.map((h,u)=>[h,i.spans[u]]));return{names:i.names,bodyOf:async h=>{let u=c.get(h);if(!u)throw new Error(`no chunk named ${h} in ${t}`);let f=await o.readRange(i.path,u.start,u.end),g=await ge(s,[f]);if(g[0].name!==h)throw new Error(`${t} changed while it was being sent, so it was not sent`);return g[0].bytes}}}let a=new Map;for(let c=0;c<i.names.length;c++){let h=i.pieces[c];a.set(i.names[c],{start:h.offset,end:h.offset+h.bytes.length})}let l=i.bytes;return{names:i.names,bodyOf:async c=>{let h=a.get(c);if(!h)throw new Error(`no chunk named ${c} in ${t}`);return(await ge(s,[l.subarray(h.start,h.end)]))[0].bytes}}}scan(e,t){return this.rehash(e,t)}async receive(e,t,r,i,s,o){let a=Jr(r.hash);this.checkChunkCount(r.uid,a.length),this.inbox.push({path:e,entry:t,remote:r,chunks:a,kind:i,why:s}),this.inboxBytes+=r.size,(this.inbox.length>=$e||this.inboxBytes>=Sn)&&await this.fill(o)}async fill(e){if(this.inbox.length===0)return;let t=this.inbox;this.inbox=[],this.inboxBytes=0;let r=[],i=new Set;for(let o of t)for(let a of o.chunks)i.has(a)||(i.add(a),r.push(a));let s=new Map;if(r.length>0)try{let o=await this.opts.transport.fetch(r);for(let a=0;a<r.length;a++)s.set(r[a],o[a])}catch(o){for(let a of t)this.recordFailure(a.path,o,e);return}for(let o of t)try{await this.land(o,s),o.kind==="download"?e.downloaded++:e.restored++,this.log(o.kind,o.path,o.why)}catch(a){this.recordFailure(o.path,a,e)}}async land(e,t){let r=e.chunks.map(s=>{let o=t.get(s);if(!o)throw new Error(`the server did not send ${s}, which ${e.path} is made of`);return o}),i=await this.assemble(e.remote.uid,r);await this.opts.vault.write(e.path,i,{mtime:e.remote.mtime,ctime:e.remote.mtime}),Pe(e.entry,{folder:!1,mtime:e.remote.mtime,ctime:e.remote.mtime,size:i.length}),e.entry.chunks=[...e.chunks],e.entry.hash=Me(e.chunks),e.entry.size=i.length,ve(e.entry,e.entry.hash,e.entry.chunks,e.remote.uid,this.now())}async contentOf(e,t){let r=t!==void 0?{chunks:t}:await this.opts.transport.get(e);return r.chunks.length===0?new Uint8Array(0):(this.checkChunkCount(e,r.chunks.length),this.assemble(e,await this.opts.transport.fetch(r.chunks)))}checkChunkCount(e,t){let r=this.limits?.maxChunks??0;if(r>0&&t>r)throw new Error(`version ${e} names ${t} chunks, and this server said it stores at most ${r}`)}async assemble(e,t){if(t.length===0)return new Uint8Array(0);let r=[],i=0,s=this.limits?.perFileMax??0;for(let l of t){let c=await qt(this.opts.keys,l);if(i+=c.length,s>0&&i>s)throw new Error(`version ${e} is over ${i} bytes, and this server said it stores at most ${s}`);r.push(c)}let o=new Uint8Array(i),a=0;for(let l of r)o.set(l,a),a+=l.length;return o}async merge(e,t,r,i){if(!r)return;let s=new TextDecoder("utf-8",{fatal:!0}),o,a,l;try{o=s.decode(await this.contentOf(t.syncuid)),a=s.decode(await this.opts.vault.read(e)),l=s.decode(await this.contentOf(r.uid))}catch{let u="one side is not valid UTF-8, so merging it would rewrite bytes nobody edited";this.log("merge refused",e,u),await this.conflict(e,t,r,i,u);return}let c=cn(o,a,l,sn(e)?Zr:void 0);if(c.kind==="conflict"){this.log("merge refused",e,c.why),await this.conflict(e,t,r,i,c.why);return}let h=c.text;h!==a&&await this.opts.vault.write(e,new TextEncoder().encode(h),{mtime:this.now(),ctime:t.ctime}),Pe(t,{folder:!1,mtime:this.now(),ctime:t.ctime,size:h.length}),await this.upload(e,t,i),i.merged++,this.log("merged",e,c.kind==="merged"?"three-way":c.why)}freeConflictPath(e){return Gr(un(e,this.opts.device,new Date(this.now())),t=>this.opts.vault.exists(t))}async conflict(e,t,r,i,s){if(!r)return;let o=await this.freeConflictPath(e),a=await this.contentOf(r.uid);await this.opts.vault.write(o,a,{mtime:r.mtime,ctime:r.mtime});let l=this.entryFor(o);Pe(l,{folder:!1,mtime:r.mtime,ctime:r.mtime,size:a.length}),await this.upload(o,l,i),await this.upload(e,t,i),i.conflicted++,this.log("kept both",e,{copy:o,why:s})}async sealedPath(e){let t=await Be(this.opts.keys,e);return this.unsealed.set(t,e),t}recordFailure(e,t,r){let i=t instanceof Error?t.message:String(t),s=t?.code;if(s!==void 0&&["badentry","badname","toolarge"].includes(s)){this.skipped.set(e,{why:i,fingerprint:vt(this.entries.get(e))}),r.skipped++,this.log("skipped for good",e,i);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),r.retrying++,this.log("will retry",e,{attempt:a.count,error:i})}prune(e){for(let[t,r]of this.entries){if(e.has(t))continue;let i=this.remote.get(t);i&&!i.deleted||r.synchash===""&&r.hash===""&&this.entries.delete(t)}for(let[t,r]of this.remote)r.deleted&&(e.has(t)||this.entries.has(t)||this.pending.has(t)||this.remote.delete(t))}async save(){let e={};for(let[r,i]of this.entries)e[r]=i;let t={};for(let[r,i]of this.remote)t[r]=i;await this.opts.store.save({cursor:this.cursor,entries:e,remote:t,pending:[...this.pending]})}noteRename(e,t){let r=this.entries.get(e);r&&(this.entries.delete(e),dn(r,e,t),this.entries.set(t,r))}};function Kr(n,e){let t={...n};for(let r of Object.keys(t))t[r]=n[r]+e[r];return t}function vt(n){return n?`${n.mtime}:${n.size}`:"gone"}var kn=8*1024*1024,Hr=16;async function jr(n,e,t=Hr){let r=[];for(let i=0;i<e.length;i+=t){let s=await ge(n,e.slice(i,i+t));for(let o of s)r.push(o.name)}return r}var Sn=8*1024*1024;async function Gr(n,e){if(!await e(n))return n;let t=n.lastIndexOf("."),r=n.lastIndexOf("/"),i=t>r,s=i?n.slice(0,t):n,o=i?n.slice(t):"";for(let a=2;a<1e3;a++){let l=`${s} ${a}${o}`;if(!await e(l))return l}throw new Error(`cannot find an unused name beside ${n}`)}function qr(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}async function En(n){throw new Error(`this put has no bodies, and the server asked for ${n}`)}function Zr(n){try{return JSON.parse(n),!0}catch{return!1}}var Xr=150,_e=class{constructor(e){this.opts=e;let t;this.transport=new Ve(e.url,{onBatch:async r=>{await t.acceptBatch(r),r.entries.length>0&&this.soon()},onCaughtUp:()=>{this.caughtUp=!0},onClosed:r=>{this.endedWith=r,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 Ke({vault:e.vault,store:e.store,keys:e.keys,transport:this.transport,device:e.device,vaultId:e.vaultId,token:e.token,...e.claim!==void 0?{claim:e.claim}:{},...e.coalesceWrites!==void 0?{coalesceWrites:e.coalesceWrites}:{},...e.log!==void 0?{log:e.log}:{},...e.onProgress!==void 0?{onProgress:e.onProgress}:{}}),this.engine=t}opts;engine;transport;limits;soonTimer;caughtUp=!1;endedWith;notifyEnded;queue=Promise.resolve();serial(e){let t=this.queue.then(e,e);return this.queue=t.catch(()=>{}),t}get requestsSent(){return this.transport.requestsSent}get serverCursor(){return this.limits?.cursor??0}async connect(){await this.transport.connect(),this.limits=await this.engine.start();let e=this.opts.timeoutMs??3e4,t=Date.now()+e;for(;!this.caughtUp&&Date.now()<t;){if(this.endedWith)throw this.endedWith;await pt(25)}if(!this.caughtUp)throw new Error("the server never finished sending what it already had");return this.limits}async settle(e={},t=8){let r=await this.pass(e),i=r;for(let s=0;s<t&&ti(r);s++)await pt(60),r=await this.pass(e),i=ei(i,r);return i}pass(e){return this.serial(()=>this.engine.sync(e))}async runUntilClosed(e=3e4){if(this.endedWith)return this.endedWith;let t=this.opts.vault.watch?.(()=>{this.sync()}),r=setInterval(()=>{this.sync().then(()=>this.keepalive())},e);try{return await new Promise(i=>{this.notifyEnded=i})}finally{clearInterval(r),t?.()}}async keepalive(){try{await this.transport.ping()}catch{}}soon(){this.soonTimer===void 0&&(this.soonTimer=setTimeout(()=>{this.soonTimer=void 0,this.sync()},Xr))}async sync(e={}){try{return await this.pass(e)}catch(t){this.opts.log?.("sync failed",t.message);return}}async history(e,t={}){let r=await Be(this.opts.keys,e);return(await this.serial(()=>this.transport.history(r,t))).map(s=>this.asVersion(s,e))}async deleted(e){let t=await this.serial(()=>this.transport.deleted(e)),r=[];for(let i of t.entries)r.push({...this.asVersion(i,await Le(this.opts.keys,i.path)),restorable:i.restorable??0});return{notes:r,more:t.more}}async contentAt(e){return e.deleted||e.folder?new Uint8Array(0):this.serial(()=>this.engine.contentOf(e.uid))}async restore(e,t){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 o=t??e.path;return await this.opts.vault.mkdir(o),{path:o,bytes:0}}let r=await this.serial(()=>this.engine.contentOf(e.uid)),i=t??e.path,s=await this.opts.vault.exists(i)?Yr(i,e):i;return await this.opts.vault.write(s,r,{mtime:e.mtime,ctime:e.ctime}),{path:s,bytes:r.length}}async newestContentVersion(e){return(await this.history(e,{limit:50})).find(r=>!r.deleted)}asVersion(e,t){return{uid:e.uid,path:t,size:e.size,ctime:e.ctime,mtime:e.mtime,folder:e.folder,deleted:e.deleted,device:e.device,chunks:e.chunks?.length??0}}close(){this.soonTimer!==void 0&&(clearTimeout(this.soonTimer),this.soonTimer=void 0),this.transport.close()}};function Yr(n,e){let t=n.lastIndexOf("/"),r=t===-1?"":n.slice(0,t+1),i=t===-1?n:n.slice(t+1),s=i.lastIndexOf("."),o=s<=0?i:i.slice(0,s),a=s<=0?"":i.slice(s);return`${r}${o} (restored ${e.uid})${a}`}async function An(n,e={}){let t=new Je(0,3e5,5e3,!0);for(;e.keepGoing?.()??!0;){let r,i,s=!1;try{r=new _e(n),await r.connect(),s=!0,t.success(Date.now()),e.onClient?.(r),e.onSynced?.(await r.settle(),r.serverCursor),i=await r.runUntilClosed()}catch(l){i=l}finally{e.onClient?.(void 0),r?.close()}if(i&&Qr(i)){e.onFatal?.(i);return}if(!(e.keepGoing?.()??!0))return;t.fail(Date.now());let o=t.delay(),a=i??new Error("the connection ended");s?e.onDisconnected?.(a,o):e.onUnreachable?.(a,o),await pt(o)}}function Qr(n){return n instanceof P&&n.fatal}function ei(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,chunksSent:n.chunksSent+e.chunksSent,bytesSent:n.bytesSent+e.bytesSent,unchanged:e.unchanged,waiting:e.waiting,retrying:e.retrying,skipped:e.skipped,blocked:e.blocked}}function ti(n){return n.uploaded+n.downloaded+n.merged+n.conflicted+n.deletedLocally+n.deletedRemotely+n.restored+n.foldersCreated+n.waiting>0}var pt=n=>new Promise(e=>setTimeout(e,n));var He="basalt2_",yt=2,Ce=4,xn=new TextEncoder,ni=new TextDecoder;function wt(n){if(n.secret.length!==Z)throw new Error(`a root secret is ${Z} bytes, not ${n.secret.length}`);let e=[xn.encode(n.url),xn.encode(n.vaultId)];for(let o of e)if(o.length>255)throw new Error("a pairing field is too long to encode");let t=1+Z+e.reduce((o,a)=>o+1+a.length,0),r=new Uint8Array(t);r[0]=yt,r.set(n.secret,1);let i=1+Z;for(let o of e)r[i++]=o.length,r.set(o,i),i+=o.length;let s=new Uint8Array(t+Ce);return s.set(r,0),s.set($n(r),t),He+xe(s)}function Pn(n){let e=n.trim();if(e.startsWith("basalt1_"))throw new Error("this is a version 1 pairing string, from before the server token was folded into the root secret. Run basalt invite on a device that is already paired to get a current one.");if(!e.startsWith(He))throw new Error(`not a pairing string: it should start with ${He}`);let t;try{t=We(e.slice(He.length))}catch{throw new Error("this pairing string is damaged: it is not valid base64url")}if(t.length<1+Z+2+Ce)throw new Error("this pairing string is too short to be complete");let r=t.subarray(0,t.length-Ce),i=t.subarray(t.length-Ce),s=$n(r);for(let u=0;u<Ce;u++)if(i[u]!==s[u])throw new Error("this pairing string is damaged: it did not survive being copied");if(r[0]!==yt)throw new Error(`this pairing string is version ${r[0]}, and this device understands ${yt}`);let o=r.slice(1,1+Z),a=1+Z,l=u=>{if(a>=r.length)throw new Error(`this pairing string ends before its ${u}`);let f=r[a++];if(a+f>r.length)throw new Error(`this pairing string ends inside its ${u}`);let g=ni.decode(r.subarray(a,a+f));return a+=f,g},c=l("server address"),h=l("vault name");if(a!==r.length)throw new Error("this pairing string has more in it than it should");if(c===""||h==="")throw new Error("this pairing string has an empty field");return{url:c,secret:o,vaultId:h}}function $n(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=(e^4294967295)>>>0,new Uint8Array([e>>>24&255,e>>>16&255,e>>>8&255,e&255])}function Mn(n){return{url:n.url,vaultId:n.vaultId,device:n.device,secret:xe(n.secret),...n.bootstrap?{bootstrap:n.bootstrap}:{}}}function _n(n,e){if(typeof n!="object"||n===null)throw new Error(`${e} does not hold a configuration`);let t=n,r=o=>{let a=t[o];if(typeof a!="string"||a==="")throw new Error(`${e} has no ${o}`);return a},i=We(r("secret"));if(i.length!==Z)throw new Error(`${e} holds a ${i.length} byte secret, and a root secret is ${Z}`);let s=t.bootstrap;return{url:r("url"),vaultId:r("vaultId"),device:r("device"),secret:i,...typeof s=="string"&&s!==""?{bootstrap:s}:{}}}function Cn(n){let e=n.trim().replace(/\/+$/,"");if(e==="")throw new Error("that is not a server address");if(e.startsWith("ws://")||e.startsWith("wss://"))return e;if(e.startsWith("http://"))return"ws://"+e.slice(7);if(e.startsWith("https://"))return"wss://"+e.slice(8);if(e.includes("://"))throw new Error(`a server address is ws:// or wss://, not ${e.split("://")[0]}://`);return"wss://"+e}import{constants as bt,watch as ri}from"node:fs";import{access as kt,cp as ii,mkdir as je,open as Ge,readFile as Un,readdir as si,rename as Dn,rm as oi,stat as ai,utimes as li}from"node:fs/promises";import{basename as St,dirname as qe,join as Tn,relative as hi,resolve as Rn,sep as In}from"node:path";var On=".trash",ci=new Set([".obsidian",".basalt",On,".git",".DS_Store","node_modules"]),Ze=class{root;ignore;constructor(e,t={}){this.root=Rn(e),this.ignore=new Set([...ci,...t.alsoIgnore??[]])}absolute(e){let t=Rn(this.root,e),r=hi(this.root,t);if(r===""||r.startsWith("..")||r.startsWith(`..${In}`))throw new Error(`refusing a path outside the vault: ${e}`);return t}async list(){let e=[],t=async(r,i)=>{let s;try{s=await si(r,{withFileTypes:!0})}catch(o){throw new Error(`cannot read ${r}: ${o.message}`)}for(let o of s){if(this.ignore.has(o.name)||zn(o.name))continue;let a=i?`${i}/${o.name}`:o.name,l=Tn(r,o.name);if(o.isDirectory())e.push({path:a,folder:!0,mtime:0,ctime:0,size:0}),await t(l,a);else if(o.isFile()){let c=await ai(l);e.push({path:a,folder:!1,mtime:c.mtimeMs,ctime:c.birthtimeMs||c.ctimeMs,size:c.size})}}};return await t(this.root,""),e}async read(e){return new Uint8Array(await Un(this.absolute(e)))}async*readBlocks(e,t=1024*1024){let r=await Ge(this.absolute(e),"r");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 Ge(this.absolute(e),"r");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){let i=this.absolute(e);if(await je(qe(i),{recursive:!0}),await Nn(i,t),r.mtime>0){let s=r.mtime/1e3;await li(i,s,s)}}async remove(e){let t=this.absolute(e);try{await kt(t,bt.F_OK)}catch{return}let r=await this.freeTrashPath(e);await je(qe(r),{recursive:!0});try{await Dn(t,r);return}catch(i){if(i.code!=="EXDEV")throw i}await ii(t,r,{recursive:!0}),await oi(t,{recursive:!0,force:!0})}async freeTrashPath(e){let t=Tn(this.root,On,e),r=St(e).lastIndexOf("."),[i,s]=r<=0?[t,""]:[t.slice(0,t.length-(St(e).length-r)),t.slice(t.length-(St(e).length-r))];for(let o=0;o<1e3;o++){let a=o===0?t:`${i} (${o})${s}`;try{await kt(a,bt.F_OK)}catch{return a}}throw new Error(`the trash already holds a thousand copies of ${e}`)}async mkdir(e){await je(this.absolute(e),{recursive:!0})}async exists(e){try{return await kt(this.absolute(e),bt.F_OK),!0}catch{return!1}}watch(e){let t,r="",i;try{i=ri(this.root,{recursive:!0,persistent:!0},(s,o)=>{if(!o)return;let a=o.toString().split(In).join("/");a.split("/").some(l=>this.ignore.has(l))||zn(a)||(r=a,t&&clearTimeout(t),t=setTimeout(()=>{t=void 0,e(r)},150))}),i.on("error",()=>{})}catch{return()=>{}}return()=>{t&&clearTimeout(t),i?.close()}}},Te=class{constructor(e){this.file=e}file;async load(){let e;try{e=await Un(this.file,"utf8")}catch(t){if(t.code==="ENOENT")return;throw new Error(`cannot read the index at ${this.file}: ${t.message}`)}try{return JSON.parse(e)}catch(t){throw new Error(`the index at ${this.file} is not valid JSON, so it cannot be trusted: ${t.message}`)}}async save(e){await je(qe(this.file),{recursive:!0}),await Nn(this.file,new TextEncoder().encode(JSON.stringify(e)))}},Fn=".basalt-tmp-";function zn(n){return n.includes(Fn)}var ui=0;async function fi(n){for(let e=0;e<64;e++){let t=`${n}${Fn}${(ui++).toString(36)}${e?`-${e}`:""}`;try{return{tmp:t,handle:await Ge(t,"wx")}}catch(r){if(r.code!=="EEXIST")throw r}}throw new Error(`could not find an unused temporary name beside ${n}`)}async function Nn(n,e){let{tmp:t,handle:r}=await fi(n);try{await r.write(e),await r.sync()}finally{await r.close()}await Dn(t,n);let i=await Ge(qe(n),"r");try{await i.sync()}finally{await i.close()}}import{chmod as di,mkdir as gi,readFile as mi,rename as vi,rm as Bn,writeFile as pi}from"node:fs/promises";import{join as Et}from"node:path";var At=".basalt",xt=n=>Et(n,At,"config.json"),Xe=n=>Et(n,At,"index.json");async function Re(n){let e=xt(n),t;try{t=await mi(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 _n(r,e)}async function Ye(n,e){let t=Et(n,At);await gi(t,{recursive:!0});let r=xt(n),i=`${r}.tmp`;await pi(i,JSON.stringify(Mn(e),null,2)+`
9
- `,{mode:384}),await di(i,384),await vi(i,r)}async function Ln(n){await Bn(xt(n),{force:!0}),await Bn(Xe(n),{force:!0})}var Wn=`basalt: self-hosted sync for Obsidian
8
+ `).sort();if(n.length!==r.length)return!1;for(let i=0;i<n.length;i++)if(n[i]!==r[i])return!1;return!0}function bn(t,e,n,r){let[i,s]=t.patch_apply(t.patch_make(e,n),r);return{text:i,failed:s.filter(o=>!o).length,total:s.length}}function Zr(t,e){for(let[n,r]of t)if(n===jr&&!e.includes(r))return r}function Xr(t){let e=t.replace(/\s+/g," ").trim(),n=e.length>60?`${e.slice(0,57)}...`:e;return`a local edit (${JSON.stringify(n)})`}function En(t,e,n){let r=t.lastIndexOf("."),i=t.lastIndexOf("/"),s=r>i,o=s?t.slice(0,r):t,a=s?t.slice(r):"",l=(c,u=2)=>String(c).padStart(u,"0"),h=`${n.getFullYear()}${l(n.getMonth()+1)}${l(n.getDate())}${l(n.getHours())}${l(n.getMinutes())}`;return`${o} (Conflicted copy ${Yr(e)} ${h})${a}`}function Yr(t){return t.replace(/[-\\/:*?"<>|\s]/g,"-").replace(/-{2,}/g,"-").replace(/^[.\-\s]+|[.\-\s]+$/g,"").slice(0,32)||"device"}function kt(t){return{path:t,prev:"",folder:!1,ctime:0,mtime:0,size:0,hash:"",chunks:[],synchash:"",syncuid:0,synctime:0}}function An(t){let{local:e,remote:n,index:r,mergeable:i}=t,s=r.synchash;return e?.folder||n?.folder?Qr(e,n):e===void 0&&(n===void 0||n.deleted)?{kind:"nothing",why:"absent on both sides"}:n===void 0?{kind:"upload",why:"new file, the server has never held this path"}:e===void 0?ei(n,r):n.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===n.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"}:n.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 Qr(t,e){return t!==void 0&&t.folder?e===void 0?{kind:"upload",why:"new folder, the server has never held this path"}:e.deleted?{kind:"nothing",why:"folder deleted elsewhere; its files decide"}: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?t!==void 0?{kind:"clash",why:"a file here and a folder of the same name on another device"}:{kind:"createLocalFolder",why:"folder exists on the server and not here"}:{kind:"nothing",why:"folder absent on both sides"}}function ei(t,e){let n=e.synchash;return t.deleted?{kind:"nothing",why:"deleted on both sides"}:n===""?{kind:"download",why:"new on the server"}:t.hash===n?{kind:"deleteRemote",why:"deleted here and unchanged on the server"}:{kind:"restoreLocal",why:"deleted here but changed on another device, so the newer content is restored"}}function St(t,e,n){return t.hash===""||t.chunks.length===0?!0:t.mtime!==e||t.size!==n}function be(t,e){let n=Math.ceil(e.mtime),r=Math.ceil(e.ctime);if(e.folder){t.folder=!0,t.mtime=0,t.ctime=0,t.size=0,t.hash="",t.chunks=[];return}St(t,n,ti(e))&&(t.hash="",t.chunks=[]),t.folder=!1,t.mtime=n,t.ctime=r,t.size=e.size}function ti(t){return t.size}function xn(t,e,n){t.path=n,t.prev===""&&(t.prev=e),t.prev===n&&(t.prev=""),t.synctime=0}function de(t,e,n,r,i){t.hash=e,t.chunks=[...n],t.synchash=e,t.syncuid=r,t.synctime=i,t.prev=""}function Pn(t,e){if(!t.synctime)return!0;let n=t.size>102400?30:t.size>10240?20:10;return e-t.synctime>n*1e3}var Et=2,$n=6e4,_e=256;function Mn(t){return{size:t.size,ctime:t.ctime,mtime:t.mtime,folder:t.folder??!1,deleted:t.deleted??!1,...t.prev?{prev:t.prev}:{}}}var P=class extends Error{constructor(n,r){super(r);this.code=n;this.name="ProtocolError"}code;get fatal(){return["proto","auth","cursor","busy","protostate","badchunk","internal"].includes(this.code)}};function ni(t){return t.startsWith("wss://")?`. If that server has no TLS in front of it, pair with ws://${t.slice(6)} instead`:""}var j=class extends Error{constructor(e){super(e),this.name="ConnectionError"}},Ke=class{constructor(e,n){this.url=e;this.opts=n}url;opts;socket;replyWaiter;replyTimer;bodyWaiter;bodyQueue=[];expecting=0;requestsSent=0;closed=!1;closeReason;cursor=0;notifying=Promise.resolve();log(e,...n){this.opts.log?.(e,...n)}get appliedCursor(){return this.cursor}async connect(){if(this.socket)throw new Error("already connected");let n=(this.opts.socketFactory??ri)(this.url);n.binaryType="arraybuffer",this.socket=n,await new Promise((r,i)=>{n.onopen=()=>r(),n.onerror=()=>i(new j(`could not connect to ${this.url}${ni(this.url)}`)),n.onclose=s=>i(new j(`connection closed before opening: ${Cn(s)}`))}),n.onerror=()=>this.die(new j("the connection failed")),n.onclose=r=>this.die(new j(`the connection closed: ${Cn(r)}`)),n.onmessage=r=>this.onFrame(r.data)}die(e){if(this.closed)return;this.closed=!0,this.closeReason=e,this.log("transport closed",e.message),this.disarmReply();let n=this.replyWaiter,r=this.bodyWaiter;this.replyWaiter=void 0,this.bodyWaiter=void 0,n?.reject(e),r?.reject(e);try{this.socket?.close()}catch{}try{this.opts.onClosed?.(e)}catch{}}disarmReply(){this.replyTimer!==void 0&&(clearTimeout(this.replyTimer),this.replyTimer=void 0)}close(){this.die(new j("closed by this device"))}get isClosed(){return this.closed}onFrame(e){if(typeof e=="string"){let i;try{i=JSON.parse(e)}catch{this.die(new P("protostate",`server sent a frame that is not JSON: ${e.slice(0,120)}`));return}this.onTextFrame(i);return}let n=ii(e);if(n===void 0){this.die(new P("protostate","server sent a frame of an unexpected type"));return}let r=this.bodyWaiter;if(r){this.bodyWaiter=void 0,r.resolve(n);return}if(this.bodyQueue.length>=this.expecting){this.die(new P("protostate",`server sent a ${n.length} byte body with nothing outstanding to receive it`));return}this.bodyQueue.push(n)}onTextFrame(e){if(e.op==="batch"){this.queueNotification(()=>this.onBatchFrame(e));return}if(e.op==="caught-up"){let r=H(e.cursor);this.queueNotification(async()=>{if(r!==this.cursor){this.die(new P("protostate",`server says caught up at ${r}, this device reached ${this.cursor}`));return}this.opts.onCaughtUp?.(r)});return}let n=this.replyWaiter;if(!n){this.die(new P("protostate",`server sent an unexpected reply: ${JSON.stringify(e)}`));return}this.replyWaiter=void 0,n.resolve(e)}queueNotification(e){this.notifying=this.notifying.then(e).catch(n=>{this.die(n instanceof Error?n:new Error(String(n)))})}async onBatchFrame(e){let n=H(e.from),r=H(e.to),i=e.entries;if(!Array.isArray(i))throw new P("protostate",`batch ${n} to ${r} carries no entries array, so an empty batch cannot be told from a lost one`);let s=i;if(n!==this.cursor+1)throw new P("protostate",`batch covers ${n} to ${r} but this device has applied up to ${this.cursor}, so something was skipped`);if(r<n)throw new P("protostate",`batch covers an empty range, ${n} to ${r}`);for(let o of s){if(typeof o?.uid!="number"||!Number.isFinite(o.uid))throw new P("protostate",`batch ${n}..${r} contains an entry with no uid`);if(typeof o.path!="string"||o.path==="")throw new P("protostate",`batch ${n}..${r} contains uid ${o.uid} with no path`);if(!Array.isArray(o.chunks))throw new P("protostate",`batch ${n}..${r} contains uid ${o.uid} with no chunks array`);if(o.uid<n||o.uid>r)throw new P("protostate",`batch ${n}..${r} contains uid ${o.uid}`)}await this.opts.onBatch({from:n,to:r,entries:s}),this.cursor=r}send(e){if(this.closed||!this.socket)throw this.closeReason??new j("not connected");this.socket.send(JSON.stringify(e))}sendBody(e){if(this.closed||!this.socket)throw this.closeReason??new j("not connected");this.socket.send(e)}async request(e){if(this.replyWaiter)throw new Error("a request is already in flight");this.requestsSent++;let n=this.opts.timeoutMs??$n,r=await new Promise((i,s)=>{let o=setTimeout(()=>{this.die(new j(`no reply within ${n}ms`))},n);this.replyTimer=o,this.replyWaiter={resolve:a=>{this.disarmReply(),i(a)},reject:a=>{this.disarmReply(),s(a)}};try{this.send(e)}catch(a){this.disarmReply(),this.replyWaiter=void 0,s(a instanceof Error?a:new Error(String(a)))}});if(r.res==="err"){let i=new P(String(r.code??"unknown"),String(r.msg??"no message"));throw i.fatal&&this.die(i),i}return r}async body(){let e=this.bodyQueue.shift();if(e)return e;if(this.closed)throw this.closeReason??new j("not connected");return new Promise((n,r)=>{this.bodyWaiter={resolve:n,reject:r}})}async hello(e){this.cursor=e.cursor;let n=await this.request({op:"hello",proto:Et,crypto:Yt,vault:e.vault,token:e.token,device:e.device,cursor:e.cursor,...e.claim!==void 0?{claim:e.claim}:{}});if(n.res!=="ready")throw new P("protostate",`expected ready, got ${JSON.stringify(n)}`);let r={proto:H(n.proto),cursor:H(n.cursor),perFileMax:H(n.perFileMax),chunkMax:H(n.chunkMax),maxChunks:H(n.maxChunks)};if(r.proto!==Et)throw new P("proto",`server speaks protocol ${r.proto}, this client speaks ${Et}`);return this.log("ready",r),r}async put(e,n,r,i,s={mac:"",parent:""}){let o=await this.request({op:"put",path:e,meta:Mn(n),chunks:[...r],mac:s.mac,parent:s.parent});if(o.res==="have")return{uid:H(o.uid),uploaded:0,bytes:0};if(o.res!=="want")throw new P("protostate",`expected want or have, got ${JSON.stringify(o)}`);let a=At(o.chunks),l=new Set(r),h=0;for(let u of a){if(!l.has(u))throw new P("badchunk",`server asked for ${u}, which this put does not contain`);let f=await i(u);this.sendBody(f),h+=f.length}return{uid:await this.awaitAck(),uploaded:a.length,bytes:h}}async putMany(e,n){if(e.length===0)return{results:[],uploaded:0,bytes:0};if(e.length>_e)throw new P("toolarge",`${e.length} entries in one batch, the limit is ${_e}`);let r=await this.request({op:"putmany",entries:e.map(h=>({path:h.path,meta:Mn(h.meta),chunks:[...h.names],mac:h.mac,parent:h.parent}))}),i=r,s=0,o=0;if(r.res==="want"){let h=At(r.chunks),c=new Set;for(let u of e)for(let f of u.names)c.add(f);for(let u of h){if(!c.has(u))throw new P("badchunk",`server asked for ${u}, which this batch does not contain`);let f=await n(u);this.sendBody(f),o+=f.length}s=h.length,i=await this.awaitReply()}if(i.res!=="acks")throw new P("protostate",`expected acks, got ${JSON.stringify(i)}`);let a=i.results;if(!Array.isArray(a)||a.length!==e.length)throw new P("protostate",`${e.length} entries went up and ${Array.isArray(a)?a.length:"no"} results came back`);let l=a.map(h=>{let c=h??{};return c.code!==void 0?{uid:0,error:new P(String(c.code),String(c.msg??"no message"))}:{uid:H(c.uid)}});for(let h of l)h.error?.fatal&&this.die(h.error);return{results:l,uploaded:s,bytes:o}}async awaitAck(){let e=await this.awaitReply();if(e.res!=="ack")throw new P("protostate",`expected ack, got ${JSON.stringify(e)}`);return H(e.uid)}async awaitReply(){let e=await new Promise((n,r)=>{if(this.closed){r(this.closeReason??new j("not connected"));return}let i=this.opts.timeoutMs??$n,s=setTimeout(()=>{this.die(new j(`no acknowledgement within ${i}ms`))},i);this.replyWaiter={resolve:o=>{clearTimeout(s),n(o)},reject:o=>{clearTimeout(s),r(o)}}});if(e.res==="err"){let n=new P(String(e.code??"unknown"),String(e.msg??"no message"));throw n.fatal&&this.die(n),n}return e}async get(e){let n=await this.request({op:"get",uid:e});if(n.res!=="chunks")throw new P("protostate",`expected chunks, got ${JSON.stringify(n)}`);return{uid:H(n.uid),size:H(n.size),chunks:At(n.chunks)}}async history(e,n={}){let r=await this.request({op:"history",path:e,...n.before!==void 0?{before:n.before}:{},...n.limit!==void 0?{limit:n.limit}:{}});if(r.res!=="history")throw new P("protostate",`expected history, got ${JSON.stringify(r)}`);return Tn(r.entries,"history")}async deleted(e){let n=await this.request({op:"deleted",...e!==void 0?{limit:e}:{}});if(n.res!=="deleted")throw new P("protostate",`expected deleted, got ${JSON.stringify(n)}`);return{entries:Tn(n.entries,"deleted"),more:n.more===!0}}async fetch(e){if(e.length===0)return[];this.expecting+=e.length;let n=this.request({op:"fetch",chunks:[...e]}),r=[],i=[];try{for(let s=0;s<e.length;s++){let o=await Promise.race([this.body(),n.then(l=>{throw new P("protostate",`expected a chunk body, got ${JSON.stringify(l)}`)})]),a=e[s];i.push(mt(o).then(l=>{if(l!==a)throw new P("badchunk",`asked for ${a} and received ${o.length} bytes that hash to ${l}`)})),r.push(o)}await Promise.all(i)}catch(s){throw this.expecting=0,this.disarmReply(),this.replyWaiter=void 0,s instanceof P&&s.code==="badchunk"&&this.die(s),s}return this.expecting=Math.max(0,this.expecting-e.length),this.disarmReply(),this.replyWaiter=void 0,r}async ping(){let e=await this.request({op:"ping"});if(e.res!=="pong")throw new P("protostate",`expected pong, got ${JSON.stringify(e)}`)}},He=class{constructor(e=0,n=3e5,r=5e3,i=!0,s=Math.random){this.min=e;this.max=n;this.base=r;this.jitter=i;this.random=s}min;max;base;jitter;random;count=0;nextAt=0;success(e){this.count=0,this.nextAt=e+this.delay()}fail(e){this.count++,this.nextAt=e+this.delay()}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))}readyAt(){return this.nextAt}isReady(e){return e>=this.nextAt}get failures(){return this.count}};function ri(t){let e=globalThis.WebSocket;if(!e)throw new Error("no WebSocket available in this environment");return new e(t)}function ii(t){if(t instanceof Uint8Array)return t;if(t instanceof ArrayBuffer)return new Uint8Array(t);if(ArrayBuffer.isView(t))return new Uint8Array(t.buffer,t.byteOffset,t.byteLength)}function H(t){return typeof t=="number"&&Number.isFinite(t)?t:0}function At(t){return Array.isArray(t)?t.filter(e=>typeof e=="string"):[]}function Cn(t){let e=t.code??0,n=t.reason?`, ${t.reason}`:"";return`code ${e}${n}`}function Tn(t,e){if(!Array.isArray(t))throw new P("protostate",`${e} came back without a list of entries`);return t}function _n(t){let e=t.split("/");e.pop();let n=[],r="";for(let i of e)r=r?`${r}/${i}`:i,n.push(r);return n}function si(t){let e={...t};return t.hash===q(t.chunks)&&delete e.hash,t.synchash===t.hash&&delete e.synchash,e}function oi(t,e){let n={...kt(t),...e};return e.hash===void 0&&(n.hash=q(n.chunks)),e.synchash===void 0&&(n.synchash=n.hash),n}function q(t){return t.length===0?"-empty-":t.join(",")}function ai(t,e){if(t<e)throw new Error(`this server is at version ${t} 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`)}var Rn={perFileMax:1<<28,maxChunks:65536};function In(t,e){return t>0?Math.min(t,e):e}function li(t){if(!t.folder&&!t.deleted&&t.size>0&&t.chunks.length===0)throw new Error(`version ${t.uid} declares ${t.size} bytes and names no chunks, which cannot both be true`);if(t.chunks.length>0&&(t.folder||t.deleted)){let e=t.folder?"a folder":"a deletion";throw new Error(`version ${t.uid} is ${e} and names ${t.chunks.length} chunks`)}}function hi(t){return t===""||t==="-empty-"?[]:t.split(",")}function zn(){return{uploaded:0,downloaded:0,merged:0,conflicted:0,deletedLocally:0,deletedRemotely:0,restored:0,foldersCreated:0,unchanged:0,waiting:0,retrying:0,skipped:0,blocked:0,chunksSent:0,bytesSent:0}}var je=class{constructor(e){this.opts=e}opts;entries=new Map;remote=new Map;pending=new Set;retries=new Map;skipped=new Map;blocked=new Set;cannotStream=!1;outbox=[];outboxBytes=0;inbox=[];inboxBytes=0;limits;unsealed=new Map;cursor=0;syncing=!1;again=!1;started=!1;now(){return this.opts.now?.()??Date.now()}log(e,...n){this.opts.log?.(e,...n)}mergeable(e){return(this.opts.mergeable??pn)(e)}sizesFor(e,n){return dn(e,n,this.limits?.chunkMax)}get coalesce(){return this.opts.coalesceWrites??!0}status(){let e=0;for(let n of this.entries.values())n.folder||e++;return{cursor:this.cursor,files:e,pending:this.pending.size,retrying:this.retries.size,skipped:this.skipped.size,syncing:this.syncing}}async start(){if(this.started)throw new Error("already started");this.started=!0;let e=await this.opts.store.load();if(e){this.cursor=e.cursor;for(let[r,i]of Object.entries(e.entries))this.entries.set(r,oi(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 n=await this.opts.transport.hello({vault:this.opts.vaultId,token:this.opts.token,device:this.opts.device,cursor:this.cursor,...this.opts.claim!==void 0?{claim:this.opts.claim}:{}});return ai(n.cursor,this.cursor),this.limits=n,this.log("connected",n),n}async authFor(e,n){let r=await cn(n);return{mac:await yt(this.opts.keys,{path:e.path,size:e.meta.size,ctime:e.meta.ctime,mtime:e.meta.mtime,folder:e.meta.folder??!1,deleted:e.meta.deleted??!1,prev:e.meta.prev,chunks:e.names,parent:r}),parent:r}}async acceptBatch(e){let n=e.entries.map(l=>({path:l.path,size:l.size,ctime:l.ctime,mtime:l.mtime,folder:l.folder,deleted:l.deleted,prev:l.prev,chunks:l.chunks,parent:l.parent??""})),i=(await Promise.all(n.map((l,h)=>hn(this.opts.keys,l,e.entries[h].mac)))).indexOf(!1);if(i>=0)throw new Error(`version ${e.entries[i].uid} is not authenticated by this vault's key, so nothing that holds the key wrote it`);for(let l of e.entries)li(l);let s=await Promise.all(e.entries.map(l=>this.plaintextPath(l.path))),o=await Promise.all(e.entries.map(l=>l.prev?this.plaintextPath(l.prev):void 0)),a=new Map;for(let l=0;l<e.entries.length;l++){let h=e.entries[l],c=s[l];if(a.set(c,{uid:h.uid,folder:h.folder,deleted:h.deleted,mtime:h.mtime,size:h.size,hash:q(h.chunks)}),h.prev){let u=o[l];a.set(u,{uid:h.uid,folder:!1,deleted:!0,mtime:h.mtime,size:0,hash:""})}}for(let[l,h]of a)this.remote.set(l,h),this.pending.add(l);this.cursor=e.to}async plaintextPath(e){let n=this.unsealed.get(e);if(n!==void 0)return n;let r=await Ve(this.opts.keys,e);return this.unsealed.set(e,r),r}async sync(e={}){if(this.syncing)return this.again=!0,zn();this.syncing=!0;try{let n=await this.pass(e);for(;this.again;){this.again=!1;let r=await this.pass(e);n=ci(n,r)}return n}finally{this.syncing=!1}}async pass(e={}){let n=zn(),r=this.now(),i=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.outboxBytes=0,this.inbox=[],this.inboxBytes=0);let s=await this.opts.vault.list(),o=new Map(s.map(c=>[c.path,c]));for(let c of s){let u=this.entryFor(c.path);be(u,c)}let a=new Set;for(let[c,u]of o)u.folder||a.add(c);let l=new Set,h=new Set([...o.keys(),...this.entries.keys(),...this.remote.keys()]);for(let c of[...h].sort()){let u=this.skipped.get(c);if(u){if(xt(this.entries.get(c))===u.fingerprint){n.skipped++;continue}this.skipped.delete(c),this.log("skipped file changed, trying again",c)}let f=_n(c).find(m=>a.has(m));if(f!==void 0&&!o.has(c)){l.add(c),this.blocked.has(c)||this.log("cannot be both",c,`${f} is a file here and a folder elsewhere`),n.blocked++;continue}let g=this.retries.get(c);if(g&&g.at>r){n.retrying++;continue}try{this.opts.onProgress?.(c),await this.reconcile(c,o.get(c),n,r,i),this.retries.delete(c)}catch(m){this.recordFailure(c,m,n)}}return this.wroteThisPass=[],await this.fill(n),await this.applyDeletes(n),this.wroteThisPass=[],await this.flush(n),this.opts.onProgress?.(void 0),this.blocked=l,this.prune(o),await this.opts.vault.flush?.(),await this.save(),n}entryFor(e){let n=this.entries.get(e);return n||(n=kt(e),this.entries.set(e,n)),n}async reconcile(e,n,r,i,s){let o=this.entryFor(e),a=this.remote.get(e),l=this.limits?.perFileMax??0;if(n&&!n.folder&&l>0&&n.size>l){this.recordFailure(e,di(n.size,l),r);return}let h,c;n&&(!n.folder&&St(o,Math.ceil(n.mtime),n.size)&&(c=await this.rehash(o,e,n.size)),h={folder:n.folder,mtime:o.mtime,size:o.size,hash:o.hash});let u=An({local:h,remote:a,index:o,mergeable:this.mergeable(e)});if(s&&u.kind!=="nothing"&&h&&!n?.folder&&!Pn(o,i)){r.waiting++;return}await this.act(e,u,o,h,a,r,c),this.pending.delete(e)}async rehash(e,n,r){let i=await this.streamScan(e,n,r);if(i)return i;let s=await this.opts.vault.read(n),o=this.mergeable(n),a=[...bt(s,this.sizesFor(s.length,o),o)],l=a.map(h=>h.bytes);if(s.length<=Dn){let h=await ue(this.opts.keys,l);return e.chunks=h.map(c=>c.name),e.hash=q(e.chunks),e.size=s.length,{bytes:s,pieces:a,names:e.chunks,sealed:h}}return e.chunks=await this.namesOf(l),e.hash=q(e.chunks),e.size=s.length,{bytes:s,pieces:a,names:e.chunks}}async streamScan(e,n,r){let i=this.opts.vault;if(!(!i.readBlocks||!i.readRange||this.cannotStream)&&!(r===void 0||r<=Dn))try{return await this.streamed(e,n,r)}catch(s){this.cannotStream=!0,this.log("streaming is not available here, reading whole files instead",n,{why:s.message});return}}async streamed(e,n,r){let i=this.opts.vault,s=this.mergeable(n),o=[],a=[],l=0;for await(let h of mn(i.readBlocks(n),this.sizesFor(r,s),s)){let c=await ue(this.opts.keys,[h.bytes]);o.push(c[0].name),a.push({start:h.offset,end:h.offset+h.bytes.length}),l+=h.bytes.length}return e.chunks=o,e.hash=q(o),e.size=l,{names:o,spans:a,path:n,size:l}}namesOf(e){return ui(this.opts.keys,e)}async act(e,n,r,i,s,o,a){switch(n.kind){case"nothing":o.unchanged++,i&&s&&!s.deleted&&i.hash===s.hash&&de(r,i.hash,r.chunks,s.uid,this.now());return;case"upload":await this.upload(e,r,o,!0,a);return;case"download":case"restoreLocal":{if(!s)return;await this.receive(e,r,s,n.kind,n.why,o);return}case"createLocalFolder":await this.opts.vault.mkdir(e),r.folder=!0,s&&de(r,"",[],s.uid,this.now()),o.foldersCreated++;return;case"clash":this.skipped.set(e,{why:`${n.why}. Rename one of them, and it will sync.`,fingerprint:xt(r)}),o.skipped++,this.log("cannot be both",e,n.why);return;case"deleteLocal":this.pendingDeletes.push({path:e,why:n.why});return;case"deleteRemote":{let l=this.now(),h={path:await this.sealedPath(e),meta:{size:0,ctime:0,mtime:l,deleted:!0},names:[]};await this.queue({path:e,size:0,entry:{...h,...await this.authFor(h,r.synchash)},bodyOf:Fn,commit:c=>{this.remote.set(e,{uid:c,folder:!1,deleted:!0,mtime:this.now(),size:0,hash:""}),this.entries.delete(e),o.deletedRemotely++,this.log("deleted on the server",e,n.why)}},o);return}case"merge":await this.merge(e,r,s,o);return;case"conflict":await this.conflict(e,r,s,o,n.why);return}}async upload(e,n,r,i=!1,s){if(n.folder){let f={path:await this.sealedPath(e),meta:{size:0,ctime:0,mtime:0,folder:!0},names:[]};await this.queue({path:e,size:0,entry:{...f,...await this.authFor(f,"")},bodyOf:Fn,commit:g=>{de(n,"",[],g,this.now()),this.remote.set(e,{uid:g,folder:!0,deleted:!1,mtime:0,size:0,hash:""}),i&&r.uploaded++}},r);return}let o=await this.planUpload(n,e,s),a=n.hash,l=[...n.chunks],h=n.size,c=n.mtime,u={path:await this.sealedPath(e),meta:{size:h,ctime:n.ctime,mtime:c,...n.prev?{prev:await this.sealedPath(n.prev)}:{}},names:o.names};await this.queue({path:e,size:h,entry:{...u,...await this.authFor(u,n.synchash)},bodyOf:o.bodyOf,commit:f=>{de(n,a,l,f,this.now()),this.remote.set(e,{uid:f,folder:!1,deleted:!1,mtime:c,size:h,hash:a}),i&&r.uploaded++,this.log("uploaded",e)}},r)}async queue(e,n){this.outbox.push(e),this.outboxBytes+=e.size,(this.outbox.length>=_e||this.outboxBytes>=Un)&&await this.flush(n)}async flush(e){if(this.outbox.length===0)return;let n=this.outbox;this.outbox=[],this.outboxBytes=0;let r=new Map;for(let s of n)for(let o of s.entry.names)r.has(o)||r.set(o,s.bodyOf);let i;try{i=await this.opts.transport.putMany(n.map(s=>s.entry),async s=>{let o=r.get(s);if(!o)throw new Error(`server asked for ${s}, which no queued file contains`);return o(s)})}catch(s){for(let o of n)this.recordFailure(o.path,s,e);return}e.chunksSent+=i.uploaded,e.bytesSent+=i.bytes;for(let s=0;s<n.length;s++){let o=n[s],a=i.results[s];if(a.error){this.recordFailure(o.path,a.error,e);continue}o.commit(a.uid)}}async planUpload(e,n,r){let i=r??await this.scan(e,n);if(i.sealed){let h=new Map(i.sealed.map(c=>[c.name,c.bytes]));return{names:i.names,bodyOf:async c=>{let u=h.get(c);if(!u)throw new Error(`no sealed body for ${c} of ${n}`);return u}}}let s=this.opts.keys,o=this.opts.vault;if(i.spans){let h=new Map(i.names.map((c,u)=>[c,i.spans[u]]));return{names:i.names,bodyOf:async c=>{let u=h.get(c);if(!u)throw new Error(`no chunk named ${c} in ${n}`);let f=await o.readRange(i.path,u.start,u.end),g=await ue(s,[f]);if(g[0].name!==c)throw new Error(`${n} changed while it was being sent, so it was not sent`);return g[0].bytes}}}let a=new Map;for(let h=0;h<i.names.length;h++){let c=i.pieces[h];a.set(i.names[h],{start:c.offset,end:c.offset+c.bytes.length})}let l=i.bytes;return{names:i.names,bodyOf:async h=>{let c=a.get(h);if(!c)throw new Error(`no chunk named ${h} in ${n}`);return(await ue(s,[l.subarray(c.start,c.end)]))[0].bytes}}}scan(e,n){return this.rehash(e,n)}async receive(e,n,r,i,s,o){let a=hi(r.hash);this.checkChunkCount(r.uid,a.length),this.inbox.push({path:e,entry:n,remote:r,chunks:a,kind:i,why:s}),this.inboxBytes+=r.size,(this.inbox.length>=_e||this.inboxBytes>=Un)&&await this.fill(o)}async fill(e){if(this.inbox.length===0)return;let n=this.inbox;this.inbox=[],this.inboxBytes=0;let r=new Map,i=this.heldByContent();for(let l of n){let h=i.get(q(l.chunks));h!==void 0&&h!==l.path&&r.set(l,h)}let s=[],o=new Set;for(let l of n)if(!r.has(l))for(let h of l.chunks)o.has(h)||(o.add(h),s.push(h));let a=new Map;if(s.length>0)try{let l=await this.opts.transport.fetch(s);for(let h=0;h<s.length;h++)a.set(s[h],l[h])}catch(l){for(let h of n)this.recordFailure(h.path,l,e);return}for(let l of n)try{let h=r.get(l);if(h!==void 0&&await this.landFromLocal(l,h)){l.kind==="download"?e.downloaded++:e.restored++,this.log(l.kind,l.path,`${l.why}, from ${h} without asking`);continue}h!==void 0?await this.land(l,await this.fetchFor(l)):await this.land(l,a),l.kind==="download"?e.downloaded++:e.restored++,this.log(l.kind,l.path,l.why)}catch(h){this.recordFailure(l.path,h,e)}}pendingDeletes=[];wroteThisPass=[];async wouldUndoAWrite(e){let n=this.opts.vault;for(let r of this.wroteThisPass){if(r===e)continue;if(n.sameFile?await n.sameFile(r,e):r.normalize("NFC").toLowerCase()===e.normalize("NFC").toLowerCase())return r}}async applyDeletes(e){let n=this.pendingDeletes;this.pendingDeletes=[];for(let{path:r,why:i}of n)try{let s=await this.wouldUndoAWrite(r);if(s!==void 0){this.entries.delete(r),this.log("kept",r,`deleting it would remove ${s}, which is the same file`);continue}await this.opts.vault.remove(r),this.entries.delete(r),e.deletedLocally++,this.log("deleted locally",r,i)}catch(s){this.recordFailure(r,s,e)}}heldByContent(){let e=new Map;for(let[n,r]of this.entries)r.folder||r.hash===""||r.hash==="-empty-"||e.set(r.hash,n);return e}async fetchFor(e){let n=await this.opts.transport.fetch([...e.chunks]),r=new Map;return e.chunks.forEach((i,s)=>r.set(i,n[s])),r}async landFromLocal(e,n){let r;try{r=await this.opts.vault.read(n)}catch{return!1}if(r.length!==e.remote.size)return!1;let i=this.mergeable(n),s=[...bt(r,this.sizesFor(r.length,i),i)].map(a=>a.bytes),o=(await ue(this.opts.keys,s)).map(a=>a.name);return q(o)!==q(e.chunks)?!1:(await this.opts.vault.write(e.path,r,{mtime:e.remote.mtime,ctime:e.remote.mtime}),this.wroteThisPass.push(e.path),be(e.entry,{folder:!1,mtime:e.remote.mtime,ctime:e.remote.mtime,size:r.length}),e.entry.chunks=[...e.chunks],e.entry.hash=q(e.chunks),e.entry.size=r.length,de(e.entry,e.entry.hash,e.entry.chunks,e.remote.uid,this.now()),!0)}async land(e,n){let r=e.chunks.map(s=>{let o=n.get(s);if(!o)throw new Error(`the server did not send ${s}, which ${e.path} is made of`);return o}),i=await this.assemble(e.remote.uid,r);if(i.length!==e.remote.size)throw new Error(`version ${e.remote.uid} of ${e.path} assembled to ${i.length} bytes, not the ${e.remote.size} it declares`);await this.opts.vault.write(e.path,i,{mtime:e.remote.mtime,ctime:e.remote.mtime}),this.wroteThisPass.push(e.path),be(e.entry,{folder:!1,mtime:e.remote.mtime,ctime:e.remote.mtime,size:i.length}),e.entry.chunks=[...e.chunks],e.entry.hash=q(e.chunks),e.entry.size=i.length,de(e.entry,e.entry.hash,e.entry.chunks,e.remote.uid,this.now())}async contentOf(e,n,r){let i=n!==void 0?{chunks:n}:await this.opts.transport.get(e);if(r!==void 0&&q(i.chunks)!==r)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`);return i.chunks.length===0?new Uint8Array(0):(this.checkChunkCount(e,i.chunks.length),this.assemble(e,await this.opts.transport.fetch(i.chunks)))}checkChunkCount(e,n){let r=In(this.limits?.maxChunks??0,Rn.maxChunks);if(n>r)throw new Error(`version ${e} names ${n} chunks, and this server said it stores at most ${r}`)}async assemble(e,n){if(n.length===0)return new Uint8Array(0);let r=[],i=0,s=In(this.limits?.perFileMax??0,Rn.perFileMax);for(let l=0;l<n.length;l+=Pt){let h=await Promise.all(n.slice(l,l+Pt).map(c=>an(this.opts.keys,c)));for(let c of h){if(i+=c.length,i>s)throw new Error(`version ${e} is over ${i} bytes, and this server said it stores at most ${s}`);r.push(c)}}let o=new Uint8Array(i),a=0;for(let l of r)o.set(l,a),a+=l.length;return o}async merge(e,n,r,i){if(!r)return;let s=new TextDecoder("utf-8",{fatal:!0}),o,a,l;try{o=s.decode(await this.contentOf(n.syncuid,void 0,n.synchash)),a=s.decode(await this.opts.vault.read(e)),l=s.decode(await this.contentOf(r.uid,void 0,r.hash))}catch{let u="one side is not valid UTF-8, so merging it would rewrite bytes nobody edited";this.log("merge refused",e,u),await this.conflict(e,n,r,i,u);return}let h=Sn(o,a,l,yn(e)?gi:void 0);if(h.kind==="conflict"){this.log("merge refused",e,h.why),await this.conflict(e,n,r,i,h.why);return}let c=h.text;c!==a&&await this.opts.vault.write(e,new TextEncoder().encode(c),{mtime:this.now(),ctime:n.ctime}),be(n,{folder:!1,mtime:this.now(),ctime:n.ctime,size:c.length}),await this.upload(e,n,i),i.merged++,this.log("merged",e,h.kind==="merged"?"three-way":h.why)}freeConflictPath(e){return fi(En(e,this.opts.device,new Date(this.now())),n=>this.opts.vault.exists(n))}async conflict(e,n,r,i,s){if(!r)return;let o=await this.freeConflictPath(e),a=await this.contentOf(r.uid,void 0,r.hash);await this.opts.vault.write(o,a,{mtime:r.mtime,ctime:r.mtime});let l=this.entryFor(o);be(l,{folder:!1,mtime:r.mtime,ctime:r.mtime,size:a.length}),await this.upload(o,l,i),await this.upload(e,n,i),i.conflicted++,this.log("kept both",e,{copy:o,why:s})}async sealedPath(e){let n=await We(this.opts.keys,e);return this.unsealed.set(n,e),n}recordFailure(e,n,r){let i=n instanceof Error?n.message:String(n),s=n?.code;if(s!==void 0&&["badentry","badname","toolarge"].includes(s)){this.skipped.set(e,{why:i,fingerprint:xt(this.entries.get(e))}),r.skipped++,this.log("skipped for good",e,i);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),r.retrying++,this.log("will retry",e,{attempt:a.count,error:i})}prune(e){for(let[n,r]of this.entries){if(e.has(n))continue;let i=this.remote.get(n);i&&!i.deleted||r.synchash===""&&r.hash===""&&this.entries.delete(n)}for(let[n,r]of this.remote)r.deleted&&(e.has(n)||this.entries.has(n)||this.pending.has(n)||this.remote.delete(n))}async save(){let e={};for(let[r,i]of this.entries)e[r]=si(i);let n={};for(let[r,i]of this.remote)n[r]=i;await this.opts.store.save({cursor:this.cursor,entries:e,remote:n,pending:[...this.pending]})}noteRename(e,n){let r=this.entries.get(e);r&&(this.entries.delete(e),xn(r,e,n),this.entries.set(n,r))}};function ci(t,e){let n={...t};for(let r of Object.keys(n))n[r]=t[r]+e[r];return n}function xt(t){return t?`${t.mtime}:${t.size}`:"gone"}var Dn=8*1024*1024,Pt=16;async function ui(t,e,n=Pt){let r=[];for(let i=0;i<e.length;i+=n){let s=await ue(t,e.slice(i,i+n));for(let o of s)r.push(o.name)}return r}var Un=8*1024*1024;async function fi(t,e){if(!await e(t))return t;let n=t.lastIndexOf("."),r=t.lastIndexOf("/"),i=n>r,s=i?t.slice(0,n):t,o=i?t.slice(n):"";for(let a=2;a<1e3;a++){let l=`${s} ${a}${o}`;if(!await e(l))return l}throw new Error(`cannot find an unused name beside ${t}`)}function di(t,e){let n=new Error(`${t} bytes, and this server said it stores at most ${e}, so it was not read`);return n.code="toolarge",n}async function Fn(t){throw new Error(`this put has no bodies, and the server asked for ${t}`)}function gi(t){try{return JSON.parse(t),!0}catch{return!1}}var mi=150,Re=class{constructor(e){this.opts=e;let n;this.transport=new Ke(e.url,{onBatch:async r=>{await n.acceptBatch(r),r.entries.length>0&&this.soon()},onCaughtUp:()=>{this.caughtUp=!0},onClosed:r=>{this.endedWith=r,this.notifyEnded?.(r)},...e.timeoutMs!==void 0?{timeoutMs:e.timeoutMs}:{},...e.log!==void 0?{log:e.log}:{},...e.socketFactory!==void 0?{socketFactory:e.socketFactory}:{}}),n=new je({vault:e.vault,store:e.store,keys:e.keys,transport:this.transport,device:e.device,vaultId:e.vaultId,token:e.token,...e.claim!==void 0?{claim:e.claim}:{},...e.coalesceWrites!==void 0?{coalesceWrites:e.coalesceWrites}:{},...e.log!==void 0?{log:e.log}:{},...e.onProgress!==void 0?{onProgress:e.onProgress}:{}}),this.engine=n}opts;engine;transport;limits;soonTimer;caughtUp=!1;endedWith;notifyEnded;queue=Promise.resolve();serial(e){let n=this.queue.then(e,e);return this.queue=n.catch(()=>{}),n}get requestsSent(){return this.transport.requestsSent}get serverCursor(){return this.limits?.cursor??0}async connect(){await this.transport.connect(),this.limits=await this.engine.start();let e=this.opts.timeoutMs??3e4,n=Date.now()+e;for(;!this.caughtUp&&Date.now()<n;){if(this.endedWith)throw this.endedWith;await $t(25)}if(!this.caughtUp)throw new Error("the server never finished sending what it already had");return this.limits}async settle(e={},n=8){let r=await this.pass(e),i=r;for(let s=0;s<n&&wi(r);s++)await $t(60),r=await this.pass(e),i=vi(i,r);return i}pass(e){return this.serial(()=>this.engine.sync(e))}async runUntilClosed(e=3e4){if(this.endedWith)return this.endedWith;let n=this.opts.vault.watch?.(()=>{this.sync()}),r=setInterval(()=>{this.sync().then(()=>this.keepalive())},e);try{return await new Promise(i=>{this.notifyEnded=i})}finally{clearInterval(r),n?.()}}async keepalive(){try{await this.transport.ping()}catch{}}soon(){this.soonTimer===void 0&&(this.soonTimer=setTimeout(()=>{this.soonTimer=void 0,this.sync()},mi))}async sync(e={}){try{return await this.pass(e)}catch(n){this.opts.log?.("sync failed",n.message);return}}async history(e,n={}){let r=await We(this.opts.keys,e);return(await this.serial(()=>this.transport.history(r,n))).map(s=>this.asVersion(s,e))}async deleted(e){let n=await this.serial(()=>this.transport.deleted(e)),r=[];for(let i of n.entries)r.push({...this.asVersion(i,await Ve(this.opts.keys,i.path)),restorable:i.restorable??0});return{notes:r,more:n.more}}async contentAt(e){return e.deleted||e.folder?new Uint8Array(0):this.serial(()=>this.engine.contentOf(e.uid))}async restore(e,n){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 o=n??e.path;return await this.opts.vault.mkdir(o),{path:o,bytes:0}}let r=await this.serial(()=>this.engine.contentOf(e.uid)),i=n??e.path,s=await this.opts.vault.exists(i)?pi(i,e):i;return await this.opts.vault.write(s,r,{mtime:e.mtime,ctime:e.ctime}),{path:s,bytes:r.length}}async newestContentVersion(e){return(await this.history(e,{limit:50})).find(r=>!r.deleted)}asVersion(e,n){return{uid:e.uid,path:n,size:e.size,ctime:e.ctime,mtime:e.mtime,folder:e.folder,deleted:e.deleted,device:e.device,chunks:e.chunks?.length??0}}close(){this.soonTimer!==void 0&&(clearTimeout(this.soonTimer),this.soonTimer=void 0),this.transport.close()}};function pi(t,e){let n=t.lastIndexOf("/"),r=n===-1?"":t.slice(0,n+1),i=n===-1?t:t.slice(n+1),s=i.lastIndexOf("."),o=s<=0?i:i.slice(0,s),a=s<=0?"":i.slice(s);return`${r}${o} (restored ${e.uid})${a}`}async function On(t,e={}){let n=new He(0,3e5,5e3,!0);for(;e.keepGoing?.()??!0;){let r,i,s=!1;try{r=new Re(t),await r.connect(),s=!0,n.success(Date.now()),e.onClient?.(r),e.onSynced?.(await r.settle(),r.serverCursor),i=await r.runUntilClosed()}catch(l){i=l}finally{e.onClient?.(void 0),r?.close()}if(i&&yi(i)){e.onFatal?.(i);return}if(!(e.keepGoing?.()??!0))return;n.fail(Date.now());let o=n.delay(),a=i??new Error("the connection ended");s?e.onDisconnected?.(a,o):e.onUnreachable?.(a,o),await $t(o)}}function yi(t){return t instanceof P&&t.fatal}function vi(t,e){return{uploaded:t.uploaded+e.uploaded,downloaded:t.downloaded+e.downloaded,merged:t.merged+e.merged,conflicted:t.conflicted+e.conflicted,deletedLocally:t.deletedLocally+e.deletedLocally,deletedRemotely:t.deletedRemotely+e.deletedRemotely,restored:t.restored+e.restored,foldersCreated:t.foldersCreated+e.foldersCreated,chunksSent:t.chunksSent+e.chunksSent,bytesSent:t.bytesSent+e.bytesSent,unchanged:e.unchanged,waiting:e.waiting,retrying:e.retrying,skipped:e.skipped,blocked:e.blocked}}function wi(t){return t.uploaded+t.downloaded+t.merged+t.conflicted+t.deletedLocally+t.deletedRemotely+t.restored+t.foldersCreated+t.waiting>0}var $t=t=>new Promise(e=>setTimeout(e,t));var Ge="basalt2_",Mt=2,Ie=4,Nn=new TextEncoder,bi=new TextDecoder;function Ct(t){if(t.secret.length!==X)throw new Error(`a root secret is ${X} bytes, not ${t.secret.length}`);let e=[Nn.encode(t.url),Nn.encode(t.vaultId)];for(let o of e)if(o.length>255)throw new Error("a pairing field is too long to encode");let n=1+X+e.reduce((o,a)=>o+1+a.length,0),r=new Uint8Array(n);r[0]=Mt,r.set(t.secret,1);let i=1+X;for(let o of e)r[i++]=o.length,r.set(o,i),i+=o.length;let s=new Uint8Array(n+Ie);return s.set(r,0),s.set(Ln(r),n),Ge+Te(s)}function Bn(t){let e=t.trim();if(e.startsWith("basalt1_"))throw new Error("this is a version 1 pairing string, from before the server token was folded into the root secret. Run basalt invite on a device that is already paired to get a current one.");if(!e.startsWith(Ge))throw new Error(`not a pairing string: it should start with ${Ge}`);let n;try{n=Je(e.slice(Ge.length))}catch{throw new Error("this pairing string is damaged: it is not valid base64url")}if(n.length<1+X+2+Ie)throw new Error("this pairing string is too short to be complete");let r=n.subarray(0,n.length-Ie),i=n.subarray(n.length-Ie),s=Ln(r);for(let u=0;u<Ie;u++)if(i[u]!==s[u])throw new Error("this pairing string is damaged: it did not survive being copied");if(r[0]!==Mt)throw new Error(`this pairing string is version ${r[0]}, and this device understands ${Mt}`);let o=r.slice(1,1+X),a=1+X,l=u=>{if(a>=r.length)throw new Error(`this pairing string ends before its ${u}`);let f=r[a++];if(a+f>r.length)throw new Error(`this pairing string ends inside its ${u}`);let g=bi.decode(r.subarray(a,a+f));return a+=f,g},h=l("server address"),c=l("vault name");if(a!==r.length)throw new Error("this pairing string has more in it than it should");if(h===""||c==="")throw new Error("this pairing string has an empty field");return{url:h,secret:o,vaultId:c}}function Ln(t){let e=4294967295;for(let n of t){e^=n;for(let r=0;r<8;r++)e=e&1?e>>>1^3988292384:e>>>1}return e=(e^4294967295)>>>0,new Uint8Array([e>>>24&255,e>>>16&255,e>>>8&255,e&255])}function Wn(t){return{url:t.url,vaultId:t.vaultId,device:t.device,secret:Te(t.secret),...t.bootstrap?{bootstrap:t.bootstrap}:{}}}function Vn(t,e){if(typeof t!="object"||t===null)throw new Error(`${e} does not hold a configuration`);let n=t,r=o=>{let a=n[o];if(typeof a!="string"||a==="")throw new Error(`${e} has no ${o}`);return a},i=Je(r("secret"));if(i.length!==X)throw new Error(`${e} holds a ${i.length} byte secret, and a root secret is ${X}`);let s=n.bootstrap;return{url:r("url"),vaultId:r("vaultId"),device:r("device"),secret:i,...typeof s=="string"&&s!==""?{bootstrap:s}:{}}}function Jn(t){let e=t.trim().replace(/\/+$/,"");if(e==="")throw new Error("that is not a server address");if(e.startsWith("ws://")||e.startsWith("wss://"))return e;if(e.startsWith("http://"))return"ws://"+e.slice(7);if(e.startsWith("https://"))return"wss://"+e.slice(8);if(e.includes("://"))throw new Error(`a server address is ws:// or wss://, not ${e.split("://")[0]}://`);return"wss://"+e}import{constants as Tt,watch as ki}from"node:fs";import{access as _t,cp as Si,mkdir as Qe,open as et,readFile as qn,readdir as Kn,realpath as Hn,rename as Rt,rm as Ei,stat as qe,utimes as Ai}from"node:fs/promises";import{basename as Ze,dirname as le,join as Xe,relative as xi,resolve as jn,sep as Ye}from"node:path";var Zn=".trash",Pi=new Set([".basalt",Zn,".git",".DS_Store","node_modules"]),It=".obsidian";function zt(t){let e=t.replace(/^\/+|\/+$/g,"");if(e===""||e.includes("/"))throw new Error(`refusing to sync: the config folder ${JSON.stringify(t)} is not a plain name`);return e}var tt=class{root;ignore;constructor(e,n={}){this.root=jn(e);let r=zt(n.configDir??It);this.ignore=new Set([...Pi,r,...n.alsoIgnore??[]])}realRootOnce;unflushed=new Set;async flush(){let e=[...this.unflushed];this.unflushed.clear(),await Promise.all(e.map(n=>Qn(n)))}async insideForReal(e){let n=await(this.realRootOnce??=Hn(this.root)),r=le(e);for(;;){let i=await Hn(r).catch(o=>{if(o.code!=="ENOENT")throw o});if(i!==void 0){if(i!==n&&!i.startsWith(n+Ye))throw new Error(`refusing a path that leaves the vault through a link: ${e}`);return}let s=le(r);if(s===r)return;r=s}}absolute(e){let n=jn(this.root,e),r=xi(this.root,n);if(r===""||r===".."||r.startsWith(`..${Ye}`))throw new Error(`refusing a path outside the vault: ${e}`);let i=r.split(Ye)[0];if(this.ignore.has(i))throw new Error(`refusing to write inside ${i}, which is never synced: ${e}`);return n}async list(){let e=async(n,r)=>{let i;try{i=await Kn(n,{withFileTypes:!0})}catch(h){throw new Error(`cannot read ${n}: ${h.message}`)}let s=i.filter(h=>!this.ignore.has(h.name)&&!Gn(h.name)&&(h.isDirectory()||h.isFile())),o=await Promise.all(s.map(h=>h.isFile()?qe(Xe(n,h.name)):void 0)),a=await Promise.all(s.map(h=>h.isDirectory()?e(Xe(n,h.name),r?`${r}/${h.name}`:h.name):void 0)),l=[];for(let h=0;h<s.length;h++){let c=s[h],u=r?`${r}/${c.name}`:c.name;if(c.isDirectory())l.push({path:u,folder:!0,mtime:0,ctime:0,size:0}),l.push(...a[h]);else{let f=o[h];l.push({path:u,folder:!1,mtime:f.mtimeMs,ctime:f.birthtimeMs||f.ctimeMs,size:f.size})}}return l};return e(this.root,"")}async read(e){return new Uint8Array(await qn(this.absolute(e)))}async*readBlocks(e,n=1024*1024){let r=await et(this.absolute(e),"r");try{let i=new Uint8Array(n);for(;;){let{bytesRead:s}=await r.read(i,0,n,null);if(s===0)return;yield i.slice(0,s)}}finally{await r.close()}}async readRange(e,n,r){let i=await et(this.absolute(e),"r");try{let s=new Uint8Array(r-n),o=0;for(;o<s.length;){let{bytesRead:a}=await i.read(s,o,s.length-o,n+o);if(a===0)break;o+=a}return o===s.length?s:s.subarray(0,o)}finally{await i.close()}}async write(e,n,r){let i=this.absolute(e);if(await this.insideForReal(i),await Qe(le(i),{recursive:!0}),await this.matchCase(i),await Yn(i,n,!1),this.unflushed.add(le(i)),r.mtime>0){let s=r.mtime/1e3;await Ai(i,s,s)}}async matchCase(e){let n;try{n=await qe(e)}catch{return}if(n.isDirectory())return;let r=le(e),i=Ze(e),s;try{s=await Kn(r)}catch{return}if(s.includes(i))return;let o=i.normalize("NFC").toLowerCase(),a=s.find(l=>l.normalize("NFC").toLowerCase()===o);a!==void 0&&await Rt(Xe(r,a),e)}async remove(e){let n=this.absolute(e);await this.insideForReal(n);try{await _t(n,Tt.F_OK)}catch{return}let r=await this.freeTrashPath(e);await Qe(le(r),{recursive:!0});try{await Rt(n,r);return}catch(i){if(i.code!=="EXDEV")throw i}await Si(n,r,{recursive:!0}),await Ei(n,{recursive:!0,force:!0})}async freeTrashPath(e){let n=Xe(this.root,Zn,e),r=Ze(e).lastIndexOf("."),[i,s]=r<=0?[n,""]:[n.slice(0,n.length-(Ze(e).length-r)),n.slice(n.length-(Ze(e).length-r))];for(let o=0;o<1e3;o++){let a=o===0?n:`${i} (${o})${s}`;try{await _t(a,Tt.F_OK)}catch{return a}}throw new Error(`the trash already holds a thousand copies of ${e}`)}async mkdir(e){let n=this.absolute(e);await this.insideForReal(n),await Qe(n,{recursive:!0})}async exists(e){try{return await _t(this.absolute(e),Tt.F_OK),!0}catch{return!1}}async sameFile(e,n){if(e===n)return!0;try{let[r,i]=await Promise.all([qe(this.absolute(e)),qe(this.absolute(n))]);return r.dev===i.dev&&r.ino===i.ino}catch{return!1}}watch(e){let n,r="",i;try{i=ki(this.root,{recursive:!0,persistent:!0},(s,o)=>{if(!o)return;let a=o.toString().split(Ye).join("/");a.split("/").some(l=>this.ignore.has(l))||Gn(a)||(r=a,n&&clearTimeout(n),n=setTimeout(()=>{n=void 0,e(r)},150))}),i.on("error",()=>{})}catch{return()=>{}}return()=>{n&&clearTimeout(n),i?.close()}}},ze=class{constructor(e){this.file=e}file;lastWritten;async load(){let e;try{e=await qn(this.file,"utf8")}catch(n){if(n.code==="ENOENT")return;throw new Error(`cannot read the index at ${this.file}: ${n.message}`)}try{return JSON.parse(e)}catch(n){throw new Error(`the index at ${this.file} is not valid JSON, so it cannot be trusted: ${n.message}`)}}async save(e){let n=JSON.stringify(e);n!==this.lastWritten&&(await Qe(le(this.file),{recursive:!0}),await Yn(this.file,new TextEncoder().encode(n)),this.lastWritten=n)}},Xn=".basalt-tmp-";function Gn(t){return t.includes(Xn)}var $i=0;async function Mi(t){for(let e=0;e<64;e++){let n=`${t}${Xn}${($i++).toString(36)}${e?`-${e}`:""}`;try{return{tmp:n,handle:await et(n,"wx")}}catch(r){if(r.code!=="EEXIST")throw r}}throw new Error(`could not find an unused temporary name beside ${t}`)}async function Yn(t,e,n=!0){let{tmp:r,handle:i}=await Mi(t);try{await i.write(e),await i.sync()}finally{await i.close()}await Rt(r,t),n&&await Qn(le(t))}async function Qn(t){let e=await et(t,"r");try{await e.sync()}finally{await e.close()}}import{chmod as Ci,mkdir as Ti,readFile as _i,rename as Ri,rm as er,writeFile as Ii}from"node:fs/promises";import{join as Dt}from"node:path";var Ut=".basalt",Ft=t=>Dt(t,Ut,"config.json"),nt=t=>Dt(t,Ut,"index.json");async function De(t){let e=Ft(t),n;try{n=await _i(e,"utf8")}catch(i){if(i.code==="ENOENT")return;throw new Error(`cannot read ${e}: ${i.message}`)}let r;try{r=JSON.parse(n)}catch(i){throw new Error(`${e} is not valid JSON, so it cannot be trusted: ${i.message}`)}return Vn(r,e)}async function rt(t,e){let n=Dt(t,Ut);await Ti(n,{recursive:!0});let r=Ft(t),i=`${r}.tmp`;await Ii(i,JSON.stringify(Wn(e),null,2)+`
9
+ `,{mode:384}),await Ci(i,384),await Ri(i,r)}async function tr(t){await er(Ft(t),{force:!0}),await er(nt(t),{force:!0})}var nr=`basalt: self-hosted sync for Obsidian
10
10
 
11
11
  basalt init --server URL --token TOKEN claim a new vault, with the server's first-run token
12
12
  basalt pair PAIRING-STRING pair this vault with an existing one
@@ -28,6 +28,8 @@ Options
28
28
  --uid N restore one exact version, from basalt history
29
29
  --to PATH restore somewhere other than where it came from
30
30
  --limit N how many versions history shows (default: 20)
31
- `;async function Jn(n,e){let t;try{t=Ci(n)}catch(r){return e.err(String(r.message)),2}if(t.help||t.command===void 0)return e.out(Wn),t.command===void 0&&!t.help?2:0;try{switch(t.command){case"init":return await bi(t,e);case"pair":return await ki(t,e);case"invite":return await Si(t,e);case"sync":return await Ei(t,e);case"status":return await xi(t,e);case"deleted":return await Pi(t,e);case"history":return await $i(t,e);case"restore":return await Mi(t,e);case"unlink":return await _i(t,e);default:return e.err(`no such command: ${t.command}`),e.err(Wn),2}}catch(r){let i=r instanceof Error?r.message:String(r);return t.json?e.out(JSON.stringify({ok:!1,error:i})):e.err(`basalt: ${i}`),1}}async function bi(n,e){if(!n.server||!n.token)throw new Error("init needs --server and --token, from the server's first run");if(await Re(n.dir))throw new Error(`${n.dir} is already paired. Use unlink first if that is really what you want.`);let t={url:Cn(n.server),vaultId:n.vaultId,device:n.device,secret:Vt(),bootstrap:n.token};await Ye(n.dir,t);let r=wt(t);return n.json?e.out(JSON.stringify({ok:!0,paired:n.dir,device:t.device,pairing:r})):(e.out(`Paired ${n.dir} as "${t.device}".`),e.out(""),e.out("Give this to every other device. Anyone who has it has the vault:"),e.out(""),e.out(` ${r}`),e.out(""),e.out("It is the only copy. The server cannot reissue it, because the server"),e.out("has never seen the secret in it.")),0}async function ki(n,e){if(!n.rest[0])throw new Error("pair needs the string another device printed");if(await Re(n.dir))throw new Error(`${n.dir} is already paired. Use unlink first if that is really what you want.`);let r={...Pn(n.rest[0]),device:n.device};return await Ye(n.dir,r),n.json?e.out(JSON.stringify({ok:!0,paired:n.dir,device:r.device,url:r.url})):e.out(`Paired ${n.dir} with ${r.url} as "${r.device}". Run basalt sync.`),0}async function Si(n,e){let t=await pe(n.dir),r=wt(t);return n.json?e.out(JSON.stringify({ok:!0,pairing:r})):(e.out(r),e.err("Anyone who has that string has this vault.")),0}async function Ei(n,e){let t=await pe(n.dir);if(n.watch)return await Ai(t,n,e);let r=await Ie(t,n,e);try{let i=await r.settle();return Hn(i,n,e,r.serverCursor),i.skipped>0||i.retrying>0?1:0}finally{r.close()}}async function Ai(n,e,t){let r;return await An(await Kn(n,e,t),{onSynced:(i,s)=>{Hn(i,e,t,s),e.json||t.err("Watching for changes. Ctrl-C to stop.")},onDisconnected:(i,s)=>{t.err(`Disconnected: ${i.message}. Trying again in ${Vn(s)}.`)},onUnreachable:(i,s)=>{t.err(`Cannot reach the server: ${i.message}. Trying again in ${Vn(s)}.`)},onFatal:i=>{r=i}}),r?(t.err(`basalt: ${r.message}`),t.err("That will not fix itself by trying again."),1):0}async function xi(n,e){let t=await pe(n.dir),r=await new Te(Xe(n.dir)).load(),i={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},s;try{let o=await Ie(t,n,e);s={reachable:!0,cursor:o.serverCursor,behind:Math.max(0,o.serverCursor-i.cursor)},o.close()}catch(o){s={reachable:!1,error:o.message}}return n.json?(e.out(JSON.stringify({ok:!0,...i,server:s})),s.reachable?0:1):(e.out(`vault ${i.vault}`),e.out(`device ${i.device}`),e.out(`server ${i.server} (vault "${i.vaultId}")`),e.out(`tracked ${i.tracked} files`),e.out(`cursor ${i.cursor}`),i.pending>0&&e.out(`pending ${i.pending} files with work outstanding`),s.reachable?(e.out(s.behind===0?"state up to date with the server":`state ${s.behind} changes behind`),0):(e.out(`state cannot reach the server: ${s.error}`),1))}async function Pi(n,e){let t=await pe(n.dir),r=await Ie(t,n,e);try{let i=await r.deleted(n.limit>20?n.limit:void 0);if(n.json)return e.out(JSON.stringify({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 l=a.restorable===0?" (content purged)":"";a.restorable===0&&s++,e.out(`${Pt(a.mtime)} ${a.device.padEnd(12)} ${a.path}${l}`)}e.out("");let o=i.notes.length-s;return s===0?e.out(`${o} deleted, all still recoverable. basalt 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&&e.out("There are older deletions than these. --limit N shows more."),0}finally{r.close()}}async function $i(n,e){let t=n.rest[0];if(!t)throw new Error("history needs the path of a note");let r=await pe(n.dir),i=await Ie(r,n,e);try{let s=await i.history(t,{limit:n.limit});if(n.json)return e.out(JSON.stringify({ok:!0,path:t,versions:s})),0;if(s.length===0)return e.out(`The server holds no versions of ${t}.`),0;for(let o of s){let a=o.deleted?"deleted":o.folder?"folder":`${$t(o.size)}`;e.out(`${String(o.uid).padStart(7)} ${Pt(o.mtime)} ${o.device.padEnd(12)} ${a}`)}return e.out(""),e.out("basalt restore PATH --uid N brings one of these back."),0}finally{i.close()}}async function Mi(n,e){let t=n.rest[0];if(!t)throw new Error("restore needs the path of a note");let r=await pe(n.dir),i=await Ie(r,n,e);try{let s;if(n.uid!==void 0){if(s=(await i.history(t,{limit:500})).find(c=>c.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=await i.settle({coalesceWrites:!1});return n.json?(e.out(JSON.stringify({ok:!0,path:o.path,uid:s.uid,bytes:o.bytes,sync:a})),0):(e.out(`Restored version ${s.uid} of ${t} (${$t(o.bytes)}, from ${Pt(s.mtime)}).`),o.path!==(n.to??t)&&e.out(`Written to ${o.path}, because something is already at ${n.to??t}.`),a.uploaded>0&&e.out("Sent to the server, so your other devices will pick it up."),0)}finally{i.close()}}async function _i(n,e){let t=await Re(n.dir).catch(()=>{});return await Ln(n.dir),n.json?e.out(JSON.stringify({ok:!0,unlinked:n.dir,wasPaired:t!==void 0})):(e.out(`Forgot the pairing for ${n.dir}. Every note is where it was.`),e.out("Nothing was removed from the server.")),0}async function Ie(n,e,t){let r=new _e(await Kn(n,e,t));if(await r.connect(),n.bootstrap){let{bootstrap:i,...s}=n;await Ye(e.dir,s)}return r}async function Kn(n,e,t){let r=await Jt(n.secret),i=Zt(r);return{vault:new Ze(e.dir),store:new Te(Xe(e.dir)),keys:r,url:n.url,token:n.bootstrap??i,claim:i,vaultId:n.vaultId,device:n.device,timeoutMs:e.timeout,coalesceWrites:e.watch,...e.watch&&t?{onProgress:s=>{s!==void 0&&t.err(` ... ${s}`)}}:{},...e.verbose&&t?{log:(s,...o)=>t.err(` ${s} ${o.map(Ti).join(" ")}`.trimEnd())}:{}}}function Hn(n,e,t,r){if(e.json){t.out(JSON.stringify({ok:!0,...n,serverCursor:r}));return}let i=[],s=(o,a)=>{o>0&&i.push(`${String(o).padStart(5)} ${a}`)};if(s(n.uploaded,"uploaded"),s(n.downloaded,"downloaded"),s(n.merged,"merged"),s(n.conflicted,"kept both versions"),s(n.deletedLocally,"deleted here"),s(n.deletedRemotely,"deleted on the server"),s(n.restored,"brought back, having been edited elsewhere"),s(n.foldersCreated,"folders created"),s(n.waiting,"waiting for a write to settle"),s(n.retrying,"failed, will try again"),s(n.skipped,"cannot sync and will not be retried"),s(n.blocked,"waiting on a name that is a file here and a folder elsewhere"),i.length===0)t.out("Nothing to do. Everything here matches the server.");else for(let o of i)t.out(o);n.chunksSent>0&&t.out(`${String(n.chunksSent).padStart(5)} chunks sent, ${$t(n.bytesSent)}`),n.conflicted>0&&t.err('Look for files with "Conflicted copy" in the name. Both versions are kept.')}function Ci(n){let e={rest:[],dir:process.cwd(),device:yi().split(".")[0]||"device",vaultId:"default",json:!1,watch:!1,limit:20,verbose:!1,help:!1,timeout:3e4},t=new Set(["--dir","--device","--vault-id","--server","--token","--timeout","--uid","--to","--limit"]);for(let r=0;r<n.length;r++){let i=n[r],s;if(t.has(i)&&(s=n[++r],s===void 0||s.startsWith("--")))throw new Error(`${i} needs a value`);switch(i){case"--dir":e.dir=wi(s);break;case"--device":e.device=s;break;case"--vault-id":e.vaultId=s;break;case"--server":e.server=s;break;case"--token":e.token=s;break;case"--timeout":{let o=Number(s);if(!Number.isFinite(o)||o<=0)throw new Error(`--timeout wants a number of milliseconds, not ${s}`);e.timeout=o;break}case"--uid":{let o=Number(s);if(!Number.isInteger(o)||o<=0)throw new Error(`--uid wants a version number, not ${s}`);e.uid=o;break}case"--to":e.to=s;break;case"--limit":{let o=Number(s);if(!Number.isInteger(o)||o<=0)throw new Error(`--limit wants a count, not ${s}`);e.limit=o;break}case"--json":e.json=!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(i.startsWith("-"))throw new Error(`no such option: ${i}`);e.command===void 0?e.command=i:e.rest.push(i)}}return e}async function pe(n){let e=await Re(n);if(!e)throw new Error(`${n} is not paired. Run basalt init or basalt pair first.`);return e}function Pt(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 Vn(n){return`${Math.max(1,Math.round(n/1e3))}s`}function $t(n){return n<1024?`${n} B`:n<1024*1024?`${(n/1024).toFixed(1)} KiB`:`${(n/(1024*1024)).toFixed(1)} MiB`}function Ti(n){return typeof n=="string"?n:JSON.stringify(n)}var Ri=await Jn(process.argv.slice(2),{out:n=>process.stdout.write(n+`
32
- `),err:n=>process.stderr.write(n+`
33
- `)});process.exit(Ri);
31
+ --config-dir DIR Obsidian's config folder, if it is not .obsidian
32
+ --ignore NAME a top-level name never to sync, repeatable
33
+ `;async function ir(t,e){let n;try{n=Hi(t)}catch(r){return e.err(String(r.message)),2}if(n.help||n.command===void 0)return e.out(nr),n.command===void 0&&!n.help?2:0;try{switch(n.command){case"init":return await Ui(n,e);case"pair":return await Fi(n,e);case"invite":return await Oi(n,e);case"sync":return await Ni(n,e);case"status":return await Li(n,e);case"deleted":return await Wi(n,e);case"history":return await Vi(n,e);case"restore":return await Ji(n,e);case"unlink":return await Ki(n,e);default:return e.err(`no such command: ${n.command}`),e.err(nr),2}}catch(r){let i=r instanceof Error?r.message:String(r);return n.json?e.out(JSON.stringify({ok:!1,error:i})):e.err(`basalt: ${i}`),1}}async function Ui(t,e){if(!t.server||!t.token)throw new Error("init needs --server and --token, from the server's first run");if(await De(t.dir))throw new Error(`${t.dir} is already paired. Use unlink first if that is really what you want.`);let n={url:Jn(t.server),vaultId:t.vaultId,device:t.device,secret:en(),bootstrap:t.token};await rt(t.dir,n),(await ke(n,t,e)).close();let i=Ct(n);return t.json?e.out(JSON.stringify({ok:!0,paired:t.dir,device:n.device,pairing:i})):(e.out(`Paired ${t.dir} as "${n.device}".`),e.out(""),e.out("Give this to every other device. Anyone who has it has the vault:"),e.out(""),e.out(` ${i}`),e.out(""),e.out("It is the only copy. The server cannot reissue it, because the server"),e.out("has never seen the secret in it.")),0}async function Fi(t,e){if(!t.rest[0])throw new Error("pair needs the string another device printed");if(await De(t.dir))throw new Error(`${t.dir} is already paired. Use unlink first if that is really what you want.`);let r={...Bn(t.rest[0]),device:t.device};return await rt(t.dir,r),t.json?e.out(JSON.stringify({ok:!0,paired:t.dir,device:r.device,url:r.url})):e.out(`Paired ${t.dir} with ${r.url} as "${r.device}". Run basalt sync.`),0}async function Oi(t,e){let n=await Se(t.dir),r=Ct(n);return t.json?e.out(JSON.stringify({ok:!0,pairing:r})):(e.out(r),e.err("Anyone who has that string has this vault.")),0}async function Ni(t,e){let n=await Se(t.dir);if(t.watch)return await Bi(n,t,e);let r=await ke(n,t,e);try{let i=await r.settle();return or(i,t,e,r.serverCursor),i.skipped>0||i.retrying>0?1:0}finally{r.close()}}async function Bi(t,e,n){let r;return await On(await sr(t,e,n),{onSynced:(i,s)=>{or(i,e,n,s),e.json||n.err("Watching for changes. Ctrl-C to stop.")},onDisconnected:(i,s)=>{n.err(`Disconnected: ${i.message}. Trying again in ${rr(s)}.`)},onUnreachable:(i,s)=>{n.err(`Cannot reach the server: ${i.message}. Trying again in ${rr(s)}.`)},onFatal:i=>{r=i}}),r?(n.err(`basalt: ${r.message}`),n.err("That will not fix itself by trying again."),1):0}async function Li(t,e){let n=await Se(t.dir),r=await new ze(nt(t.dir)).load(),i={vault:t.dir,device:n.device,server:n.url,vaultId:n.vaultId,cursor:r?.cursor??0,tracked:r?Object.keys(r.entries).length:0,pending:r?.pending.length??0},s;try{let o=await ke(n,t,e);s={reachable:!0,cursor:o.serverCursor,behind:o.serverCursor-i.cursor},o.close()}catch(o){s={reachable:!1,error:o.message}}return t.json?(e.out(JSON.stringify({ok:!0,...i,server:s})),s.reachable?0:1):(e.out(`vault ${i.vault}`),e.out(`device ${i.device}`),e.out(`server ${i.server} (vault "${i.vaultId}")`),e.out(`tracked ${i.tracked} files`),e.out(`cursor ${i.cursor}`),i.pending>0&&e.out(`pending ${i.pending} files with work outstanding`),s.reachable?(e.out(s.behind===0?"state up to date with the server":`state ${s.behind} changes behind`),0):(e.out(`state cannot reach the server: ${s.error}`),1))}async function Wi(t,e){let n=await Se(t.dir),r=await ke(n,t,e);try{let i=await r.deleted(t.limit>20?t.limit:void 0);if(t.json)return e.out(JSON.stringify({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 l=a.restorable===0?" (content purged)":"";a.restorable===0&&s++,e.out(`${Ot(a.mtime)} ${a.device.padEnd(12)} ${a.path}${l}`)}e.out("");let o=i.notes.length-s;return s===0?e.out(`${o} deleted, all still recoverable. basalt 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&&e.out("There are older deletions than these. --limit N shows more."),0}finally{r.close()}}async function Vi(t,e){let n=t.rest[0];if(!n)throw new Error("history needs the path of a note");let r=await Se(t.dir),i=await ke(r,t,e);try{let s=await i.history(n,{limit:t.limit});if(t.json)return e.out(JSON.stringify({ok:!0,path:n,versions:s})),0;if(s.length===0)return e.out(`The server holds no versions of ${n}.`),0;for(let o of s){let a=o.deleted?"deleted":o.folder?"folder":`${Nt(o.size)}`;e.out(`${String(o.uid).padStart(7)} ${Ot(o.mtime)} ${o.device.padEnd(12)} ${a}`)}return e.out(""),e.out("basalt restore PATH --uid N brings one of these back."),0}finally{i.close()}}async function Ji(t,e){let n=t.rest[0];if(!n)throw new Error("restore needs the path of a note");let r=await Se(t.dir),i=await ke(r,t,e);try{let s;if(t.uid!==void 0){if(s=(await i.history(n,{limit:500})).find(h=>h.uid===t.uid),!s)throw new Error(`the server has no version ${t.uid} of ${n}`)}else if(s=await i.newestContentVersion(n),!s)throw new Error(`the server holds no version of ${n} with any content in it`);let o=await i.restore(s,t.to),a=await i.settle({coalesceWrites:!1});return t.json?(e.out(JSON.stringify({ok:!0,path:o.path,uid:s.uid,bytes:o.bytes,sync:a})),0):(e.out(`Restored version ${s.uid} of ${n} (${Nt(o.bytes)}, from ${Ot(s.mtime)}).`),o.path!==(t.to??n)&&e.out(`Written to ${o.path}, because something is already at ${t.to??n}.`),a.uploaded>0&&e.out("Sent to the server, so your other devices will pick it up."),0)}finally{i.close()}}async function Ki(t,e){let n=await De(t.dir).catch(()=>{});return await tr(t.dir),t.json?e.out(JSON.stringify({ok:!0,unlinked:t.dir,wasPaired:n!==void 0})):(e.out(`Forgot the pairing for ${t.dir}. Every note is where it was.`),e.out("Nothing was removed from the server.")),0}async function ke(t,e,n){let r=new Re(await sr(t,e,n));if(await r.connect(),t.bootstrap){let{bootstrap:i,...s}=t;await rt(e.dir,s)}return r}async function sr(t,e,n){let r=await tn(t.secret),i=ln(r);return{vault:new tt(e.dir,{configDir:e.configDir,alsoIgnore:e.ignore}),store:new ze(nt(e.dir)),keys:r,url:t.url,token:t.bootstrap??i,claim:i,vaultId:t.vaultId,device:t.device,timeoutMs:e.timeout,coalesceWrites:e.watch,...e.watch&&n?{onProgress:s=>{s!==void 0&&n.err(` ... ${s}`)}}:{},...e.verbose&&n?{log:(s,...o)=>n.err(` ${s} ${o.map(ji).join(" ")}`.trimEnd())}:{}}}function or(t,e,n,r){if(e.json){n.out(JSON.stringify({ok:!0,...t,serverCursor:r}));return}let i=[],s=(o,a)=>{o>0&&i.push(`${String(o).padStart(5)} ${a}`)};if(s(t.uploaded,"uploaded"),s(t.downloaded,"downloaded"),s(t.merged,"merged"),s(t.conflicted,"kept both versions"),s(t.deletedLocally,"deleted here"),s(t.deletedRemotely,"deleted on the server"),s(t.restored,"brought back, having been edited elsewhere"),s(t.foldersCreated,"folders created"),s(t.waiting,"waiting for a write to settle"),s(t.retrying,"failed, will try again"),s(t.skipped,"cannot sync and will not be retried"),s(t.blocked,"waiting on a name that is a file here and a folder elsewhere"),i.length===0)n.out("Nothing to do. Everything here matches the server.");else for(let o of i)n.out(o);t.chunksSent>0&&n.out(`${String(t.chunksSent).padStart(5)} chunks sent, ${Nt(t.bytesSent)}`),t.conflicted>0&&n.err('Look for files with "Conflicted copy" in the name. Both versions are kept.')}function Hi(t){let e={rest:[],dir:process.cwd(),device:zi().split(".")[0]||"device",vaultId:"default",json:!1,watch:!1,limit:20,verbose:!1,help:!1,timeout:3e4,configDir:It,ignore:[]},n=new Set(["--dir","--device","--vault-id","--server","--token","--timeout","--uid","--to","--limit","--config-dir","--ignore"]);for(let r=0;r<t.length;r++){let i=t[r],s;if(n.has(i)&&(s=t[++r],s===void 0||s.startsWith("--")))throw new Error(`${i} needs a value`);switch(i){case"--dir":e.dir=Di(s);break;case"--device":e.device=s;break;case"--vault-id":e.vaultId=s;break;case"--server":e.server=s;break;case"--token":e.token=s;break;case"--timeout":{let o=Number(s);if(!Number.isFinite(o)||o<=0)throw new Error(`--timeout wants a number of milliseconds, not ${s}`);e.timeout=o;break}case"--uid":{let o=Number(s);if(!Number.isInteger(o)||o<=0)throw new Error(`--uid wants a version number, not ${s}`);e.uid=o;break}case"--to":e.to=s;break;case"--config-dir":e.configDir=zt(s);break;case"--ignore":e.ignore.push(s);break;case"--limit":{let o=Number(s);if(!Number.isInteger(o)||o<=0)throw new Error(`--limit wants a count, not ${s}`);e.limit=o;break}case"--json":e.json=!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(i.startsWith("-"))throw new Error(`no such option: ${i}`);e.command===void 0?e.command=i:e.rest.push(i)}}return e}async function Se(t){let e=await De(t);if(!e)throw new Error(`${t} is not paired. Run basalt init or basalt pair first.`);return e}function Ot(t){if(!Number.isFinite(t)||t<=0)return"unknown ";let e=new Date(t),n=r=>String(r).padStart(2,"0");return`${e.getFullYear()}-${n(e.getMonth()+1)}-${n(e.getDate())} ${n(e.getHours())}:${n(e.getMinutes())}`}function rr(t){return`${Math.max(1,Math.round(t/1e3))}s`}function Nt(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KiB`:`${(t/(1024*1024)).toFixed(1)} MiB`}function ji(t){return typeof t=="string"?t:JSON.stringify(t)}var Gi=await ir(process.argv.slice(2),{out:t=>process.stdout.write(t+`
34
+ `),err:t=>process.stderr.write(t+`
35
+ `)});process.exit(Gi);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "basalt-sync",
3
- "version": "0.1.7",
3
+ "version": "0.2.0",
4
4
  "description": "Headless Obsidian vault sync for a Basalt server.",
5
5
  "keywords": [
6
6
  "obsidian",
@@ -29,14 +29,16 @@
29
29
  ],
30
30
  "type": "module",
31
31
  "scripts": {
32
+ "bench": "bun run bench.ts",
33
+ "bench:sync": "bun run bench-sync.ts",
32
34
  "build": "node esbuild.config.mjs production",
35
+ "build:cli": "node esbuild.config.mjs production",
33
36
  "dev": "node esbuild.config.mjs",
37
+ "format": "prettier --config ../.prettierrc --write \"src/**/*.ts\" \"*.ts\" \"*.mjs\"",
38
+ "format:check": "prettier --config ../.prettierrc --check \"src/**/*.ts\" \"*.ts\" \"*.mjs\"",
34
39
  "test": "vitest run",
35
40
  "test:watch": "vitest",
36
- "typecheck": "tsc --noEmit",
37
- "bench": "bun run bench.ts",
38
- "build:cli": "node esbuild.config.mjs production",
39
- "bench:sync": "bun run bench-sync.ts"
41
+ "typecheck": "tsc --noEmit"
40
42
  },
41
43
  "devDependencies": {
42
44
  "@types/diff-match-patch": "^1.0.36",
@@ -46,7 +48,8 @@
46
48
  "fflate": "^0.8.3",
47
49
  "obsidian": "^1.13.1",
48
50
  "typescript": "^5.9.3",
49
- "vitest": "^4.1.8"
51
+ "vitest": "^4.1.8",
52
+ "prettier": "^3.6.2"
50
53
  },
51
54
  "bin": {
52
55
  "basalt": "./dist/basalt.mjs"