@candypoets/nipworker 0.0.55 → 0.0.57

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/dist/utils.js CHANGED
@@ -1 +1 @@
1
- import{M as f,u as b,E as m,C as R,B as E,V as M,P as t,a as r,b as i,c as l,d as _}from"./message-type.js";function K(n){return n.type()!==f.ConnectionStatus?null:b(n.contentType(),n.content.bind(n))}const k=K;function g(n){return n.type()!==f.Eoce?null:n.content(new m)??null}const B=g;function T(n){return n.type()!==f.CountResponse?null:n.content(new R)??null}const I=T;function v(n){return n.type()!==f.BufferFull?null:n.content(new E)??null}const H=v;function C(n){return n.type()!==f.ValidProofs?null:n.content(new M)??null}const L=C;function P(n){return n.type()!==f.ParsedNostrEvent?null:b(n.contentType(),n.content.bind(n))}const V=P;function d(n,e){if(!n)return null;const a=P(n);return!a||a.parsedType()!==e?null:r(e,a.parsed.bind(a))}function x(n){return d(n,t.Kind0Parsed)}function A(n){return!n||n.parsedType()!==t.Kind0Parsed?null:r(t.Kind0Parsed,n.parsed.bind(n))}function N(n){return d(n,t.Kind1Parsed)}function $(n){return n.parsedType()!==t.Kind1Parsed?null:r(t.Kind1Parsed,n.parsed.bind(n))}function F(n){return d(n,t.Kind3Parsed)}function G(n){return n.parsedType()!==t.Kind3Parsed?null:r(t.Kind3Parsed,n.parsed.bind(n))}function O(n){return d(n,t.Kind4Parsed)}function U(n){return n.parsedType()!==t.Kind4Parsed?null:r(t.Kind4Parsed,n.parsed.bind(n))}function q(n){return d(n,t.Kind6Parsed)}function W(n){return n.parsedType()!==t.Kind6Parsed?null:r(t.Kind6Parsed,n.parsed.bind(n))}function j(n){return d(n,t.Kind7Parsed)}function z(n){return n.parsedType()!==t.Kind7Parsed?null:r(t.Kind7Parsed,n.parsed.bind(n))}function J(n){return d(n,t.Kind17Parsed)}function Q(n){return n.parsedType()!==t.Kind17Parsed?null:r(t.Kind17Parsed,n.parsed.bind(n))}function X(n){return d(n,t.Kind10002Parsed)}function Y(n){return n.parsedType()!==t.Kind10002Parsed?null:r(t.Kind10002Parsed,n.parsed.bind(n))}function Z(n){return d(n,t.Kind10019Parsed)}function nn(n){return n.parsedType()!==t.Kind10019Parsed?null:r(t.Kind10019Parsed,n.parsed.bind(n))}function tn(n){return d(n,t.Kind17375Parsed)}function en(n){return n.parsedType()!==t.Kind17375Parsed?null:r(t.Kind17375Parsed,n.parsed.bind(n))}function an(n){return d(n,t.Kind39089Parsed)}function sn(n){return n.parsedType()!==t.Kind39089Parsed?null:r(t.Kind39089Parsed,n.parsed.bind(n))}function rn(n){return d(n,t.Kind7374Parsed)}function dn(n){return n.parsedType()!==t.Kind7374Parsed?null:r(t.Kind7374Parsed,n.parsed.bind(n))}function un(n){return d(n,t.Kind7375Parsed)}function on(n){return n.parsedType()!==t.Kind7375Parsed?null:r(t.Kind7375Parsed,n.parsed.bind(n))}function ln(n){return d(n,t.Kind7376Parsed)}function cn(n){return n.parsedType()!==t.Kind7376Parsed?null:r(t.Kind7376Parsed,n.parsed.bind(n))}function fn(n){return d(n,t.Kind9321Parsed)}function pn(n){return n.parsedType()!==t.Kind9321Parsed?null:r(t.Kind9321Parsed,n.parsed.bind(n))}function Kn(n){return d(n,t.Kind9735Parsed)}function Pn(n){return n.parsedType()!==t.Kind9735Parsed?null:r(t.Kind9735Parsed,n.parsed.bind(n))}function hn(n){return n.dataType()!==i.CodeData?null:l(i.CodeData,n.data.bind(n))}function yn(n){return n.dataType()!==i.HashtagData?null:l(i.HashtagData,n.data.bind(n))}function bn(n){return n.dataType()!==i.CashuData?null:l(i.CashuData,n.data.bind(n))}function gn(n){return n.dataType()!==i.ImageData?null:l(i.ImageData,n.data.bind(n))}function Tn(n){return n.dataType()!==i.VideoData?null:l(i.VideoData,n.data.bind(n))}function vn(n){return n.dataType()!==i.MediaGroupData?null:l(i.MediaGroupData,n.data.bind(n))}function Cn(n){return n.dataType()!==i.NostrData?null:l(i.NostrData,n.data.bind(n))}function wn(n){return n.dataType()!==i.LinkPreviewData?null:l(i.LinkPreviewData,n.data.bind(n))}class Dn{constructor(){this.knownRelays=new Map,this.incomingCount=0,this.resolvedCount=0}handleMessage(e){const a=K(e);if(!a)return;const s=a.relayUrl()?.fnv1aHash();s&&!this.knownRelays.has(s)&&(this.incomingCount++,this.knownRelays.set(s,a)),this.isResolved(a)&&this.resolvedCount++}isResolved(e){return e.status()?.toString()==="EOSE"}get totalIncoming(){return this.incomingCount}get totalResolved(){return this.resolvedCount}get resolutionRate(){return this.incomingCount===0?0:this.resolvedCount/this.incomingCount}}_.prototype.__stringByteString=function(n){n+=this.readInt32(n);const e=this.readInt32(n),a=n+4,s=this.bytes().subarray(a,a+e);return new S(s)};const w=new TextDecoder("utf-8"),D=new WeakMap,Sn=(()=>{const n=new Array(256);for(let e=0;e<256;e++)n[e]=e.toString(16).padStart(2,"0");return n})();class S{constructor(e){this.view=e}bytes(){return this.view}fnv1aHash(){let e=2166136261;const a=this.view;for(let s=0;s<a.length;s++)e^=a[s],e=Math.imul(e,16777619);return e>>>0}toHex(){const e=this.view;let a="";for(let s=0;s<e.length;s++)a+=Sn[e[s]];return a}utf8String(){if(this._utf8!==void 0)return this._utf8;const e=this.view;let a=0;for(let o=0;o<e.length;o++)a|=e[o];if(!(a&128)){let o="";for(let c=0;c<e.length;c+=32768)o+=String.fromCharCode.apply(null,e.subarray(c,c+32768));return this._utf8=o}const s=e.buffer;if(!(s instanceof SharedArrayBuffer)){let o=D.get(s);o||(o=new Map,D.set(s,o));const c=`${e.byteOffset}:${e.byteLength}`,h=o.get(c);if(h!==void 0)return this._utf8=h;const y=w.decode(e);return o.set(c,y),this._utf8=y}const u=new Uint8Array(e),p=w.decode(u);return this._utf8=p}toString(){return this.utf8String()}equals(e){const a=this.view,s=e.view;if(a.length!==s.length)return!1;for(let u=0;u<a.length;u++)if(a[u]!==s[u])return!1;return!0}}function mn(n,e){const a=n[`${String(e)}Length`]();return{[Symbol.iterator](){let s=0;return{next(){for(;s<a;){const u=n[e](s);if(s++,u!=null)return{value:u,done:!1}}return{value:void 0,done:!0}}}}}}function Rn(n,e){if(!n)return[];const a=n[`${String(e)}Length`].bind(n)(),s=[];for(let u=0;u<a;u++){const p=n[e](u);p!=null&&s.push(p)}return s}export{S as ByteString,Dn as ConnectionTracker,H as asBufferFull,bn as asCashuData,hn as asCodeData,k as asConnectionStatus,I as asCountResponse,B as asEoce,yn as asHashtagData,gn as asImageData,A as asKind0,$ as asKind1,Y as asKind10002,nn as asKind10019,Q as asKind17,en as asKind17375,G as asKind3,sn as asKind39089,U as asKind4,W as asKind6,z as asKind7,dn as asKind7374,on as asKind7375,cn as asKind7376,pn as asKind9321,Pn as asKind9735,wn as asLinkPreview,vn as asMediaGroupData,Cn as asNostrData,V as asParsedEvent,L as asValidProofs,Tn as asVideoData,Rn as fbArray,mn as fbIterable,v as isBufferFull,K as isConnectionStatus,T as isCountResponse,g as isEoce,x as isKind0,N as isKind1,X as isKind10002,Z as isKind10019,J as isKind17,tn as isKind17375,F as isKind3,an as isKind39089,O as isKind4,q as isKind6,j as isKind7,rn as isKind7374,un as isKind7375,ln as isKind7376,fn as isKind9321,Kn as isKind9735,P as isParsedEvent,C as isValidProofs};
1
+ import{M as f,u as b,E as m,C as R,B,V as E,P as t,a as r,b as i,c as l}from"./message-type.js";import{ByteBuffer as M}from"flatbuffers";function K(n){return n.type()!==f.ConnectionStatus?null:b(n.contentType(),n.content.bind(n))}const _=K;function g(n){return n.type()!==f.Eoce?null:n.content(new m)??null}const k=g;function T(n){return n.type()!==f.CountResponse?null:n.content(new R)??null}const H=T;function v(n){return n.type()!==f.BufferFull?null:n.content(new B)??null}const I=v;function C(n){return n.type()!==f.ValidProofs?null:n.content(new E)??null}const L=C;function P(n){return n.type()!==f.ParsedNostrEvent?null:b(n.contentType(),n.content.bind(n))}const V=P;function d(n,e){if(!n)return null;const a=P(n);return!a||a.parsedType()!==e?null:r(e,a.parsed.bind(a))}function x(n){return d(n,t.Kind0Parsed)}function A(n){return!n||n.parsedType()!==t.Kind0Parsed?null:r(t.Kind0Parsed,n.parsed.bind(n))}function N(n){return d(n,t.Kind1Parsed)}function $(n){return n.parsedType()!==t.Kind1Parsed?null:r(t.Kind1Parsed,n.parsed.bind(n))}function G(n){return d(n,t.Kind3Parsed)}function F(n){return n.parsedType()!==t.Kind3Parsed?null:r(t.Kind3Parsed,n.parsed.bind(n))}function O(n){return d(n,t.Kind4Parsed)}function U(n){return n.parsedType()!==t.Kind4Parsed?null:r(t.Kind4Parsed,n.parsed.bind(n))}function q(n){return d(n,t.Kind6Parsed)}function W(n){return n.parsedType()!==t.Kind6Parsed?null:r(t.Kind6Parsed,n.parsed.bind(n))}function j(n){return d(n,t.Kind7Parsed)}function z(n){return n.parsedType()!==t.Kind7Parsed?null:r(t.Kind7Parsed,n.parsed.bind(n))}function J(n){return d(n,t.Kind17Parsed)}function Q(n){return n.parsedType()!==t.Kind17Parsed?null:r(t.Kind17Parsed,n.parsed.bind(n))}function X(n){return d(n,t.Kind10002Parsed)}function Y(n){return n.parsedType()!==t.Kind10002Parsed?null:r(t.Kind10002Parsed,n.parsed.bind(n))}function Z(n){return d(n,t.Kind10019Parsed)}function nn(n){return n.parsedType()!==t.Kind10019Parsed?null:r(t.Kind10019Parsed,n.parsed.bind(n))}function tn(n){return d(n,t.Kind17375Parsed)}function en(n){return n.parsedType()!==t.Kind17375Parsed?null:r(t.Kind17375Parsed,n.parsed.bind(n))}function an(n){return d(n,t.Kind39089Parsed)}function sn(n){return n.parsedType()!==t.Kind39089Parsed?null:r(t.Kind39089Parsed,n.parsed.bind(n))}function rn(n){return d(n,t.Kind7374Parsed)}function dn(n){return n.parsedType()!==t.Kind7374Parsed?null:r(t.Kind7374Parsed,n.parsed.bind(n))}function un(n){return d(n,t.Kind7375Parsed)}function on(n){return n.parsedType()!==t.Kind7375Parsed?null:r(t.Kind7375Parsed,n.parsed.bind(n))}function ln(n){return d(n,t.Kind7376Parsed)}function cn(n){return n.parsedType()!==t.Kind7376Parsed?null:r(t.Kind7376Parsed,n.parsed.bind(n))}function fn(n){return d(n,t.Kind9321Parsed)}function pn(n){return n.parsedType()!==t.Kind9321Parsed?null:r(t.Kind9321Parsed,n.parsed.bind(n))}function Kn(n){return d(n,t.Kind9735Parsed)}function Pn(n){return n.parsedType()!==t.Kind9735Parsed?null:r(t.Kind9735Parsed,n.parsed.bind(n))}function hn(n){return n.dataType()!==i.CodeData?null:l(i.CodeData,n.data.bind(n))}function yn(n){return n.dataType()!==i.HashtagData?null:l(i.HashtagData,n.data.bind(n))}function bn(n){return n.dataType()!==i.CashuData?null:l(i.CashuData,n.data.bind(n))}function gn(n){return n.dataType()!==i.ImageData?null:l(i.ImageData,n.data.bind(n))}function Tn(n){return n.dataType()!==i.VideoData?null:l(i.VideoData,n.data.bind(n))}function vn(n){return n.dataType()!==i.MediaGroupData?null:l(i.MediaGroupData,n.data.bind(n))}function Cn(n){return n.dataType()!==i.NostrData?null:l(i.NostrData,n.data.bind(n))}function wn(n){return n.dataType()!==i.LinkPreviewData?null:l(i.LinkPreviewData,n.data.bind(n))}class Dn{constructor(){this.knownRelays=new Map,this.incomingCount=0,this.resolvedCount=0}handleMessage(e){const a=K(e);if(!a)return;const s=a.relayUrl()?.fnv1aHash();s&&!this.knownRelays.has(s)&&(this.incomingCount++,this.knownRelays.set(s,a)),this.isResolved(a)&&this.resolvedCount++}isResolved(e){return e.status()?.toString()==="EOSE"}get totalIncoming(){return this.incomingCount}get totalResolved(){return this.resolvedCount}get resolutionRate(){return this.incomingCount===0?0:this.resolvedCount/this.incomingCount}}M.prototype.__stringByteString=function(n){n+=this.readInt32(n);const e=this.readInt32(n),a=n+4,s=this.bytes().subarray(a,a+e);return new S(s)};const w=new TextDecoder("utf-8"),D=new WeakMap,Sn=(()=>{const n=new Array(256);for(let e=0;e<256;e++)n[e]=e.toString(16).padStart(2,"0");return n})();class S{constructor(e){this.view=e}bytes(){return this.view}fnv1aHash(){let e=2166136261;const a=this.view;for(let s=0;s<a.length;s++)e^=a[s],e=Math.imul(e,16777619);return e>>>0}toHex(){const e=this.view;let a="";for(let s=0;s<e.length;s++)a+=Sn[e[s]];return a}utf8String(){if(this._utf8!==void 0)return this._utf8;const e=this.view;let a=0;for(let o=0;o<e.length;o++)a|=e[o];if(!(a&128)){let o="";for(let c=0;c<e.length;c+=32768)o+=String.fromCharCode.apply(null,e.subarray(c,c+32768));return this._utf8=o}const s=e.buffer;if(!(s instanceof SharedArrayBuffer)){let o=D.get(s);o||(o=new Map,D.set(s,o));const c=`${e.byteOffset}:${e.byteLength}`,h=o.get(c);if(h!==void 0)return this._utf8=h;const y=w.decode(e);return o.set(c,y),this._utf8=y}const u=new Uint8Array(e),p=w.decode(u);return this._utf8=p}toString(){return this.utf8String()}equals(e){const a=this.view,s=e.view;if(a.length!==s.length)return!1;for(let u=0;u<a.length;u++)if(a[u]!==s[u])return!1;return!0}}function mn(n,e){const a=n[`${String(e)}Length`]();return{[Symbol.iterator](){let s=0;return{next(){for(;s<a;){const u=n[e](s);if(s++,u!=null)return{value:u,done:!1}}return{value:void 0,done:!0}}}}}}function Rn(n,e){if(!n)return[];const a=n[`${String(e)}Length`].bind(n)(),s=[];for(let u=0;u<a;u++){const p=n[e](u);p!=null&&s.push(p)}return s}export{S as ByteString,Dn as ConnectionTracker,I as asBufferFull,bn as asCashuData,hn as asCodeData,_ as asConnectionStatus,H as asCountResponse,k as asEoce,yn as asHashtagData,gn as asImageData,A as asKind0,$ as asKind1,Y as asKind10002,nn as asKind10019,Q as asKind17,en as asKind17375,F as asKind3,sn as asKind39089,U as asKind4,W as asKind6,z as asKind7,dn as asKind7374,on as asKind7375,cn as asKind7376,pn as asKind9321,Pn as asKind9735,wn as asLinkPreview,vn as asMediaGroupData,Cn as asNostrData,V as asParsedEvent,L as asValidProofs,Tn as asVideoData,Rn as fbArray,mn as fbIterable,v as isBufferFull,K as isConnectionStatus,T as isCountResponse,g as isEoce,x as isKind0,N as isKind1,X as isKind10002,Z as isKind10019,J as isKind17,tn as isKind17375,G as isKind3,an as isKind39089,O as isKind4,q as isKind6,j as isKind7,rn as isKind7374,un as isKind7375,ln as isKind7376,fn as isKind9321,Kn as isKind9735,P as isParsedEvent,C as isValidProofs};
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../src/lib/NarrowTypes.ts","../src/lib/ConnectionTracker.ts","../src/lib/ByteString.ts","../src/utils.ts"],"sourcesContent":["import {\n WorkerMessage,\n MessageType,\n ConnectionStatus,\n Eoce,\n CountResponse,\n BufferFull,\n ValidProofs,\n ParsedEvent,\n Kind0Parsed,\n Kind1Parsed,\n Kind3Parsed,\n Kind4Parsed,\n Kind6Parsed,\n Kind7Parsed,\n Kind17Parsed,\n Kind10002Parsed,\n Kind10019Parsed,\n Kind17375Parsed,\n Kind39089Parsed,\n Kind7374Parsed,\n Kind7375Parsed,\n Kind7376Parsed,\n Kind9321Parsed,\n Kind9735Parsed,\n ContentBlock,\n LinkPreviewData,\n ContentData,\n CashuData,\n HashtagData,\n CodeData,\n MediaGroupData,\n NostrData,\n VideoData,\n} from \"src/generated/nostr/fb\";\nimport { unionToContentData } from \"src/generated/nostr/fb/content-data\";\nimport { unionToMessage } from \"src/generated/nostr/fb/message\";\nimport { unionToParsedData, ParsedData } from \"src/generated/nostr/fb/parsed-data\";\n\n// ---- Top-level Message helpers ----\nexport function isConnectionStatus(msg: WorkerMessage): ConnectionStatus | null {\n if (msg.type() !== MessageType.ConnectionStatus) return null;\n return unionToMessage(msg.contentType(), msg.content.bind(msg)) as ConnectionStatus;\n}\n\nexport const asConnectionStatus = isConnectionStatus;\n\nexport function isEoce(msg: WorkerMessage): Eoce | null {\n if (msg.type() !== MessageType.Eoce) return null;\n return msg.content(new Eoce()) ?? null;\n}\n\nexport const asEoce = isEoce;\n\nexport function isCountResponse(msg: WorkerMessage): CountResponse | null {\n if (msg.type() !== MessageType.CountResponse) return null;\n return msg.content(new CountResponse()) ?? null;\n}\n\nexport const asCountResponse = isCountResponse;\n\nexport function isBufferFull(msg: WorkerMessage): BufferFull | null {\n if (msg.type() !== MessageType.BufferFull) return null;\n return msg.content(new BufferFull()) ?? null;\n}\n\nexport const asBufferFull = isBufferFull;\n\nexport function isValidProofs(msg: WorkerMessage): ValidProofs | null {\n if (msg.type() !== MessageType.ValidProofs) return null;\n return msg.content(new ValidProofs()) ?? null;\n}\n\nexport const asValidProofs = isValidProofs;\n\n// ---- Generic ParsedEvent --------\nexport function isParsedEvent(msg: WorkerMessage): ParsedEvent | null {\n if (msg.type() !== MessageType.ParsedNostrEvent) return null;\n return unionToMessage(msg.contentType(), msg.content.bind(msg)) as ParsedEvent;\n}\n\nexport const asParsedEvent = isParsedEvent;\n\n// ---- ParsedData Kind helpers ----\nfunction parsedKind<T>(msg: WorkerMessage, kind: ParsedData): T | null {\n if (!msg) return null;\n const ev = isParsedEvent(msg);\n if (!ev) return null;\n if (ev.parsedType() !== kind) return null;\n return unionToParsedData(kind, ev.parsed.bind(ev)) as T;\n}\n\nexport function isKind0(msg: WorkerMessage): Kind0Parsed | null {\n return parsedKind<Kind0Parsed>(msg, ParsedData.Kind0Parsed);\n}\nexport function asKind0(ev: ParsedEvent): Kind0Parsed | null {\n if (!ev) return null;\n if (ev.parsedType() !== ParsedData.Kind0Parsed) return null;\n return unionToParsedData(ParsedData.Kind0Parsed, ev.parsed.bind(ev)) as Kind0Parsed;\n}\nexport function isKind1(msg: WorkerMessage): Kind1Parsed | null {\n return parsedKind<Kind1Parsed>(msg, ParsedData.Kind1Parsed);\n}\nexport function asKind1(ev: ParsedEvent): Kind1Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind1Parsed) return null;\n return unionToParsedData(ParsedData.Kind1Parsed, ev.parsed.bind(ev)) as Kind1Parsed;\n}\nexport function isKind3(msg: WorkerMessage): Kind3Parsed | null {\n return parsedKind<Kind3Parsed>(msg, ParsedData.Kind3Parsed);\n}\nexport function asKind3(ev: ParsedEvent): Kind3Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind3Parsed) return null;\n return unionToParsedData(ParsedData.Kind3Parsed, ev.parsed.bind(ev)) as Kind3Parsed;\n}\nexport function isKind4(msg: WorkerMessage): Kind4Parsed | null {\n return parsedKind<Kind4Parsed>(msg, ParsedData.Kind4Parsed);\n}\nexport function asKind4(ev: ParsedEvent): Kind4Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind4Parsed) return null;\n return unionToParsedData(ParsedData.Kind4Parsed, ev.parsed.bind(ev)) as Kind4Parsed;\n}\nexport function isKind6(msg: WorkerMessage): Kind6Parsed | null {\n return parsedKind<Kind6Parsed>(msg, ParsedData.Kind6Parsed);\n}\nexport function asKind6(ev: ParsedEvent): Kind6Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind6Parsed) return null;\n return unionToParsedData(ParsedData.Kind6Parsed, ev.parsed.bind(ev)) as Kind6Parsed;\n}\nexport function isKind7(msg: WorkerMessage): Kind7Parsed | null {\n return parsedKind<Kind7Parsed>(msg, ParsedData.Kind7Parsed);\n}\nexport function asKind7(ev: ParsedEvent): Kind7Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind7Parsed) return null;\n return unionToParsedData(ParsedData.Kind7Parsed, ev.parsed.bind(ev)) as Kind7Parsed;\n}\nexport function isKind17(msg: WorkerMessage): Kind17Parsed | null {\n return parsedKind<Kind17Parsed>(msg, ParsedData.Kind17Parsed);\n}\nexport function asKind17(ev: ParsedEvent): Kind17Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind17Parsed) return null;\n return unionToParsedData(ParsedData.Kind17Parsed, ev.parsed.bind(ev)) as Kind17Parsed;\n}\nexport function isKind10002(msg: WorkerMessage): Kind10002Parsed | null {\n return parsedKind<Kind10002Parsed>(msg, ParsedData.Kind10002Parsed);\n}\nexport function asKind10002(ev: ParsedEvent): Kind10002Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind10002Parsed) return null;\n return unionToParsedData(ParsedData.Kind10002Parsed, ev.parsed.bind(ev)) as Kind10002Parsed;\n}\n\nexport function isKind10019(msg: WorkerMessage): Kind10019Parsed | null {\n return parsedKind<Kind10019Parsed>(msg, ParsedData.Kind10019Parsed);\n}\nexport function asKind10019(ev: ParsedEvent): Kind10019Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind10019Parsed) return null;\n return unionToParsedData(ParsedData.Kind10019Parsed, ev.parsed.bind(ev)) as Kind10019Parsed;\n}\n\nexport function isKind17375(msg: WorkerMessage): Kind17375Parsed | null {\n return parsedKind<Kind17375Parsed>(msg, ParsedData.Kind17375Parsed);\n}\nexport function asKind17375(ev: ParsedEvent): Kind17375Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind17375Parsed) return null;\n return unionToParsedData(ParsedData.Kind17375Parsed, ev.parsed.bind(ev)) as Kind17375Parsed;\n}\nexport function isKind39089(msg: WorkerMessage): Kind39089Parsed | null {\n return parsedKind<Kind39089Parsed>(msg, ParsedData.Kind39089Parsed);\n}\nexport function asKind39089(ev: ParsedEvent): Kind39089Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind39089Parsed) return null;\n return unionToParsedData(ParsedData.Kind39089Parsed, ev.parsed.bind(ev)) as Kind39089Parsed;\n}\n\nexport function isKind7374(msg: WorkerMessage): Kind7374Parsed | null {\n return parsedKind<Kind7374Parsed>(msg, ParsedData.Kind7374Parsed);\n}\nexport function asKind7374(ev: ParsedEvent): Kind7374Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind7374Parsed) return null;\n return unionToParsedData(ParsedData.Kind7374Parsed, ev.parsed.bind(ev)) as Kind7374Parsed;\n}\n\nexport function isKind7375(msg: WorkerMessage): Kind7375Parsed | null {\n return parsedKind<Kind7375Parsed>(msg, ParsedData.Kind7375Parsed);\n}\nexport function asKind7375(ev: ParsedEvent): Kind7375Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind7375Parsed) return null;\n return unionToParsedData(ParsedData.Kind7375Parsed, ev.parsed.bind(ev)) as Kind7375Parsed;\n}\n\nexport function isKind7376(msg: WorkerMessage): Kind7376Parsed | null {\n return parsedKind<Kind7376Parsed>(msg, ParsedData.Kind7376Parsed);\n}\nexport function asKind7376(ev: ParsedEvent): Kind7376Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind7376Parsed) return null;\n return unionToParsedData(ParsedData.Kind7376Parsed, ev.parsed.bind(ev)) as Kind7376Parsed;\n}\n\nexport function isKind9321(msg: WorkerMessage): Kind9321Parsed | null {\n return parsedKind<Kind9321Parsed>(msg, ParsedData.Kind9321Parsed);\n}\nexport function asKind9321(ev: ParsedEvent): Kind9321Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind9321Parsed) return null;\n return unionToParsedData(ParsedData.Kind9321Parsed, ev.parsed.bind(ev)) as Kind9321Parsed;\n}\n\nexport function isKind9735(msg: WorkerMessage): Kind9735Parsed | null {\n return parsedKind<Kind9735Parsed>(msg, ParsedData.Kind9735Parsed);\n}\nexport function asKind9735(ev: ParsedEvent): Kind9735Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind9735Parsed) return null;\n return unionToParsedData(ParsedData.Kind9735Parsed, ev.parsed.bind(ev)) as Kind9735Parsed;\n}\n\nexport function asCodeData(block: ContentBlock): CodeData | null {\n if (block.dataType() !== ContentData.CodeData) return null;\n return unionToContentData(ContentData.CodeData, block.data.bind(block)) as CodeData;\n}\n\nexport function asHashtagData(block: ContentBlock): HashtagData | null {\n if (block.dataType() !== ContentData.HashtagData) return null;\n return unionToContentData(ContentData.HashtagData, block.data.bind(block)) as HashtagData;\n}\n\nexport function asCashuData(block: ContentBlock): CashuData | null {\n if (block.dataType() !== ContentData.CashuData) return null;\n return unionToContentData(ContentData.CashuData, block.data.bind(block)) as CashuData;\n}\n\nexport function asImageData(block: ContentBlock): ImageData | null {\n if (block.dataType() !== ContentData.ImageData) return null;\n return unionToContentData(ContentData.ImageData, block.data.bind(block)) as unknown as ImageData;\n}\n\nexport function asVideoData(block: ContentBlock): VideoData | null {\n if (block.dataType() !== ContentData.VideoData) return null;\n return unionToContentData(ContentData.VideoData, block.data.bind(block)) as VideoData;\n}\n\nexport function asMediaGroupData(block: ContentBlock): MediaGroupData | null {\n if (block.dataType() !== ContentData.MediaGroupData) return null;\n return unionToContentData(ContentData.MediaGroupData, block.data.bind(block)) as MediaGroupData;\n}\n\nexport function asNostrData(block: ContentBlock): NostrData | null {\n if (block.dataType() !== ContentData.NostrData) return null;\n return unionToContentData(ContentData.NostrData, block.data.bind(block)) as NostrData;\n}\n\nexport function asLinkPreview(block: ContentBlock): LinkPreviewData | null {\n if (block.dataType() !== ContentData.LinkPreviewData) return null;\n return unionToContentData(ContentData.LinkPreviewData, block.data.bind(block)) as LinkPreviewData;\n}\n","import { ConnectionStatus, WorkerMessage } from \"src/generated/nostr/fb\";\nimport { isConnectionStatus } from \"./NarrowTypes\";\n\nexport class ConnectionTracker {\n private knownRelays: Map<number, ConnectionStatus> = new Map();\n private incomingCount = 0;\n private resolvedCount = 0;\n\n /**\n * Feed a new message into the tracker\n */\n handleMessage(msg: WorkerMessage) {\n const status = isConnectionStatus(msg);\n if (!status) return; // not a connection status, ignore\n\n const id = status.relayUrl()?.fnv1aHash()\n if(id && !this.knownRelays.has(id)) {\n this.incomingCount++;\n this.knownRelays.set(id, status);\n }\n if (this.isResolved(status)) {\n this.resolvedCount++;\n }\n }\n\n /**\n * Define what counts as a \"resolved\" connection.\n * Adjust based on your real ConnectionStatus enum/shape.\n */\n private isResolved(status: ConnectionStatus): boolean {\n return status.status()?.toString() === \"EOSE\";\n }\n\n /** Total connection attempts processed */\n get totalIncoming(): number {\n return this.incomingCount;\n }\n\n /** How many actually resolved */\n get totalResolved(): number {\n return this.resolvedCount;\n }\n\n /** Quick ratio (0...1) of resolved vs incoming */\n get resolutionRate(): number {\n return this.incomingCount === 0 ? 0 : this.resolvedCount / this.incomingCount;\n }\n}\n","import { ByteBuffer } from 'flatbuffers';\n\n(ByteBuffer.prototype as any).__stringByteString = function (offset: number): ByteString {\n\t// Follow indirect: add the relative offset stored at this location\n\toffset += this.readInt32(offset);\n\n\t// Now at the start of the string object → first 4 bytes = length\n\tconst length = this.readInt32(offset);\n\tconst start = offset + 4;\n\n\t// Slice out exactly [start, start+length]\n\tconst slice = this.bytes().subarray(start, start + length);\n\n\treturn new ByteString(slice);\n};\n\n// Shared decoder for all instances (cheap, stateless for non-streaming use)\nconst UTF8_DECODER = new TextDecoder('utf-8');\n\n// Cross-instance cache: per underlying buffer → (offset:length) → decoded string\n// WeakMap ensures entries are eligible for GC once the ArrayBuffer becomes unreachable.\nconst BUFFER_STRING_CACHE = new WeakMap<ArrayBufferLike, Map<string, string>>();\n\n// Hex lookup table to speed up toHex()\nconst HEX_TABLE: string[] = (() => {\n\tconst t = new Array(256);\n\tfor (let i = 0; i < 256; i++) t[i] = i.toString(16).padStart(2, '0');\n\treturn t;\n})();\n\n// lib/ByteString.ts\nexport class ByteString {\n\tprivate readonly view: Uint8Array;\n\tprivate _utf8?: string;\n\n\tconstructor(view: Uint8Array) {\n\t\tthis.view = view;\n\t}\n\n\t/**\n\t * Access underlying bytes\n\t */\n\tbytes(): Uint8Array {\n\t\treturn this.view;\n\t}\n\n\t/**\n\t * Fast numeric discriminant (FNV-1a hash).\n\t * Not cryptographically secure, but great for Map/Set keys.\n\t */\n\tfnv1aHash(): number {\n\t\tlet h = 2166136261 >>> 0;\n\t\tconst v = this.view;\n\t\tfor (let i = 0; i < v.length; i++) {\n\t\t\th ^= v[i];\n\t\t\th = Math.imul(h, 16777619);\n\t\t}\n\t\treturn h >>> 0;\n\t}\n\n\t/**\n\t * Return a stable hex string representation.\n\t */\n\ttoHex(): string {\n\t\tconst v = this.view;\n\t\tlet out = '';\n\t\tfor (let i = 0; i < v.length; i++) out += HEX_TABLE[v[i]];\n\t\treturn out;\n\t}\n\n\t/**\n\t * Decode as UTF-8 string.\n\t * If backed by SharedArrayBuffer, makes a safe copy.\n\t * Optimizations:\n\t * - Reuses a shared TextDecoder\n\t * - ASCII fast path\n\t * - Cross-instance cache (non-SAB only) keyed by buffer+offset+length\n\t */\n\tutf8String(): string {\n\t\tif (this._utf8 !== undefined) return this._utf8;\n\n\t\tconst v = this.view;\n\n\t\t// 1) ASCII fast path (quick OR-scan for any high bit)\n\t\tlet acc = 0;\n\t\tfor (let i = 0; i < v.length; i++) acc |= v[i];\n\t\tif ((acc & 0x80) === 0) {\n\t\t\t// All ASCII → decode via String.fromCharCode in chunks\n\t\t\tlet s = '';\n\t\t\tconst CHUNK = 0x8000; // 32k is safe for apply()\n\t\t\tfor (let i = 0; i < v.length; i += CHUNK) {\n\t\t\t\ts += String.fromCharCode.apply(null, v.subarray(i, i + CHUNK) as unknown as number[]);\n\t\t\t}\n\t\t\treturn (this._utf8 = s);\n\t\t}\n\n\t\t// 2) Non-ASCII: try cross-instance cache (non-SAB only)\n\t\tconst buf = v.buffer;\n\t\tif (!(buf instanceof SharedArrayBuffer)) {\n\t\t\tlet cache = BUFFER_STRING_CACHE.get(buf);\n\t\t\tif (!cache) {\n\t\t\t\tcache = new Map<string, string>();\n\t\t\t\tBUFFER_STRING_CACHE.set(buf, cache);\n\t\t\t}\n\t\t\tconst key = `${v.byteOffset}:${v.byteLength}`;\n\t\t\tconst cached = cache.get(key);\n\t\t\tif (cached !== undefined) return (this._utf8 = cached);\n\n\t\t\tconst s = UTF8_DECODER.decode(v);\n\t\t\tcache.set(key, s);\n\t\t\treturn (this._utf8 = s);\n\t\t}\n\n\t\t// 3) SAB path: copy then decode, avoid cross-instance cache by default\n\t\tconst safeCopy = new Uint8Array(v);\n\t\tconst s = UTF8_DECODER.decode(safeCopy);\n\t\treturn (this._utf8 = s);\n\t}\n\n\t/**\n\t * For debugging/logging\n\t */\n\ttoString(): string {\n\t\treturn this.utf8String();\n\t}\n\n\t/**\n\t * Equality check by bytes\n\t */\n\tequals(other: ByteString): boolean {\n\t\tconst a = this.view,\n\t\t\tb = other.view;\n\t\tif (a.length !== b.length) return false;\n\t\tfor (let i = 0; i < a.length; i++) {\n\t\t\tif (a[i] !== b[i]) return false;\n\t\t}\n\t\treturn true;\n\t}\n}\n","export { ConnectionTracker } from \"./lib/ConnectionTracker\";\nexport {ByteString} from \"./lib/ByteString\"\n\n\nexport * from \"./lib/NarrowTypes\";\n\n\n/**\n * Extracts keys from T where the value is a `function(i: number): any`\n */\ntype FlatBufferKeys<T> = {\n [K in keyof T]: T[K] extends (i: number) => any ? K : never\n}[keyof T];\n\n/**\n * Non-nullable version: Filters out null results\n */\nexport function fbIterable<\n T,\n K extends FlatBufferKeys<T>\n>(\n obj: T,\n fieldName: K\n): Iterable<NonNullable<ReturnType<Extract<T[K], (i: number) => any>>>> {\n const length = (obj as any)[`${String(fieldName)}Length`]();\n return {\n [Symbol.iterator](): Iterator<NonNullable<ReturnType<Extract<T[K], (i: number) => any>>>> {\n let i = 0;\n return {\n next(): IteratorResult<NonNullable<ReturnType<Extract<T[K], (i: number) => any>>>> {\n while (i < length) {\n const value = (obj as any)[fieldName](i);\n i++;\n if (value != null) {\n return { value, done: false };\n }\n // if null → skip this index\n }\n return { value: undefined as any, done: true };\n }\n };\n }\n };\n}\n\n\n/**\n * Eager array version (non-null)\n */\nexport function fbArray<\n T,\n K extends FlatBufferKeys<T>\n>(\n obj: T,\n fieldName: K\n): Array<NonNullable<ReturnType<Extract<T[K], (i: number) => any>>>> {\n if(!obj) return []\n const lengthGetter = (obj as any)[`${String(fieldName)}Length`].bind(obj);\n const length = lengthGetter();\n\n const result: Array<NonNullable<ReturnType<Extract<T[K], (i: number) => any>>>> = [];\n for (let i = 0; i < length; i++) {\n const v = (obj as any)[fieldName](i);\n if (v != null) result.push(v);\n }\n return result;\n}\n"],"names":["isConnectionStatus","msg","MessageType","unionToMessage","asConnectionStatus","isEoce","Eoce","asEoce","isCountResponse","CountResponse","asCountResponse","isBufferFull","BufferFull","asBufferFull","isValidProofs","ValidProofs","asValidProofs","isParsedEvent","asParsedEvent","parsedKind","kind","ev","unionToParsedData","isKind0","ParsedData","asKind0","isKind1","asKind1","isKind3","asKind3","isKind4","asKind4","isKind6","asKind6","isKind7","asKind7","isKind17","asKind17","isKind10002","asKind10002","isKind10019","asKind10019","isKind17375","asKind17375","isKind39089","asKind39089","isKind7374","asKind7374","isKind7375","asKind7375","isKind7376","asKind7376","isKind9321","asKind9321","isKind9735","asKind9735","asCodeData","block","ContentData","unionToContentData","asHashtagData","asCashuData","asImageData","asVideoData","asMediaGroupData","asNostrData","asLinkPreview","ConnectionTracker","status","id","ByteBuffer","offset","length","start","slice","ByteString","UTF8_DECODER","BUFFER_STRING_CACHE","HEX_TABLE","t","i","view","h","v","out","acc","s","buf","cache","key","cached","safeCopy","other","a","b","fbIterable","obj","fieldName","value","fbArray","result"],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":["../src/lib/NarrowTypes.ts","../src/lib/ConnectionTracker.ts","../src/lib/ByteString.ts","../src/utils.ts"],"sourcesContent":["import {\n WorkerMessage,\n MessageType,\n ConnectionStatus,\n Eoce,\n CountResponse,\n BufferFull,\n ValidProofs,\n ParsedEvent,\n Kind0Parsed,\n Kind1Parsed,\n Kind3Parsed,\n Kind4Parsed,\n Kind6Parsed,\n Kind7Parsed,\n Kind17Parsed,\n Kind10002Parsed,\n Kind10019Parsed,\n Kind17375Parsed,\n Kind39089Parsed,\n Kind7374Parsed,\n Kind7375Parsed,\n Kind7376Parsed,\n Kind9321Parsed,\n Kind9735Parsed,\n ContentBlock,\n LinkPreviewData,\n ContentData,\n CashuData,\n HashtagData,\n CodeData,\n MediaGroupData,\n NostrData,\n VideoData,\n} from \"src/generated/nostr/fb\";\nimport { unionToContentData } from \"src/generated/nostr/fb/content-data\";\nimport { unionToMessage } from \"src/generated/nostr/fb/message\";\nimport { unionToParsedData, ParsedData } from \"src/generated/nostr/fb/parsed-data\";\n\n// ---- Top-level Message helpers ----\nexport function isConnectionStatus(msg: WorkerMessage): ConnectionStatus | null {\n if (msg.type() !== MessageType.ConnectionStatus) return null;\n return unionToMessage(msg.contentType(), msg.content.bind(msg)) as ConnectionStatus;\n}\n\nexport const asConnectionStatus = isConnectionStatus;\n\nexport function isEoce(msg: WorkerMessage): Eoce | null {\n if (msg.type() !== MessageType.Eoce) return null;\n return msg.content(new Eoce()) ?? null;\n}\n\nexport const asEoce = isEoce;\n\nexport function isCountResponse(msg: WorkerMessage): CountResponse | null {\n if (msg.type() !== MessageType.CountResponse) return null;\n return msg.content(new CountResponse()) ?? null;\n}\n\nexport const asCountResponse = isCountResponse;\n\nexport function isBufferFull(msg: WorkerMessage): BufferFull | null {\n if (msg.type() !== MessageType.BufferFull) return null;\n return msg.content(new BufferFull()) ?? null;\n}\n\nexport const asBufferFull = isBufferFull;\n\nexport function isValidProofs(msg: WorkerMessage): ValidProofs | null {\n if (msg.type() !== MessageType.ValidProofs) return null;\n return msg.content(new ValidProofs()) ?? null;\n}\n\nexport const asValidProofs = isValidProofs;\n\n// ---- Generic ParsedEvent --------\nexport function isParsedEvent(msg: WorkerMessage): ParsedEvent | null {\n if (msg.type() !== MessageType.ParsedNostrEvent) return null;\n return unionToMessage(msg.contentType(), msg.content.bind(msg)) as ParsedEvent;\n}\n\nexport const asParsedEvent = isParsedEvent;\n\n// ---- ParsedData Kind helpers ----\nfunction parsedKind<T>(msg: WorkerMessage, kind: ParsedData): T | null {\n if (!msg) return null;\n const ev = isParsedEvent(msg);\n if (!ev) return null;\n if (ev.parsedType() !== kind) return null;\n return unionToParsedData(kind, ev.parsed.bind(ev)) as T;\n}\n\nexport function isKind0(msg: WorkerMessage): Kind0Parsed | null {\n return parsedKind<Kind0Parsed>(msg, ParsedData.Kind0Parsed);\n}\nexport function asKind0(ev: ParsedEvent): Kind0Parsed | null {\n if (!ev) return null;\n if (ev.parsedType() !== ParsedData.Kind0Parsed) return null;\n return unionToParsedData(ParsedData.Kind0Parsed, ev.parsed.bind(ev)) as Kind0Parsed;\n}\nexport function isKind1(msg: WorkerMessage): Kind1Parsed | null {\n return parsedKind<Kind1Parsed>(msg, ParsedData.Kind1Parsed);\n}\nexport function asKind1(ev: ParsedEvent): Kind1Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind1Parsed) return null;\n return unionToParsedData(ParsedData.Kind1Parsed, ev.parsed.bind(ev)) as Kind1Parsed;\n}\nexport function isKind3(msg: WorkerMessage): Kind3Parsed | null {\n return parsedKind<Kind3Parsed>(msg, ParsedData.Kind3Parsed);\n}\nexport function asKind3(ev: ParsedEvent): Kind3Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind3Parsed) return null;\n return unionToParsedData(ParsedData.Kind3Parsed, ev.parsed.bind(ev)) as Kind3Parsed;\n}\nexport function isKind4(msg: WorkerMessage): Kind4Parsed | null {\n return parsedKind<Kind4Parsed>(msg, ParsedData.Kind4Parsed);\n}\nexport function asKind4(ev: ParsedEvent): Kind4Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind4Parsed) return null;\n return unionToParsedData(ParsedData.Kind4Parsed, ev.parsed.bind(ev)) as Kind4Parsed;\n}\nexport function isKind6(msg: WorkerMessage): Kind6Parsed | null {\n return parsedKind<Kind6Parsed>(msg, ParsedData.Kind6Parsed);\n}\nexport function asKind6(ev: ParsedEvent): Kind6Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind6Parsed) return null;\n return unionToParsedData(ParsedData.Kind6Parsed, ev.parsed.bind(ev)) as Kind6Parsed;\n}\nexport function isKind7(msg: WorkerMessage): Kind7Parsed | null {\n return parsedKind<Kind7Parsed>(msg, ParsedData.Kind7Parsed);\n}\nexport function asKind7(ev: ParsedEvent): Kind7Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind7Parsed) return null;\n return unionToParsedData(ParsedData.Kind7Parsed, ev.parsed.bind(ev)) as Kind7Parsed;\n}\nexport function isKind17(msg: WorkerMessage): Kind17Parsed | null {\n return parsedKind<Kind17Parsed>(msg, ParsedData.Kind17Parsed);\n}\nexport function asKind17(ev: ParsedEvent): Kind17Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind17Parsed) return null;\n return unionToParsedData(ParsedData.Kind17Parsed, ev.parsed.bind(ev)) as Kind17Parsed;\n}\nexport function isKind10002(msg: WorkerMessage): Kind10002Parsed | null {\n return parsedKind<Kind10002Parsed>(msg, ParsedData.Kind10002Parsed);\n}\nexport function asKind10002(ev: ParsedEvent): Kind10002Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind10002Parsed) return null;\n return unionToParsedData(ParsedData.Kind10002Parsed, ev.parsed.bind(ev)) as Kind10002Parsed;\n}\n\nexport function isKind10019(msg: WorkerMessage): Kind10019Parsed | null {\n return parsedKind<Kind10019Parsed>(msg, ParsedData.Kind10019Parsed);\n}\nexport function asKind10019(ev: ParsedEvent): Kind10019Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind10019Parsed) return null;\n return unionToParsedData(ParsedData.Kind10019Parsed, ev.parsed.bind(ev)) as Kind10019Parsed;\n}\n\nexport function isKind17375(msg: WorkerMessage): Kind17375Parsed | null {\n return parsedKind<Kind17375Parsed>(msg, ParsedData.Kind17375Parsed);\n}\nexport function asKind17375(ev: ParsedEvent): Kind17375Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind17375Parsed) return null;\n return unionToParsedData(ParsedData.Kind17375Parsed, ev.parsed.bind(ev)) as Kind17375Parsed;\n}\nexport function isKind39089(msg: WorkerMessage): Kind39089Parsed | null {\n return parsedKind<Kind39089Parsed>(msg, ParsedData.Kind39089Parsed);\n}\nexport function asKind39089(ev: ParsedEvent): Kind39089Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind39089Parsed) return null;\n return unionToParsedData(ParsedData.Kind39089Parsed, ev.parsed.bind(ev)) as Kind39089Parsed;\n}\n\nexport function isKind7374(msg: WorkerMessage): Kind7374Parsed | null {\n return parsedKind<Kind7374Parsed>(msg, ParsedData.Kind7374Parsed);\n}\nexport function asKind7374(ev: ParsedEvent): Kind7374Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind7374Parsed) return null;\n return unionToParsedData(ParsedData.Kind7374Parsed, ev.parsed.bind(ev)) as Kind7374Parsed;\n}\n\nexport function isKind7375(msg: WorkerMessage): Kind7375Parsed | null {\n return parsedKind<Kind7375Parsed>(msg, ParsedData.Kind7375Parsed);\n}\nexport function asKind7375(ev: ParsedEvent): Kind7375Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind7375Parsed) return null;\n return unionToParsedData(ParsedData.Kind7375Parsed, ev.parsed.bind(ev)) as Kind7375Parsed;\n}\n\nexport function isKind7376(msg: WorkerMessage): Kind7376Parsed | null {\n return parsedKind<Kind7376Parsed>(msg, ParsedData.Kind7376Parsed);\n}\nexport function asKind7376(ev: ParsedEvent): Kind7376Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind7376Parsed) return null;\n return unionToParsedData(ParsedData.Kind7376Parsed, ev.parsed.bind(ev)) as Kind7376Parsed;\n}\n\nexport function isKind9321(msg: WorkerMessage): Kind9321Parsed | null {\n return parsedKind<Kind9321Parsed>(msg, ParsedData.Kind9321Parsed);\n}\nexport function asKind9321(ev: ParsedEvent): Kind9321Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind9321Parsed) return null;\n return unionToParsedData(ParsedData.Kind9321Parsed, ev.parsed.bind(ev)) as Kind9321Parsed;\n}\n\nexport function isKind9735(msg: WorkerMessage): Kind9735Parsed | null {\n return parsedKind<Kind9735Parsed>(msg, ParsedData.Kind9735Parsed);\n}\nexport function asKind9735(ev: ParsedEvent): Kind9735Parsed | null {\n if (ev.parsedType() !== ParsedData.Kind9735Parsed) return null;\n return unionToParsedData(ParsedData.Kind9735Parsed, ev.parsed.bind(ev)) as Kind9735Parsed;\n}\n\nexport function asCodeData(block: ContentBlock): CodeData | null {\n if (block.dataType() !== ContentData.CodeData) return null;\n return unionToContentData(ContentData.CodeData, block.data.bind(block)) as CodeData;\n}\n\nexport function asHashtagData(block: ContentBlock): HashtagData | null {\n if (block.dataType() !== ContentData.HashtagData) return null;\n return unionToContentData(ContentData.HashtagData, block.data.bind(block)) as HashtagData;\n}\n\nexport function asCashuData(block: ContentBlock): CashuData | null {\n if (block.dataType() !== ContentData.CashuData) return null;\n return unionToContentData(ContentData.CashuData, block.data.bind(block)) as CashuData;\n}\n\nexport function asImageData(block: ContentBlock): ImageData | null {\n if (block.dataType() !== ContentData.ImageData) return null;\n return unionToContentData(ContentData.ImageData, block.data.bind(block)) as unknown as ImageData;\n}\n\nexport function asVideoData(block: ContentBlock): VideoData | null {\n if (block.dataType() !== ContentData.VideoData) return null;\n return unionToContentData(ContentData.VideoData, block.data.bind(block)) as VideoData;\n}\n\nexport function asMediaGroupData(block: ContentBlock): MediaGroupData | null {\n if (block.dataType() !== ContentData.MediaGroupData) return null;\n return unionToContentData(ContentData.MediaGroupData, block.data.bind(block)) as MediaGroupData;\n}\n\nexport function asNostrData(block: ContentBlock): NostrData | null {\n if (block.dataType() !== ContentData.NostrData) return null;\n return unionToContentData(ContentData.NostrData, block.data.bind(block)) as NostrData;\n}\n\nexport function asLinkPreview(block: ContentBlock): LinkPreviewData | null {\n if (block.dataType() !== ContentData.LinkPreviewData) return null;\n return unionToContentData(ContentData.LinkPreviewData, block.data.bind(block)) as LinkPreviewData;\n}\n","import { ConnectionStatus, WorkerMessage } from \"src/generated/nostr/fb\";\nimport { isConnectionStatus } from \"./NarrowTypes\";\n\nexport class ConnectionTracker {\n private knownRelays: Map<number, ConnectionStatus> = new Map();\n private incomingCount = 0;\n private resolvedCount = 0;\n\n /**\n * Feed a new message into the tracker\n */\n handleMessage(msg: WorkerMessage) {\n const status = isConnectionStatus(msg);\n if (!status) return; // not a connection status, ignore\n\n const id = status.relayUrl()?.fnv1aHash()\n if(id && !this.knownRelays.has(id)) {\n this.incomingCount++;\n this.knownRelays.set(id, status);\n }\n if (this.isResolved(status)) {\n this.resolvedCount++;\n }\n }\n\n /**\n * Define what counts as a \"resolved\" connection.\n * Adjust based on your real ConnectionStatus enum/shape.\n */\n private isResolved(status: ConnectionStatus): boolean {\n return status.status()?.toString() === \"EOSE\";\n }\n\n /** Total connection attempts processed */\n get totalIncoming(): number {\n return this.incomingCount;\n }\n\n /** How many actually resolved */\n get totalResolved(): number {\n return this.resolvedCount;\n }\n\n /** Quick ratio (0...1) of resolved vs incoming */\n get resolutionRate(): number {\n return this.incomingCount === 0 ? 0 : this.resolvedCount / this.incomingCount;\n }\n}\n","import { ByteBuffer } from 'flatbuffers';\n\n(ByteBuffer.prototype as any).__stringByteString = function (offset: number): ByteString {\n\t// Follow indirect: add the relative offset stored at this location\n\toffset += this.readInt32(offset);\n\n\t// Now at the start of the string object → first 4 bytes = length\n\tconst length = this.readInt32(offset);\n\tconst start = offset + 4;\n\n\t// Slice out exactly [start, start+length]\n\tconst slice = this.bytes().subarray(start, start + length);\n\n\treturn new ByteString(slice);\n};\n\n// Shared decoder for all instances (cheap, stateless for non-streaming use)\nconst UTF8_DECODER = new TextDecoder('utf-8');\n\n// Cross-instance cache: per underlying buffer → (offset:length) → decoded string\n// WeakMap ensures entries are eligible for GC once the ArrayBuffer becomes unreachable.\nconst BUFFER_STRING_CACHE = new WeakMap<ArrayBufferLike, Map<string, string>>();\n\n// Hex lookup table to speed up toHex()\nconst HEX_TABLE: string[] = (() => {\n\tconst t = new Array(256);\n\tfor (let i = 0; i < 256; i++) t[i] = i.toString(16).padStart(2, '0');\n\treturn t;\n})();\n\n// lib/ByteString.ts\nexport class ByteString {\n\tprivate readonly view: Uint8Array;\n\tprivate _utf8?: string;\n\n\tconstructor(view: Uint8Array) {\n\t\tthis.view = view;\n\t}\n\n\t/**\n\t * Access underlying bytes\n\t */\n\tbytes(): Uint8Array {\n\t\treturn this.view;\n\t}\n\n\t/**\n\t * Fast numeric discriminant (FNV-1a hash).\n\t * Not cryptographically secure, but great for Map/Set keys.\n\t */\n\tfnv1aHash(): number {\n\t\tlet h = 2166136261 >>> 0;\n\t\tconst v = this.view;\n\t\tfor (let i = 0; i < v.length; i++) {\n\t\t\th ^= v[i];\n\t\t\th = Math.imul(h, 16777619);\n\t\t}\n\t\treturn h >>> 0;\n\t}\n\n\t/**\n\t * Return a stable hex string representation.\n\t */\n\ttoHex(): string {\n\t\tconst v = this.view;\n\t\tlet out = '';\n\t\tfor (let i = 0; i < v.length; i++) out += HEX_TABLE[v[i]];\n\t\treturn out;\n\t}\n\n\t/**\n\t * Decode as UTF-8 string.\n\t * If backed by SharedArrayBuffer, makes a safe copy.\n\t * Optimizations:\n\t * - Reuses a shared TextDecoder\n\t * - ASCII fast path\n\t * - Cross-instance cache (non-SAB only) keyed by buffer+offset+length\n\t */\n\tutf8String(): string {\n\t\tif (this._utf8 !== undefined) return this._utf8;\n\n\t\tconst v = this.view;\n\n\t\t// 1) ASCII fast path (quick OR-scan for any high bit)\n\t\tlet acc = 0;\n\t\tfor (let i = 0; i < v.length; i++) acc |= v[i];\n\t\tif ((acc & 0x80) === 0) {\n\t\t\t// All ASCII → decode via String.fromCharCode in chunks\n\t\t\tlet s = '';\n\t\t\tconst CHUNK = 0x8000; // 32k is safe for apply()\n\t\t\tfor (let i = 0; i < v.length; i += CHUNK) {\n\t\t\t\ts += String.fromCharCode.apply(null, v.subarray(i, i + CHUNK) as unknown as number[]);\n\t\t\t}\n\t\t\treturn (this._utf8 = s);\n\t\t}\n\n\t\t// 2) Non-ASCII: try cross-instance cache (non-SAB only)\n\t\tconst buf = v.buffer;\n\t\tif (!(buf instanceof SharedArrayBuffer)) {\n\t\t\tlet cache = BUFFER_STRING_CACHE.get(buf);\n\t\t\tif (!cache) {\n\t\t\t\tcache = new Map<string, string>();\n\t\t\t\tBUFFER_STRING_CACHE.set(buf, cache);\n\t\t\t}\n\t\t\tconst key = `${v.byteOffset}:${v.byteLength}`;\n\t\t\tconst cached = cache.get(key);\n\t\t\tif (cached !== undefined) return (this._utf8 = cached);\n\n\t\t\tconst s = UTF8_DECODER.decode(v);\n\t\t\tcache.set(key, s);\n\t\t\treturn (this._utf8 = s);\n\t\t}\n\n\t\t// 3) SAB path: copy then decode, avoid cross-instance cache by default\n\t\tconst safeCopy = new Uint8Array(v);\n\t\tconst s = UTF8_DECODER.decode(safeCopy);\n\t\treturn (this._utf8 = s);\n\t}\n\n\t/**\n\t * For debugging/logging\n\t */\n\ttoString(): string {\n\t\treturn this.utf8String();\n\t}\n\n\t/**\n\t * Equality check by bytes\n\t */\n\tequals(other: ByteString): boolean {\n\t\tconst a = this.view,\n\t\t\tb = other.view;\n\t\tif (a.length !== b.length) return false;\n\t\tfor (let i = 0; i < a.length; i++) {\n\t\t\tif (a[i] !== b[i]) return false;\n\t\t}\n\t\treturn true;\n\t}\n}\n","export { ConnectionTracker } from \"./lib/ConnectionTracker\";\nexport {ByteString} from \"./lib/ByteString\"\n\n\nexport * from \"./lib/NarrowTypes\";\n\n\n/**\n * Extracts keys from T where the value is a `function(i: number): any`\n */\ntype FlatBufferKeys<T> = {\n [K in keyof T]: T[K] extends (i: number) => any ? K : never\n}[keyof T];\n\n/**\n * Non-nullable version: Filters out null results\n */\nexport function fbIterable<\n T,\n K extends FlatBufferKeys<T>\n>(\n obj: T,\n fieldName: K\n): Iterable<NonNullable<ReturnType<Extract<T[K], (i: number) => any>>>> {\n const length = (obj as any)[`${String(fieldName)}Length`]();\n return {\n [Symbol.iterator](): Iterator<NonNullable<ReturnType<Extract<T[K], (i: number) => any>>>> {\n let i = 0;\n return {\n next(): IteratorResult<NonNullable<ReturnType<Extract<T[K], (i: number) => any>>>> {\n while (i < length) {\n const value = (obj as any)[fieldName](i);\n i++;\n if (value != null) {\n return { value, done: false };\n }\n // if null → skip this index\n }\n return { value: undefined as any, done: true };\n }\n };\n }\n };\n}\n\n\n/**\n * Eager array version (non-null)\n */\nexport function fbArray<\n T,\n K extends FlatBufferKeys<T>\n>(\n obj: T,\n fieldName: K\n): Array<NonNullable<ReturnType<Extract<T[K], (i: number) => any>>>> {\n if(!obj) return []\n const lengthGetter = (obj as any)[`${String(fieldName)}Length`].bind(obj);\n const length = lengthGetter();\n\n const result: Array<NonNullable<ReturnType<Extract<T[K], (i: number) => any>>>> = [];\n for (let i = 0; i < length; i++) {\n const v = (obj as any)[fieldName](i);\n if (v != null) result.push(v);\n }\n return result;\n}\n"],"names":["isConnectionStatus","msg","MessageType","unionToMessage","asConnectionStatus","isEoce","Eoce","asEoce","isCountResponse","CountResponse","asCountResponse","isBufferFull","BufferFull","asBufferFull","isValidProofs","ValidProofs","asValidProofs","isParsedEvent","asParsedEvent","parsedKind","kind","ev","unionToParsedData","isKind0","ParsedData","asKind0","isKind1","asKind1","isKind3","asKind3","isKind4","asKind4","isKind6","asKind6","isKind7","asKind7","isKind17","asKind17","isKind10002","asKind10002","isKind10019","asKind10019","isKind17375","asKind17375","isKind39089","asKind39089","isKind7374","asKind7374","isKind7375","asKind7375","isKind7376","asKind7376","isKind9321","asKind9321","isKind9735","asKind9735","asCodeData","block","ContentData","unionToContentData","asHashtagData","asCashuData","asImageData","asVideoData","asMediaGroupData","asNostrData","asLinkPreview","ConnectionTracker","status","id","ByteBuffer","offset","length","start","slice","ByteString","UTF8_DECODER","BUFFER_STRING_CACHE","HEX_TABLE","t","i","view","h","v","out","acc","s","buf","cache","key","cached","safeCopy","other","a","b","fbIterable","obj","fieldName","value","fbArray","result"],"mappings":"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"}
package/dist/ws/index.js CHANGED
@@ -1 +1 @@
1
- import{B as R}from"../ring-buffer.js";var r=(n=>(n.Idle="idle",n.Connecting="connecting",n.Ready="ready",n.Closing="closing",n.Closed="closed",n.Error="error",n))(r||{});class D{constructor(t,e={}){this.wantReconnect=!0,this.status=r.Closed,this.ws=null,this.reconnectTimer=null,this.abortController=null,this.attempts=0,this.givenUp=!1,this.lastActivity=Date.now(),this.stats={dropped:0,sent:0,received:0,reconnects:0,lastActivity:Date.now()},this.readyWaiters=[],this.messageHandler=null,this.url=t,this.config={connectTimeoutMs:5e3,writeTimeoutMs:1e4,retry:{baseMs:300,maxMs:1e4,multiplier:1.6,jitter:.1},maxReconnectAttempts:2,idleTimeoutMs:3e5,...e}}getUrl(){return this.url}getStatus(){return this.status}getStats(){return{...this.stats,reconnects:this.attempts,lastActivity:this.lastActivity}}getLastActivity(){return this.lastActivity}hasGivenUp(){return this.givenUp}setMessageHandler(t){this.messageHandler=t}connect(){if(this.givenUp||this.status===r.Connecting||this.status===r.Ready)return;this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.status=r.Connecting,this.abortController=new AbortController;const t=this.abortController.signal;try{this.ws=new WebSocket(this.url),this.ws.binaryType="arraybuffer";const e=()=>{this.ws&&(this.ws.onopen=null,this.ws.onclose=null,this.ws.onerror=null,this.ws.onmessage=null)},s=()=>{clearTimeout(c),this.status=r.Ready,this.attempts=0,this.givenUp=!1,this.lastActivity=Date.now(),this.stats.lastActivity=this.lastActivity,this.resolveReady(!0)},i=d=>{clearTimeout(c),e(),this.status=r.Closed,this.resolveReady(!1),d.code!==1e3&&this.scheduleReconnect()},o=d=>{clearTimeout(c),e(),this.status=r.Closed,this.resolveReady(!1),this.scheduleReconnect()},a=d=>{if(this.lastActivity=Date.now(),this.stats.lastActivity=this.lastActivity,this.stats.received++,typeof d.data=="string"){const C=d.data,M=this.extractSubId(C);this.messageHandler&&this.messageHandler(this.url,M,C)}};this.ws.onopen=s,this.ws.onclose=i,this.ws.onerror=o,this.ws.onmessage=a;const c=setTimeout(()=>{if(this.status===r.Connecting){e();try{this.ws?.close()}catch{}this.status=r.Closed,this.resolveReady(!1),this.scheduleReconnect()}},this.config.connectTimeoutMs),l=()=>{clearTimeout(c),e();try{this.ws?.close()}catch{}this.status=r.Closed,this.resolveReady(!1),this.wantReconnect&&this.scheduleReconnect()};t.addEventListener("abort",l)}catch{this.status=r.Closed,this.resolveReady(!1),this.scheduleReconnect()}}async sendMessage(t){if(this.status!==r.Ready||!this.ws)throw new Error("Connection not ready");this.ws.send(t),this.stats.sent++,this.lastActivity=Date.now(),this.stats.lastActivity=this.lastActivity}async waitForReady(t=this.config.connectTimeoutMs??5e3){if(this.status!==r.Ready)return new Promise((e,s)=>{const i=setTimeout(()=>{this.removeReadyResolver(o),s(new Error("Timeout waiting for ready"))},t),o=a=>{clearTimeout(i),a?e():s(new Error("Connection closed"))};this.readyWaiters.push(o)})}async close(){this.wantReconnect=!1,this.abortController&&this.abortController.abort(),this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.closeWebSocket(),this.status=r.Closed,this.resolveReady(!1)}shouldCloseDueToInactivity(){return Date.now()-this.lastActivity>(this.config.idleTimeoutMs??3e5)}resolveReady(t){if(this.readyWaiters.length===0)return;const e=this.readyWaiters.slice();this.readyWaiters.length=0;for(const s of e)try{s(t)}catch{}}removeReadyResolver(t){const e=this.readyWaiters.indexOf(t);e>=0&&this.readyWaiters.splice(e,1)}closeWebSocket(){if(this.ws){try{this.ws.close(1e3,"Normal closure")}catch{}this.ws=null}}scheduleReconnect(){if(!this.wantReconnect||this.status!==r.Closed||!this.config.retry?.baseMs)return;const t=this.config.maxReconnectAttempts??2;if(t>0&&this.attempts>=t){this.givenUp=!0;return}const e=this.config.retry.baseMs,s=this.config.retry.maxMs??1e4,i=this.config.retry.multiplier??1.6,o=this.config.retry.jitter??.1,a=Math.min(e*Math.pow(i,this.attempts),s)*(1+(Math.random()-.5)*o*2);this.reconnectTimer=setTimeout(()=>{this.attempts++,this.stats.reconnects=this.attempts,this.connect()},a)}extractSubId(t){let e=0;const s=t.length;for(;e<s&&t.charCodeAt(e)<=32;)e++;if(e>=s||t[e]!=="[")return null;for(e++;e<s&&t.charCodeAt(e)<=32;)e++;if(e>=s)return null;if(t[e]==='"'){for(e++;e<s&&t[e]!=='"';)e++;if(e>=s)return null;e++}else for(;e<s&&t[e]!==","&&t[e]!=="]";)e++;for(;e<s&&t[e]!==",";)e++;if(e>=s||t[e]!==",")return null;for(e++;e<s&&t.charCodeAt(e)<=32;)e++;if(e>=s)return null;if(t[e]==='"'){e++;const i=e;for(;e<s&&t[e]!=='"';)e++;return e>s?null:t.slice(i,e)}return null}}class S{constructor(t){this.connections=new Map,this.disabledRelays=new Set,this.nextAllowed=new Map,this.subCounts=new Map,this.disconnectTimers=new Map,this.cooldownMs=6e4,this.closeDelayMs=1e3,this.config={maxReconnectAttempts:2,...t}}now(){return Date.now()}detectKind(t){const e=t.match(/^\s*\[\s*"([^"]+)"/);if(!e)return"OTHER";const s=e[1].toUpperCase();return s==="REQ"?"REQ":s==="CLOSE"?"CLOSE":"OTHER"}getCount(t){return this.subCounts.get(t)??0}setCount(t,e){this.subCounts.set(t,Math.max(0,e))}cancelPendingDisconnect(t){const e=this.disconnectTimers.get(t);typeof e=="number"&&(clearTimeout(e),this.disconnectTimers.delete(t))}scheduleDisconnectIfIdle(t){if(this.disconnectTimers.has(t))return;const e=setTimeout(async()=>{this.disconnectTimers.delete(t),this.getCount(t)===0&&await this.disconnect(t)},this.closeDelayMs);this.disconnectTimers.set(t,e)}bumpCount(t,e){const s=this.getCount(t)+e;this.setCount(t,s),e>0?this.cancelPendingDisconnect(t):e<0&&this.getCount(t)===0&&this.scheduleDisconnectIfIdle(t)}giveUpOrCooldown(t,e){e?.hasGivenUp()?(this.disabledRelays.has(t)||console.warn(`[registry] disabling relay ${t}: max attempts reached`),this.disabledRelays.add(t),this.nextAllowed.set(t,this.now()+this.cooldownMs)):this.nextAllowed.set(t,this.now()+Math.min(this.cooldownMs,1e4))}isCoolingDown(t){const e=this.nextAllowed.get(t)??0;return this.now()<e}async ensureConnection(t){if(this.disabledRelays.has(t))throw new Error(`Relay disabled: ${t}`);if(this.isCoolingDown(t))throw new Error(`Relay ${t} cooling down until ${new Date(this.nextAllowed.get(t)).toISOString()}`);let e=this.connections.get(t);if(e?e.getStatus()!==r.Ready&&e.connect():(e=new D(t,this.config),this.connections.set(t,e),e.connect()),e.getStatus()!==r.Ready)try{await e.waitForReady(this.config.connectTimeoutMs??5e3)}catch(s){throw this.giveUpOrCooldown(t,e),s}if(e.getStatus()!==r.Ready)throw this.giveUpOrCooldown(t,e),new Error(`Relay ${t} not ready`);return e}async sendFrame(t,e){if(this.disabledRelays.has(t)||this.isCoolingDown(t))return;const s=this.detectKind(e),i=await this.ensureConnection(t);try{await i.sendMessage(e)}catch(o){throw this.giveUpOrCooldown(t,i),await this.disconnect(t),o}s==="REQ"?this.bumpCount(t,1):s==="CLOSE"&&this.bumpCount(t,-1)}async sendAllFramesToRelay(t,e){for(const s of e)await this.sendFrame(t,s)}async sendToRelays(t,e){const s=[];for(const i of t)this.disabledRelays.has(i)||this.isCoolingDown(i)||s.push(this.sendAllFramesToRelay(i,e).catch(o=>{console.error(`[registry] failed to send to ${i}:`,o)}));await Promise.allSettled(s)}async disconnect(t){const e=this.connections.get(t);e&&(await e.close(),this.connections.delete(t)),this.cancelPendingDisconnect(t),this.subCounts.delete(t)}async disconnectAll(){for(const[t]of this.connections)await this.disconnect(t)}enableRelay(t){this.disabledRelays.delete(t),this.nextAllowed.delete(t)}isRelayDisabled(t){return this.disabledRelays.has(t)}getActiveReqCount(t){return this.getCount(t)}getConnectionStatus(t){const e=this.connections.get(t);return e?e.getStatus():void 0}getAllStatuses(){return new Map(Array.from(this.connections.entries()).map(([t,e])=>[t,e.getStatus()]))}}const p=new TextEncoder,v=new Map;function x(n){const t=v.get(n);if(t)return t;const e=p.encode(n);return v.set(n,e),e}function E(n,t,e){const s=x(t),i=p.encode(e),o=2+s.length+4+i.length,a=new Uint8Array(o),c=new DataView(a.buffer,a.byteOffset,a.byteLength);let l=0;c.setUint16(l,s.length,!1),l+=2,a.set(s,l),l+=s.length,c.setUint32(l,i.length,!1),l+=4,a.set(i,l),n.write(a)}function U(n){let t=0,e=n.length;for(;t<e&&n.charCodeAt(t)<=32;)t++;if(t>=e||n[t]!=="[")return null;for(t++;t<e&&n.charCodeAt(t)<=32;)t++;if(t>=e)return null;if(n[t]==='"'){for(t++;t<e&&n[t]!=='"';)t++;if(t>=e)return null;t++}else for(;t<e&&n[t]!==","&&n[t]!=="]";)t++;for(;t<e&&n[t]!==",";)t++;if(t>=e||n[t]!==",")return null;for(t++;t<e&&n.charCodeAt(t)<=32;)t++;if(t>=e)return null;if(n[t]==='"'){t++;const s=t;for(;t<e&&n[t]!=='"';)t++;return t>e?null:n.slice(s,t)}return null}let w=[],f=[],y=null;const T=new Map,O=new TextDecoder;function I(n){const t=n.includes("_")?n.split("_")[1]??"":n;let e=0;for(let s=0;s<t.length;s++)e=(e<<5)-e+t.charCodeAt(s);return Math.abs(e)%f.length}function W(n){let t=T.get(n);return t||(t=f[I(n)],T.set(n,t),t)}let A=0,h=10;const g=10,b=1e3;let u=null;function m(){u=setTimeout(H,h)}function H(){let n=0;const t=w.length;if(t===0)return h=Math.min(h*2,b),m();let e;do{e=!1;for(let s=0;s<t;s++){const i=(A+s)%t,o=w[i].read();if(!o)continue;e=!0,n++;const a=O.decode(o);let c;try{c=JSON.parse(a)}catch{continue}!Array.isArray(c.relays)||!Array.isArray(c.frames)||(y?.sendToRelays(c.relays,c.frames).catch(console.error),A=(i+1)%t)}}while(e);h=n>0?g:Math.min(h*2,b),m()}self.addEventListener("message",n=>{const t=n.data;if(!t||t.type==="init"){w=t.payload.inRings.map(i=>new R(i)),f=t.payload.outRings.map(i=>new R(i)),y=new S(t.payload.relayConfig||{});const e=(i,o,a)=>{const c=o??U(a);c&&E(W(c),i,a)},s=y.ensureConnection.bind(y);y.ensureConnection=async i=>{const o=await s(i);return o.messageHandler||o.setMessageHandler(e),o},h=g,u!==null&&clearTimeout(u);return}if(t?.type==="wake"){h=g,u!==null&&(clearTimeout(u),u=null),m();return}});
1
+ class C{constructor(t){this.dataStart=32,this.dropped=0,this.sab=t,this.dataView=new DataView(t),this.capacity=this.dataView.getUint32(0,!0)}getHead(){return this.dataView.getUint32(4,!0)%this.capacity}setHead(t){this.dataView.setUint32(4,t%this.capacity,!0)}getTail(){return this.dataView.getUint32(8,!0)%this.capacity}setTail(t){this.dataView.setUint32(8,t%this.capacity,!0)}getSeq(){return this.dataView.getUint32(12,!0)}setSeq(t){this.dataView.setUint32(12,t,!0)}getFreeSpace(){const t=this.getHead(),e=this.getTail(),s=(t-e+this.capacity)%this.capacity;return this.capacity-s}getDropped(){return this.dropped}hasRecords(){return this.getHead()!==this.getTail()}readNext(){const t=this.read();return t?{payload:t}:null}write(t){const e=t.byteLength,s=8+e,a=4+s+4;let o=0;for(;this.getFreeSpace()<a;){if(!this.skipRecord())return this.dropped+=o+1,-1;o++}const r=this.getSeq()+1;this.setSeq(r);let n=this.getHead();return this.dataView.setUint32(this.dataStart+n,s,!0),n=(n+4)%this.capacity,this.dataView.setUint16(this.dataStart+n,0,!0),n=(n+2)%this.capacity,this.dataView.setUint16(this.dataStart+n,0,!0),n=(n+2)%this.capacity,this.dataView.setUint32(this.dataStart+n,r,!0),n=(n+4)%this.capacity,this.copyBytes(n,t,0,e),n=(n+e)%this.capacity,this.dataView.setUint32(this.dataStart+n,s,!0),n=(n+4)%this.capacity,this.setHead(n),this.dropped+=o,r}read(){let t=this.getTail();if(t===this.getHead())return null;const e=this.dataView.getUint32(this.dataStart+t,!0);if(e===0)return null;const s=(t+4+e)%this.capacity;if(this.dataView.getUint32(this.dataStart+s,!0)!==e)return null;const a=new Uint8Array(e);this.copyFromRing((t+4)%this.capacity,a,0,e);const o=a.subarray(8),r=4+e+4;return this.setTail((this.getTail()+r)%this.capacity),o}skipRecord(){let t=this.getTail();if(t===this.getHead())return!1;const e=this.dataView.getUint32(this.dataStart+t,!0);if(e===0)return!1;const s=(t+4+e)%this.capacity;if(this.dataView.getUint32(this.dataStart+s,!0)!==e)return!1;const a=4+e+4;return this.setTail((this.getTail()+a)%this.capacity),!0}copyBytes(t,e,s,a){let o=a,r=s,n=t;for(;o>0;){const l=this.capacity-n%this.capacity,h=Math.min(o,l),u=this.dataStart+n%this.capacity,g=e.subarray(r,r+h);new Uint8Array(this.sab,u,h).set(g),o-=h,r+=h,n+=h}}copyFromRing(t,e,s,a){let o=a,r=s,n=t;for(;o>0;){const l=this.capacity-n%this.capacity,h=Math.min(o,l),u=this.dataStart+n%this.capacity,g=new Uint8Array(this.sab,u,h);e.set(g,r),o-=h,r+=h,n+=h}}}var c=(i=>(i.Idle="idle",i.Connecting="connecting",i.Ready="ready",i.Closing="closing",i.Closed="closed",i.Error="error",i))(c||{});class M{constructor(t,e={}){this.wantReconnect=!0,this.status=c.Closed,this.ws=null,this.reconnectTimer=null,this.abortController=null,this.attempts=0,this.givenUp=!1,this.lastActivity=Date.now(),this.stats={dropped:0,sent:0,received:0,reconnects:0,lastActivity:Date.now()},this.readyWaiters=[],this.messageHandler=null,this.url=t,this.config={connectTimeoutMs:5e3,writeTimeoutMs:1e4,retry:{baseMs:300,maxMs:1e4,multiplier:1.6,jitter:.1},maxReconnectAttempts:2,idleTimeoutMs:3e5,...e}}getUrl(){return this.url}getStatus(){return this.status}getStats(){return{...this.stats,reconnects:this.attempts,lastActivity:this.lastActivity}}getLastActivity(){return this.lastActivity}hasGivenUp(){return this.givenUp}setMessageHandler(t){this.messageHandler=t}connect(){if(this.givenUp||this.status===c.Connecting||this.status===c.Ready)return;this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.status=c.Connecting,this.abortController=new AbortController;const t=this.abortController.signal;try{this.ws=new WebSocket(this.url),this.ws.binaryType="arraybuffer";const e=()=>{this.ws&&(this.ws.onopen=null,this.ws.onclose=null,this.ws.onerror=null,this.ws.onmessage=null)},s=()=>{clearTimeout(n),this.status=c.Ready,this.attempts=0,this.givenUp=!1,this.lastActivity=Date.now(),this.stats.lastActivity=this.lastActivity,this.resolveReady(!0)},a=h=>{clearTimeout(n),e(),this.status=c.Closed,this.resolveReady(!1),h.code!==1e3&&this.scheduleReconnect()},o=h=>{clearTimeout(n),e(),this.status=c.Closed,this.resolveReady(!1),this.scheduleReconnect()},r=h=>{if(this.lastActivity=Date.now(),this.stats.lastActivity=this.lastActivity,this.stats.received++,typeof h.data=="string"){const u=h.data,g=this.extractSubId(u);this.messageHandler&&this.messageHandler(this.url,g,u)}};this.ws.onopen=s,this.ws.onclose=a,this.ws.onerror=o,this.ws.onmessage=r;const n=setTimeout(()=>{if(this.status===c.Connecting){e();try{this.ws?.close()}catch{}this.status=c.Closed,this.resolveReady(!1),this.scheduleReconnect()}},this.config.connectTimeoutMs),l=()=>{clearTimeout(n),e();try{this.ws?.close()}catch{}this.status=c.Closed,this.resolveReady(!1),this.wantReconnect&&this.scheduleReconnect()};t.addEventListener("abort",l)}catch{this.status=c.Closed,this.resolveReady(!1),this.scheduleReconnect()}}async sendMessage(t){if(this.status!==c.Ready||!this.ws)throw new Error("Connection not ready");this.ws.send(t),this.stats.sent++,this.lastActivity=Date.now(),this.stats.lastActivity=this.lastActivity}async waitForReady(t=this.config.connectTimeoutMs??5e3){if(this.status!==c.Ready)return new Promise((e,s)=>{const a=setTimeout(()=>{this.removeReadyResolver(o),s(new Error("Timeout waiting for ready"))},t),o=r=>{clearTimeout(a),r?e():s(new Error("Connection closed"))};this.readyWaiters.push(o)})}async close(){this.wantReconnect=!1,this.abortController&&this.abortController.abort(),this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.closeWebSocket(),this.status=c.Closed,this.resolveReady(!1)}shouldCloseDueToInactivity(){return Date.now()-this.lastActivity>(this.config.idleTimeoutMs??3e5)}resolveReady(t){if(this.readyWaiters.length===0)return;const e=this.readyWaiters.slice();this.readyWaiters.length=0;for(const s of e)try{s(t)}catch{}}removeReadyResolver(t){const e=this.readyWaiters.indexOf(t);e>=0&&this.readyWaiters.splice(e,1)}closeWebSocket(){if(this.ws){try{this.ws.close(1e3,"Normal closure")}catch{}this.ws=null}}scheduleReconnect(){if(!this.wantReconnect||this.status!==c.Closed||!this.config.retry?.baseMs)return;const t=this.config.maxReconnectAttempts??2;if(t>0&&this.attempts>=t){this.givenUp=!0;return}const e=this.config.retry.baseMs,s=this.config.retry.maxMs??1e4,a=this.config.retry.multiplier??1.6,o=this.config.retry.jitter??.1,r=Math.min(e*Math.pow(a,this.attempts),s)*(1+(Math.random()-.5)*o*2);this.reconnectTimer=setTimeout(()=>{this.attempts++,this.stats.reconnects=this.attempts,this.connect()},r)}extractSubId(t){let e=0;const s=t.length;for(;e<s&&t.charCodeAt(e)<=32;)e++;if(e>=s||t[e]!=="[")return null;for(e++;e<s&&t.charCodeAt(e)<=32;)e++;if(e>=s)return null;if(t[e]==='"'){for(e++;e<s&&t[e]!=='"';)e++;if(e>=s)return null;e++}else for(;e<s&&t[e]!==","&&t[e]!=="]";)e++;for(;e<s&&t[e]!==",";)e++;if(e>=s||t[e]!==",")return null;for(e++;e<s&&t.charCodeAt(e)<=32;)e++;if(e>=s)return null;if(t[e]==='"'){e++;const a=e;for(;e<s&&t[e]!=='"';)e++;return e>s?null:t.slice(a,e)}return null}}class U{constructor(t){this.connections=new Map,this.disabledRelays=new Set,this.nextAllowed=new Map,this.subCounts=new Map,this.disconnectTimers=new Map,this.cooldownMs=6e4,this.closeDelayMs=1e3,this.config={maxReconnectAttempts:2,...t}}now(){return Date.now()}detectKind(t){const e=t.match(/^\s*\[\s*"([^"]+)"/);if(!e)return"OTHER";const s=e[1].toUpperCase();return s==="REQ"?"REQ":s==="CLOSE"?"CLOSE":"OTHER"}getCount(t){return this.subCounts.get(t)??0}setCount(t,e){this.subCounts.set(t,Math.max(0,e))}cancelPendingDisconnect(t){const e=this.disconnectTimers.get(t);typeof e=="number"&&(clearTimeout(e),this.disconnectTimers.delete(t))}scheduleDisconnectIfIdle(t){if(this.disconnectTimers.has(t))return;const e=setTimeout(async()=>{this.disconnectTimers.delete(t),this.getCount(t)===0&&await this.disconnect(t)},this.closeDelayMs);this.disconnectTimers.set(t,e)}bumpCount(t,e){const s=this.getCount(t)+e;this.setCount(t,s),e>0?this.cancelPendingDisconnect(t):e<0&&this.getCount(t)===0&&this.scheduleDisconnectIfIdle(t)}giveUpOrCooldown(t,e){e?.hasGivenUp()?(this.disabledRelays.has(t)||console.warn(`[registry] disabling relay ${t}: max attempts reached`),this.disabledRelays.add(t),this.nextAllowed.set(t,this.now()+this.cooldownMs)):this.nextAllowed.set(t,this.now()+Math.min(this.cooldownMs,1e4))}isCoolingDown(t){const e=this.nextAllowed.get(t)??0;return this.now()<e}async ensureConnection(t){if(this.disabledRelays.has(t))throw new Error(`Relay disabled: ${t}`);if(this.isCoolingDown(t))throw new Error(`Relay ${t} cooling down until ${new Date(this.nextAllowed.get(t)).toISOString()}`);let e=this.connections.get(t);if(e?e.getStatus()!==c.Ready&&e.connect():(e=new M(t,this.config),this.connections.set(t,e),e.connect()),e.getStatus()!==c.Ready)try{await e.waitForReady(this.config.connectTimeoutMs??5e3)}catch(s){throw this.giveUpOrCooldown(t,e),s}if(e.getStatus()!==c.Ready)throw this.giveUpOrCooldown(t,e),new Error(`Relay ${t} not ready`);return e}async sendFrame(t,e){if(this.disabledRelays.has(t)||this.isCoolingDown(t))return;const s=this.detectKind(e),a=await this.ensureConnection(t);try{await a.sendMessage(e)}catch(o){throw this.giveUpOrCooldown(t,a),await this.disconnect(t),o}s==="REQ"?this.bumpCount(t,1):s==="CLOSE"&&this.bumpCount(t,-1)}async sendAllFramesToRelay(t,e){for(const s of e)await this.sendFrame(t,s)}async sendToRelays(t,e){const s=[];for(const a of t)this.disabledRelays.has(a)||this.isCoolingDown(a)||s.push(this.sendAllFramesToRelay(a,e).catch(o=>{console.error(`[registry] failed to send to ${a}:`,o)}));await Promise.allSettled(s)}async disconnect(t){const e=this.connections.get(t);e&&(await e.close(),this.connections.delete(t)),this.cancelPendingDisconnect(t),this.subCounts.delete(t)}async disconnectAll(){for(const[t]of this.connections)await this.disconnect(t)}enableRelay(t){this.disabledRelays.delete(t),this.nextAllowed.delete(t)}isRelayDisabled(t){return this.disabledRelays.has(t)}getActiveReqCount(t){return this.getCount(t)}getConnectionStatus(t){const e=this.connections.get(t);return e?e.getStatus():void 0}getAllStatuses(){return new Map(Array.from(this.connections.entries()).map(([t,e])=>[t,e.getStatus()]))}}const T=new TextEncoder,b=new Map;function D(i){const t=b.get(i);if(t)return t;const e=T.encode(i);return b.set(i,e),e}function x(i,t,e){const s=D(t),a=T.encode(e),o=2+s.length+4+a.length,r=new Uint8Array(o),n=new DataView(r.buffer,r.byteOffset,r.byteLength);let l=0;n.setUint16(l,s.length,!1),l+=2,r.set(s,l),l+=s.length,n.setUint32(l,a.length,!1),l+=4,r.set(a,l),i.write(r)}function V(i){let t=0,e=i.length;for(;t<e&&i.charCodeAt(t)<=32;)t++;if(t>=e||i[t]!=="[")return null;for(t++;t<e&&i.charCodeAt(t)<=32;)t++;if(t>=e)return null;if(i[t]==='"'){for(t++;t<e&&i[t]!=='"';)t++;if(t>=e)return null;t++}else for(;t<e&&i[t]!==","&&i[t]!=="]";)t++;for(;t<e&&i[t]!==",";)t++;if(t>=e||i[t]!==",")return null;for(t++;t<e&&i.charCodeAt(t)<=32;)t++;if(t>=e)return null;if(i[t]==='"'){t++;const s=t;for(;t<e&&i[t]!=='"';)t++;return t>e?null:i.slice(s,t)}return null}let f=[],p=[],w=null;const v=new Map,E=new TextDecoder;function H(i){const t=i.includes("_")?i.split("_")[1]??"":i;let e=0;for(let s=0;s<t.length;s++)e=(e<<5)-e+t.charCodeAt(s);return Math.abs(e)%p.length}function O(i){let t=v.get(i);return t||(t=p[H(i)],v.set(i,t),t)}let A=0,d=10;const m=10,S=1e3;let y=null;function R(){y=setTimeout(F,d)}function F(){let i=0;const t=f.length;if(t===0)return d=Math.min(d*2,S),R();let e;do{e=!1;for(let s=0;s<t;s++){const a=(A+s)%t,o=f[a].read();if(!o)continue;e=!0,i++;const r=E.decode(o);let n;try{n=JSON.parse(r)}catch{continue}!Array.isArray(n.relays)||!Array.isArray(n.frames)||(w?.sendToRelays(n.relays,n.frames).catch(console.error),A=(a+1)%t)}}while(e);d=i>0?m:Math.min(d*2,S),R()}self.addEventListener("message",i=>{const t=i.data;if(!t||t.type==="init"){f=t.payload.inRings.map(a=>new C(a)),p=t.payload.outRings.map(a=>new C(a)),w=new U(t.payload.relayConfig||{});const e=(a,o,r)=>{const n=o??V(r);n&&x(O(n),a,r)},s=w.ensureConnection.bind(w);w.ensureConnection=async a=>{const o=await s(a);return o.messageHandler||o.setMessageHandler(e),o},d=m,y!==null&&clearTimeout(y);return}if(t?.type==="wake"){d=m,y!==null&&(clearTimeout(y),y=null),R();return}});
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/ws/types.ts","../../src/ws/connection.ts","../../src/ws/registry.ts","../../src/ws/index.ts"],"sourcesContent":["export enum ConnectionStatus {\n Idle = 'idle',\n Connecting = 'connecting',\n Ready = 'ready',\n Closing = 'closing',\n Closed = 'closed',\n Error = 'error',\n}\n\nexport enum MsgKind {\n Unknown = 0,\n Event = 1,\n Eose = 2,\n Ok = 3,\n Closed = 4,\n Notice = 5,\n Auth = 6,\n}\n\n // MsgKind is defined in FlatBuffers schema; import from generated code\n // export type { MsgKind } from '../fb/worker_messages_generated';\n\nexport interface RelayConfig {\n connectTimeoutMs?: number;\n writeTimeoutMs?: number;\n retryBaseMs?: number;\n retryMaxMs?: number;\n retryMultiplier?: number;\n retryJitter?: number;\n retry?: {\n baseMs: number;\n maxMs: number;\n multiplier: number;\n jitter: number;\n };\n idleTimeoutMs?: number;\n}\n\nexport interface RelayStats {\n sent: number;\n received: number;\n reconnects: number;\n lastActivity: number; // timestamp\n uptime?: number;\n dropped: number; // for ring buffer overwrites\n}\n\nexport interface InboundEnvelope {\n relays: string[];\n frames: string[];\n}\n\nexport interface WorkerLine {\n relay: {\n url: string;\n };\n kind: number; // MsgKind from generated\n sub_id?: string;\n raw: Uint8Array; // UTF-8 bytes\n}\n\nexport type FrameCallback = (frame: string) => void;\nexport type MessageHandler = (url: string, kind: MsgKind, subId: string | null, rawText: string) => void;\n","import { ConnectionStatus, RelayConfig, RelayStats } from './types';\n\n// Callback invoked for every incoming websocket text frame\nexport type MessageHandler = (\n\turl: string,\n\tsubId: string | null, // present for EVENT/EOSE/CLOSED\n\trawText: string\n) => void;\n\nexport class RelayConnection {\n\tprivate wantReconnect = true;\n\tprivate url: string;\n\tprivate config: RelayConfig;\n\tprivate status: ConnectionStatus = ConnectionStatus.Closed;\n\tprivate ws: WebSocket | null = null;\n\tprivate reconnectTimer: number | null = null;\n\tprivate abortController: AbortController | null = null;\n\n\tprivate attempts: number = 0; // reconnection attempts after first failure\n\tprivate givenUp: boolean = false; // set when attempts reached cap\n\tprivate lastActivity: number = Date.now();\n\tprivate stats: RelayStats = {\n\t\tdropped: 0,\n\t\tsent: 0,\n\t\treceived: 0,\n\t\treconnects: 0, // mirrors attempts for visibility\n\t\tlastActivity: Date.now()\n\t};\n\tprivate readyWaiters: Array<(ok: boolean) => void> = [];\n\tpublic messageHandler: MessageHandler | null = null;\n\n\tconstructor(url: string, config: Partial<RelayConfig> = {}) {\n\t\tthis.url = url;\n\t\tthis.config = {\n\t\t\tconnectTimeoutMs: 5_000,\n\t\t\twriteTimeoutMs: 10_000,\n\t\t\tretry: {\n\t\t\t\tbaseMs: 300,\n\t\t\t\tmaxMs: 10_000,\n\t\t\t\tmultiplier: 1.6,\n\t\t\t\tjitter: 0.1\n\t\t\t},\n\t\t\tmaxReconnectAttempts: 2, // default: 2 retries\n\t\t\tidleTimeoutMs: 300_000,\n\t\t\t...config\n\t\t};\n\t}\n\n\tgetUrl(): string {\n\t\treturn this.url;\n\t}\n\tgetStatus(): ConnectionStatus {\n\t\treturn this.status;\n\t}\n\tgetStats(): RelayStats {\n\t\treturn { ...this.stats, reconnects: this.attempts, lastActivity: this.lastActivity };\n\t}\n\tgetLastActivity(): number {\n\t\treturn this.lastActivity;\n\t}\n\thasGivenUp(): boolean {\n\t\treturn this.givenUp;\n\t}\n\n\tsetMessageHandler(handler: MessageHandler): void {\n\t\tthis.messageHandler = handler;\n\t}\n\n\t// Fire-and-forget connect. It never throws. Use waitForReady() to await.\n\tconnect(): void {\n\t\tif (this.givenUp) return;\n\t\tif (this.status === ConnectionStatus.Connecting || this.status === ConnectionStatus.Ready)\n\t\t\treturn;\n\n\t\t// Clear pending reconnect\n\t\tif (this.reconnectTimer) {\n\t\t\tclearTimeout(this.reconnectTimer);\n\t\t\tthis.reconnectTimer = null;\n\t\t}\n\n\t\tthis.status = ConnectionStatus.Connecting;\n\t\tthis.abortController = new AbortController();\n\t\tconst signal = this.abortController.signal;\n\n\t\ttry {\n\t\t\tthis.ws = new WebSocket(this.url);\n\t\t\tthis.ws.binaryType = 'arraybuffer';\n\n\t\t\tconst cleanup = () => {\n\t\t\t\tif (!this.ws) return;\n\t\t\t\tthis.ws.onopen = null as any;\n\t\t\t\tthis.ws.onclose = null as any;\n\t\t\t\tthis.ws.onerror = null as any;\n\t\t\t\tthis.ws.onmessage = null as any;\n\t\t\t};\n\n\t\t\tconst onOpen = () => {\n\t\t\t\t// Clear connect timeout\n\t\t\t\tclearTimeout(to);\n\t\t\t\t// Success: reset attempts and flags\n\t\t\t\tthis.status = ConnectionStatus.Ready;\n\t\t\t\tthis.attempts = 0;\n\t\t\t\tthis.givenUp = false;\n\t\t\t\tthis.lastActivity = Date.now();\n\t\t\t\tthis.stats.lastActivity = this.lastActivity;\n\t\t\t\tthis.resolveReady(true);\n\t\t\t};\n\n\t\t\tconst onClose = (ev: CloseEvent) => {\n\t\t\t\t// Clear connect timeout\n\t\t\t\tclearTimeout(to);\n\t\t\t\tcleanup();\n\t\t\t\tthis.status = ConnectionStatus.Closed;\n\t\t\t\tthis.resolveReady(false);\n\t\t\t\tif (ev.code !== 1000) {\n\t\t\t\t\tthis.scheduleReconnect();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst onError = (_ev: Event) => {\n\t\t\t\t// Clear connect timeout\n\t\t\t\tclearTimeout(to);\n\t\t\t\t// Treat like close; don’t throw\n\t\t\t\tcleanup();\n\t\t\t\tthis.status = ConnectionStatus.Closed;\n\t\t\t\tthis.resolveReady(false);\n\t\t\t\tthis.scheduleReconnect();\n\t\t\t};\n\n\t\t\tconst onMessage = (event: MessageEvent) => {\n\t\t\t\tthis.lastActivity = Date.now();\n\t\t\t\tthis.stats.lastActivity = this.lastActivity;\n\t\t\t\tthis.stats.received++;\n\n\t\t\t\tif (typeof event.data === 'string') {\n\t\t\t\t\tconst rawText = event.data;\n\t\t\t\t\tconst subId = this.extractSubId(rawText);\n\t\t\t\t\tif (this.messageHandler) {\n\t\t\t\t\t\tthis.messageHandler(this.url, subId, rawText);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Attach\n\t\t\tthis.ws.onopen = onOpen;\n\t\t\tthis.ws.onclose = onClose;\n\t\t\tthis.ws.onerror = onError;\n\t\t\tthis.ws.onmessage = onMessage;\n\n\t\t\t// Timeout and abort\n\t\t\tconst to = setTimeout(() => {\n\t\t\t\tif (this.status === ConnectionStatus.Connecting) {\n\t\t\t\t\tcleanup();\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.ws?.close();\n\t\t\t\t\t} catch {}\n\t\t\t\t\tthis.status = ConnectionStatus.Closed;\n\t\t\t\t\tthis.resolveReady(false);\n\t\t\t\t\tthis.scheduleReconnect();\n\t\t\t\t}\n\t\t\t}, this.config.connectTimeoutMs);\n\n\t\t\tconst onAbort = () => {\n\t\t\t\tclearTimeout(to);\n\t\t\t\tcleanup();\n\t\t\t\ttry {\n\t\t\t\t\tthis.ws?.close();\n\t\t\t\t} catch {}\n\t\t\t\tthis.status = ConnectionStatus.Closed;\n\t\t\t\tthis.resolveReady(false);\n\t\t\t\tif (this.wantReconnect) this.scheduleReconnect(); // guard here\n\t\t\t};\n\n\t\t\tsignal.addEventListener('abort', onAbort);\n\t\t} catch {\n\t\t\tthis.status = ConnectionStatus.Closed;\n\t\t\tthis.resolveReady(false);\n\t\t\tthis.scheduleReconnect();\n\t\t}\n\t}\n\n\tasync sendMessage(frame: string): Promise<void> {\n\t\tif (this.status !== ConnectionStatus.Ready || !this.ws) {\n\t\t\tthrow new Error('Connection not ready');\n\t\t}\n\t\tthis.ws.send(frame);\n\t\tthis.stats.sent++;\n\t\tthis.lastActivity = Date.now();\n\t\tthis.stats.lastActivity = this.lastActivity;\n\t}\n\n\tasync waitForReady(timeoutMs: number = this.config.connectTimeoutMs ?? 5_000): Promise<void> {\n\t\tif (this.status === ConnectionStatus.Ready) return;\n\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tthis.removeReadyResolver(resolver);\n\t\t\t\treject(new Error('Timeout waiting for ready'));\n\t\t\t}, timeoutMs);\n\n\t\t\tconst resolver = (ok: boolean) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tif (ok) resolve();\n\t\t\t\telse reject(new Error('Connection closed'));\n\t\t\t};\n\t\t\tthis.readyWaiters.push(resolver);\n\t\t});\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.wantReconnect = false;\n\t\tif (this.abortController) this.abortController.abort();\n\t\tif (this.reconnectTimer) {\n\t\t\tclearTimeout(this.reconnectTimer);\n\t\t\tthis.reconnectTimer = null;\n\t\t}\n\t\tthis.closeWebSocket();\n\t\tthis.status = ConnectionStatus.Closed;\n\t\tthis.resolveReady(false);\n\t}\n\n\tshouldCloseDueToInactivity(): boolean {\n\t\treturn Date.now() - this.lastActivity > (this.config.idleTimeoutMs ?? 300_000);\n\t}\n\n\t// Internals\n\n\tprivate resolveReady(ok: boolean) {\n\t\tif (this.readyWaiters.length === 0) return;\n\t\tconst waiters = this.readyWaiters.slice();\n\t\tthis.readyWaiters.length = 0;\n\t\tfor (const fn of waiters) {\n\t\t\ttry {\n\t\t\t\tfn(ok);\n\t\t\t} catch {}\n\t\t}\n\t}\n\n\tprivate removeReadyResolver(fn: (ok: boolean) => void) {\n\t\tconst idx = this.readyWaiters.indexOf(fn);\n\t\tif (idx >= 0) this.readyWaiters.splice(idx, 1);\n\t}\n\n\tprivate closeWebSocket() {\n\t\tif (this.ws) {\n\t\t\ttry {\n\t\t\t\tthis.ws.close(1000, 'Normal closure');\n\t\t\t} catch {}\n\t\t\tthis.ws = null;\n\t\t}\n\t}\n\n\tprivate scheduleReconnect(): void {\n\t\tif (!this.wantReconnect) return;\n\t\tif (this.status !== ConnectionStatus.Closed || !this.config.retry?.baseMs) return;\n\n\t\tconst cap = this.config.maxReconnectAttempts ?? 2;\n\t\tif (cap > 0 && this.attempts >= cap) {\n\t\t\tthis.givenUp = true;\n\t\t\treturn;\n\t\t}\n\n\t\tconst base = this.config.retry.baseMs;\n\t\tconst max = this.config.retry.maxMs ?? 10_000;\n\t\tconst mult = this.config.retry.multiplier ?? 1.6;\n\t\tconst jitter = this.config.retry.jitter ?? 0.1;\n\n\t\t// Calculate delay using current attempts\n\t\tconst delay =\n\t\t\tMath.min(base * Math.pow(mult, this.attempts), max) *\n\t\t\t(1 + (Math.random() - 0.5) * jitter * 2);\n\n\t\tthis.reconnectTimer = setTimeout(() => {\n\t\t\t// Increment attempts when actually trying again\n\t\t\tthis.attempts++;\n\t\t\tthis.stats.reconnects = this.attempts;\n\t\t\tthis.connect();\n\t\t}, delay) as unknown as number;\n\t}\n\n\tprivate extractSubId(s: string): string | null {\n\t\tlet i = 0;\n\t\tconst n = s.length;\n\n\t\t// Skip leading whitespace\n\t\twhile (i < n && s.charCodeAt(i) <= 32) i++;\n\t\tif (i >= n || s[i] !== '[') return null;\n\t\ti++;\n\n\t\t// Skip whitespace before first element\n\t\twhile (i < n && s.charCodeAt(i) <= 32) i++;\n\t\tif (i >= n) return null;\n\n\t\t// Skip first element (kind or similar)\n\t\tif (s[i] === '\"') {\n\t\t\t// Fast-skip a quoted string (no escape handling, consistent with existing code)\n\t\t\ti++;\n\t\t\twhile (i < n && s[i] !== '\"') i++;\n\t\t\tif (i >= n) return null;\n\t\t\ti++; // past closing quote\n\t\t} else {\n\t\t\t// Non-quoted first element; skip until comma or end of array\n\t\t\twhile (i < n && s[i] !== ',' && s[i] !== ']') i++;\n\t\t}\n\n\t\t// Move to the comma after first element\n\t\twhile (i < n && s[i] !== ',') i++;\n\t\tif (i >= n || s[i] !== ',') return null;\n\t\ti++; // skip comma\n\n\t\t// Skip whitespace before second element\n\t\twhile (i < n && s.charCodeAt(i) <= 32) i++;\n\t\tif (i >= n) return null;\n\n\t\t// Extract second element only if it's a quoted string\n\t\tif (s[i] === '\"') {\n\t\t\ti++;\n\t\t\tconst start = i;\n\t\t\twhile (i < n && s[i] !== '\"') i++;\n\t\t\tif (i > n) return null;\n\t\t\treturn s.slice(start, i);\n\t\t}\n\t\treturn null;\n\t}\n}\n","import { RelayConfig, ConnectionStatus } from './types';\nimport { RelayConnection } from './connection';\n\nexport class ConnectionRegistry {\n\tprivate connections = new Map<string, RelayConnection>();\n\tprivate disabledRelays = new Set<string>();\n\tprivate nextAllowed = new Map<string, number>(); // cooldown timestamps per URL (ms)\n\tprivate subCounts = new Map<string, number>(); // active subscription count per URL\n\tprivate disconnectTimers = new Map<string, number>(); // delayed disconnect timers\n\tprivate config: RelayConfig;\n\n\tprivate readonly cooldownMs = 60_000; // after failures\n\tprivate readonly closeDelayMs = 1_000; // after last CLOSE\n\n\tconstructor(config: RelayConfig) {\n\t\tthis.config = { maxReconnectAttempts: 2, ...config };\n\t}\n\n\tprivate now(): number {\n\t\treturn Date.now();\n\t}\n\n\tprivate detectKind(frame: string): 'REQ' | 'CLOSE' | 'OTHER' {\n\t\tconst m = frame.match(/^\\s*\\[\\s*\"([^\"]+)\"/);\n\t\tif (!m) return 'OTHER';\n\t\tconst k = m[1].toUpperCase();\n\t\tif (k === 'REQ') return 'REQ';\n\t\tif (k === 'CLOSE') return 'CLOSE';\n\t\treturn 'OTHER';\n\t}\n\n\tprivate getCount(url: string): number {\n\t\treturn this.subCounts.get(url) ?? 0;\n\t}\n\tprivate setCount(url: string, value: number): void {\n\t\tthis.subCounts.set(url, Math.max(0, value));\n\t}\n\tprivate cancelPendingDisconnect(url: string): void {\n\t\tconst id = this.disconnectTimers.get(url);\n\t\tif (typeof id === 'number') {\n\t\t\tclearTimeout(id);\n\t\t\tthis.disconnectTimers.delete(url);\n\t\t}\n\t}\n\tprivate scheduleDisconnectIfIdle(url: string): void {\n\t\tif (this.disconnectTimers.has(url)) return;\n\t\tconst id = setTimeout(async () => {\n\t\t\tthis.disconnectTimers.delete(url);\n\t\t\tif (this.getCount(url) === 0) {\n\t\t\t\tawait this.disconnect(url);\n\t\t\t}\n\t\t}, this.closeDelayMs) as unknown as number;\n\t\tthis.disconnectTimers.set(url, id);\n\t}\n\tprivate bumpCount(url: string, delta: number): void {\n\t\tconst next = this.getCount(url) + delta;\n\t\tthis.setCount(url, next);\n\t\tif (delta > 0) {\n\t\t\tthis.cancelPendingDisconnect(url);\n\t\t} else if (delta < 0 && this.getCount(url) === 0) {\n\t\t\tthis.scheduleDisconnectIfIdle(url);\n\t\t}\n\t}\n\n\tprivate giveUpOrCooldown(url: string, conn?: RelayConnection) {\n\t\tif (conn?.hasGivenUp()) {\n\t\t\tif (!this.disabledRelays.has(url)) {\n\t\t\t\tconsole.warn(`[registry] disabling relay ${url}: max attempts reached`);\n\t\t\t}\n\t\t\tthis.disabledRelays.add(url);\n\t\t\tthis.nextAllowed.set(url, this.now() + this.cooldownMs);\n\t\t} else {\n\t\t\tthis.nextAllowed.set(url, this.now() + Math.min(this.cooldownMs, 10_000));\n\t\t}\n\t}\n\n\tprivate isCoolingDown(url: string): boolean {\n\t\tconst at = this.nextAllowed.get(url) ?? 0;\n\t\treturn this.now() < at;\n\t}\n\n\tasync ensureConnection(url: string): Promise<RelayConnection> {\n\t\tif (this.disabledRelays.has(url)) {\n\t\t\tthrow new Error(`Relay disabled: ${url}`);\n\t\t}\n\t\tif (this.isCoolingDown(url)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Relay ${url} cooling down until ${new Date(this.nextAllowed.get(url)!).toISOString()}`\n\t\t\t);\n\t\t}\n\n\t\tlet conn = this.connections.get(url);\n\t\tif (!conn) {\n\t\t\tconn = new RelayConnection(url, this.config);\n\t\t\tthis.connections.set(url, conn);\n\t\t\tconn.connect(); // fire-and-forget\n\t\t} else if (conn.getStatus() !== ConnectionStatus.Ready) {\n\t\t\t// nudge reconnect on existing connection\n\t\t\tconn.connect();\n\t\t}\n\n\t\tif (conn.getStatus() !== ConnectionStatus.Ready) {\n\t\t\ttry {\n\t\t\t\tawait conn.waitForReady(this.config.connectTimeoutMs ?? 5_000);\n\t\t\t} catch (e) {\n\t\t\t\tthis.giveUpOrCooldown(url, conn);\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t}\n\n\t\tif (conn.getStatus() !== ConnectionStatus.Ready) {\n\t\t\tthis.giveUpOrCooldown(url, conn);\n\t\t\tthrow new Error(`Relay ${url} not ready`);\n\t\t}\n\n\t\treturn conn;\n\t}\n\n\tasync sendFrame(url: string, frame: string): Promise<void> {\n\t\tif (this.disabledRelays.has(url) || this.isCoolingDown(url)) return;\n\n\t\tconst kind = this.detectKind(frame);\n\t\tconst conn = await this.ensureConnection(url);\n\n\t\ttry {\n\t\t\tawait conn.sendMessage(frame);\n\t\t} catch (e) {\n\t\t\tthis.giveUpOrCooldown(url, conn);\n\t\t\tawait this.disconnect(url);\n\t\t\tthrow e;\n\t\t}\n\n\t\tif (kind === 'REQ') this.bumpCount(url, +1);\n\t\telse if (kind === 'CLOSE') this.bumpCount(url, -1);\n\t}\n\n\tprivate async sendAllFramesToRelay(url: string, frames: string[]): Promise<void> {\n\t\tfor (const frame of frames) {\n\t\t\tawait this.sendFrame(url, frame);\n\t\t}\n\t}\n\n\tasync sendToRelays(relays: string[], frames: string[]): Promise<void> {\n\t\tconst tasks: Promise<void>[] = [];\n\t\tfor (const url of relays) {\n\t\t\tif (this.disabledRelays.has(url) || this.isCoolingDown(url)) continue;\n\n\t\t\ttasks.push(\n\t\t\t\tthis.sendAllFramesToRelay(url, frames).catch((error) => {\n\t\t\t\t\tconsole.error(`[registry] failed to send to ${url}:`, error);\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\n\t\tawait Promise.allSettled(tasks);\n\t}\n\n\tasync disconnect(url: string): Promise<void> {\n\t\tconst connection = this.connections.get(url);\n\t\tif (connection) {\n\t\t\tawait connection.close();\n\t\t\tthis.connections.delete(url);\n\t\t}\n\t\tthis.cancelPendingDisconnect(url);\n\t\tthis.subCounts.delete(url);\n\t}\n\n\tasync disconnectAll(): Promise<void> {\n\t\tfor (const [url] of this.connections) {\n\t\t\tawait this.disconnect(url);\n\t\t}\n\t}\n\n\tenableRelay(url: string): void {\n\t\tthis.disabledRelays.delete(url);\n\t\tthis.nextAllowed.delete(url);\n\t}\n\n\tisRelayDisabled(url: string): boolean {\n\t\treturn this.disabledRelays.has(url);\n\t}\n\n\tgetActiveReqCount(url: string): number {\n\t\treturn this.getCount(url);\n\t}\n\n\tgetConnectionStatus(url: string): ConnectionStatus | undefined {\n\t\tconst connection = this.connections.get(url);\n\t\treturn connection ? connection.getStatus() : undefined;\n\t}\n\n\tgetAllStatuses(): Map<string, ConnectionStatus> {\n\t\treturn new Map(\n\t\t\tArray.from(this.connections.entries()).map(([url, conn]) => [url, conn.getStatus()])\n\t\t);\n\t}\n}\n","/* Worker runtime (dedicated Web Worker, module) */\nimport { ByteRingBuffer } from 'src/ws/ring-buffer';\nimport { ConnectionRegistry } from 'src/ws/registry';\n\nconst __encoder = new TextEncoder();\nconst __urlBytesCache = new Map<string, Uint8Array>();\nfunction __getUrlBytes(url: string): Uint8Array {\n\tconst cached = __urlBytesCache.get(url);\n\tif (cached) return cached;\n\tconst bytes = __encoder.encode(url);\n\t__urlBytesCache.set(url, bytes);\n\treturn bytes;\n}\n\nfunction writeEnvelope(outputRing: ByteRingBuffer, url: string, rawText: string): void {\n\tconst urlBytes = __getUrlBytes(url);\n\tconst rawBytes = __encoder.encode(rawText);\n\tconst totalLen = 2 + urlBytes.length + 4 + rawBytes.length;\n\tconst out = new Uint8Array(totalLen);\n\tconst view = new DataView(out.buffer, out.byteOffset, out.byteLength);\n\tlet o = 0;\n\tview.setUint16(o, urlBytes.length, false);\n\to += 2;\n\tout.set(urlBytes, o);\n\to += urlBytes.length;\n\tview.setUint32(o, rawBytes.length, false);\n\to += 4;\n\tout.set(rawBytes, o);\n\toutputRing.write(out);\n}\n\nfunction extractSubIdFast(s: string): string | null {\n\tlet i = 0,\n\t\tn = s.length;\n\twhile (i < n && s.charCodeAt(i) <= 32) i++;\n\tif (i >= n || s[i] !== '[') return null;\n\ti++;\n\twhile (i < n && s.charCodeAt(i) <= 32) i++;\n\tif (i >= n) return null;\n\tif (s[i] === '\"') {\n\t\ti++;\n\t\twhile (i < n && s[i] !== '\"') i++;\n\t\tif (i >= n) return null;\n\t\ti++;\n\t} else {\n\t\twhile (i < n && s[i] !== ',' && s[i] !== ']') i++;\n\t}\n\twhile (i < n && s[i] !== ',') i++;\n\tif (i >= n || s[i] !== ',') return null;\n\ti++;\n\twhile (i < n && s.charCodeAt(i) <= 32) i++;\n\tif (i >= n) return null;\n\tif (s[i] === '\"') {\n\t\ti++;\n\t\tconst start = i;\n\t\twhile (i < n && s[i] !== '\"') i++;\n\t\tif (i > n) return null;\n\t\treturn s.slice(start, i);\n\t}\n\treturn null;\n}\n\ntype InitMsg = {\n\ttype: 'init';\n\tpayload: {\n\t\tinRings: SharedArrayBuffer[];\n\t\toutRings: SharedArrayBuffer[];\n\t\trelayConfig: any;\n\t};\n};\n\nlet inputRings: ByteRingBuffer[] = [];\nlet outputRings: ByteRingBuffer[] = [];\nlet registry: ConnectionRegistry | null = null;\nconst subIdToRing = new Map<string, ByteRingBuffer>();\nconst decoder = new TextDecoder();\n\nfunction hashSubId(sub_id: string): number {\n\tconst target = sub_id.includes('_') ? (sub_id.split('_')[1] ?? '') : sub_id;\n\tlet hash = 0;\n\tfor (let i = 0; i < target.length; i++) hash = (hash << 5) - hash + target.charCodeAt(i);\n\treturn Math.abs(hash) % outputRings.length;\n}\n\nfunction getOutRingForSubId(subId: string): ByteRingBuffer {\n\tlet ring = subIdToRing.get(subId);\n\tif (ring) return ring;\n\tring = outputRings[hashSubId(subId)];\n\tsubIdToRing.set(subId, ring);\n\treturn ring;\n}\n\nlet lastRingIndex = 0;\nlet backoffMs = 10;\nconst MIN_BACKOFF_MS = 10;\nconst MAX_BACKOFF_MS = 1000;\nlet loopTimer: number | null = null;\n\nfunction scheduleLoop() {\n\tloopTimer = setTimeout(processLoop, backoffMs) as unknown as number;\n}\n\nfunction processLoop() {\n\tlet processed = 0;\n\tconst ringCount = inputRings.length;\n\tif (ringCount === 0) {\n\t\tbackoffMs = Math.min(backoffMs * 2, MAX_BACKOFF_MS);\n\t\treturn scheduleLoop();\n\t}\n\n\tlet madeProgress: boolean;\n\tdo {\n\t\tmadeProgress = false;\n\t\tfor (let i = 0; i < ringCount; i++) {\n\t\t\tconst idx = (lastRingIndex + i) % ringCount;\n\t\t\tconst ring = inputRings[idx];\n\t\t\tconst record = ring.read();\n\t\t\tif (!record) continue;\n\n\t\t\tmadeProgress = true;\n\t\t\tprocessed++;\n\n\t\t\tconst envelopeStr = decoder.decode(record);\n\t\t\tlet envelope: any;\n\t\t\ttry {\n\t\t\t\tenvelope = JSON.parse(envelopeStr);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!Array.isArray(envelope.relays) || !Array.isArray(envelope.frames)) continue;\n\n\t\t\tregistry?.sendToRelays(envelope.relays, envelope.frames).catch(console.error);\n\t\t\tlastRingIndex = (idx + 1) % ringCount;\n\t\t}\n\t} while (madeProgress);\n\n\tbackoffMs = processed > 0 ? MIN_BACKOFF_MS : Math.min(backoffMs * 2, MAX_BACKOFF_MS);\n\tscheduleLoop();\n}\n\nself.addEventListener('message', (evt: MessageEvent<InitMsg>) => {\n\tconst msg = evt.data;\n\tif (!msg || msg.type === 'init') {\n\t\tinputRings = msg.payload.inRings.map((s) => new ByteRingBuffer(s));\n\t\toutputRings = msg.payload.outRings.map((s) => new ByteRingBuffer(s));\n\t\tregistry = new ConnectionRegistry(msg.payload.relayConfig || {});\n\n\t\tconst onIncoming = (url: string, subId: string | null, rawText: string) => {\n\t\t\tconst sid = subId ?? extractSubIdFast(rawText);\n\t\t\tif (sid) writeEnvelope(getOutRingForSubId(sid), url, rawText);\n\t\t};\n\n\t\tconst originalEnsure = registry.ensureConnection.bind(registry);\n\t\tregistry.ensureConnection = async (url: string) => {\n\t\t\tconst conn = await originalEnsure(url);\n\t\t\tif (!conn.messageHandler) conn.setMessageHandler(onIncoming);\n\t\t\treturn conn;\n\t\t};\n\n\t\t// Kick off the polling loop (no Atomics)\n\t\tbackoffMs = MIN_BACKOFF_MS;\n\t\tif (loopTimer !== null) clearTimeout(loopTimer as any);\n\t\t// scheduleLoop();\n\t\treturn;\n\t}\n\n\t// NEW: minimal wake signal to reset backoff and run soon\n\tif (msg?.type === 'wake') {\n\t\t// ensure these are in scope: backoffMs, MIN_BACKOFF_MS, loopTimer, scheduleLoop\n\t\tbackoffMs = MIN_BACKOFF_MS;\n\t\tif (loopTimer !== null) {\n\t\t\tclearTimeout(loopTimer as any);\n\t\t\tloopTimer = null;\n\t\t}\n\t\tscheduleLoop();\n\t\treturn;\n\t}\n});\n"],"names":["ConnectionStatus","RelayConnection","url","config","handler","signal","cleanup","onOpen","to","onClose","ev","onError","_ev","onMessage","event","rawText","subId","onAbort","frame","timeoutMs","resolve","reject","timer","resolver","ok","waiters","fn","idx","cap","base","max","mult","jitter","delay","s","i","n","start","ConnectionRegistry","m","k","value","id","delta","next","conn","at","e","kind","frames","relays","tasks","error","connection","__encoder","__urlBytesCache","__getUrlBytes","cached","bytes","writeEnvelope","outputRing","urlBytes","rawBytes","totalLen","out","view","o","extractSubIdFast","inputRings","outputRings","registry","subIdToRing","decoder","hashSubId","sub_id","target","hash","getOutRingForSubId","ring","lastRingIndex","backoffMs","MIN_BACKOFF_MS","MAX_BACKOFF_MS","loopTimer","scheduleLoop","processLoop","processed","ringCount","madeProgress","record","envelopeStr","envelope","evt","msg","ByteRingBuffer","onIncoming","sid","originalEnsure"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/ws/ring-buffer.ts","../../src/ws/types.ts","../../src/ws/connection.ts","../../src/ws/registry.ts","../../src/ws/index.ts"],"sourcesContent":["export class ByteRingBuffer {\n\tprivate readonly sab: SharedArrayBuffer;\n\tprivate readonly dataView: DataView;\n\tprivate readonly dataStart: number = 32;\n\tprivate readonly capacity: number;\n\tprivate dropped: number = 0;\n\n\tconstructor(buffer: SharedArrayBuffer) {\n\t\tthis.sab = buffer;\n\t\tthis.dataView = new DataView(buffer);\n\t\tthis.capacity = this.dataView.getUint32(0, true); // little-endian\n\n\t\t// Read initial state (assume Rust sets capacity, head=0, tail=0, seq=0)\n\t\t// We don't reset here; assume initialized\n\t}\n\n\tprivate getHead(): number {\n\t\treturn this.dataView.getUint32(4, true) % this.capacity;\n\t}\n\n\tprivate setHead(value: number): void {\n\t\tthis.dataView.setUint32(4, value % this.capacity, true);\n\t}\n\n\tprivate getTail(): number {\n\t\treturn this.dataView.getUint32(8, true) % this.capacity;\n\t}\n\n\tprivate setTail(value: number): void {\n\t\tthis.dataView.setUint32(8, value % this.capacity, true);\n\t}\n\n\tprivate getSeq(): number {\n\t\treturn this.dataView.getUint32(12, true);\n\t}\n\n\tprivate setSeq(value: number): void {\n\t\tthis.dataView.setUint32(12, value, true);\n\t}\n\n\tgetFreeSpace(): number {\n\t\tconst head = this.getHead();\n\t\tconst tail = this.getTail();\n\t\tconst used = (head - tail + this.capacity) % this.capacity;\n\t\treturn this.capacity - used;\n\t}\n\n\tgetDropped(): number {\n\t\treturn this.dropped;\n\t}\n\n\thasRecords(): boolean {\n\t\treturn this.getHead() !== this.getTail();\n\t}\n\n\treadNext(): { payload: Uint8Array } | null {\n\t\tconst p = this.read();\n\t\treturn p ? { payload: p } : null;\n\t}\n\n\t/**\n\t * Writes a payload to the ring buffer, overwriting old records if necessary.\n\t * Returns the sequence number if successful, -1 if dropped (couldn't make space).\n\t */\n\twrite(payload: Uint8Array): number {\n\t\tconst N = payload.byteLength;\n\t\tconst len = 8 + N; // type(2) + pad(2) + seq(4) + payload(N)\n\t\tconst totalSize = 4 + len + 4; // len + variable + trailer\n\n\t\t// Make space by skipping records\n\t\tlet droppedThisWrite = 0;\n\t\twhile (this.getFreeSpace() < totalSize) {\n\t\t\tif (!this.skipRecord()) {\n\t\t\t\t// Can't skip more (uncommitted record), drop this write\n\t\t\t\tthis.dropped += droppedThisWrite + 1;\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tdroppedThisWrite++;\n\t\t}\n\n\t\t// Enough space, write\n\t\tconst mySeq = this.getSeq() + 1;\n\t\tthis.setSeq(mySeq);\n\n\t\tlet writePos = this.getHead();\n\n\t\t// Write len\n\t\tthis.dataView.setUint32(this.dataStart + writePos, len, true);\n\t\twritePos = (writePos + 4) % this.capacity;\n\n\t\t// Write type (0)\n\t\tthis.dataView.setUint16(this.dataStart + writePos, 0, true);\n\t\twritePos = (writePos + 2) % this.capacity;\n\n\t\t// Write pad (0)\n\t\tthis.dataView.setUint16(this.dataStart + writePos, 0, true);\n\t\twritePos = (writePos + 2) % this.capacity;\n\n\t\t// Write seq\n\t\tthis.dataView.setUint32(this.dataStart + writePos, mySeq, true);\n\t\twritePos = (writePos + 4) % this.capacity;\n\n\t\t// Write payload (possibly wrapped)\n\t\tthis.copyBytes(writePos, payload, 0, N);\n\t\twritePos = (writePos + N) % this.capacity;\n\n\t\t// Write trailer (len)\n\t\tthis.dataView.setUint32(this.dataStart + writePos, len, true);\n\t\twritePos = (writePos + 4) % this.capacity;\n\n\t\t// Advance head\n\t\tthis.setHead(writePos);\n\n\t\tthis.dropped += droppedThisWrite;\n\t\treturn mySeq;\n\t}\n\n\t/**\n\t * Reads the next committed payload or null if none ready.\n\t * Advances tail on success.\n\t */\n\tread(): Uint8Array | null {\n\t\tlet readPos = this.getTail();\n\t\tif (readPos === this.getHead()) return null; // empty\n\n\t\tconst len = this.dataView.getUint32(this.dataStart + readPos, true);\n\t\tif (len === 0) return null;\n\n\t\tconst trailerPos = (readPos + 4 + len) % this.capacity;\n\t\tconst trailer = this.dataView.getUint32(this.dataStart + trailerPos, true);\n\n\t\tif (trailer !== len) return null; // not committed\n\n\t\t// Read variable part (len bytes from readPos + 4)\n\t\tconst variable = new Uint8Array(len);\n\t\tthis.copyFromRing((readPos + 4) % this.capacity, variable, 0, len);\n\n\t\t// Extract payload (skip type+pad+seq = 8 bytes)\n\t\tconst payload = variable.subarray(8);\n\n\t\t// Advance tail\n\t\tconst advance = 4 + len + 4; // len field + variable + trailer\n\t\tthis.setTail((this.getTail() + advance) % this.capacity);\n\n\t\treturn payload;\n\t}\n\n\tprivate skipRecord(): boolean {\n\t\tlet readPos = this.getTail();\n\t\tif (readPos === this.getHead()) return false; // empty\n\n\t\tconst len = this.dataView.getUint32(this.dataStart + readPos, true);\n\t\tif (len === 0) return false;\n\n\t\tconst trailerPos = (readPos + 4 + len) % this.capacity;\n\t\tconst trailer = this.dataView.getUint32(this.dataStart + trailerPos, true);\n\n\t\tif (trailer !== len) return false; // not committed\n\n\t\t// Skip by advancing tail\n\t\tconst advance = 4 + len + 4;\n\t\tthis.setTail((this.getTail() + advance) % this.capacity);\n\t\treturn true;\n\t}\n\n\tprivate copyBytes(\n\t\ttargetPos: number,\n\t\tsource: Uint8Array,\n\t\tsourceOffset: number,\n\t\tlength: number\n\t): void {\n\t\tlet remaining = length;\n\t\tlet srcOffset = sourceOffset;\n\t\tlet tgt = targetPos;\n\n\t\twhile (remaining > 0) {\n\t\t\tconst spaceToEnd = this.capacity - (tgt % this.capacity);\n\t\t\tconst chunkSize = Math.min(remaining, spaceToEnd);\n\t\t\tconst tgtAbs = this.dataStart + (tgt % this.capacity);\n\t\t\tconst srcChunk = source.subarray(srcOffset, srcOffset + chunkSize);\n\t\t\tnew Uint8Array(this.sab, tgtAbs, chunkSize).set(srcChunk);\n\t\t\tremaining -= chunkSize;\n\t\t\tsrcOffset += chunkSize;\n\t\t\ttgt += chunkSize;\n\t\t}\n\t}\n\n\tprivate copyFromRing(\n\t\tsourcePos: number,\n\t\ttarget: Uint8Array,\n\t\ttargetOffset: number,\n\t\tlength: number\n\t): void {\n\t\tlet remaining = length;\n\t\tlet tgtOffset = targetOffset;\n\t\tlet src = sourcePos;\n\n\t\twhile (remaining > 0) {\n\t\t\tconst spaceToEnd = this.capacity - (src % this.capacity);\n\t\t\tconst chunkSize = Math.min(remaining, spaceToEnd);\n\t\t\tconst srcAbs = this.dataStart + (src % this.capacity);\n\t\t\tconst srcChunk = new Uint8Array(this.sab, srcAbs, chunkSize);\n\t\t\ttarget.set(srcChunk, tgtOffset);\n\t\t\tremaining -= chunkSize;\n\t\t\ttgtOffset += chunkSize;\n\t\t\tsrc += chunkSize;\n\t\t}\n\t}\n}\n","export enum ConnectionStatus {\n Idle = 'idle',\n Connecting = 'connecting',\n Ready = 'ready',\n Closing = 'closing',\n Closed = 'closed',\n Error = 'error',\n}\n\nexport enum MsgKind {\n Unknown = 0,\n Event = 1,\n Eose = 2,\n Ok = 3,\n Closed = 4,\n Notice = 5,\n Auth = 6,\n}\n\n // MsgKind is defined in FlatBuffers schema; import from generated code\n // export type { MsgKind } from '../fb/worker_messages_generated';\n\nexport interface RelayConfig {\n connectTimeoutMs?: number;\n writeTimeoutMs?: number;\n retryBaseMs?: number;\n retryMaxMs?: number;\n retryMultiplier?: number;\n retryJitter?: number;\n retry?: {\n baseMs: number;\n maxMs: number;\n multiplier: number;\n jitter: number;\n };\n idleTimeoutMs?: number;\n}\n\nexport interface RelayStats {\n sent: number;\n received: number;\n reconnects: number;\n lastActivity: number; // timestamp\n uptime?: number;\n dropped: number; // for ring buffer overwrites\n}\n\nexport interface InboundEnvelope {\n relays: string[];\n frames: string[];\n}\n\nexport interface WorkerLine {\n relay: {\n url: string;\n };\n kind: number; // MsgKind from generated\n sub_id?: string;\n raw: Uint8Array; // UTF-8 bytes\n}\n\nexport type FrameCallback = (frame: string) => void;\nexport type MessageHandler = (url: string, kind: MsgKind, subId: string | null, rawText: string) => void;\n","import { ConnectionStatus, RelayConfig, RelayStats } from './types';\n\n// Callback invoked for every incoming websocket text frame\nexport type MessageHandler = (\n\turl: string,\n\tsubId: string | null, // present for EVENT/EOSE/CLOSED\n\trawText: string\n) => void;\n\nexport class RelayConnection {\n\tprivate wantReconnect = true;\n\tprivate url: string;\n\tprivate config: RelayConfig;\n\tprivate status: ConnectionStatus = ConnectionStatus.Closed;\n\tprivate ws: WebSocket | null = null;\n\tprivate reconnectTimer: number | null = null;\n\tprivate abortController: AbortController | null = null;\n\n\tprivate attempts: number = 0; // reconnection attempts after first failure\n\tprivate givenUp: boolean = false; // set when attempts reached cap\n\tprivate lastActivity: number = Date.now();\n\tprivate stats: RelayStats = {\n\t\tdropped: 0,\n\t\tsent: 0,\n\t\treceived: 0,\n\t\treconnects: 0, // mirrors attempts for visibility\n\t\tlastActivity: Date.now()\n\t};\n\tprivate readyWaiters: Array<(ok: boolean) => void> = [];\n\tpublic messageHandler: MessageHandler | null = null;\n\n\tconstructor(url: string, config: Partial<RelayConfig> = {}) {\n\t\tthis.url = url;\n\t\tthis.config = {\n\t\t\tconnectTimeoutMs: 5_000,\n\t\t\twriteTimeoutMs: 10_000,\n\t\t\tretry: {\n\t\t\t\tbaseMs: 300,\n\t\t\t\tmaxMs: 10_000,\n\t\t\t\tmultiplier: 1.6,\n\t\t\t\tjitter: 0.1\n\t\t\t},\n\t\t\tmaxReconnectAttempts: 2, // default: 2 retries\n\t\t\tidleTimeoutMs: 300_000,\n\t\t\t...config\n\t\t};\n\t}\n\n\tgetUrl(): string {\n\t\treturn this.url;\n\t}\n\tgetStatus(): ConnectionStatus {\n\t\treturn this.status;\n\t}\n\tgetStats(): RelayStats {\n\t\treturn { ...this.stats, reconnects: this.attempts, lastActivity: this.lastActivity };\n\t}\n\tgetLastActivity(): number {\n\t\treturn this.lastActivity;\n\t}\n\thasGivenUp(): boolean {\n\t\treturn this.givenUp;\n\t}\n\n\tsetMessageHandler(handler: MessageHandler): void {\n\t\tthis.messageHandler = handler;\n\t}\n\n\t// Fire-and-forget connect. It never throws. Use waitForReady() to await.\n\tconnect(): void {\n\t\tif (this.givenUp) return;\n\t\tif (this.status === ConnectionStatus.Connecting || this.status === ConnectionStatus.Ready)\n\t\t\treturn;\n\n\t\t// Clear pending reconnect\n\t\tif (this.reconnectTimer) {\n\t\t\tclearTimeout(this.reconnectTimer);\n\t\t\tthis.reconnectTimer = null;\n\t\t}\n\n\t\tthis.status = ConnectionStatus.Connecting;\n\t\tthis.abortController = new AbortController();\n\t\tconst signal = this.abortController.signal;\n\n\t\ttry {\n\t\t\tthis.ws = new WebSocket(this.url);\n\t\t\tthis.ws.binaryType = 'arraybuffer';\n\n\t\t\tconst cleanup = () => {\n\t\t\t\tif (!this.ws) return;\n\t\t\t\tthis.ws.onopen = null as any;\n\t\t\t\tthis.ws.onclose = null as any;\n\t\t\t\tthis.ws.onerror = null as any;\n\t\t\t\tthis.ws.onmessage = null as any;\n\t\t\t};\n\n\t\t\tconst onOpen = () => {\n\t\t\t\t// Clear connect timeout\n\t\t\t\tclearTimeout(to);\n\t\t\t\t// Success: reset attempts and flags\n\t\t\t\tthis.status = ConnectionStatus.Ready;\n\t\t\t\tthis.attempts = 0;\n\t\t\t\tthis.givenUp = false;\n\t\t\t\tthis.lastActivity = Date.now();\n\t\t\t\tthis.stats.lastActivity = this.lastActivity;\n\t\t\t\tthis.resolveReady(true);\n\t\t\t};\n\n\t\t\tconst onClose = (ev: CloseEvent) => {\n\t\t\t\t// Clear connect timeout\n\t\t\t\tclearTimeout(to);\n\t\t\t\tcleanup();\n\t\t\t\tthis.status = ConnectionStatus.Closed;\n\t\t\t\tthis.resolveReady(false);\n\t\t\t\tif (ev.code !== 1000) {\n\t\t\t\t\tthis.scheduleReconnect();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst onError = (_ev: Event) => {\n\t\t\t\t// Clear connect timeout\n\t\t\t\tclearTimeout(to);\n\t\t\t\t// Treat like close; don’t throw\n\t\t\t\tcleanup();\n\t\t\t\tthis.status = ConnectionStatus.Closed;\n\t\t\t\tthis.resolveReady(false);\n\t\t\t\tthis.scheduleReconnect();\n\t\t\t};\n\n\t\t\tconst onMessage = (event: MessageEvent) => {\n\t\t\t\tthis.lastActivity = Date.now();\n\t\t\t\tthis.stats.lastActivity = this.lastActivity;\n\t\t\t\tthis.stats.received++;\n\n\t\t\t\tif (typeof event.data === 'string') {\n\t\t\t\t\tconst rawText = event.data;\n\t\t\t\t\tconst subId = this.extractSubId(rawText);\n\t\t\t\t\tif (this.messageHandler) {\n\t\t\t\t\t\tthis.messageHandler(this.url, subId, rawText);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Attach\n\t\t\tthis.ws.onopen = onOpen;\n\t\t\tthis.ws.onclose = onClose;\n\t\t\tthis.ws.onerror = onError;\n\t\t\tthis.ws.onmessage = onMessage;\n\n\t\t\t// Timeout and abort\n\t\t\tconst to = setTimeout(() => {\n\t\t\t\tif (this.status === ConnectionStatus.Connecting) {\n\t\t\t\t\tcleanup();\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.ws?.close();\n\t\t\t\t\t} catch {}\n\t\t\t\t\tthis.status = ConnectionStatus.Closed;\n\t\t\t\t\tthis.resolveReady(false);\n\t\t\t\t\tthis.scheduleReconnect();\n\t\t\t\t}\n\t\t\t}, this.config.connectTimeoutMs);\n\n\t\t\tconst onAbort = () => {\n\t\t\t\tclearTimeout(to);\n\t\t\t\tcleanup();\n\t\t\t\ttry {\n\t\t\t\t\tthis.ws?.close();\n\t\t\t\t} catch {}\n\t\t\t\tthis.status = ConnectionStatus.Closed;\n\t\t\t\tthis.resolveReady(false);\n\t\t\t\tif (this.wantReconnect) this.scheduleReconnect(); // guard here\n\t\t\t};\n\n\t\t\tsignal.addEventListener('abort', onAbort);\n\t\t} catch {\n\t\t\tthis.status = ConnectionStatus.Closed;\n\t\t\tthis.resolveReady(false);\n\t\t\tthis.scheduleReconnect();\n\t\t}\n\t}\n\n\tasync sendMessage(frame: string): Promise<void> {\n\t\tif (this.status !== ConnectionStatus.Ready || !this.ws) {\n\t\t\tthrow new Error('Connection not ready');\n\t\t}\n\t\tthis.ws.send(frame);\n\t\tthis.stats.sent++;\n\t\tthis.lastActivity = Date.now();\n\t\tthis.stats.lastActivity = this.lastActivity;\n\t}\n\n\tasync waitForReady(timeoutMs: number = this.config.connectTimeoutMs ?? 5_000): Promise<void> {\n\t\tif (this.status === ConnectionStatus.Ready) return;\n\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tthis.removeReadyResolver(resolver);\n\t\t\t\treject(new Error('Timeout waiting for ready'));\n\t\t\t}, timeoutMs);\n\n\t\t\tconst resolver = (ok: boolean) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tif (ok) resolve();\n\t\t\t\telse reject(new Error('Connection closed'));\n\t\t\t};\n\t\t\tthis.readyWaiters.push(resolver);\n\t\t});\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.wantReconnect = false;\n\t\tif (this.abortController) this.abortController.abort();\n\t\tif (this.reconnectTimer) {\n\t\t\tclearTimeout(this.reconnectTimer);\n\t\t\tthis.reconnectTimer = null;\n\t\t}\n\t\tthis.closeWebSocket();\n\t\tthis.status = ConnectionStatus.Closed;\n\t\tthis.resolveReady(false);\n\t}\n\n\tshouldCloseDueToInactivity(): boolean {\n\t\treturn Date.now() - this.lastActivity > (this.config.idleTimeoutMs ?? 300_000);\n\t}\n\n\t// Internals\n\n\tprivate resolveReady(ok: boolean) {\n\t\tif (this.readyWaiters.length === 0) return;\n\t\tconst waiters = this.readyWaiters.slice();\n\t\tthis.readyWaiters.length = 0;\n\t\tfor (const fn of waiters) {\n\t\t\ttry {\n\t\t\t\tfn(ok);\n\t\t\t} catch {}\n\t\t}\n\t}\n\n\tprivate removeReadyResolver(fn: (ok: boolean) => void) {\n\t\tconst idx = this.readyWaiters.indexOf(fn);\n\t\tif (idx >= 0) this.readyWaiters.splice(idx, 1);\n\t}\n\n\tprivate closeWebSocket() {\n\t\tif (this.ws) {\n\t\t\ttry {\n\t\t\t\tthis.ws.close(1000, 'Normal closure');\n\t\t\t} catch {}\n\t\t\tthis.ws = null;\n\t\t}\n\t}\n\n\tprivate scheduleReconnect(): void {\n\t\tif (!this.wantReconnect) return;\n\t\tif (this.status !== ConnectionStatus.Closed || !this.config.retry?.baseMs) return;\n\n\t\tconst cap = this.config.maxReconnectAttempts ?? 2;\n\t\tif (cap > 0 && this.attempts >= cap) {\n\t\t\tthis.givenUp = true;\n\t\t\treturn;\n\t\t}\n\n\t\tconst base = this.config.retry.baseMs;\n\t\tconst max = this.config.retry.maxMs ?? 10_000;\n\t\tconst mult = this.config.retry.multiplier ?? 1.6;\n\t\tconst jitter = this.config.retry.jitter ?? 0.1;\n\n\t\t// Calculate delay using current attempts\n\t\tconst delay =\n\t\t\tMath.min(base * Math.pow(mult, this.attempts), max) *\n\t\t\t(1 + (Math.random() - 0.5) * jitter * 2);\n\n\t\tthis.reconnectTimer = setTimeout(() => {\n\t\t\t// Increment attempts when actually trying again\n\t\t\tthis.attempts++;\n\t\t\tthis.stats.reconnects = this.attempts;\n\t\t\tthis.connect();\n\t\t}, delay) as unknown as number;\n\t}\n\n\tprivate extractSubId(s: string): string | null {\n\t\tlet i = 0;\n\t\tconst n = s.length;\n\n\t\t// Skip leading whitespace\n\t\twhile (i < n && s.charCodeAt(i) <= 32) i++;\n\t\tif (i >= n || s[i] !== '[') return null;\n\t\ti++;\n\n\t\t// Skip whitespace before first element\n\t\twhile (i < n && s.charCodeAt(i) <= 32) i++;\n\t\tif (i >= n) return null;\n\n\t\t// Skip first element (kind or similar)\n\t\tif (s[i] === '\"') {\n\t\t\t// Fast-skip a quoted string (no escape handling, consistent with existing code)\n\t\t\ti++;\n\t\t\twhile (i < n && s[i] !== '\"') i++;\n\t\t\tif (i >= n) return null;\n\t\t\ti++; // past closing quote\n\t\t} else {\n\t\t\t// Non-quoted first element; skip until comma or end of array\n\t\t\twhile (i < n && s[i] !== ',' && s[i] !== ']') i++;\n\t\t}\n\n\t\t// Move to the comma after first element\n\t\twhile (i < n && s[i] !== ',') i++;\n\t\tif (i >= n || s[i] !== ',') return null;\n\t\ti++; // skip comma\n\n\t\t// Skip whitespace before second element\n\t\twhile (i < n && s.charCodeAt(i) <= 32) i++;\n\t\tif (i >= n) return null;\n\n\t\t// Extract second element only if it's a quoted string\n\t\tif (s[i] === '\"') {\n\t\t\ti++;\n\t\t\tconst start = i;\n\t\t\twhile (i < n && s[i] !== '\"') i++;\n\t\t\tif (i > n) return null;\n\t\t\treturn s.slice(start, i);\n\t\t}\n\t\treturn null;\n\t}\n}\n","import { RelayConfig, ConnectionStatus } from './types';\nimport { RelayConnection } from './connection';\n\nexport class ConnectionRegistry {\n\tprivate connections = new Map<string, RelayConnection>();\n\tprivate disabledRelays = new Set<string>();\n\tprivate nextAllowed = new Map<string, number>(); // cooldown timestamps per URL (ms)\n\tprivate subCounts = new Map<string, number>(); // active subscription count per URL\n\tprivate disconnectTimers = new Map<string, number>(); // delayed disconnect timers\n\tprivate config: RelayConfig;\n\n\tprivate readonly cooldownMs = 60_000; // after failures\n\tprivate readonly closeDelayMs = 1_000; // after last CLOSE\n\n\tconstructor(config: RelayConfig) {\n\t\tthis.config = { maxReconnectAttempts: 2, ...config };\n\t}\n\n\tprivate now(): number {\n\t\treturn Date.now();\n\t}\n\n\tprivate detectKind(frame: string): 'REQ' | 'CLOSE' | 'OTHER' {\n\t\tconst m = frame.match(/^\\s*\\[\\s*\"([^\"]+)\"/);\n\t\tif (!m) return 'OTHER';\n\t\tconst k = m[1].toUpperCase();\n\t\tif (k === 'REQ') return 'REQ';\n\t\tif (k === 'CLOSE') return 'CLOSE';\n\t\treturn 'OTHER';\n\t}\n\n\tprivate getCount(url: string): number {\n\t\treturn this.subCounts.get(url) ?? 0;\n\t}\n\tprivate setCount(url: string, value: number): void {\n\t\tthis.subCounts.set(url, Math.max(0, value));\n\t}\n\tprivate cancelPendingDisconnect(url: string): void {\n\t\tconst id = this.disconnectTimers.get(url);\n\t\tif (typeof id === 'number') {\n\t\t\tclearTimeout(id);\n\t\t\tthis.disconnectTimers.delete(url);\n\t\t}\n\t}\n\tprivate scheduleDisconnectIfIdle(url: string): void {\n\t\tif (this.disconnectTimers.has(url)) return;\n\t\tconst id = setTimeout(async () => {\n\t\t\tthis.disconnectTimers.delete(url);\n\t\t\tif (this.getCount(url) === 0) {\n\t\t\t\tawait this.disconnect(url);\n\t\t\t}\n\t\t}, this.closeDelayMs) as unknown as number;\n\t\tthis.disconnectTimers.set(url, id);\n\t}\n\tprivate bumpCount(url: string, delta: number): void {\n\t\tconst next = this.getCount(url) + delta;\n\t\tthis.setCount(url, next);\n\t\tif (delta > 0) {\n\t\t\tthis.cancelPendingDisconnect(url);\n\t\t} else if (delta < 0 && this.getCount(url) === 0) {\n\t\t\tthis.scheduleDisconnectIfIdle(url);\n\t\t}\n\t}\n\n\tprivate giveUpOrCooldown(url: string, conn?: RelayConnection) {\n\t\tif (conn?.hasGivenUp()) {\n\t\t\tif (!this.disabledRelays.has(url)) {\n\t\t\t\tconsole.warn(`[registry] disabling relay ${url}: max attempts reached`);\n\t\t\t}\n\t\t\tthis.disabledRelays.add(url);\n\t\t\tthis.nextAllowed.set(url, this.now() + this.cooldownMs);\n\t\t} else {\n\t\t\tthis.nextAllowed.set(url, this.now() + Math.min(this.cooldownMs, 10_000));\n\t\t}\n\t}\n\n\tprivate isCoolingDown(url: string): boolean {\n\t\tconst at = this.nextAllowed.get(url) ?? 0;\n\t\treturn this.now() < at;\n\t}\n\n\tasync ensureConnection(url: string): Promise<RelayConnection> {\n\t\tif (this.disabledRelays.has(url)) {\n\t\t\tthrow new Error(`Relay disabled: ${url}`);\n\t\t}\n\t\tif (this.isCoolingDown(url)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Relay ${url} cooling down until ${new Date(this.nextAllowed.get(url)!).toISOString()}`\n\t\t\t);\n\t\t}\n\n\t\tlet conn = this.connections.get(url);\n\t\tif (!conn) {\n\t\t\tconn = new RelayConnection(url, this.config);\n\t\t\tthis.connections.set(url, conn);\n\t\t\tconn.connect(); // fire-and-forget\n\t\t} else if (conn.getStatus() !== ConnectionStatus.Ready) {\n\t\t\t// nudge reconnect on existing connection\n\t\t\tconn.connect();\n\t\t}\n\n\t\tif (conn.getStatus() !== ConnectionStatus.Ready) {\n\t\t\ttry {\n\t\t\t\tawait conn.waitForReady(this.config.connectTimeoutMs ?? 5_000);\n\t\t\t} catch (e) {\n\t\t\t\tthis.giveUpOrCooldown(url, conn);\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t}\n\n\t\tif (conn.getStatus() !== ConnectionStatus.Ready) {\n\t\t\tthis.giveUpOrCooldown(url, conn);\n\t\t\tthrow new Error(`Relay ${url} not ready`);\n\t\t}\n\n\t\treturn conn;\n\t}\n\n\tasync sendFrame(url: string, frame: string): Promise<void> {\n\t\tif (this.disabledRelays.has(url) || this.isCoolingDown(url)) return;\n\n\t\tconst kind = this.detectKind(frame);\n\t\tconst conn = await this.ensureConnection(url);\n\n\t\ttry {\n\t\t\tawait conn.sendMessage(frame);\n\t\t} catch (e) {\n\t\t\tthis.giveUpOrCooldown(url, conn);\n\t\t\tawait this.disconnect(url);\n\t\t\tthrow e;\n\t\t}\n\n\t\tif (kind === 'REQ') this.bumpCount(url, +1);\n\t\telse if (kind === 'CLOSE') this.bumpCount(url, -1);\n\t}\n\n\tprivate async sendAllFramesToRelay(url: string, frames: string[]): Promise<void> {\n\t\tfor (const frame of frames) {\n\t\t\tawait this.sendFrame(url, frame);\n\t\t}\n\t}\n\n\tasync sendToRelays(relays: string[], frames: string[]): Promise<void> {\n\t\tconst tasks: Promise<void>[] = [];\n\t\tfor (const url of relays) {\n\t\t\tif (this.disabledRelays.has(url) || this.isCoolingDown(url)) continue;\n\n\t\t\ttasks.push(\n\t\t\t\tthis.sendAllFramesToRelay(url, frames).catch((error) => {\n\t\t\t\t\tconsole.error(`[registry] failed to send to ${url}:`, error);\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\n\t\tawait Promise.allSettled(tasks);\n\t}\n\n\tasync disconnect(url: string): Promise<void> {\n\t\tconst connection = this.connections.get(url);\n\t\tif (connection) {\n\t\t\tawait connection.close();\n\t\t\tthis.connections.delete(url);\n\t\t}\n\t\tthis.cancelPendingDisconnect(url);\n\t\tthis.subCounts.delete(url);\n\t}\n\n\tasync disconnectAll(): Promise<void> {\n\t\tfor (const [url] of this.connections) {\n\t\t\tawait this.disconnect(url);\n\t\t}\n\t}\n\n\tenableRelay(url: string): void {\n\t\tthis.disabledRelays.delete(url);\n\t\tthis.nextAllowed.delete(url);\n\t}\n\n\tisRelayDisabled(url: string): boolean {\n\t\treturn this.disabledRelays.has(url);\n\t}\n\n\tgetActiveReqCount(url: string): number {\n\t\treturn this.getCount(url);\n\t}\n\n\tgetConnectionStatus(url: string): ConnectionStatus | undefined {\n\t\tconst connection = this.connections.get(url);\n\t\treturn connection ? connection.getStatus() : undefined;\n\t}\n\n\tgetAllStatuses(): Map<string, ConnectionStatus> {\n\t\treturn new Map(\n\t\t\tArray.from(this.connections.entries()).map(([url, conn]) => [url, conn.getStatus()])\n\t\t);\n\t}\n}\n","/* Worker runtime (dedicated Web Worker, module) */\nimport { ByteRingBuffer } from './ring-buffer';\nimport { ConnectionRegistry } from './registry';\n\nconst __encoder = new TextEncoder();\nconst __urlBytesCache = new Map<string, Uint8Array>();\nfunction __getUrlBytes(url: string): Uint8Array {\n\tconst cached = __urlBytesCache.get(url);\n\tif (cached) return cached;\n\tconst bytes = __encoder.encode(url);\n\t__urlBytesCache.set(url, bytes);\n\treturn bytes;\n}\n\nfunction writeEnvelope(outputRing: ByteRingBuffer, url: string, rawText: string): void {\n\tconst urlBytes = __getUrlBytes(url);\n\tconst rawBytes = __encoder.encode(rawText);\n\tconst totalLen = 2 + urlBytes.length + 4 + rawBytes.length;\n\tconst out = new Uint8Array(totalLen);\n\tconst view = new DataView(out.buffer, out.byteOffset, out.byteLength);\n\tlet o = 0;\n\tview.setUint16(o, urlBytes.length, false);\n\to += 2;\n\tout.set(urlBytes, o);\n\to += urlBytes.length;\n\tview.setUint32(o, rawBytes.length, false);\n\to += 4;\n\tout.set(rawBytes, o);\n\toutputRing.write(out);\n}\n\nfunction extractSubIdFast(s: string): string | null {\n\tlet i = 0,\n\t\tn = s.length;\n\twhile (i < n && s.charCodeAt(i) <= 32) i++;\n\tif (i >= n || s[i] !== '[') return null;\n\ti++;\n\twhile (i < n && s.charCodeAt(i) <= 32) i++;\n\tif (i >= n) return null;\n\tif (s[i] === '\"') {\n\t\ti++;\n\t\twhile (i < n && s[i] !== '\"') i++;\n\t\tif (i >= n) return null;\n\t\ti++;\n\t} else {\n\t\twhile (i < n && s[i] !== ',' && s[i] !== ']') i++;\n\t}\n\twhile (i < n && s[i] !== ',') i++;\n\tif (i >= n || s[i] !== ',') return null;\n\ti++;\n\twhile (i < n && s.charCodeAt(i) <= 32) i++;\n\tif (i >= n) return null;\n\tif (s[i] === '\"') {\n\t\ti++;\n\t\tconst start = i;\n\t\twhile (i < n && s[i] !== '\"') i++;\n\t\tif (i > n) return null;\n\t\treturn s.slice(start, i);\n\t}\n\treturn null;\n}\n\ntype InitMsg = {\n\ttype: 'init';\n\tpayload: {\n\t\tinRings: SharedArrayBuffer[];\n\t\toutRings: SharedArrayBuffer[];\n\t\trelayConfig: any;\n\t};\n};\n\nlet inputRings: ByteRingBuffer[] = [];\nlet outputRings: ByteRingBuffer[] = [];\nlet registry: ConnectionRegistry | null = null;\nconst subIdToRing = new Map<string, ByteRingBuffer>();\nconst decoder = new TextDecoder();\n\nfunction hashSubId(sub_id: string): number {\n\tconst target = sub_id.includes('_') ? (sub_id.split('_')[1] ?? '') : sub_id;\n\tlet hash = 0;\n\tfor (let i = 0; i < target.length; i++) hash = (hash << 5) - hash + target.charCodeAt(i);\n\treturn Math.abs(hash) % outputRings.length;\n}\n\nfunction getOutRingForSubId(subId: string): ByteRingBuffer {\n\tlet ring = subIdToRing.get(subId);\n\tif (ring) return ring;\n\tring = outputRings[hashSubId(subId)];\n\tsubIdToRing.set(subId, ring);\n\treturn ring;\n}\n\nlet lastRingIndex = 0;\nlet backoffMs = 10;\nconst MIN_BACKOFF_MS = 10;\nconst MAX_BACKOFF_MS = 1000;\nlet loopTimer: number | null = null;\n\nfunction scheduleLoop() {\n\tloopTimer = setTimeout(processLoop, backoffMs) as unknown as number;\n}\n\nfunction processLoop() {\n\tlet processed = 0;\n\tconst ringCount = inputRings.length;\n\tif (ringCount === 0) {\n\t\tbackoffMs = Math.min(backoffMs * 2, MAX_BACKOFF_MS);\n\t\treturn scheduleLoop();\n\t}\n\n\tlet madeProgress: boolean;\n\tdo {\n\t\tmadeProgress = false;\n\t\tfor (let i = 0; i < ringCount; i++) {\n\t\t\tconst idx = (lastRingIndex + i) % ringCount;\n\t\t\tconst ring = inputRings[idx];\n\t\t\tconst record = ring.read();\n\t\t\tif (!record) continue;\n\n\t\t\tmadeProgress = true;\n\t\t\tprocessed++;\n\n\t\t\tconst envelopeStr = decoder.decode(record);\n\t\t\tlet envelope: any;\n\t\t\ttry {\n\t\t\t\tenvelope = JSON.parse(envelopeStr);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!Array.isArray(envelope.relays) || !Array.isArray(envelope.frames)) continue;\n\n\t\t\tregistry?.sendToRelays(envelope.relays, envelope.frames).catch(console.error);\n\t\t\tlastRingIndex = (idx + 1) % ringCount;\n\t\t}\n\t} while (madeProgress);\n\n\tbackoffMs = processed > 0 ? MIN_BACKOFF_MS : Math.min(backoffMs * 2, MAX_BACKOFF_MS);\n\tscheduleLoop();\n}\n\nself.addEventListener('message', (evt: MessageEvent<InitMsg>) => {\n\tconst msg = evt.data;\n\tif (!msg || msg.type === 'init') {\n\t\tinputRings = msg.payload.inRings.map((s) => new ByteRingBuffer(s));\n\t\toutputRings = msg.payload.outRings.map((s) => new ByteRingBuffer(s));\n\t\tregistry = new ConnectionRegistry(msg.payload.relayConfig || {});\n\n\t\tconst onIncoming = (url: string, subId: string | null, rawText: string) => {\n\t\t\tconst sid = subId ?? extractSubIdFast(rawText);\n\t\t\tif (sid) writeEnvelope(getOutRingForSubId(sid), url, rawText);\n\t\t};\n\n\t\tconst originalEnsure = registry.ensureConnection.bind(registry);\n\t\tregistry.ensureConnection = async (url: string) => {\n\t\t\tconst conn = await originalEnsure(url);\n\t\t\tif (!conn.messageHandler) conn.setMessageHandler(onIncoming);\n\t\t\treturn conn;\n\t\t};\n\n\t\t// Kick off the polling loop (no Atomics)\n\t\tbackoffMs = MIN_BACKOFF_MS;\n\t\tif (loopTimer !== null) clearTimeout(loopTimer as any);\n\t\t// scheduleLoop();\n\t\treturn;\n\t}\n\n\t// NEW: minimal wake signal to reset backoff and run soon\n\tif (msg?.type === 'wake') {\n\t\t// ensure these are in scope: backoffMs, MIN_BACKOFF_MS, loopTimer, scheduleLoop\n\t\tbackoffMs = MIN_BACKOFF_MS;\n\t\tif (loopTimer !== null) {\n\t\t\tclearTimeout(loopTimer as any);\n\t\t\tloopTimer = null;\n\t\t}\n\t\tscheduleLoop();\n\t\treturn;\n\t}\n});\n"],"names":["ByteRingBuffer","buffer","value","head","tail","used","p","payload","N","len","totalSize","droppedThisWrite","mySeq","writePos","readPos","trailerPos","variable","advance","targetPos","source","sourceOffset","length","remaining","srcOffset","tgt","spaceToEnd","chunkSize","tgtAbs","srcChunk","sourcePos","target","targetOffset","tgtOffset","src","srcAbs","ConnectionStatus","RelayConnection","url","config","handler","signal","cleanup","onOpen","to","onClose","ev","onError","_ev","onMessage","event","rawText","subId","onAbort","frame","timeoutMs","resolve","reject","timer","resolver","ok","waiters","fn","idx","cap","base","max","mult","jitter","delay","s","i","n","start","ConnectionRegistry","m","k","id","delta","next","conn","at","e","kind","frames","relays","tasks","error","connection","__encoder","__urlBytesCache","__getUrlBytes","cached","bytes","writeEnvelope","outputRing","urlBytes","rawBytes","totalLen","out","view","o","extractSubIdFast","inputRings","outputRings","registry","subIdToRing","decoder","hashSubId","sub_id","hash","getOutRingForSubId","ring","lastRingIndex","backoffMs","MIN_BACKOFF_MS","MAX_BACKOFF_MS","loopTimer","scheduleLoop","processLoop","processed","ringCount","madeProgress","record","envelopeStr","envelope","evt","msg","onIncoming","sid","originalEnsure"],"mappings":"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"}
@@ -31,5 +31,4 @@ export declare class ByteRingBuffer {
31
31
  private copyBytes;
32
32
  private copyFromRing;
33
33
  }
34
- export declare function initializeRingHeader(buffer: SharedArrayBuffer): void;
35
34
  //# sourceMappingURL=ring-buffer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ring-buffer.d.ts","sourceRoot":"","sources":["../../src/ws/ring-buffer.ts"],"names":[],"mappings":"AAIA,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,OAAO,CAAa;gBAEhB,MAAM,EAAE,iBAAiB;IASrC,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,MAAM;IAId,YAAY,IAAI,MAAM;IAOtB,UAAU,IAAI,MAAM;IAIpB,UAAU,IAAI,OAAO;IAIrB,QAAQ,IAAI;QAAE,OAAO,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI;IAK1C;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM;IAsDlC;;;OAGG;IACH,IAAI,IAAI,UAAU,GAAG,IAAI;IA0BzB,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,SAAS;IAiBjB,OAAO,CAAC,YAAY;CAgBrB;AAKD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CA6BpE"}
1
+ {"version":3,"file":"ring-buffer.d.ts","sourceRoot":"","sources":["../../src/ws/ring-buffer.ts"],"names":[],"mappings":"AAAA,qBAAa,cAAc;IAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,OAAO,CAAa;gBAEhB,MAAM,EAAE,iBAAiB;IASrC,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,MAAM;IAId,YAAY,IAAI,MAAM;IAOtB,UAAU,IAAI,MAAM;IAIpB,UAAU,IAAI,OAAO;IAIrB,QAAQ,IAAI;QAAE,OAAO,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI;IAK1C;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM;IAqDlC;;;OAGG;IACH,IAAI,IAAI,UAAU,GAAG,IAAI;IA0BzB,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,SAAS;IAsBjB,OAAO,CAAC,YAAY;CAqBpB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@candypoets/nipworker",
3
- "version": "0.0.55",
3
+ "version": "0.0.57",
4
4
  "description": "Nostr client library with worker-based architecture using Rust WASM",
5
5
  "type": "module",
6
6
  "module": "./dist/index.js",
@@ -50,6 +50,9 @@
50
50
  "url": "https://github.com/candypoets/nipworker/issues"
51
51
  },
52
52
  "homepage": "https://github.com/candypoets/nipworker#readme",
53
+ "peerDependencies": {
54
+ "flatbuffers": "^25.2.10"
55
+ },
53
56
  "devDependencies": {
54
57
  "@types/node": "^20.19.17",
55
58
  "typescript": "^5.0.0",
@@ -60,10 +63,7 @@
60
63
  "vite-plugin-wasm": "^3.0.0"
61
64
  },
62
65
  "dependencies": {
63
- "@candypoets/rust-worker": "0.0.55",
64
- "@msgpack/msgpack": "^3.0.0",
65
- "flatbuffers": "^25.2.10",
66
- "msgpackr": "^1.11.5",
66
+ "@candypoets/rust-worker": "0.0.57",
67
67
  "nostr-tools": "^2.0.0"
68
68
  },
69
69
  "engines": {
@@ -1 +0,0 @@
1
- class y{constructor(t){this.dataStart=32,this.dropped=0,this.sab=t,this.dataView=new DataView(t),this.capacity=this.dataView.getUint32(0,!0)}getHead(){return this.dataView.getUint32(4,!0)%this.capacity}setHead(t){this.dataView.setUint32(4,t%this.capacity,!0)}getTail(){return this.dataView.getUint32(8,!0)%this.capacity}setTail(t){this.dataView.setUint32(8,t%this.capacity,!0)}getSeq(){return this.dataView.getUint32(12,!0)}setSeq(t){this.dataView.setUint32(12,t,!0)}getFreeSpace(){const t=this.getHead(),a=this.getTail(),e=(t-a+this.capacity)%this.capacity;return this.capacity-e}getDropped(){return this.dropped}hasRecords(){return this.getHead()!==this.getTail()}readNext(){const t=this.read();return t?{payload:t}:null}write(t){const a=t.byteLength,e=8+a,s=4+e+4;let r=0;for(;this.getFreeSpace()<s;){if(!this.skipRecord())return this.dropped+=r+1,-1;r++}const h=this.getSeq()+1;this.setSeq(h);let i=this.getHead();return this.dataView.setUint32(this.dataStart+i,e,!0),i=(i+4)%this.capacity,this.dataView.setUint16(this.dataStart+i,0,!0),i=(i+2)%this.capacity,this.dataView.setUint16(this.dataStart+i,0,!0),i=(i+2)%this.capacity,this.dataView.setUint32(this.dataStart+i,h,!0),i=(i+4)%this.capacity,this.copyBytes(i,t,0,a),i=(i+a)%this.capacity,this.dataView.setUint32(this.dataStart+i,e,!0),i=(i+4)%this.capacity,this.setHead(i),this.dropped+=r,h}read(){let t=this.getTail();if(t===this.getHead())return null;const a=this.dataView.getUint32(this.dataStart+t,!0);if(a===0)return null;const e=(t+4+a)%this.capacity;if(this.dataView.getUint32(this.dataStart+e,!0)!==a)return null;const s=new Uint8Array(a);this.copyFromRing((t+4)%this.capacity,s,0,a);const r=s.subarray(8),h=4+a+4;return this.setTail((this.getTail()+h)%this.capacity),r}skipRecord(){let t=this.getTail();if(t===this.getHead())return!1;const a=this.dataView.getUint32(this.dataStart+t,!0);if(a===0)return!1;const e=(t+4+a)%this.capacity;if(this.dataView.getUint32(this.dataStart+e,!0)!==a)return!1;const s=4+a+4;return this.setTail((this.getTail()+s)%this.capacity),!0}copyBytes(t,a,e,s){let r=s,h=e,i=t;for(;r>0;){const d=this.capacity-i%this.capacity,n=Math.min(r,d),o=this.dataStart+i%this.capacity,p=a.subarray(h,h+n);new Uint8Array(this.sab,o,n).set(p),r-=n,h+=n,i+=n}}copyFromRing(t,a,e,s){let r=s,h=e,i=t;for(;r>0;){const d=this.capacity-i%this.capacity,n=Math.min(r,d),o=this.dataStart+i%this.capacity,p=new Uint8Array(this.sab,o,n);a.set(p,h),r-=n,h+=n,i+=n}}}function g(c){const t=new DataView(c),a=c.byteLength;if(a<32)throw new Error(`Ring buffer too small: ${a} bytes`);if(t.getUint32(0,!0)!==0)return;const e=a-32;if(e<=0)throw new Error(`Invalid ring capacity computed from total=${a}`);t.setUint32(0,e,!0),t.setUint32(4,0,!0),t.setUint32(8,0,!0),t.setUint32(12,0,!0);for(let s=16;s<32;s+=4)t.setUint32(s,0,!0)}export{y as B,g as i};
@@ -1 +0,0 @@
1
- {"version":3,"file":"ring-buffer.js","sources":["../src/ws/ring-buffer.ts"],"sourcesContent":["\n\n\n\nexport class ByteRingBuffer {\n private readonly sab: SharedArrayBuffer;\n private readonly dataView: DataView;\n private readonly dataStart: number = 32;\n private readonly capacity: number;\n private dropped: number = 0;\n\n constructor(buffer: SharedArrayBuffer) {\n this.sab = buffer;\n this.dataView = new DataView(buffer);\n this.capacity = this.dataView.getUint32(0, true); // little-endian\n\n // Read initial state (assume Rust sets capacity, head=0, tail=0, seq=0)\n // We don't reset here; assume initialized\n }\n\n private getHead(): number {\n return this.dataView.getUint32(4, true) % this.capacity;\n }\n\n private setHead(value: number): void {\n this.dataView.setUint32(4, value % this.capacity, true);\n }\n\n private getTail(): number {\n return this.dataView.getUint32(8, true) % this.capacity;\n }\n\n private setTail(value: number): void {\n this.dataView.setUint32(8, value % this.capacity, true);\n }\n\n private getSeq(): number {\n return this.dataView.getUint32(12, true);\n }\n\n private setSeq(value: number): void {\n this.dataView.setUint32(12, value, true);\n }\n\n getFreeSpace(): number {\n const head = this.getHead();\n const tail = this.getTail();\n const used = (head - tail + this.capacity) % this.capacity;\n return this.capacity - used;\n }\n\n getDropped(): number {\n return this.dropped;\n }\n\n hasRecords(): boolean {\n return this.getHead() !== this.getTail();\n }\n\n readNext(): { payload: Uint8Array } | null {\n const p = this.read();\n return p ? { payload: p } : null;\n }\n\n /**\n * Writes a payload to the ring buffer, overwriting old records if necessary.\n * Returns the sequence number if successful, -1 if dropped (couldn't make space).\n */\n write(payload: Uint8Array): number {\n const N = payload.byteLength;\n const len = 8 + N; // type(2) + pad(2) + seq(4) + payload(N)\n const totalSize = 4 + len + 4; // len + variable + trailer\n\n // Make space by skipping records\n let droppedThisWrite = 0;\n while (this.getFreeSpace() < totalSize) {\n if (!this.skipRecord()) {\n // Can't skip more (uncommitted record), drop this write\n this.dropped += droppedThisWrite + 1;\n return -1;\n }\n droppedThisWrite++;\n }\n\n // Enough space, write\n const mySeq = this.getSeq() + 1;\n this.setSeq(mySeq);\n\n let writePos = this.getHead();\n\n\n // Write len\n this.dataView.setUint32(this.dataStart + writePos, len, true);\n writePos = (writePos + 4) % this.capacity;\n\n // Write type (0)\n this.dataView.setUint16(this.dataStart + writePos, 0, true);\n writePos = (writePos + 2) % this.capacity;\n\n // Write pad (0)\n this.dataView.setUint16(this.dataStart + writePos, 0, true);\n writePos = (writePos + 2) % this.capacity;\n\n // Write seq\n this.dataView.setUint32(this.dataStart + writePos, mySeq, true);\n writePos = (writePos + 4) % this.capacity;\n\n // Write payload (possibly wrapped)\n this.copyBytes(writePos, payload, 0, N);\n writePos = (writePos + N) % this.capacity;\n\n // Write trailer (len)\n this.dataView.setUint32(this.dataStart + writePos, len, true);\n writePos = (writePos + 4) % this.capacity;\n\n // Advance head\n this.setHead(writePos);\n\n this.dropped += droppedThisWrite;\n return mySeq;\n }\n\n /**\n * Reads the next committed payload or null if none ready.\n * Advances tail on success.\n */\n read(): Uint8Array | null {\n let readPos = this.getTail();\n if (readPos === this.getHead()) return null; // empty\n\n const len = this.dataView.getUint32(this.dataStart + readPos, true);\n if (len === 0) return null;\n\n const trailerPos = (readPos + 4 + len) % this.capacity;\n const trailer = this.dataView.getUint32(this.dataStart + trailerPos, true);\n\n if (trailer !== len) return null; // not committed\n\n // Read variable part (len bytes from readPos + 4)\n const variable = new Uint8Array(len);\n this.copyFromRing((readPos + 4) % this.capacity, variable, 0, len);\n\n // Extract payload (skip type+pad+seq = 8 bytes)\n const payload = variable.subarray(8);\n\n // Advance tail\n const advance = 4 + len + 4; // len field + variable + trailer\n this.setTail((this.getTail() + advance) % this.capacity);\n\n return payload;\n }\n\n private skipRecord(): boolean {\n let readPos = this.getTail();\n if (readPos === this.getHead()) return false; // empty\n\n const len = this.dataView.getUint32(this.dataStart + readPos, true);\n if (len === 0) return false;\n\n const trailerPos = (readPos + 4 + len) % this.capacity;\n const trailer = this.dataView.getUint32(this.dataStart + trailerPos, true);\n\n if (trailer !== len) return false; // not committed\n\n // Skip by advancing tail\n const advance = 4 + len + 4;\n this.setTail((this.getTail() + advance) % this.capacity);\n return true;\n }\n\n private copyBytes(targetPos: number, source: Uint8Array, sourceOffset: number, length: number): void {\n let remaining = length;\n let srcOffset = sourceOffset;\n let tgt = targetPos;\n\n while (remaining > 0) {\n const spaceToEnd = this.capacity - (tgt % this.capacity);\n const chunkSize = Math.min(remaining, spaceToEnd);\n const tgtAbs = this.dataStart + (tgt % this.capacity);\n const srcChunk = source.subarray(srcOffset, srcOffset + chunkSize);\n new Uint8Array(this.sab, tgtAbs, chunkSize).set(srcChunk);\n remaining -= chunkSize;\n srcOffset += chunkSize;\n tgt += chunkSize;\n }\n }\n\n private copyFromRing(sourcePos: number, target: Uint8Array, targetOffset: number, length: number): void {\n let remaining = length;\n let tgtOffset = targetOffset;\n let src = sourcePos;\n\n while (remaining > 0) {\n const spaceToEnd = this.capacity - (src % this.capacity);\n const chunkSize = Math.min(remaining, spaceToEnd);\n const srcAbs = this.dataStart + (src % this.capacity);\n const srcChunk = new Uint8Array(this.sab, srcAbs, chunkSize);\n target.set(srcChunk, tgtOffset);\n remaining -= chunkSize;\n tgtOffset += chunkSize;\n src += chunkSize;\n }\n }\n}\n\n// Idempotent header initializer for rings created on the TS side.\n// If capacity (u32 at offset 0) is 0, we set it to (byteLength - 32)\n// and zero head, tail, and seq. Reserved bytes are cleared as well.\nexport function initializeRingHeader(buffer: SharedArrayBuffer): void {\n const HEADER = 32;\n const view = new DataView(buffer);\n const total = buffer.byteLength;\n\n if (total < HEADER) {\n throw new Error(`Ring buffer too small: ${total} bytes`);\n }\n\n const cap = view.getUint32(0, true);\n if (cap !== 0) {\n // Already initialized; nothing to do.\n return;\n }\n\n const capacity = total - HEADER;\n if (capacity <= 0) {\n throw new Error(`Invalid ring capacity computed from total=${total}`);\n }\n\n // Initialize header: capacity, head=0, tail=0, seq=0, reserved=0\n view.setUint32(0, capacity, true); // capacity\n view.setUint32(4, 0, true); // head\n view.setUint32(8, 0, true); // tail\n view.setUint32(12, 0, true); // seq\n // Zero reserved [16..32)\n for (let off = 16; off < 32; off += 4) {\n view.setUint32(off, 0, true);\n }\n}\n"],"names":["ByteRingBuffer","buffer","value","head","tail","used","p","payload","N","len","totalSize","droppedThisWrite","mySeq","writePos","readPos","trailerPos","variable","advance","targetPos","source","sourceOffset","length","remaining","srcOffset","tgt","spaceToEnd","chunkSize","tgtAbs","srcChunk","sourcePos","target","targetOffset","tgtOffset","src","srcAbs","initializeRingHeader","view","total","capacity","off"],"mappings":"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"}