@stacksjs/realtime 0.70.45 → 0.70.53
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/LICENSE.md +21 -0
- package/dist/index.js +10 -10
- package/dist/src/broadcast.d.ts +26 -0
- package/dist/src/heartbeat.d.ts +32 -0
- package/dist/src/index.d.ts +18 -0
- package/dist/src/replay-buffer.d.ts +83 -0
- package/dist/src/ws.d.ts +29 -4
- package/package.json +1 -1
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Open Web Foundation
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var
|
|
3
|
-
`)}async toJSON(){return this.updateSystemMetrics(),await this.updateQueueMetrics(),this.metrics}}var Ke=()=>{};var At={};Fe(At,{PrometheusExporter:()=>Z});var Mt=R(()=>{Ke();B()});import I from"process";import{existsSync as Pt,statSync as It}from"fs";import{join as Ts,relative as As,resolve as Ot}from"path";import fe from"process";import{Buffer as _}from"buffer";import{createCipheriv as Ms,createDecipheriv as Ps,randomBytes as Ze}from"crypto";import{closeSync as Qe,createReadStream as Rt,createWriteStream as Is,existsSync as ne,fsyncSync as Dt,openSync as Nt,writeFileSync as Os}from"fs";import{access as Rs,constants as Bt,mkdir as Ds,readdir as ae,rename as jt,stat as L,unlink as oe,writeFile as He}from"fs/promises";import{isAbsolute as Ns,join as U,resolve as Bs}from"path";import m from"process";import{pipeline as js}from"stream/promises";import{createGzip as Jt}from"zlib";import W from"process";import T from"process";import ce from"process";import{existsSync as le}from"fs";import{resolve as Ve}from"path";import{existsSync as Js}from"fs";import{existsSync as st,mkdirSync as Ls,readdirSync as Us,readFileSync as Ws,writeFileSync as Fs}from"fs";import{homedir as F}from"os";import{dirname as Lt,resolve as w}from"path";import N from"process";import{existsSync as qs,readdirSync as zs}from"fs";import{extname as Ge,resolve as Ut}from"path";import Ks from"process";import{Buffer as he}from"buffer";import Dr from"process";import Nr from"process";import Q from"process";import{Buffer as Br}from"buffer";import jr from"process";class me{config;pendingAcks=new Map;timeouts=new Map;constructor(e={}){this.config={enabled:e.enabled??!1,timeout:e.timeout??5000,retryAttempts:e.retryAttempts??3}}isEnabled(){return this.config.enabled}register(e,t,s,r,i){if(!this.config.enabled)return Promise.resolve(!0);return new Promise((n,a)=>{let c={messageId:e,channel:t,event:s,data:r,socketId:i,timestamp:Date.now(),attempts:1,resolve:n,reject:a};this.pendingAcks.set(e,c);let o=setTimeout(()=>{this.handleTimeout(e)},this.config.timeout);this.timeouts.set(e,o)})}acknowledge(e){let t=this.pendingAcks.get(e);if(!t)return!1;let s=this.timeouts.get(e);if(s)clearTimeout(s),this.timeouts.delete(e);return t.resolve(!0),this.pendingAcks.delete(e),!0}handleTimeout(e){let t=this.pendingAcks.get(e);if(!t)return;if(t.attempts<this.config.retryAttempts){t.attempts++,t.timestamp=Date.now();let s=setTimeout(()=>{this.handleTimeout(e)},this.config.timeout);this.timeouts.set(e,s)}else t.reject(Error(`Message acknowledgment timeout after ${t.attempts} attempts`)),this.pendingAcks.delete(e),this.timeouts.delete(e)}getPending(){return Array.from(this.pendingAcks.values())}getPendingById(e){return this.pendingAcks.get(e)}clear(){for(let e of this.timeouts.values())clearTimeout(e);for(let e of this.pendingAcks.values())e.reject(Error("Acknowledgment cleared"));this.pendingAcks.clear(),this.timeouts.clear()}getStats(){if(this.pendingAcks.size===0)return{pending:0};let e=Array.from(this.pendingAcks.values()).map((s)=>s.timestamp),t=Math.min(...e);return{pending:this.pendingAcks.size,oldest:t}}}class pe{config;channelManager;constructor(e={},t){this.config={enabled:e.enabled??!0,maxBatchSize:e.maxBatchSize??50,debounceMs:e.debounceMs??0},this.channelManager=t}async batchSubscribe(e,t){if(!this.config.enabled)throw Error("Batch operations are disabled");let{channels:s,channelData:r}=t;if(s.length>this.config.maxBatchSize)throw Error(`Batch size exceeds maximum: ${s.length} > ${this.config.maxBatchSize}`);let i={succeeded:[],failed:{}};for(let n of s)try{let a=r?.[n];if(await this.channelManager.subscribe(e,n,a))i.succeeded.push(n);else i.failed[n]="Authorization failed"}catch(a){i.failed[n]=a instanceof Error?a.message:"Unknown error"}return i}batchUnsubscribe(e,t){if(!this.config.enabled)throw Error("Batch operations are disabled");if(t.length>this.config.maxBatchSize)throw Error(`Batch size exceeds maximum: ${t.length} > ${this.config.maxBatchSize}`);let s={succeeded:[],failed:{}};for(let r of t)try{this.channelManager.unsubscribe(e,r),s.succeeded.push(r)}catch(i){s.failed[r]=i instanceof Error?i.message:"Unknown error"}return s}batchBroadcast(e,t){if(!this.config.enabled)throw Error("Batch operations are disabled");let{channels:s,event:r,data:i,excludeSocketId:n}=t;if(s.length>this.config.maxBatchSize)throw Error(`Batch size exceeds maximum: ${s.length} > ${this.config.maxBatchSize}`);let a={succeeded:[],failed:{}};for(let c of s)try{e(c,r,i,n),a.succeeded.push(c)}catch(o){a.failed[c]=o instanceof Error?o.message:"Unknown error"}return a}}class ye{server;config;queue=null;constructor(e,t){this.server=e,this.config=t}setQueue(e){return this.queue=e,this}async broadcast(e){if(!e.shouldBroadcast())return;if(e.broadcastWhen&&!e.broadcastWhen())return;let t=this.normalizeChannels(e.broadcastOn()),s=e.broadcastAs?e.broadcastAs():e.constructor.name,r=e.broadcastWith?e.broadcastWith():{},i={event:s,channel:t[0],data:r},n=e.broadcastQueue?.();if(n||this.queue)await this.queueBroadcast(i,t,n);else this.sendBroadcast(i,t)}send(e,t,s){let r=this.normalizeChannels(e),i={event:t,channel:r[0],data:s};this.sendBroadcast(i,r)}toOthers(e){return new be(this,e)}sendBroadcast(e,t){for(let s of t)this.server.broadcast(s,e.event,e.data,e.socketId)}async queueBroadcast(e,t,s){let r=this.server.queueManager;if(r&&r.isEnabled()){if(this.config.verbose)console.warn(`Queueing broadcast to queue: ${s||this.queue?.queue||"default"}`);await r.queueBroadcast(t,e.event,e.data,{excludeSocketId:e.socketId})}else{if(this.config.verbose)console.warn("Queue not available, broadcasting immediately");this.sendBroadcast(e,t)}}normalizeChannels(e){return Array.isArray(e)?e:[e]}}class be{broadcaster;excludeSocketId;constructor(e,t){this.broadcaster=e,this.excludeSocketId=t}async broadcast(e){await this.broadcaster.broadcast(e)}send(e,t,s){this.broadcaster.send(e,t,s)}}function Ht(e,t,s){return{shouldBroadcast:()=>!0,broadcastOn:()=>e,broadcastAs:()=>t,broadcastWith:()=>s||{}}}class we{channels;eventName="AnonymousEvent";data={};excludeSocketId;constructor(e){this.channels=Array.isArray(e)?e:[e]}as(e){return this.eventName=e,this}with(e){let t=this;return t.data=e,t}toOthers(e){let t=new we(this.channels);return t.eventName=this.eventName,t.data=this.data,Object.defineProperty(t,"excludeSocketId",{value:e,writable:!1,enumerable:!0}),t}send(e){for(let t of this.channels)e.send(t,this.eventName,this.data)}sendNow(e){this.send(e)}}class ve{config;state=new Map;constructor(e={}){this.config={enabled:e.enabled??!0,ttl:e.ttl??3600,maxSize:e.maxSize??1048576}}set(e,t,s){if(!this.config.enabled)return;if(!this.state.has(e))this.state.set(e,new Map);let r=this.state.get(e),i=JSON.stringify(s).length;if(i>this.config.maxSize)throw Error(`State value exceeds max size: ${i} > ${this.config.maxSize}`);r.set(t,s)}get(e,t){return this.state.get(e)?.get(t)}getAll(e){let t=this.state.get(e);if(!t)return{};return Object.fromEntries(t)}delete(e,t){this.state.get(e)?.delete(t)}clear(e){this.state.delete(e)}has(e,t){if(t)return this.state.get(e)?.has(t)??!1;return this.state.has(e)}getSize(e){let t=this.state.get(e);if(!t)return 0;return JSON.stringify(Object.fromEntries(t)).length}}class Ce{config;constructor(e={}){this.config={enabled:e.enabled??!1,separator:e.separator||":",validateNamespace:e.validateNamespace||(()=>!0)}}parse(e){if(!this.config.enabled)return{channel:e};let t=e.split(this.config.separator);if(t.length>1){let s=t[t.length-1],r=t.slice(0,-1).join(this.config.separator);if(this.config.validateNamespace(r))return{namespace:r,channel:s}}return{channel:e}}format(e,t){if(!this.config.enabled)return t;return`${e}${this.config.separator}${t}`}belongsTo(e,t){let s=this.parse(e);if(!s.namespace)return!1;return s.namespace===t||s.namespace.startsWith(t+this.config.separator)}getChannelsInNamespace(e,t){return e.filter((s)=>this.belongsTo(s,t))}}class ke{channels=new Map;authorizers=new Map;channel(e,t){return this.authorizers.set(e,t),this}getChannel(e){if(!this.channels.has(e)){let t=this.getChannelType(e),s={name:e,type:t,subscribers:new Set};if(t==="presence")s.members=new Map;this.channels.set(e,s)}return this.channels.get(e)}getChannelType(e){if(e.startsWith("presence-"))return"presence";if(e.startsWith("private-"))return"private";return"public"}async subscribe(e,t,s){let r=this.getChannel(t),i=null;if(r.type!=="public"){let n=await this.authorize(e,t,s);if(!n)return!1;if(r.type==="presence"&&typeof n==="object")r.members.set(e.data.socketId,n),i=n}return r.subscribers.add(e.data.socketId),e.data.channels.add(t),e.subscribe(t),i||!0}unsubscribe(e,t){let s=this.channels.get(t);if(!s)return;if(s.subscribers.delete(e.data.socketId),e.data.channels.delete(t),e.unsubscribe(t),s.type==="presence")s.members.delete(e.data.socketId);if(s.subscribers.size===0)this.channels.delete(t)}unsubscribeAll(e){let t=Array.from(e.data.channels);for(let s of t)this.unsubscribe(e,s)}async authorize(e,t,s){for(let[r,i]of this.authorizers){let n=this.extractParams(r,t);if(n!==null)if(typeof i==="function")return await i(e,n);else return await i.join(e,n)}return!1}extractParams(e,t){let s=[],r=e.replace(/\{([^}]+)\}/g,(c,o)=>{return s.push(o),"([^.]+)"}),i=new RegExp(`^${r}$`),n=t.match(i);if(!n)return null;let a={};for(let c=0;c<s.length;c++)a[s[c]]=n[c+1];return a}patternToRegex(e){let t=e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\{[^}]+\\\}/g,"[^.]+");return new RegExp(`^${t}$`)}getSubscribers(e){return this.channels.get(e)?.subscribers||new Set}getPresenceMembers(e){let t=this.channels.get(e);if(t?.type==="presence")return t.members;return null}getSubscriberCount(e){return this.channels.get(e)?.subscribers.size||0}hasChannel(e){return this.channels.has(e)}getChannelNames(){return Array.from(this.channels.keys())}getChannelCount(){return this.channels.size}}function Hs(e,t){this[e]=Qs.bind(null,t)}class ht{cache=new Map;totalHits=0;totalMisses=0;options;constructor(e={}){this.options={enabled:!0,ttl:300000,maxSize:100,keyPrefix:"bunfig:",...e}}generateKey(e,t){let s=t?`:${t}`:"";return`${this.options.keyPrefix}${e}${s}`}isExpired(e){return Date.now()-e.timestamp.getTime()>e.ttl}estimateSize(e){try{return JSON.stringify(e).length}catch{return 1000}}evictIfNeeded(){if(this.cache.size<=this.options.maxSize)return;let e=Array.from(this.cache.entries()).sort(([,s],[,r])=>s.timestamp.getTime()-r.timestamp.getTime()),t=e.length-this.options.maxSize+1;for(let s=0;s<t;s++)this.cache.delete(e[s][0])}set(e,t,s,r){if(!this.options.enabled)return;let i=this.generateKey(e,s),n=r??this.options.ttl,a=this.estimateSize(t);this.cache.set(i,{value:t,timestamp:new Date,ttl:n,hits:0,size:a}),this.evictIfNeeded()}get(e,t){if(!this.options.enabled){this.totalMisses++;return}let s=this.generateKey(e,t),r=this.cache.get(s);if(!r){this.totalMisses++;return}if(this.isExpired(r)){this.cache.delete(s),this.totalMisses++;return}return r.hits++,this.totalHits++,r.value}isFileModified(e,t){try{if(!Pt(e))return!0;return It(e).mtime>t}catch{return!0}}getWithFileCheck(e,t){let s=this.get(e,t);if(!s)return;if(this.isFileModified(t,s.fileTimestamp)){this.delete(e,t);return}return s.value}setWithFileCheck(e,t,s,r){try{let i=Pt(s)?It(s):null,n=i?i.mtime:new Date;this.set(e,{value:t,fileTimestamp:n},s,r)}catch{this.set(e,t,s,r)}}delete(e,t){let s=this.generateKey(e,t);return this.cache.delete(s)}clear(){this.cache.clear(),this.totalHits=0,this.totalMisses=0}cleanup(){let e=0;for(let[t,s]of this.cache.entries())if(this.isExpired(s))this.cache.delete(t),e++;return e}getStats(){let e=Array.from(this.cache.values()),t=e.reduce((r,i)=>r+i.size,0),s=e.map((r)=>r.timestamp).sort();return{size:t,maxSize:this.options.maxSize,hitRate:this.totalHits+this.totalMisses>0?this.totalHits/(this.totalHits+this.totalMisses):0,totalHits:this.totalHits,totalMisses:this.totalMisses,entries:this.cache.size,oldestEntry:s[0],newestEntry:s[s.length-1]}}export(){let e={};for(let[t,s]of this.cache.entries())e[t]={value:s.value,timestamp:s.timestamp.toISOString(),ttl:s.ttl,hits:s.hits,size:s.size};return e}import(e){this.cache.clear();for(let[t,s]of Object.entries(e))if(typeof s==="object"&&s!==null){let r=s;this.cache.set(t,{value:r.value,timestamp:new Date(r.timestamp),ttl:r.ttl,hits:r.hits,size:r.size})}}}class ut{metrics=[];maxMetrics=1000;async track(e,t,s={}){let r=performance.now(),i=new Date;try{let n=await t(),a=performance.now()-r;return this.recordMetric({operation:e,duration:a,timestamp:i,...s}),n}catch(n){let a=performance.now()-r;throw this.recordMetric({operation:`${e}:error`,duration:a,timestamp:i,...s}),n}}recordMetric(e){if(this.metrics.push(e),this.metrics.length>this.maxMetrics)this.metrics=this.metrics.slice(-this.maxMetrics)}getStats(e){let t=e?this.metrics.filter((i)=>i.operation===e):this.metrics;if(t.length===0)return{count:0,averageDuration:0,minDuration:0,maxDuration:0,totalDuration:0,recentMetrics:[]};let s=t.map((i)=>i.duration),r=s.reduce((i,n)=>i+n,0);return{count:t.length,averageDuration:r/t.length,minDuration:Math.min(...s),maxDuration:Math.max(...s),totalDuration:r,recentMetrics:t.slice(-10)}}getAllMetrics(){return[...this.metrics]}clearMetrics(){this.metrics=[]}getSlowOperations(e){return this.metrics.filter((t)=>t.duration>e)}}function Ys(e,t={}){let s=Object.keys(t).sort().map((r)=>`${r}:${t[r]}`).join("|");return s?`${e}:${s}`:e}function Xs(e,t){try{return JSON.stringify(e)===JSON.stringify(t)}catch{return e===t}}function er(e){return e.getStats().size*2}function tr(e,t={}){let s=fe.cwd();while(s.includes("storage"))s=Ot(s,"..");let r=Ot(s,e||"");if(t?.relative)return As(fe.cwd(),r);return r}function p(){if(T.env.NODE_ENV==="test"||T.env.BUN_ENV==="test")return!1;return typeof window<"u"}async function sr(){if(T.env.NODE_ENV==="test"||T.env.BUN_ENV==="test")return!0;if(typeof navigator<"u"&&navigator.product==="ReactNative")return!0;if(typeof T<"u"){let e=T.type;if(e==="renderer"||e==="worker")return!1;return!!(T.versions&&(T.versions.node||T.versions.bun))}return!1}class Gt{async format(e){let t=await sr(),s=await this.getMetadata(t);return JSON.stringify({timestamp:e.timestamp.toISOString(),level:e.level,name:e.name,message:e.message,metadata:s})}async getMetadata(e){if(e){let{hostname:t}=await import("os");return{pid:W.pid,hostname:t(),environment:W.env.NODE_ENV||"development",platform:W.platform,version:W.version}}return{userAgent:navigator.userAgent,hostname:window.location.hostname||"browser",environment:W.env.NODE_ENV||W.env.BUN_ENV||"development",viewport:{width:window.innerWidth,height:window.innerHeight},language:navigator.language}}}class $e{name;fileLocks=new Map;currentKeyId=null;keys=new Map;fingersCrossedConfig;fingersCrossedActive=!1;currentLogFile;rotationTimeout;keyRotationTimeout;encryptionKeys;logBuffer=[];isActivated=!1;pendingOperations=[];enabled;fancy;tagFormat;timestampPosition;environment;config;options;formatter;timers=new Set;subLoggers=new Set;fingersCrossedBuffer=[];ANSI_PATTERN=/\u001B\[.*?m/g;activeProgressBar=null;constructor(e,t={}){this.name=e,this.config={...V},this.options=this.normalizeOptions(t),this.formatter=this.options.formatter||new Gt,this.enabled=t.enabled??!0,this.fancy=t.fancy??!0,this.tagFormat=t.tagFormat??{prefix:"[",suffix:"]"},this.timestampPosition=t.timestampPosition??"right",this.environment=t.environment??m.env.APP_ENV??"local",this.fingersCrossedConfig=this.initializeFingersCrossedConfig(t);let s={...t},r=t.timestamp!==void 0;if(r)delete s.timestamp;if(this.config={...this.config,...s,timestamp:r||this.config.timestamp,level:this.options.level??"info"},this.currentLogFile=this.generateLogFilename(),this.encryptionKeys=new Map,this.validateEncryptionConfig()){this.setupRotation();let i=this.generateKeyId(),n=this.generateKey();this.currentKeyId=i,this.keys.set(i,n),this.encryptionKeys.set(i,{key:n,createdAt:new Date}),this.setupKeyRotation()}}shouldActivateFingersCrossed(e){if(!this.fingersCrossedConfig)return!1;let t={debug:0,info:1,success:2,warning:3,error:4},s=this.fingersCrossedConfig.activationLevel??"error";return t[e]>=t[s]}initializeFingersCrossedConfig(e){if(!e.fingersCrossedEnabled&&e.fingersCrossed)return{...ue,...e.fingersCrossed};if(!e.fingersCrossedEnabled)return null;if(!e.fingersCrossed)return{...ue};return{...ue,...e.fingersCrossed}}normalizeOptions(e){let t={format:"json",level:"info",logDirectory:V.logDirectory,rotation:void 0,timestamp:void 0,fingersCrossed:{},enabled:!0,showTags:!1,showIcons:!0,formatter:void 0},s={...t,...Object.fromEntries(Object.entries(e).filter(([,r])=>r!==void 0))};if(!s.level||!["debug","info","success","warning","error"].includes(s.level))s.level=t.level;return s}shouldWriteToFile(){return!p()&&this.config.writeToFile===!0}async writeToFile(e){let t=(async()=>{let r,i=0,n=3,a=1000;while(i<n)try{try{try{await Rs(this.config.logDirectory,Bt.F_OK|Bt.W_OK)}catch(o){if(o instanceof Error&&"code"in o)if(o.code==="ENOENT")await Ds(this.config.logDirectory,{recursive:!0,mode:493});else if(o.code==="EACCES")throw Error(`No write permission for log directory: ${this.config.logDirectory}`);else throw o;else throw o}}catch(o){throw console.error("Debug: [writeToFile] Failed to create log directory:",o),o}let c=this.validateEncryptionConfig()?(await this.encrypt(e)).encrypted:_.from(e);try{if(!ne(this.currentLogFile))await He(this.currentLogFile,"",{mode:420});if(r=Nt(this.currentLogFile,"a",420),Os(r,c,{flag:"a"}),Dt(r),r!==void 0)Qe(r),r=void 0;if((await L(this.currentLogFile)).size===0){if(await He(this.currentLogFile,c,{flag:"w",mode:420}),(await L(this.currentLogFile)).size===0)throw Error("File exists but is empty after retry write")}return}catch(o){let l=o;if(l.code&&["ENETDOWN","ENETUNREACH","ENOTFOUND","ETIMEDOUT"].includes(l.code)){if(i<n-1){let h=typeof l.message==="string"?l.message:"Unknown error";console.error(`Network error during write attempt ${i+1}/${n}:`,h);let f=a*2**i;await new Promise((d)=>setTimeout(d,f)),i++;continue}}if(l?.code&&["ENOSPC","EDQUOT"].includes(l.code))throw Error(`Disk quota exceeded or no space left on device: ${l.message}`);throw console.error("Debug: [writeToFile] Error writing to file:",l),l}finally{if(r!==void 0)try{Qe(r)}catch(o){console.error("Debug: [writeToFile] Error closing file descriptor:",o)}}}catch(c){if(i===n-1){let l=c,h=typeof l.message==="string"?l.message:"Unknown error";throw console.error("Debug: [writeToFile] Max retries reached. Final error:",h),c}i++;let o=a*2**(i-1);await new Promise((l)=>setTimeout(l,o))}})();this.pendingOperations.push(t);let s=this.pendingOperations.length-1;try{await t}catch(r){throw console.error("Debug: [writeToFile] Error in operation:",r),r}finally{this.pendingOperations.splice(s,1)}}generateLogFilename(){if(this.name.includes("stream-throughput")||this.name.includes("decompress-perf-test")||this.name.includes("decompression-latency")||this.name.includes("concurrent-read-test")||this.name.includes("clock-change-test"))return U(this.config.logDirectory,`${this.name}.log`);if(this.name.includes("pending-test")||this.name.includes("temp-file-test")||this.name==="crash-test"||this.name==="corrupt-test"||this.name.includes("rotation-load-test")||this.name==="sigterm-test"||this.name==="sigint-test"||this.name==="failed-rotation-test"||this.name==="integration-test")return U(this.config.logDirectory,`${this.name}.log`);let e=new Date().toISOString().split("T")[0];return U(this.config.logDirectory,`${this.name}-${e}.log`)}setupRotation(){if(p())return;if(!this.shouldWriteToFile())return;if(typeof this.config.rotation==="boolean")return;let e=this.config.rotation,t;switch(e.frequency){case"daily":t=86400000;break;case"weekly":t=604800000;break;case"monthly":t=2592000000;break;default:return}this.rotationTimeout=setInterval(()=>{this.rotateLog()},t)}setupKeyRotation(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation setup");return}let e=this.config.rotation.keyRotation;if(!e?.enabled)return;let t=typeof e.interval==="number"?e.interval:60,s=Math.max(t,60)*1000;this.keyRotationTimeout=setInterval(()=>{this.rotateKeys().catch((r)=>{console.error("Error rotating keys:",r)})},s)}async rotateKeys(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation");return}let e=this.config.rotation.keyRotation,t=this.generateKeyId(),s=this.generateKey();this.currentKeyId=t,this.keys.set(t,s),this.encryptionKeys.set(t,{key:s,createdAt:new Date});let r=Array.from(this.encryptionKeys.entries()).sort(([,a],[,c])=>c.createdAt.getTime()-a.createdAt.getTime()),i=typeof e.maxKeys==="number"?e.maxKeys:1,n=Math.max(1,i);if(r.length>n)for(let[a]of r.slice(n))this.encryptionKeys.delete(a),this.keys.delete(a)}generateKeyId(){return Ze(16).toString("hex")}generateKey(){return Ze(32)}getCurrentKey(){if(!this.currentKeyId)throw Error("Encryption is not properly initialized. Make sure encryption is enabled in the configuration.");let e=this.keys.get(this.currentKeyId);if(!e)throw Error(`No key found for ID ${this.currentKeyId}. The encryption key may have been rotated or removed.`);return{key:e,id:this.currentKeyId}}encrypt(e){let{key:t}=this.getCurrentKey(),s=Ze(16),r=Ms("aes-256-gcm",t,s),i=_.isBuffer(e)?e:_.from(e,"utf8"),n=r.update(i),a=r.final(),c=n.length+a.length,o=r.getAuthTag(),l=_.allocUnsafe(16+c+16);return s.copy(l,0),n.copy(l,16),a.copy(l,16+n.length),o.copy(l,16+c),{encrypted:l,iv:s}}async compressData(e){return new Promise((t,s)=>{let r=Jt(),i=[];r.on("data",(n)=>i.push(n)),r.on("end",()=>t(_.from(_.concat(i)))),r.on("error",s),r.write(e),r.end()})}getEncryptionOptions(){if(!this.config.rotation||typeof this.config.rotation==="boolean"||!this.config.rotation.encrypt)return{};let e={algorithm:"aes-256-cbc",compress:!1};if(typeof this.config.rotation.encrypt==="object"){let t=this.config.rotation.encrypt;return{...e,...t}}return e}async rotateLog(){if(p())return;if(!this.shouldWriteToFile())return;let e=await L(this.currentLogFile).catch(()=>null);if(!e)return;let t=this.config.rotation;if(typeof t==="boolean")return;if(t.maxSize&&e.size>=t.maxSize){let s=this.currentLogFile,r=this.generateLogFilename();if(this.name.includes("rotation-load-test")||this.name==="failed-rotation-test"){let i=await ae(this.config.logDirectory),n=i.filter((o)=>o.startsWith(this.name)&&/\.log\.\d+$/.test(o)).sort((o,l)=>{let h=Number.parseInt(o.match(/\.log\.(\d+)$/)?.[1]||"0");return Number.parseInt(l.match(/\.log\.(\d+)$/)?.[1]||"0")-h}),a=n.length>0?Number.parseInt(n[0].match(/\.log\.(\d+)$/)?.[1]||"0")+1:1,c=`${s}.${a}`;if(await L(s).catch(()=>null))try{if(await jt(s,c),t.compress)try{let o=`${c}.gz`;await this.compressLogFile(c,o),await oe(c)}catch(o){console.error("Error compressing rotated file:",o)}if(n.length===0&&!i.some((o)=>o.endsWith(".log.1")))try{let o=`${s}.1`;await He(o,"")}catch(o){console.error("Error creating backup file:",o)}}catch(o){console.error(`Error during rotation: ${o instanceof Error?o.message:String(o)}`)}}else{let i=new Date().toISOString().replace(/[:.]/g,"-"),n=s.replace(/\.log$/,`-${i}.log`);if(await L(s).catch(()=>null))await jt(s,n)}if(this.currentLogFile=r,t.maxFiles){let i=(await ae(this.config.logDirectory)).filter((n)=>n.startsWith(this.name)).sort((n,a)=>a.localeCompare(n));for(let n of i.slice(t.maxFiles))await oe(U(this.config.logDirectory,n))}}}async compressLogFile(e,t){let s=Rt(e),r=Is(t),i=Jt();await js(s,i,r)}async handleFingersCrossedBuffer(e,t){if(!this.fingersCrossedConfig)return;if(this.shouldActivateFingersCrossed(e)&&!this.isActivated){this.isActivated=!0;for(let s of this.logBuffer){let r=await this.formatter.format(s);if(this.shouldWriteToFile())await this.writeToFile(r);console.log(r)}if(this.fingersCrossedConfig.stopBuffering)this.logBuffer=[]}if(this.isActivated){if(this.shouldWriteToFile())await this.writeToFile(t);console.log(t)}}shouldLog(e){if(!this.enabled)return!1;let t={debug:0,info:1,success:2,warning:3,error:4};return t[e]>=t[this.config.level]}async flushPendingWrites(){if(await Promise.all(this.pendingOperations.map((e)=>{if(e instanceof Promise)return e.catch((t)=>{console.error("Error in pending write operation:",t)});return Promise.resolve()})),ne(this.currentLogFile))try{let e=Nt(this.currentLogFile,"r+");Dt(e),Qe(e)}catch(e){console.error(`Error flushing file: ${e}`)}}async destroy(){if(this.rotationTimeout)clearInterval(this.rotationTimeout);if(this.keyRotationTimeout)clearInterval(this.keyRotationTimeout);this.timers.clear();for(let e of this.pendingOperations)if(typeof e.cancel==="function")e.cancel();return(async()=>{if(this.pendingOperations.length>0)try{await Promise.allSettled(this.pendingOperations)}catch(e){console.error("Error waiting for pending operations:",e)}if(!p()&&this.config.rotation&&typeof this.config.rotation!=="boolean"&&this.config.rotation.compress)try{let e=(await ae(this.config.logDirectory)).filter((t)=>(t.includes("temp")||t.includes(".tmp"))&&t.includes(this.name));for(let t of e)try{await oe(U(this.config.logDirectory,t))}catch(s){console.error(`Failed to delete temp file ${t}:`,s)}}catch(e){console.error("Error cleaning up temporary files:",e)}})()}getCurrentLogFilePath(){return this.currentLogFile}formatTag(e){if(!e)return"";return`${this.tagFormat.prefix}${e}${this.tagFormat.suffix}`}formatFileTimestamp(e){return`[${e.toISOString()}]`}formatConsoleTimestamp(e){return this.shouldStyleConsole()?g.gray(e.toLocaleTimeString()):e.toLocaleTimeString()}shouldStyleConsole(){if(!this.fancy||p())return!1;let e=typeof m.env.NO_COLOR<"u",t=m.env.FORCE_COLOR==="0";if(e||t)return!1;return!!(typeof m.stderr<"u"&&m.stderr.isTTY||typeof m.stdout<"u"&&m.stdout.isTTY)}formatConsoleMessage(e){let{timestamp:t,icon:s="",tag:r="",message:i,level:n,showTimestamp:a=!0}=e,c=(u)=>u.replace(this.ANSI_PATTERN,"");if(!this.fancy){let u=[];if(a)u.push(t);if(n==="warning")u.push("WARN");else if(n==="error")u.push("ERROR");else if(s)u.push(s.replace(/[^\p{L}\p{N}\p{P}\p{Z}]/gu,""));if(r)u.push(r.replace(/[[\]]/g,""));return u.push(i),u.join(" ")}let o=m.stdout.columns||120,l="";if(n==="warning"||n==="error")l=`${s} ${i}`;else if(n==="info"||n==="success")l=`${s} ${r} ${i}`;else l=`${s} ${r} ${g.cyan(i)}`;if(!a)return l.trim();let h=c(l).trim().length,f=c(t).length,d=Math.max(1,o-2-h-f);return`${l.trim()}${" ".repeat(d)}${t}`}formatMessage(e,t){if(t.length===1&&Array.isArray(t[0]))return e.replace(/\{(\d+)\}/g,(n,a)=>{let c=Number.parseInt(a,10);return c<t[0].length?String(t[0][c]):n});let s=/%([sdijfo%])/g,r=0,i=e.replace(s,(n,a)=>{if(a==="%")return"%";if(r>=t.length)return n;let c=t[r++];switch(a){case"s":return String(c);case"d":case"i":return Number(c).toString();case"j":case"o":return JSON.stringify(c,null,2);default:return n}});if(r<t.length)i+=` ${t.slice(r).map((n)=>typeof n==="object"?JSON.stringify(n,null,2):String(n)).join(" ")}`;return i}formatMarkdown(e){if(!e)return e;let t=e;return t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(s,r,i)=>{let n=g.underline(g.blue(r)),a=this.toAbsoluteFilePath(i);if(a&&this.shouldStyleConsole()&&this.supportsHyperlinks()){let c=`file://${encodeURI(a)}`,o="\x1B]8;;",l="\x1B\\";return`\x1B]8;;${c}\x1B\\${n}\x1B]8;;\x1B\\`}if(this.shouldStyleConsole()&&this.supportsHyperlinks())return`\x1B]8;;${i}\x1B\\${n}\x1B]8;;\x1B\\`;return n}),t=t.replace(/`([^`]+)`/g,(s,r)=>g.bgGray(r)),t=t.replace(/\*\*([^*]+)\*\*/g,(s,r)=>g.bold(r)),t=t.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g,(s,r)=>g.italic(r)),t=t.replace(/(?<!_)_([^_]+)_(?!_)/g,(s,r)=>g.italic(r)),t=t.replace(/~([^~]+)~/g,(s,r)=>g.strikethrough(r)),t}supportsHyperlinks(){if(p())return!1;let e=m.env;if(!e)return!1;if(e.TERM_PROGRAM==="iTerm.app"||e.TERM_PROGRAM==="vscode"||e.TERM_PROGRAM==="WezTerm")return!0;if(e.WT_SESSION)return!0;if(e.TERM==="xterm-kitty")return!0;let t=e.VTE_VERSION?Number.parseInt(e.VTE_VERSION,10):0;if(!Number.isNaN(t)&&t>=5000)return!0;return!1}toAbsoluteFilePath(e){try{let t=e;if(t.startsWith("file://"))t=t.replace(/^file:\/\//,"");if(t.startsWith("~")){let s=m.env.HOME||"";if(s)t=t.replace(/^~(?=$|\/)/,s)}if(Ns(t)||t.startsWith("./")||t.startsWith("../"))t=Bs(t);else return null;return ne(t)?t:null}catch{return null}}buildOutputTexts(e){let t=this.shouldStyleConsole()?this.formatMarkdown(e):e,s=e.replace(this.ANSI_PATTERN,"");return{consoleText:t,fileText:s}}async log(e,t,...s){if(!this.shouldLog(e))return;let r=new Date,i=this.formatConsoleTimestamp(r),n=this.formatFileTimestamp(r),a,c;if(t instanceof Error)a=t.message,c=t.stack;else a=this.formatMessage(t,s);let{consoleText:o,fileText:l}=this.buildOutputTexts(a);if(this.shouldStyleConsole()){let f=this.options.showIcons===!1?"":Yt[e],d=this.options.showTags!==!1&&this.name?g.gray(this.formatTag(this.name)):"",u;switch(e){case"debug":u=this.formatConsoleMessage({timestamp:i,icon:f,tag:d,message:g.gray(o),level:e}),console.error(u);break;case"info":u=this.formatConsoleMessage({timestamp:i,icon:f,tag:d,message:o,level:e}),console.warn(u);break;case"success":u=this.formatConsoleMessage({timestamp:i,icon:f,tag:d,message:g.green(o),level:e}),console.error(u);break;case"warning":u=this.formatConsoleMessage({timestamp:i,icon:f,tag:d,message:o,level:e}),console.warn(u);break;case"error":if(u=this.formatConsoleMessage({timestamp:i,icon:f,tag:d,message:o,level:e}),console.error(u),c){let $=c.split(`
|
|
4
|
-
`);for(let
|
|
2
|
+
var Ps=Object.defineProperty;var Is=(e)=>e;function Os(e,t){this[e]=Is.bind(null,t)}var Ze=(e,t)=>{for(var s in t)Ps(e,s,{get:t[s],enumerable:!0,configurable:!0,set:Os.bind(t,s)})};var B=(e,t)=>()=>(e&&(t=e(e=0)),t);var O=import.meta.require;var J=()=>{};class N{channel;event;data;excludeSocketId;connection;queue;delay;tries;timeout;backoff;constructor(e,t,s,r){this.channel=e,this.event=t,this.data=s,this.excludeSocketId=r,this.tries=3,this.timeout=30000,this.backoff=[1000,5000]}async handle(e){try{e.broadcast(this.channel,this.event,this.data,this.excludeSocketId)}catch(t){throw console.error(`Failed to broadcast to ${this.channel}:`,t),t}}failed(e){console.error(`BroadcastJob failed for channel ${this.channel}:`,e.message)}}class U{channel;event;dataFn;cronExpression;connection;queue;delay;tries;timeout;constructor(e,t,s,r){this.channel=e,this.event=t,this.dataFn=s,this.cronExpression=r,this.tries=3,this.timeout=30000}async handle(e){try{let t=typeof this.dataFn==="function"?await this.dataFn():this.dataFn;e.broadcast(this.channel,this.event,t)}catch(t){throw console.error(`Failed to broadcast recurring event to ${this.channel}:`,t),t}}failed(e){console.error(`RecurringBroadcastJob failed for channel ${this.channel}:`,e.message)}}class H{queue=null;server;config;deadLetterQueue;constructor(e,t){if(this.server=e,this.config={enabled:t?.enabled??!1,connection:t?.connection||"default",defaultQueue:t?.defaultQueue||"broadcasts",retry:{attempts:t?.retry?.attempts??3,backoff:t?.retry?.backoff??{type:"exponential",delay:1000}},deadLetter:{enabled:t?.deadLetter?.enabled??!0,maxRetries:t?.deadLetter?.maxRetries??3}},this.config.enabled)this.initializeQueue()}async initializeQueue(){if(!Pt||!Qe){console.warn("bun-queue is not installed. Queue features will be disabled."),this.config.enabled=!1;return}try{let e=Qe();if(this.queue=e.connection(this.config.connection).queue(this.config.defaultQueue),this.config.deadLetter.enabled)this.deadLetterQueue=this.queue.getDeadLetterQueue();this.queue.processJobs(10),console.log(`\u2713 Broadcasting queue initialized: ${this.config.defaultQueue}`)}catch(e){console.error("Failed to initialize broadcasting queue:",e),this.config.enabled=!1}}async queueBroadcast(e,t,s,r){if(!this.isEnabled())throw Error("Queue system is not enabled");let i=Array.isArray(e)?e:[e],n=[];for(let a of i){let c=r?.delay?new L(a,t,s,r.delay,r?.excludeSocketId):new N(a,t,s,r?.excludeSocketId),o=await this.queue.dispatchJob(c,this.server);n.push(o)}return i.length===1?n[0]:n}async scheduleRecurringBroadcast(e,t,s,r){if(!this.isEnabled())throw Error("Queue system is not enabled");let i=new U(e,t,s,r);return await this.queue.scheduleCron({cron:r,data:{job:i,server:this.server},name:`recurring-broadcast-${e}-${t}`})}async cancelRecurringBroadcast(e){if(!this.isEnabled())return!1;return this.queue.unscheduleCron(e)}async getStats(){if(!this.isEnabled())return null;let e=await this.queue.getJobCounts(),t=this.deadLetterQueue?await this.deadLetterQueue.getJobs():[];return{waiting:e.waiting,active:e.active,completed:e.completed,failed:e.failed,delayed:e.delayed,deadLetter:t.length}}async getFailedJobs(e=0,t=-1){if(!this.isEnabled())return[];return this.queue.getJobs("failed",e,t)}async getDeadLetterJobs(e=0,t=-1){if(!this.isEnabled()||!this.deadLetterQueue)return[];return this.deadLetterQueue.getJobs(e,t)}async retryJob(e){if(!this.isEnabled())return null;return this.queue.retryJob(e)}async republishDeadLetterJob(e,t=!0){if(!this.isEnabled()||!this.deadLetterQueue)return null;return this.queue.republishDeadLetterJob(e,{resetRetries:t})}async clearFailedJobs(){if(!this.isEnabled())return;let e=(await this.queue.getJobs("failed")).map((t)=>t.id);if(e.length>0)await this.queue.bulkRemove(e)}async clearDeadLetterQueue(){if(!this.isEnabled()||!this.deadLetterQueue)return;await this.queue.clearDeadLetterQueue()}isEnabled(){return this.config.enabled&&this.queue!==null}async close(){if(this.queue)await this.queue.close(),this.queue=null}}var Pt=!1,Qe=null,L;var He=B(async()=>{J();try{Qe=(await import("bun-queue")).getQueueManager,Pt=!0}catch{}L=class L extends N{constructor(e,t,s,r,i){super(e,t,s,i);this.delay=r}}});var It={};Ze(It,{RecurringBroadcastJob:()=>U,DelayedBroadcastJob:()=>L,BroadcastQueueManager:()=>H,BroadcastJob:()=>N});var Ot=B(async()=>{J();await He()});import oe from"process";class V{server;metrics={};startTime=Date.now();constructor(e){this.server=e,this.initializeMetrics()}initializeMetrics(){this.metrics={connections_total:0,connections_active:0,channels_total:0,messages_total:0,messages_received_total:0,subscriptions_total:0,errors_total:0,uptime_seconds:0,memory_usage_bytes:0,cpu_usage_percent:0,http_requests_total:{},rate_limit_hits_total:0,auth_failures_total:0,webhook_deliveries_total:0,webhook_failures_total:0,queue_jobs_waiting:0,queue_jobs_active:0,queue_jobs_completed:0,queue_jobs_failed:0,queue_jobs_delayed:0}}increment(e,t=1){if(typeof this.metrics[e]==="number")this.metrics[e]+=t}set(e,t){this.metrics[e]=t}incrementHttpRequest(e,t){let s=`${e}_${t}`;if(!this.metrics.http_requests_total)this.metrics.http_requests_total={};this.metrics.http_requests_total[s]=(this.metrics.http_requests_total[s]||0)+1}updateSystemMetrics(){if(this.metrics.uptime_seconds=Math.floor((Date.now()-this.startTime)/1000),typeof oe.memoryUsage==="function"){let e=oe.memoryUsage();this.metrics.memory_usage_bytes=e.heapUsed}if(typeof oe.cpuUsage==="function"){let e=oe.cpuUsage();this.metrics.cpu_usage_percent=(e.user+e.system)/1e6}this.metrics.connections_active=this.server.getConnectionCount(),this.metrics.channels_total=this.server.channels.getChannelCount()}async updateQueueMetrics(){if(!this.server.queueManager)return;try{let e=await this.server.queueManager.getStats();if(e)this.metrics.queue_jobs_waiting=e.waiting,this.metrics.queue_jobs_active=e.active,this.metrics.queue_jobs_completed=e.completed,this.metrics.queue_jobs_failed=e.failed,this.metrics.queue_jobs_delayed=e.delayed}catch{}}async export(){this.updateSystemMetrics(),await this.updateQueueMetrics();let e=[],t=(s,r,i,n="counter")=>{e.push(`# HELP ${s} ${i}`),e.push(`# TYPE ${s} ${n}`),e.push(`${s} ${r}`),e.push("")};if(t("broadcasting_connections_total",this.metrics.connections_total||0,"Total number of connections since server start","counter"),t("broadcasting_connections_active",this.metrics.connections_active||0,"Current number of active connections","gauge"),t("broadcasting_channels_total",this.metrics.channels_total||0,"Current number of channels","gauge"),t("broadcasting_subscriptions_total",this.metrics.subscriptions_total||0,"Total number of subscriptions","counter"),t("broadcasting_messages_total",this.metrics.messages_total||0,"Total messages broadcasted","counter"),t("broadcasting_messages_received_total",this.metrics.messages_received_total||0,"Total messages received from clients","counter"),t("broadcasting_errors_total",this.metrics.errors_total||0,"Total errors encountered","counter"),t("broadcasting_uptime_seconds",this.metrics.uptime_seconds||0,"Server uptime in seconds","gauge"),t("broadcasting_memory_usage_bytes",this.metrics.memory_usage_bytes||0,"Memory usage in bytes","gauge"),t("broadcasting_cpu_usage_percent",this.metrics.cpu_usage_percent||0,"CPU usage percentage","gauge"),this.metrics.http_requests_total&&Object.keys(this.metrics.http_requests_total).length>0){e.push("# HELP broadcasting_http_requests_total Total HTTP requests"),e.push("# TYPE broadcasting_http_requests_total counter");for(let[s,r]of Object.entries(this.metrics.http_requests_total)){let[i,n]=s.split("_");e.push(`broadcasting_http_requests_total{path="${i}",status="${n}"} ${r}`)}e.push("")}if(t("broadcasting_rate_limit_hits_total",this.metrics.rate_limit_hits_total||0,"Total rate limit hits","counter"),t("broadcasting_auth_failures_total",this.metrics.auth_failures_total||0,"Total authentication failures","counter"),t("broadcasting_webhook_deliveries_total",this.metrics.webhook_deliveries_total||0,"Total webhook deliveries attempted","counter"),t("broadcasting_webhook_failures_total",this.metrics.webhook_failures_total||0,"Total webhook delivery failures","counter"),this.server.queueManager)t("broadcasting_queue_jobs_waiting",this.metrics.queue_jobs_waiting||0,"Number of jobs waiting in queue","gauge"),t("broadcasting_queue_jobs_active",this.metrics.queue_jobs_active||0,"Number of jobs currently being processed","gauge"),t("broadcasting_queue_jobs_completed",this.metrics.queue_jobs_completed||0,"Total completed jobs","counter"),t("broadcasting_queue_jobs_failed",this.metrics.queue_jobs_failed||0,"Total failed jobs","counter"),t("broadcasting_queue_jobs_delayed",this.metrics.queue_jobs_delayed||0,"Number of delayed jobs","gauge");return e.join(`
|
|
3
|
+
`)}async toJSON(){return this.updateSystemMetrics(),await this.updateQueueMetrics(),this.metrics}}var Ve=()=>{};var Rt={};Ze(Rt,{PrometheusExporter:()=>V});var Dt=B(()=>{Ve();J()});import R from"process";import{existsSync as Bt,statSync as Nt}from"fs";import{join as Ds,relative as Bs,resolve as jt}from"path";import me from"process";import{Buffer as A}from"buffer";import{createCipheriv as Ns,createDecipheriv as js,randomBytes as Ge}from"crypto";import{closeSync as Ye,createReadStream as Jt,createWriteStream as Js,existsSync as ce,fsyncSync as Lt,openSync as Ut,writeFileSync as Ls}from"fs";import{access as Us,constants as Wt,mkdir as Ws,readdir as le,rename as Ft,stat as W,unlink as he,writeFile as Xe}from"fs/promises";import{isAbsolute as Fs,join as F,resolve as qs}from"path";import m from"process";import{pipeline as zs}from"stream/promises";import{createGzip as qt}from"zlib";import q from"process";import M from"process";import ue from"process";import{existsSync as fe}from"fs";import{resolve as et}from"path";import{existsSync as Ks}from"fs";import{existsSync as at,mkdirSync as Zs,readdirSync as Qs,readFileSync as Hs,writeFileSync as Vs}from"fs";import{homedir as z}from"os";import{dirname as zt,resolve as C}from"path";import j from"process";import{existsSync as Gs,readdirSync as Ys}from"fs";import{extname as tt,resolve as Kt}from"path";import Xs from"process";import{Buffer as de}from"buffer";import Wr from"process";import Fr from"process";import G from"process";import{Buffer as qr}from"buffer";import zr from"process";class be{config;pendingAcks=new Map;timeouts=new Map;constructor(e={}){this.config={enabled:e.enabled??!1,timeout:e.timeout??5000,retryAttempts:e.retryAttempts??3}}isEnabled(){return this.config.enabled}register(e,t,s,r,i){if(!this.config.enabled)return Promise.resolve(!0);return new Promise((n,a)=>{let c={messageId:e,channel:t,event:s,data:r,socketId:i,timestamp:Date.now(),attempts:1,resolve:n,reject:a};this.pendingAcks.set(e,c);let o=setTimeout(()=>{this.handleTimeout(e)},this.config.timeout);this.timeouts.set(e,o)})}acknowledge(e){let t=this.pendingAcks.get(e);if(!t)return!1;let s=this.timeouts.get(e);if(s)clearTimeout(s),this.timeouts.delete(e);return t.resolve(!0),this.pendingAcks.delete(e),!0}handleTimeout(e){let t=this.pendingAcks.get(e);if(!t)return;if(t.attempts<this.config.retryAttempts){t.attempts++,t.timestamp=Date.now();let s=setTimeout(()=>{this.handleTimeout(e)},this.config.timeout);this.timeouts.set(e,s)}else t.reject(Error(`Message acknowledgment timeout after ${t.attempts} attempts`)),this.pendingAcks.delete(e),this.timeouts.delete(e)}getPending(){return Array.from(this.pendingAcks.values())}getPendingById(e){return this.pendingAcks.get(e)}clear(){for(let e of this.timeouts.values())clearTimeout(e);for(let e of this.pendingAcks.values())e.reject(Error("Acknowledgment cleared"));this.pendingAcks.clear(),this.timeouts.clear()}getStats(){if(this.pendingAcks.size===0)return{pending:0};let e=Array.from(this.pendingAcks.values()).map((s)=>s.timestamp),t=Math.min(...e);return{pending:this.pendingAcks.size,oldest:t}}}class we{config;channelManager;constructor(e={},t){this.config={enabled:e.enabled??!0,maxBatchSize:e.maxBatchSize??50,debounceMs:e.debounceMs??0},this.channelManager=t}async batchSubscribe(e,t){if(!this.config.enabled)throw Error("Batch operations are disabled");let{channels:s,channelData:r}=t;if(s.length>this.config.maxBatchSize)throw Error(`Batch size exceeds maximum: ${s.length} > ${this.config.maxBatchSize}`);let i={succeeded:[],failed:{}};for(let n of s)try{let a=r?.[n];if(await this.channelManager.subscribe(e,n,a))i.succeeded.push(n);else i.failed[n]="Authorization failed"}catch(a){i.failed[n]=a instanceof Error?a.message:"Unknown error"}return i}batchUnsubscribe(e,t){if(!this.config.enabled)throw Error("Batch operations are disabled");if(t.length>this.config.maxBatchSize)throw Error(`Batch size exceeds maximum: ${t.length} > ${this.config.maxBatchSize}`);let s={succeeded:[],failed:{}};for(let r of t)try{this.channelManager.unsubscribe(e,r),s.succeeded.push(r)}catch(i){s.failed[r]=i instanceof Error?i.message:"Unknown error"}return s}batchBroadcast(e,t){if(!this.config.enabled)throw Error("Batch operations are disabled");let{channels:s,event:r,data:i,excludeSocketId:n}=t;if(s.length>this.config.maxBatchSize)throw Error(`Batch size exceeds maximum: ${s.length} > ${this.config.maxBatchSize}`);let a={succeeded:[],failed:{}};for(let c of s)try{e(c,r,i,n),a.succeeded.push(c)}catch(o){a.failed[c]=o instanceof Error?o.message:"Unknown error"}return a}}class ve{server;config;queue=null;constructor(e,t){this.server=e,this.config=t}setQueue(e){return this.queue=e,this}async broadcast(e){if(!e.shouldBroadcast())return;if(e.broadcastWhen&&!e.broadcastWhen())return;let t=this.normalizeChannels(e.broadcastOn()),s=e.broadcastAs?e.broadcastAs():e.constructor.name,r=e.broadcastWith?e.broadcastWith():{},i={event:s,channel:t[0],data:r},n=e.broadcastQueue?.();if(n||this.queue)await this.queueBroadcast(i,t,n);else this.sendBroadcast(i,t)}send(e,t,s){let r=this.normalizeChannels(e),i={event:t,channel:r[0],data:s};this.sendBroadcast(i,r)}toOthers(e){return new Ce(this,e)}sendBroadcast(e,t){for(let s of t)this.server.broadcast(s,e.event,e.data,e.socketId)}async queueBroadcast(e,t,s){let r=this.server.queueManager;if(r&&r.isEnabled()){if(this.config.verbose)console.warn(`Queueing broadcast to queue: ${s||this.queue?.queue||"default"}`);await r.queueBroadcast(t,e.event,e.data,{excludeSocketId:e.socketId})}else{if(this.config.verbose)console.warn("Queue not available, broadcasting immediately");this.sendBroadcast(e,t)}}normalizeChannels(e){return Array.isArray(e)?e:[e]}}class Ce{broadcaster;excludeSocketId;constructor(e,t){this.broadcaster=e,this.excludeSocketId=t}async broadcast(e){await this.broadcaster.broadcast(e)}send(e,t,s){this.broadcaster.send(e,t,s)}}function es(e,t,s){return{shouldBroadcast:()=>!0,broadcastOn:()=>e,broadcastAs:()=>t,broadcastWith:()=>s||{}}}class $e{channels;eventName="AnonymousEvent";data={};excludeSocketId;constructor(e){this.channels=Array.isArray(e)?e:[e]}as(e){return this.eventName=e,this}with(e){let t=this;return t.data=e,t}toOthers(e){let t=new $e(this.channels);return t.eventName=this.eventName,t.data=this.data,Object.defineProperty(t,"excludeSocketId",{value:e,writable:!1,enumerable:!0}),t}send(e){for(let t of this.channels)e.send(t,this.eventName,this.data)}sendNow(e){this.send(e)}}class ke{config;state=new Map;constructor(e={}){this.config={enabled:e.enabled??!0,ttl:e.ttl??3600,maxSize:e.maxSize??1048576}}set(e,t,s){if(!this.config.enabled)return;if(!this.state.has(e))this.state.set(e,new Map);let r=this.state.get(e),i=JSON.stringify(s).length;if(i>this.config.maxSize)throw Error(`State value exceeds max size: ${i} > ${this.config.maxSize}`);r.set(t,s)}get(e,t){return this.state.get(e)?.get(t)}getAll(e){let t=this.state.get(e);if(!t)return{};return Object.fromEntries(t)}delete(e,t){this.state.get(e)?.delete(t)}clear(e){this.state.delete(e)}has(e,t){if(t)return this.state.get(e)?.has(t)??!1;return this.state.has(e)}getSize(e){let t=this.state.get(e);if(!t)return 0;return JSON.stringify(Object.fromEntries(t)).length}}class Ee{config;constructor(e={}){this.config={enabled:e.enabled??!1,separator:e.separator||":",validateNamespace:e.validateNamespace||(()=>!0)}}parse(e){if(!this.config.enabled)return{channel:e};let t=e.split(this.config.separator);if(t.length>1){let s=t[t.length-1],r=t.slice(0,-1).join(this.config.separator);if(this.config.validateNamespace(r))return{namespace:r,channel:s}}return{channel:e}}format(e,t){if(!this.config.enabled)return t;return`${e}${this.config.separator}${t}`}belongsTo(e,t){let s=this.parse(e);if(!s.namespace)return!1;return s.namespace===t||s.namespace.startsWith(t+this.config.separator)}getChannelsInNamespace(e,t){return e.filter((s)=>this.belongsTo(s,t))}}class Se{channels=new Map;authorizers=new Map;channel(e,t){return this.authorizers.set(e,t),this}getChannel(e){if(!this.channels.has(e)){let t=this.getChannelType(e),s={name:e,type:t,subscribers:new Set};if(t==="presence")s.members=new Map;this.channels.set(e,s)}return this.channels.get(e)}getChannelType(e){if(e.startsWith("presence-"))return"presence";if(e.startsWith("private-"))return"private";return"public"}async subscribe(e,t,s){let r=this.getChannel(t),i=null;if(r.type!=="public"){let n=await this.authorize(e,t,s);if(!n)return!1;if(r.type==="presence"&&typeof n==="object")r.members.set(e.data.socketId,n),i=n}return r.subscribers.add(e.data.socketId),e.data.channels.add(t),e.subscribe(t),i||!0}unsubscribe(e,t){let s=this.channels.get(t);if(!s)return;if(s.subscribers.delete(e.data.socketId),e.data.channels.delete(t),e.unsubscribe(t),s.type==="presence")s.members.delete(e.data.socketId);if(s.subscribers.size===0)this.channels.delete(t)}unsubscribeAll(e){let t=Array.from(e.data.channels);for(let s of t)this.unsubscribe(e,s)}async authorize(e,t,s){for(let[r,i]of this.authorizers){let n=this.extractParams(r,t);if(n!==null)if(typeof i==="function")return await i(e,n);else return await i.join(e,n)}return!1}extractParams(e,t){let s=[],r=e.replace(/\{([^}]+)\}/g,(c,o)=>{return s.push(o),"([^.]+)"}),i=new RegExp(`^${r}$`),n=t.match(i);if(!n)return null;let a={};for(let c=0;c<s.length;c++)a[s[c]]=n[c+1];return a}patternToRegex(e){let t=e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\{[^}]+\\\}/g,"[^.]+");return new RegExp(`^${t}$`)}getSubscribers(e){return this.channels.get(e)?.subscribers||new Set}getPresenceMembers(e){let t=this.channels.get(e);if(t?.type==="presence")return t.members;return null}getSubscriberCount(e){return this.channels.get(e)?.subscribers.size||0}hasChannel(e){return this.channels.has(e)}getChannelNames(){return Array.from(this.channels.keys())}getChannelCount(){return this.channels.size}}function sr(e,t){this[e]=tr.bind(null,t)}class gt{cache=new Map;totalHits=0;totalMisses=0;options;constructor(e={}){this.options={enabled:!0,ttl:300000,maxSize:100,keyPrefix:"bunfig:",...e}}generateKey(e,t){let s=t?`:${t}`:"";return`${this.options.keyPrefix}${e}${s}`}isExpired(e){return Date.now()-e.timestamp.getTime()>e.ttl}estimateSize(e){try{return JSON.stringify(e).length}catch{return 1000}}evictIfNeeded(){if(this.cache.size<=this.options.maxSize)return;let e=Array.from(this.cache.entries()).sort(([,s],[,r])=>s.timestamp.getTime()-r.timestamp.getTime()),t=e.length-this.options.maxSize+1;for(let s=0;s<t;s++)this.cache.delete(e[s][0])}set(e,t,s,r){if(!this.options.enabled)return;let i=this.generateKey(e,s),n=r??this.options.ttl,a=this.estimateSize(t);this.cache.set(i,{value:t,timestamp:new Date,ttl:n,hits:0,size:a}),this.evictIfNeeded()}get(e,t){if(!this.options.enabled){this.totalMisses++;return}let s=this.generateKey(e,t),r=this.cache.get(s);if(!r){this.totalMisses++;return}if(this.isExpired(r)){this.cache.delete(s),this.totalMisses++;return}return r.hits++,this.totalHits++,r.value}isFileModified(e,t){try{if(!Bt(e))return!0;return Nt(e).mtime>t}catch{return!0}}getWithFileCheck(e,t){let s=this.get(e,t);if(!s)return;if(this.isFileModified(t,s.fileTimestamp)){this.delete(e,t);return}return s.value}setWithFileCheck(e,t,s,r){try{let i=Bt(s)?Nt(s):null,n=i?i.mtime:new Date;this.set(e,{value:t,fileTimestamp:n},s,r)}catch{this.set(e,t,s,r)}}delete(e,t){let s=this.generateKey(e,t);return this.cache.delete(s)}clear(){this.cache.clear(),this.totalHits=0,this.totalMisses=0}cleanup(){let e=0;for(let[t,s]of this.cache.entries())if(this.isExpired(s))this.cache.delete(t),e++;return e}getStats(){let e=Array.from(this.cache.values()),t=e.reduce((r,i)=>r+i.size,0),s=e.map((r)=>r.timestamp).sort();return{size:t,maxSize:this.options.maxSize,hitRate:this.totalHits+this.totalMisses>0?this.totalHits/(this.totalHits+this.totalMisses):0,totalHits:this.totalHits,totalMisses:this.totalMisses,entries:this.cache.size,oldestEntry:s[0],newestEntry:s[s.length-1]}}export(){let e={};for(let[t,s]of this.cache.entries())e[t]={value:s.value,timestamp:s.timestamp.toISOString(),ttl:s.ttl,hits:s.hits,size:s.size};return e}import(e){this.cache.clear();for(let[t,s]of Object.entries(e))if(typeof s==="object"&&s!==null){let r=s;this.cache.set(t,{value:r.value,timestamp:new Date(r.timestamp),ttl:r.ttl,hits:r.hits,size:r.size})}}}class mt{metrics=[];maxMetrics=1000;async track(e,t,s={}){let r=performance.now(),i=new Date;try{let n=await t(),a=performance.now()-r;return this.recordMetric({operation:e,duration:a,timestamp:i,...s}),n}catch(n){let a=performance.now()-r;throw this.recordMetric({operation:`${e}:error`,duration:a,timestamp:i,...s}),n}}recordMetric(e){if(this.metrics.push(e),this.metrics.length>this.maxMetrics)this.metrics=this.metrics.slice(-this.maxMetrics)}getStats(e){let t=e?this.metrics.filter((i)=>i.operation===e):this.metrics;if(t.length===0)return{count:0,averageDuration:0,minDuration:0,maxDuration:0,totalDuration:0,recentMetrics:[]};let s=t.map((i)=>i.duration),r=s.reduce((i,n)=>i+n,0);return{count:t.length,averageDuration:r/t.length,minDuration:Math.min(...s),maxDuration:Math.max(...s),totalDuration:r,recentMetrics:t.slice(-10)}}getAllMetrics(){return[...this.metrics]}clearMetrics(){this.metrics=[]}getSlowOperations(e){return this.metrics.filter((t)=>t.duration>e)}}function nr(e,t={}){let s=Object.keys(t).sort().map((r)=>`${r}:${t[r]}`).join("|");return s?`${e}:${s}`:e}function ar(e,t){try{return JSON.stringify(e)===JSON.stringify(t)}catch{return e===t}}function or(e){return e.getStats().size*2}function cr(e,t={}){let s=me.cwd();while(s.includes("storage"))s=jt(s,"..");let r=jt(s,e||"");if(t?.relative)return Bs(me.cwd(),r);return r}function p(){if(M.env.NODE_ENV==="test"||M.env.BUN_ENV==="test")return!1;return typeof window<"u"}async function lr(){if(M.env.NODE_ENV==="test"||M.env.BUN_ENV==="test")return!0;if(typeof navigator<"u"&&navigator.product==="ReactNative")return!0;if(typeof M<"u"){let e=M.type;if(e==="renderer"||e==="worker")return!1;return!!(M.versions&&(M.versions.node||M.versions.bun))}return!1}class ss{async format(e){let t=await lr(),s=await this.getMetadata(t);return JSON.stringify({timestamp:e.timestamp.toISOString(),level:e.level,name:e.name,message:e.message,metadata:s})}async getMetadata(e){if(e){let{hostname:t}=await import("os");return{pid:q.pid,hostname:t(),environment:q.env.NODE_ENV||"development",platform:q.platform,version:q.version}}return{userAgent:navigator.userAgent,hostname:window.location.hostname||"browser",environment:q.env.NODE_ENV||q.env.BUN_ENV||"development",viewport:{width:window.innerWidth,height:window.innerHeight},language:navigator.language}}}class xe{name;fileLocks=new Map;currentKeyId=null;keys=new Map;fingersCrossedConfig;fingersCrossedActive=!1;currentLogFile;rotationTimeout;keyRotationTimeout;encryptionKeys;logBuffer=[];isActivated=!1;pendingOperations=[];enabled;fancy;tagFormat;timestampPosition;environment;config;options;formatter;timers=new Set;subLoggers=new Set;fingersCrossedBuffer=[];ANSI_PATTERN=/\u001B\[.*?m/g;activeProgressBar=null;constructor(e,t={}){this.name=e,this.config={...X},this.options=this.normalizeOptions(t),this.formatter=this.options.formatter||new ss,this.enabled=t.enabled??!0,this.fancy=t.fancy??!0,this.tagFormat=t.tagFormat??{prefix:"[",suffix:"]"},this.timestampPosition=t.timestampPosition??"right",this.environment=t.environment??m.env.APP_ENV??"local",this.fingersCrossedConfig=this.initializeFingersCrossedConfig(t);let s={...t},r=t.timestamp!==void 0;if(r)delete s.timestamp;if(this.config={...this.config,...s,timestamp:r||this.config.timestamp,level:this.options.level??"info"},this.currentLogFile=this.generateLogFilename(),this.encryptionKeys=new Map,this.validateEncryptionConfig()){this.setupRotation();let i=this.generateKeyId(),n=this.generateKey();this.currentKeyId=i,this.keys.set(i,n),this.encryptionKeys.set(i,{key:n,createdAt:new Date}),this.setupKeyRotation()}}shouldActivateFingersCrossed(e){if(!this.fingersCrossedConfig)return!1;let t={debug:0,info:1,success:2,warning:3,error:4},s=this.fingersCrossedConfig.activationLevel??"error";return t[e]>=t[s]}initializeFingersCrossedConfig(e){if(!e.fingersCrossedEnabled&&e.fingersCrossed)return{...ge,...e.fingersCrossed};if(!e.fingersCrossedEnabled)return null;if(!e.fingersCrossed)return{...ge};return{...ge,...e.fingersCrossed}}normalizeOptions(e){let t={format:"json",level:"info",logDirectory:X.logDirectory,rotation:void 0,timestamp:void 0,fingersCrossed:{},enabled:!0,showTags:!1,showIcons:!0,formatter:void 0},s={...t,...Object.fromEntries(Object.entries(e).filter(([,r])=>r!==void 0))};if(!s.level||!["debug","info","success","warning","error"].includes(s.level))s.level=t.level;return s}shouldWriteToFile(){return!p()&&this.config.writeToFile===!0}async writeToFile(e){let t=(async()=>{let r,i=0,n=3,a=1000;while(i<n)try{try{try{await Us(this.config.logDirectory,Wt.F_OK|Wt.W_OK)}catch(o){if(o instanceof Error&&"code"in o)if(o.code==="ENOENT")await Ws(this.config.logDirectory,{recursive:!0,mode:493});else if(o.code==="EACCES")throw Error(`No write permission for log directory: ${this.config.logDirectory}`);else throw o;else throw o}}catch(o){throw console.error("Debug: [writeToFile] Failed to create log directory:",o),o}let c=this.validateEncryptionConfig()?(await this.encrypt(e)).encrypted:A.from(e);try{if(!ce(this.currentLogFile))await Xe(this.currentLogFile,"",{mode:420});if(r=Ut(this.currentLogFile,"a",420),Ls(r,c,{flag:"a"}),Lt(r),r!==void 0)Ye(r),r=void 0;if((await W(this.currentLogFile)).size===0){if(await Xe(this.currentLogFile,c,{flag:"w",mode:420}),(await W(this.currentLogFile)).size===0)throw Error("File exists but is empty after retry write")}return}catch(o){let l=o;if(l.code&&["ENETDOWN","ENETUNREACH","ENOTFOUND","ETIMEDOUT"].includes(l.code)){if(i<n-1){let h=typeof l.message==="string"?l.message:"Unknown error";console.error(`Network error during write attempt ${i+1}/${n}:`,h);let f=a*2**i;await new Promise((d)=>setTimeout(d,f)),i++;continue}}if(l?.code&&["ENOSPC","EDQUOT"].includes(l.code))throw Error(`Disk quota exceeded or no space left on device: ${l.message}`);throw console.error("Debug: [writeToFile] Error writing to file:",l),l}finally{if(r!==void 0)try{Ye(r)}catch(o){console.error("Debug: [writeToFile] Error closing file descriptor:",o)}}}catch(c){if(i===n-1){let l=c,h=typeof l.message==="string"?l.message:"Unknown error";throw console.error("Debug: [writeToFile] Max retries reached. Final error:",h),c}i++;let o=a*2**(i-1);await new Promise((l)=>setTimeout(l,o))}})();this.pendingOperations.push(t);let s=this.pendingOperations.length-1;try{await t}catch(r){throw console.error("Debug: [writeToFile] Error in operation:",r),r}finally{this.pendingOperations.splice(s,1)}}generateLogFilename(){if(this.name.includes("stream-throughput")||this.name.includes("decompress-perf-test")||this.name.includes("decompression-latency")||this.name.includes("concurrent-read-test")||this.name.includes("clock-change-test"))return F(this.config.logDirectory,`${this.name}.log`);if(this.name.includes("pending-test")||this.name.includes("temp-file-test")||this.name==="crash-test"||this.name==="corrupt-test"||this.name.includes("rotation-load-test")||this.name==="sigterm-test"||this.name==="sigint-test"||this.name==="failed-rotation-test"||this.name==="integration-test")return F(this.config.logDirectory,`${this.name}.log`);let e=new Date().toISOString().split("T")[0];return F(this.config.logDirectory,`${this.name}-${e}.log`)}setupRotation(){if(p())return;if(!this.shouldWriteToFile())return;if(typeof this.config.rotation==="boolean")return;let e=this.config.rotation,t;switch(e.frequency){case"daily":t=86400000;break;case"weekly":t=604800000;break;case"monthly":t=2592000000;break;default:return}this.rotationTimeout=setInterval(()=>{this.rotateLog()},t)}setupKeyRotation(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation setup");return}let e=this.config.rotation.keyRotation;if(!e?.enabled)return;let t=typeof e.interval==="number"?e.interval:60,s=Math.max(t,60)*1000;this.keyRotationTimeout=setInterval(()=>{this.rotateKeys().catch((r)=>{console.error("Error rotating keys:",r)})},s)}async rotateKeys(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation");return}let e=this.config.rotation.keyRotation,t=this.generateKeyId(),s=this.generateKey();this.currentKeyId=t,this.keys.set(t,s),this.encryptionKeys.set(t,{key:s,createdAt:new Date});let r=Array.from(this.encryptionKeys.entries()).sort(([,a],[,c])=>c.createdAt.getTime()-a.createdAt.getTime()),i=typeof e.maxKeys==="number"?e.maxKeys:1,n=Math.max(1,i);if(r.length>n)for(let[a]of r.slice(n))this.encryptionKeys.delete(a),this.keys.delete(a)}generateKeyId(){return Ge(16).toString("hex")}generateKey(){return Ge(32)}getCurrentKey(){if(!this.currentKeyId)throw Error("Encryption is not properly initialized. Make sure encryption is enabled in the configuration.");let e=this.keys.get(this.currentKeyId);if(!e)throw Error(`No key found for ID ${this.currentKeyId}. The encryption key may have been rotated or removed.`);return{key:e,id:this.currentKeyId}}encrypt(e){let{key:t}=this.getCurrentKey(),s=Ge(16),r=Ns("aes-256-gcm",t,s),i=A.isBuffer(e)?e:A.from(e,"utf8"),n=r.update(i),a=r.final(),c=n.length+a.length,o=r.getAuthTag(),l=A.allocUnsafe(16+c+16);return s.copy(l,0),n.copy(l,16),a.copy(l,16+n.length),o.copy(l,16+c),{encrypted:l,iv:s}}async compressData(e){return new Promise((t,s)=>{let r=qt(),i=[];r.on("data",(n)=>i.push(n)),r.on("end",()=>t(A.from(A.concat(i)))),r.on("error",s),r.write(e),r.end()})}getEncryptionOptions(){if(!this.config.rotation||typeof this.config.rotation==="boolean"||!this.config.rotation.encrypt)return{};let e={algorithm:"aes-256-cbc",compress:!1};if(typeof this.config.rotation.encrypt==="object"){let t=this.config.rotation.encrypt;return{...e,...t}}return e}async rotateLog(){if(p())return;if(!this.shouldWriteToFile())return;let e=await W(this.currentLogFile).catch(()=>null);if(!e)return;let t=this.config.rotation;if(typeof t==="boolean")return;if(t.maxSize&&e.size>=t.maxSize){let s=this.currentLogFile,r=this.generateLogFilename();if(this.name.includes("rotation-load-test")||this.name==="failed-rotation-test"){let i=await le(this.config.logDirectory),n=i.filter((o)=>o.startsWith(this.name)&&/\.log\.\d+$/.test(o)).sort((o,l)=>{let h=Number.parseInt(o.match(/\.log\.(\d+)$/)?.[1]||"0");return Number.parseInt(l.match(/\.log\.(\d+)$/)?.[1]||"0")-h}),a=n.length>0?Number.parseInt(n[0].match(/\.log\.(\d+)$/)?.[1]||"0")+1:1,c=`${s}.${a}`;if(await W(s).catch(()=>null))try{if(await Ft(s,c),t.compress)try{let o=`${c}.gz`;await this.compressLogFile(c,o),await he(c)}catch(o){console.error("Error compressing rotated file:",o)}if(n.length===0&&!i.some((o)=>o.endsWith(".log.1")))try{let o=`${s}.1`;await Xe(o,"")}catch(o){console.error("Error creating backup file:",o)}}catch(o){console.error(`Error during rotation: ${o instanceof Error?o.message:String(o)}`)}}else{let i=new Date().toISOString().replace(/[:.]/g,"-"),n=s.replace(/\.log$/,`-${i}.log`);if(await W(s).catch(()=>null))await Ft(s,n)}if(this.currentLogFile=r,t.maxFiles){let i=(await le(this.config.logDirectory)).filter((n)=>n.startsWith(this.name)).sort((n,a)=>a.localeCompare(n));for(let n of i.slice(t.maxFiles))await he(F(this.config.logDirectory,n))}}}async compressLogFile(e,t){let s=Jt(e),r=Js(t),i=qt();await zs(s,i,r)}async handleFingersCrossedBuffer(e,t){if(!this.fingersCrossedConfig)return;if(this.shouldActivateFingersCrossed(e)&&!this.isActivated){this.isActivated=!0;for(let s of this.logBuffer){let r=await this.formatter.format(s);if(this.shouldWriteToFile())await this.writeToFile(r);console.log(r)}if(this.fingersCrossedConfig.stopBuffering)this.logBuffer=[]}if(this.isActivated){if(this.shouldWriteToFile())await this.writeToFile(t);console.log(t)}}shouldLog(e){if(!this.enabled)return!1;let t={debug:0,info:1,success:2,warning:3,error:4};return t[e]>=t[this.config.level]}async flushPendingWrites(){if(await Promise.all(this.pendingOperations.map((e)=>{if(e instanceof Promise)return e.catch((t)=>{console.error("Error in pending write operation:",t)});return Promise.resolve()})),ce(this.currentLogFile))try{let e=Ut(this.currentLogFile,"r+");Lt(e),Ye(e)}catch(e){console.error(`Error flushing file: ${e}`)}}async destroy(){if(this.rotationTimeout)clearInterval(this.rotationTimeout);if(this.keyRotationTimeout)clearInterval(this.keyRotationTimeout);this.timers.clear();for(let e of this.pendingOperations)if(typeof e.cancel==="function")e.cancel();return(async()=>{if(this.pendingOperations.length>0)try{await Promise.allSettled(this.pendingOperations)}catch(e){console.error("Error waiting for pending operations:",e)}if(!p()&&this.config.rotation&&typeof this.config.rotation!=="boolean"&&this.config.rotation.compress)try{let e=(await le(this.config.logDirectory)).filter((t)=>(t.includes("temp")||t.includes(".tmp"))&&t.includes(this.name));for(let t of e)try{await he(F(this.config.logDirectory,t))}catch(s){console.error(`Failed to delete temp file ${t}:`,s)}}catch(e){console.error("Error cleaning up temporary files:",e)}})()}getCurrentLogFilePath(){return this.currentLogFile}formatTag(e){if(!e)return"";return`${this.tagFormat.prefix}${e}${this.tagFormat.suffix}`}formatFileTimestamp(e){return`[${e.toISOString()}]`}formatConsoleTimestamp(e){return this.shouldStyleConsole()?g.gray(e.toLocaleTimeString()):e.toLocaleTimeString()}shouldStyleConsole(){if(!this.fancy||p())return!1;let e=typeof m.env.NO_COLOR<"u",t=m.env.FORCE_COLOR==="0";if(e||t)return!1;return!!(typeof m.stderr<"u"&&m.stderr.isTTY||typeof m.stdout<"u"&&m.stdout.isTTY)}formatConsoleMessage(e){let{timestamp:t,icon:s="",tag:r="",message:i,level:n,showTimestamp:a=!0}=e,c=(u)=>u.replace(this.ANSI_PATTERN,"");if(!this.fancy){let u=[];if(a)u.push(t);if(n==="warning")u.push("WARN");else if(n==="error")u.push("ERROR");else if(s)u.push(s.replace(/[^\p{L}\p{N}\p{P}\p{Z}]/gu,""));if(r)u.push(r.replace(/[[\]]/g,""));return u.push(i),u.join(" ")}let o=m.stdout.columns||120,l="";if(n==="warning"||n==="error")l=`${s} ${i}`;else if(n==="info"||n==="success")l=`${s} ${r} ${i}`;else l=`${s} ${r} ${g.cyan(i)}`;if(!a)return l.trim();let h=c(l).trim().length,f=c(t).length,d=Math.max(1,o-2-h-f);return`${l.trim()}${" ".repeat(d)}${t}`}formatMessage(e,t){if(t.length===1&&Array.isArray(t[0]))return e.replace(/\{(\d+)\}/g,(n,a)=>{let c=Number.parseInt(a,10);return c<t[0].length?String(t[0][c]):n});let s=/%([sdijfo%])/g,r=0,i=e.replace(s,(n,a)=>{if(a==="%")return"%";if(r>=t.length)return n;let c=t[r++];switch(a){case"s":return String(c);case"d":case"i":return Number(c).toString();case"j":case"o":return JSON.stringify(c,null,2);default:return n}});if(r<t.length)i+=` ${t.slice(r).map((n)=>typeof n==="object"?JSON.stringify(n,null,2):String(n)).join(" ")}`;return i}formatMarkdown(e){if(!e)return e;let t=e;return t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(s,r,i)=>{let n=g.underline(g.blue(r)),a=this.toAbsoluteFilePath(i);if(a&&this.shouldStyleConsole()&&this.supportsHyperlinks()){let c=`file://${encodeURI(a)}`,o="\x1B]8;;",l="\x1B\\";return`\x1B]8;;${c}\x1B\\${n}\x1B]8;;\x1B\\`}if(this.shouldStyleConsole()&&this.supportsHyperlinks())return`\x1B]8;;${i}\x1B\\${n}\x1B]8;;\x1B\\`;return n}),t=t.replace(/`([^`]+)`/g,(s,r)=>g.bgGray(r)),t=t.replace(/\*\*([^*]+)\*\*/g,(s,r)=>g.bold(r)),t=t.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g,(s,r)=>g.italic(r)),t=t.replace(/(?<!_)_([^_]+)_(?!_)/g,(s,r)=>g.italic(r)),t=t.replace(/~([^~]+)~/g,(s,r)=>g.strikethrough(r)),t}supportsHyperlinks(){if(p())return!1;let e=m.env;if(!e)return!1;if(e.TERM_PROGRAM==="iTerm.app"||e.TERM_PROGRAM==="vscode"||e.TERM_PROGRAM==="WezTerm")return!0;if(e.WT_SESSION)return!0;if(e.TERM==="xterm-kitty")return!0;let t=e.VTE_VERSION?Number.parseInt(e.VTE_VERSION,10):0;if(!Number.isNaN(t)&&t>=5000)return!0;return!1}toAbsoluteFilePath(e){try{let t=e;if(t.startsWith("file://"))t=t.replace(/^file:\/\//,"");if(t.startsWith("~")){let s=m.env.HOME||"";if(s)t=t.replace(/^~(?=$|\/)/,s)}if(Fs(t)||t.startsWith("./")||t.startsWith("../"))t=qs(t);else return null;return ce(t)?t:null}catch{return null}}buildOutputTexts(e){let t=this.shouldStyleConsole()?this.formatMarkdown(e):e,s=e.replace(this.ANSI_PATTERN,"");return{consoleText:t,fileText:s}}async log(e,t,...s){if(!this.shouldLog(e))return;let r=new Date,i=this.formatConsoleTimestamp(r),n=this.formatFileTimestamp(r),a,c;if(t instanceof Error)a=t.message,c=t.stack;else a=this.formatMessage(t,s);let{consoleText:o,fileText:l}=this.buildOutputTexts(a);if(this.shouldStyleConsole()){let f=this.options.showIcons===!1?"":rs[e],d=this.options.showTags!==!1&&this.name?g.gray(this.formatTag(this.name)):"",u;switch(e){case"debug":u=this.formatConsoleMessage({timestamp:i,icon:f,tag:d,message:g.gray(o),level:e}),console.error(u);break;case"info":u=this.formatConsoleMessage({timestamp:i,icon:f,tag:d,message:o,level:e}),console.warn(u);break;case"success":u=this.formatConsoleMessage({timestamp:i,icon:f,tag:d,message:g.green(o),level:e}),console.error(u);break;case"warning":u=this.formatConsoleMessage({timestamp:i,icon:f,tag:d,message:o,level:e}),console.warn(u);break;case"error":if(u=this.formatConsoleMessage({timestamp:i,icon:f,tag:d,message:o,level:e}),console.error(u),c){let S=c.split(`
|
|
4
|
+
`);for(let w of S)if(w.trim()&&!w.includes(a))console.error(this.formatConsoleMessage({timestamp:i,message:g.gray(` ${w}`),level:e,showTimestamp:!1}))}break}}else if(!p()){if(console.error(`${n} ${this.environment}.${e.toUpperCase()}: ${a}`),c)console.error(c)}let h=`${n} ${this.environment}.${e.toUpperCase()}: ${l}
|
|
5
5
|
`;if(c)h+=`${c}
|
|
6
6
|
`;if(h=h.replace(this.ANSI_PATTERN,""),this.shouldWriteToFile())await this.writeToFile(h)}progress(e,t=""){let s={update:(i,n)=>{},finish:(i)=>{},interrupt:(i,n)=>{}};if(!this.enabled)return s;let r=30;if(this.activeProgressBar={total:Math.max(1,e||1),current:0,message:t||"",barLength:r,lastRenderedLine:""},this.shouldStyleConsole()&&!p()&&m.stdout.isTTY)this.renderProgressBar(this.activeProgressBar);return{update:(i,n)=>{if(!this.enabled||!this.activeProgressBar)return;if(this.activeProgressBar.current=Math.min(Math.max(0,i),this.activeProgressBar.total),n!==void 0)this.activeProgressBar.message=n;if(this.shouldStyleConsole()&&!p()&&m.stdout.isTTY)this.renderProgressBar(this.activeProgressBar)},finish:(i)=>{if(!this.activeProgressBar)return;this.finishProgressBar(this.activeProgressBar,i)},interrupt:(i,n="info")=>{if(!p()&&m.stdout.isTTY)m.stdout.write(`
|
|
7
7
|
`);if(this[n==="warning"?"warn":n](i),this.activeProgressBar&&this.shouldStyleConsole()&&!p()&&m.stdout.isTTY)this.renderProgressBar(this.activeProgressBar)}}}time(e){let t=performance.now();if(this.shouldStyleConsole()){let s=this.options.showTags!==!1&&this.name?g.gray(this.formatTag(this.name)):"",r=this.formatConsoleTimestamp(new Date);console.error(this.formatConsoleMessage({timestamp:r,icon:this.options.showIcons===!1?"":g.blue("\u25D0"),tag:s,message:`${g.cyan(e)}...`}))}return async(s)=>{if(!this.enabled)return;let r=performance.now(),i=Math.round(r-t),n=`${e} completed in ${i}ms`,a=new Date,c=this.formatConsoleTimestamp(a),o=`${this.formatFileTimestamp(a)} ${this.environment}.INFO: ${n}`;if(s)o+=` ${JSON.stringify(s)}`;if(o+=`
|
|
8
|
-
`,o=o.replace(this.ANSI_PATTERN,""),this.shouldStyleConsole()){let l=this.options.showTags!==!1&&this.name?g.gray(this.formatTag(this.name)):"";console.error(this.formatConsoleMessage({timestamp:c,icon:this.options.showIcons===!1?"":g.green("\u2713"),tag:l,message:`${n}${s?` ${JSON.stringify(s)}`:""}`}))}else if(!p())console.error(o.trim());if(this.shouldWriteToFile())await this.writeToFile(o)}}async debug(e,...t){await this.log("debug",e,...t)}async info(e,...t){await this.log("info",e,...t)}async success(e,...t){await this.log("success",e,...t)}async warn(e,...t){await this.log("warning",e,...t)}async error(e,...t){await this.log("error",e,...t)}validateEncryptionConfig(){if(!this.config.rotation)return!1;if(typeof this.config.rotation==="boolean")return!1;let e=this.config.rotation,{encrypt:t}=e;return!!t}async only(e){if(!this.enabled)return;return await e()}isEnabled(){return this.enabled}setEnabled(e){this.enabled=e}extend(e){let t=`${this.name}:${e}`,s=new
|
|
8
|
+
`,o=o.replace(this.ANSI_PATTERN,""),this.shouldStyleConsole()){let l=this.options.showTags!==!1&&this.name?g.gray(this.formatTag(this.name)):"";console.error(this.formatConsoleMessage({timestamp:c,icon:this.options.showIcons===!1?"":g.green("\u2713"),tag:l,message:`${n}${s?` ${JSON.stringify(s)}`:""}`}))}else if(!p())console.error(o.trim());if(this.shouldWriteToFile())await this.writeToFile(o)}}async debug(e,...t){await this.log("debug",e,...t)}async info(e,...t){await this.log("info",e,...t)}async success(e,...t){await this.log("success",e,...t)}async warn(e,...t){await this.log("warning",e,...t)}async error(e,...t){await this.log("error",e,...t)}validateEncryptionConfig(){if(!this.config.rotation)return!1;if(typeof this.config.rotation==="boolean")return!1;let e=this.config.rotation,{encrypt:t}=e;return!!t}async only(e){if(!this.enabled)return;return await e()}isEnabled(){return this.enabled}setEnabled(e){this.enabled=e}extend(e){let t=`${this.name}:${e}`,s=new xe(t,{...this.options,logDirectory:this.config.logDirectory,level:this.config.level,format:this.config.format,rotation:typeof this.config.rotation==="boolean"?void 0:this.config.rotation,timestamp:typeof this.config.timestamp==="boolean"?void 0:this.config.timestamp});return this.subLoggers.add(s),s}createReadStream(){if(p())throw Error("createReadStream is not supported in browser environments");if(!ce(this.currentLogFile))throw Error(`Log file does not exist: ${this.currentLogFile}`);return Jt(this.currentLogFile,{encoding:"utf8"})}async decrypt(e){if(!this.validateEncryptionConfig())throw Error("Encryption is not configured");let t=this.config.rotation;if(!t.encrypt||typeof t.encrypt==="boolean")throw Error("Invalid encryption configuration");if(!this.currentKeyId||!this.keys.has(this.currentKeyId))throw Error("No valid encryption key available");let s=this.keys.get(this.currentKeyId);try{let r=A.isBuffer(e)?e:A.from(e,"base64"),i=r.subarray(0,16),n=r.subarray(r.length-16),a=r.subarray(16,r.length-16),c=js("aes-256-gcm",s,i);c.setAuthTag(n);let o=c.update(a),l=c.final(),h=o.length+l.length,f=A.allocUnsafe(h);return o.copy(f,0),l.copy(f,o.length),f.toString("utf8")}catch(r){throw Error(`Decryption failed: ${r instanceof Error?r.message:String(r)}`)}}getLevel(){return this.config.level}getLogDirectory(){return this.config.logDirectory}getFormat(){return this.config.format}getRotationConfig(){return this.config.rotation}isBrowserMode(){return p()}isServerMode(){return!p()}setTestEncryptionKey(e,t){this.currentKeyId=e,this.keys.set(e,t)}getTestCurrentKey(){if(!this.currentKeyId||!this.keys.has(this.currentKeyId))return null;return{id:this.currentKeyId,key:this.keys.get(this.currentKeyId)}}getConfig(){return this.config}async box(e){if(!this.enabled)return;let t=new Date,s=this.formatConsoleTimestamp(t),r=this.formatFileTimestamp(t),{consoleText:i,fileText:n}=this.buildOutputTexts(e);if(this.shouldStyleConsole()){let c=i.split(`
|
|
9
9
|
`),o=Math.max(...c.map((d)=>d.length))+2,l=`\u250C${"\u2500".repeat(o)}\u2510`,h=`\u2514${"\u2500".repeat(o)}\u2518`,f=c.map((d)=>{return this.formatConsoleMessage({timestamp:s,message:g.cyan(d),showTimestamp:!1})});console.error(this.formatConsoleMessage({timestamp:s,message:g.cyan(l),showTimestamp:!1})),f.forEach((d)=>console.error(d)),console.error(this.formatConsoleMessage({timestamp:s,message:g.cyan(h),showTimestamp:!1}))}else if(!p())console.error(`${r} ${this.environment}.INFO: [BOX] ${n}`);let a=`${r} ${this.environment}.INFO: [BOX] ${n}
|
|
10
10
|
`.replace(this.ANSI_PATTERN,"");if(this.shouldWriteToFile())await this.writeToFile(a)}async prompt(e){if(p())return Promise.resolve(!0);return new Promise((t)=>{console.error(`${g.cyan("?")} ${e} (y/n) `);let s=(r)=>{let i=r.toString().trim().toLowerCase();m.stdin.removeListener("data",s);try{if(typeof m.stdin.setRawMode==="function")m.stdin.setRawMode(!1)}catch{}m.stdin.pause(),console.error(""),t(i==="y"||i==="yes")};try{if(typeof m.stdin.setRawMode==="function")m.stdin.setRawMode(!0)}catch{}m.stdin.resume(),m.stdin.once("data",s)})}setFancy(e){this.fancy=e}isFancy(){return this.fancy}pause(){this.enabled=!1}resume(){this.enabled=!0}async start(e,...t){if(!this.enabled)return;let s=e;if(t&&t.length>0){let a=/%([sdijfo%])/g,c=0;if(s=e.replace(a,(o,l)=>{if(l==="%")return"%";if(c>=t.length)return o;let h=t[c++];switch(l){case"s":return String(h);case"d":case"i":return Number(h).toString();case"j":case"o":return JSON.stringify(h,null,2);default:return o}}),c<t.length)s+=` ${t.slice(c).map((o)=>typeof o==="object"?JSON.stringify(o,null,2):String(o)).join(" ")}`}let{consoleText:r,fileText:i}=this.buildOutputTexts(s);if(this.shouldStyleConsole()){let a=this.options.showTags!==!1&&this.name?g.gray(this.formatTag(this.name)):"",c=this.options.showIcons===!1?"":`${g.blue("\u25D0")} `;console.error(`${c}${a} ${g.cyan(r)}`)}let n=`[${new Date().toISOString()}] ${this.environment}.INFO: [START] ${i}
|
|
11
|
-
`.replace(this.ANSI_PATTERN,"");if(this.shouldWriteToFile())await this.writeToFile(n)}renderProgressBar(e,t=!1){if(!this.enabled||!this.shouldStyleConsole()||!m.stdout.isTTY)return;let s=Math.min(100,Math.max(0,Math.round(e.current/e.total*100))),r=Math.round(e.barLength*s/100),i=e.barLength-r,n=g.green("\u2501".repeat(r)),a=g.gray("\u2501".repeat(i)),c=`[${n}${a}]`,o=`${s}%`.padStart(4),l=e.message?` ${e.message}`:"",h=this.options.showIcons===!1?"":t||s===100?g.green("\u2713"):g.blue("\u25B6"),f=this.options.showTags!==!1&&this.name?` ${g.gray(this.formatTag(this.name))}`:"",d=`\r${h}${f} ${c} ${o}${l}`,u=m.stdout.columns||80
|
|
12
|
-
`)}finishProgressBar(e,t){if(!this.enabled||!this.fancy||p()||!m.stdout.isTTY){this.activeProgressBar=null;return}if(e.current<e.total)e.current=e.total;if(t)e.message=t;this.renderProgressBar(e,!0),this.activeProgressBar=null}async clear(e={}){if(p()){console.warn("Log clearing is not supported in browser environments.");return}try{console.warn("Clearing logs...",this.config.logDirectory);let t=await
|
|
11
|
+
`.replace(this.ANSI_PATTERN,"");if(this.shouldWriteToFile())await this.writeToFile(n)}renderProgressBar(e,t=!1){if(!this.enabled||!this.shouldStyleConsole()||!m.stdout.isTTY)return;let s=Math.min(100,Math.max(0,Math.round(e.current/e.total*100))),r=Math.round(e.barLength*s/100),i=e.barLength-r,n=g.green("\u2501".repeat(r)),a=g.gray("\u2501".repeat(i)),c=`[${n}${a}]`,o=`${s}%`.padStart(4),l=e.message?` ${e.message}`:"",h=this.options.showIcons===!1?"":t||s===100?g.green("\u2713"):g.blue("\u25B6"),f=this.options.showTags!==!1&&this.name?` ${g.gray(this.formatTag(this.name))}`:"",d=`\r${h}${f} ${c} ${o}${l}`,u=m.stdout.columns||80,S=" ".repeat(Math.max(0,u-d.replace(this.ANSI_PATTERN,"").length));if(e.lastRenderedLine=`${d}${S}`,m.stdout.write(e.lastRenderedLine),t)m.stdout.write(`
|
|
12
|
+
`)}finishProgressBar(e,t){if(!this.enabled||!this.fancy||p()||!m.stdout.isTTY){this.activeProgressBar=null;return}if(e.current<e.total)e.current=e.total;if(t)e.message=t;this.renderProgressBar(e,!0),this.activeProgressBar=null}async clear(e={}){if(p()){console.warn("Log clearing is not supported in browser environments.");return}try{console.warn("Clearing logs...",this.config.logDirectory);let t=await le(this.config.logDirectory),s=[];for(let r of t){if(!(e.name?new RegExp(e.name.replace("*",".*")).test(r):r.startsWith(this.name))||!r.endsWith(".log"))continue;let i=F(this.config.logDirectory,r);if(e.before)try{if((await W(i)).mtime>=e.before)continue}catch(n){console.error(`Failed to get stats for file ${i}:`,n);continue}s.push(i)}if(s.length===0){console.warn("No log files matched the criteria for clearing.");return}console.warn(`Preparing to delete ${s.length} log file(s)...`);for(let r of s)try{await he(r),console.warn(`Deleted log file: ${r}`)}catch(i){console.error(`Failed to delete log file ${r}:`,i)}console.warn("Log clearing process finished.")}catch(t){console.error("Error during log clearing process:",t)}}}async function is(e,t={}){let{maxRetries:s=3,retryDelay:r=1000,isRetryable:i=()=>!0,fallback:n}=t,a=Error("Unknown error occurred");for(let c=0;c<=s;c++)try{return await e()}catch(o){if(a=o instanceof Error?o:Error(String(o)),c===s||!i(a))break;if(r>0)await new Promise((l)=>setTimeout(l,r))}if(n!==void 0)return n;throw a instanceof Error?a:Error(`Unknown error: ${String(a)}`)}function ns(e){return e instanceof E}function xr(e){return e instanceof pe}function _r(e){if(ns(e))return e.code==="FILE_SYSTEM_ERROR"||e.code==="BROWSER_CONFIG_ERROR";return["ENOENT","EACCES","EMFILE","ENFILE","EBUSY","network","timeout","connection"].some((t)=>e.message.toLowerCase().includes(t.toLowerCase()))}class _e{defaultParsers;constructor(){this.defaultParsers=[{name:"boolean",canParse:(e,t)=>t==="boolean"||["true","false","1","0","yes","no"].includes(e.toLowerCase()),parse:(e)=>{let t=e.toLowerCase();return["true","1","yes"].includes(t)}},{name:"number",canParse:(e,t)=>t==="number"||!Number.isNaN(Number(e))&&!Number.isNaN(Number.parseFloat(e)),parse:(e)=>{let t=Number(e);if(Number.isNaN(t))throw TypeError(`Cannot parse "${e}" as number`);return t}},{name:"array",canParse:(e,t)=>t==="array"||e.startsWith("[")||e.includes(","),parse:(e)=>{try{let t=JSON.parse(e);if(Array.isArray(t))return t}catch{}return e.split(",").map((t)=>t.trim())}},{name:"json",canParse:(e,t)=>t==="object"||(e.startsWith("{")&&e.endsWith("}")||e.startsWith("[")&&e.endsWith("]")),parse:(e)=>{try{return JSON.parse(e)}catch(t){throw Error(`Cannot parse "${e}" as JSON: ${t}`)}}}]}async applyEnvironmentVariables(e,t,s={}){let{prefix:r,useCamelCase:i=!0,useBackwardCompatibility:n=!0,customParsers:a={},verbose:c=!1,trackPerformance:o=!0}=s,l=async()=>{if(!e)return{config:t,source:{type:"environment",priority:50,timestamp:new Date}};let h=r||this.generateEnvPrefix(e),f={...t};return this.processObject(f,[],h,{useCamelCase:i,useBackwardCompatibility:n,customParsers:a,verbose:c,configName:e}),{config:f,source:{type:"environment",priority:50,timestamp:new Date}}};if(o)return se.track("applyEnvironmentVariables",l,{configName:e});return l()}generateEnvPrefix(e){return e.toUpperCase().replace(/-/g,"_")}formatEnvKey(e,t){if(!t)return e.toUpperCase();return e.replace(/([A-Z])/g,"_$1").toUpperCase()}processObject(e,t,s,r){for(let[i,n]of Object.entries(e)){let a=[...t,i],c=a.map((h)=>this.formatEnvKey(h,r.useCamelCase)),o=`${s}_${c.join("_")}`,l=r.useBackwardCompatibility?`${s}_${a.map((h)=>h.toUpperCase()).join("_")}`:null;if(r.verbose);if(typeof n==="object"&&n!==null&&!Array.isArray(n))this.processObject(n,a,s,r);else{let h=ue.env[o]||(l?ue.env[l]:void 0);if(h!==void 0){if(r.verbose){let f=ue.env[o]?o:l}try{e[i]=this.parseEnvironmentValue(h,typeof n,o,r.customParsers,r.configName)}catch(f){if(f instanceof ye)throw f;throw D.envVar(o,h,typeof n,r.configName)}}}}}parseEnvironmentValue(e,t,s,r,i){for(let[n,a]of Object.entries(r))try{return a(e)}catch{continue}for(let n of this.defaultParsers)if(n.canParse(e,t))try{return n.parse(e)}catch{throw D.envVar(s,e,`${t} (via ${n.name} parser)`,i)}return e}getEnvironmentVariables(e){let t={},s=e.toUpperCase();for(let[r,i]of Object.entries(ue.env))if(r.startsWith(s)&&i!==void 0)t[r]=i;return t}validateEnvironmentVariable(e,t,s){let r=[];if(!/^[A-Z_][A-Z0-9_]*$/.test(e))r.push(`Environment variable key "${e}" should only contain uppercase letters, numbers, and underscores`);if(s)try{this.parseEnvironmentValue(e,t,s,{})}catch(i){r.push(`Cannot parse value "${t}" as ${s}: ${i}`)}return{isValid:r.length===0,errors:r}}generateEnvVarDocs(e,t,s={}){let{prefix:r,format:i="text"}=s,n=r||this.generateEnvPrefix(e),a=[];switch(this.extractEnvVarInfo(t,[],n,a),i){case"markdown":return this.formatAsMarkdown(a,e);case"json":return JSON.stringify(a,null,2);default:return this.formatAsText(a,e)}}extractEnvVarInfo(e,t,s,r){for(let[i,n]of Object.entries(e)){let a=[...t,i],c=`${s}_${a.map((o)=>this.formatEnvKey(o,!0)).join("_")}`;if(typeof n==="object"&&n!==null&&!Array.isArray(n))this.extractEnvVarInfo(n,a,s,r);else r.push({key:c,type:Array.isArray(n)?"array":typeof n,description:`Configuration for ${a.join(".")}`,example:this.generateExample(n)})}}generateExample(e){if(Array.isArray(e))return JSON.stringify(e);if(typeof e==="object"&&e!==null)return JSON.stringify(e);return String(e)}formatAsText(e,t){let s=`Environment Variables for ${t}:
|
|
13
13
|
|
|
14
14
|
`;for(let r of e)s+=`${r.key}
|
|
15
15
|
`,s+=` Type: ${r.type}
|
|
@@ -21,13 +21,13 @@ var Es=Object.defineProperty;var Ss=(e)=>e;function xs(e,t){this[e]=Ss.bind(null
|
|
|
21
21
|
`;s+=`| Variable | Type | Description | Example |
|
|
22
22
|
`,s+=`|----------|------|-------------|----------|
|
|
23
23
|
`;for(let r of e)s+=`| \`${r.key}\` | ${r.type} | ${r.description} | \`${r.example}\` |
|
|
24
|
-
`;return s}}function Cr(e,t){let s=Gs("process");if(typeof s>"u"||!s.env)return t;let r=s.env[e];return r!==void 0?r:t}function ss(e,t,s={}){return rs(e,t,s,new WeakMap)}function rs(e,t,s,r){let{arrayMergeMode:i="replace",skipNullish:n=!1,customMerger:a}=s;if(t===null||t===void 0)return n?e:t;if(a){let c=a(e,t);if(c!==void 0)return c}if(Array.isArray(t)||Array.isArray(e))return is(e,t,i,r);if(!S(t)||!S(e))return t;return Sr(e,t,s,r)}function is(e,t,s,r){if(Array.isArray(t)&&!Array.isArray(e))return t;if(Array.isArray(e)&&!Array.isArray(t))return t;if(Array.isArray(t)&&Array.isArray(e))switch(s){case"replace":return t;case"concat":return kr(e,t);case"smart":return $r(e,t,r);default:return t}return t}function kr(e,t){let s=[...t];for(let r of e)if(!s.some((i)=>lt(i,r)))s.push(r);return s}function $r(e,t,s){if(t.length===0)return e;if(e.length===0)return t;if(S(t[0])&&S(e[0]))return Er(e,t,s);if(t.every((r)=>typeof r==="string")&&e.every((r)=>typeof r==="string")){let r=[...t];for(let i of e)if(!r.includes(i))r.push(i);return r}return t}function Er(e,t,s){let r=[...t];for(let i of e){if(!S(i)){r.push(i);continue}let n=["id","name","key","path","type"],a=!1;for(let c of n)if(c in i){if(r.find((o)=>S(o)&&(c in o)&&o[c]===i[c])){a=!0;break}}if(!a)r.push(i)}return r}function Sr(e,t,s,r){let i=t;if(S(i)&&r.has(i))return r.get(i);let n={...e};if(S(i))r.set(i,n);for(let a in i){if(!Object.prototype.hasOwnProperty.call(i,a))continue;let c=i[a],o=n[a];if(s.skipNullish&&(c===null||c===void 0))continue;if(c===null||c===void 0){n[a]=c;continue}if(S(c)&&S(o))n[a]=rs(o,c,s,r);else if(Array.isArray(c)||Array.isArray(o))n[a]=is(o,c,s.arrayMergeMode||"smart",r);else n[a]=c}return n}function ft(e,t,s="replace"){return ss(e,t,{arrayMergeMode:s==="replace"?"replace":"smart",skipNullish:!0})}function lt(e,t){if(e===t)return!0;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let s=0;s<e.length;s++)if(!lt(e[s],t[s]))return!1;return!0}if(S(e)&&S(t)){let s=Object.keys(e),r=Object.keys(t);if(s.length!==r.length)return!1;for(let i of s){if(!Object.prototype.hasOwnProperty.call(t,i))return!1;if(!lt(e[i],t[i]))return!1}return!0}return!1}function S(e){return Boolean(e&&typeof e==="object"&&!Array.isArray(e))}class Se{extensions=[".ts",".js",".mjs",".cjs",".json",".mts",".cts"];async loadFromPath(e,t,s={}){let{arrayStrategy:r="replace",useCache:i=!0,cacheTtl:n,trackPerformance:a=!0,verbose:c=!1}=s;if(i){let l=q.getWithFileCheck("file",e);if(l){if(c)console.log(`Configuration loaded from cache: ${e}`);return l}}let o=async()=>{if(!le(e))return null;try{let l=`?t=${Date.now()}`,h=await import(e+l),f=h.default||h,d="default"in h,u=Object.keys(h).length>0;if(!d&&!u)throw new G(e,Error("Configuration file is empty and exports nothing"),"unknown");if(typeof f!=="object"||f===null||Array.isArray(f))throw new G(e,Error("Configuration must export a valid object"),"unknown");let $={config:ft(t,f,r),source:{type:"file",path:e,priority:100,timestamp:new Date}};if(i)q.setWithFileCheck("file",$,e,n);return $}catch(l){throw l instanceof Error?O.configLoad(e,l):O.configLoad(e,Error(String(l)))}};if(a)return X.track("loadFromPath",o,{path:e});return o()}async tryLoadFromPaths(e,t,s={}){for(let r of e)try{let i=await this.loadFromPath(r,t,s);if(i)return i}catch(i){if(i instanceof Error&&i.name==="ConfigLoadError")throw i;if(s.verbose)console.warn(`Failed to load config from ${r}:`,i)}return null}generateConfigPaths(e,t,s){let r=this.generateNamePatterns(e,s),i=[];for(let n of r)for(let a of this.extensions)i.push(Ve(t,`${n}${a}`));return i}generateNamePatterns(e,t){let s=[];if(s.push("config",".config"),e)s.push(e,`.${e}.config`,`${e}.config`,`.${e}`);let r=t===void 0?[]:Array.isArray(t)?t:[t];for(let n of r){if(!n)continue;if(s.push(n,`.${n}.config`,`${n}.config`,`.${n}`),e)s.push(`${e}.${n}.config`,`.${e}.${n}.config`)}let i=new Set;return s.filter((n)=>{if(!n||i.has(n))return!1;return i.add(n),!0})}checkFileAccess(e){return Xt(async()=>{return le(e)},{maxRetries:2,retryDelay:100,fallback:!1})}async discoverConfigFiles(e,t,s){let r=[];if(!le(e))return r;if(t||s){let i=this.generateNamePatterns(t||"",s);for(let n of i)for(let a of this.extensions){let c=Ve(e,`${n}${a}`);if(await this.checkFileAccess(c))r.push(c)}}else try{let{readdirSync:i}=await import("fs"),n=i(e);for(let a of n)if(this.looksLikeConfigFile(a)){let c=Ve(e,a);if(await this.checkFileAccess(c))r.push(c)}}catch{return[]}return r}looksLikeConfigFile(e){return[/\.config\.(ts|js|mjs|cjs|json|mts|cts)$/,/^\..*\.(ts|js|mjs|cjs|json|mts|cts)$/,/config\.(ts|js|mjs|cjs|json|mts|cts)$/].some((t)=>t.test(e))}async validateConfigFile(e){let t=[];try{if(!le(e))return t.push("Configuration file does not exist"),t;let s=await import(e),r=s.default||s;if(r===void 0)t.push("Configuration file must export a default value or named exports");else if(typeof r!=="object"||r===null)t.push("Configuration must be an object");else if(Array.isArray(r))t.push("Configuration cannot be an array at the root level");if(e.endsWith(".json"))try{let{readFileSync:i}=await import("fs"),n=i(e,"utf8");JSON.parse(n)}catch(i){t.push(`Invalid JSON syntax: ${i}`)}}catch(s){t.push(`Failed to load configuration file: ${s}`)}return t}async getFileModificationTime(e){try{let{statSync:t}=await import("fs");return t(e).mtime}catch{return null}}async preloadConfigurations(e,t={}){let s=new Map;return await Promise.allSettled(e.map(async(r)=>{try{let i=await this.loadFromPath(r,{},t);if(i)s.set(r,i.config)}catch(i){if(t.verbose)console.warn(`Failed to preload ${r}:`,i)}})),s}}class gt{async validateConfiguration(e,t,s={}){let{stopOnFirstError:r=!1,validateRequired:i=!0,validateTypes:n=!0,customRules:a=[],trackPerformance:c=!0,verbose:o=!1}=s,l=async()=>{let h=[],f=[],d={stopOnFirstError:r,validateRequired:i,validateTypes:n,customRules:a,trackPerformance:c,verbose:o};try{if(typeof t==="string")return await this.validateWithSchemaFile(e,t,d);else if(Array.isArray(t))return this.validateWithRules(e,[...t,...a],d);else return this.validateWithJSONSchema(e,t,d)}catch(u){return h.push({path:"",message:`Validation failed: ${u}`,rule:"system"}),{isValid:!1,errors:h,warnings:f}}};if(c)return await X.track("validateConfiguration",l);return l()}async validateWithSchemaFile(e,t,s){try{if(!Js(t))throw new Y(t,[{path:"",message:"Schema file does not exist"}]);let r=await import(t),i=r.default||r;if(Array.isArray(i))return this.validateWithRules(e,i,s);else return this.validateWithJSONSchema(e,i,s)}catch(r){throw new Y(t,[{path:"",message:`Failed to load schema: ${r}`}])}}validateWithJSONSchema(e,t,s){let r=[],i=[];return this.validateObjectAgainstSchema(e,t,"",r,i,s),{isValid:r.length===0,errors:r,warnings:i}}validateObjectAgainstSchema(e,t,s,r,i,n){if(n.validateTypes&&t.type){let a=Array.isArray(e)?"array":typeof e,c=Array.isArray(t.type)?t.type:[t.type];if(!c.includes(a)){if(r.push({path:s,message:`Expected type ${c.join(" or ")}, got ${a}`,expected:c.join(" or "),actual:a,rule:"type"}),n.stopOnFirstError)return}}if(t.enum&&!t.enum.includes(e)){if(r.push({path:s,message:`Value must be one of: ${t.enum.join(", ")}`,expected:t.enum.join(", "),actual:e,rule:"enum"}),n.stopOnFirstError)return}if(typeof e==="string"){if(t.minLength!==void 0&&e.length<t.minLength)r.push({path:s,message:`String length must be at least ${t.minLength}`,expected:`>= ${t.minLength}`,actual:e.length,rule:"minLength"});if(t.maxLength!==void 0&&e.length>t.maxLength)r.push({path:s,message:`String length must not exceed ${t.maxLength}`,expected:`<= ${t.maxLength}`,actual:e.length,rule:"maxLength"});if(t.pattern){if(!new RegExp(t.pattern).test(e))r.push({path:s,message:`String does not match pattern ${t.pattern}`,expected:t.pattern,actual:e,rule:"pattern"})}}if(typeof e==="number"){if(t.minimum!==void 0&&e<t.minimum)r.push({path:s,message:`Value must be at least ${t.minimum}`,expected:`>= ${t.minimum}`,actual:e,rule:"minimum"});if(t.maximum!==void 0&&e>t.maximum)r.push({path:s,message:`Value must not exceed ${t.maximum}`,expected:`<= ${t.maximum}`,actual:e,rule:"maximum"})}if(Array.isArray(e)&&t.items)for(let a=0;a<e.length;a++){let c=s?`${s}[${a}]`:`[${a}]`;if(this.validateObjectAgainstSchema(e[a],t.items,c,r,i,n),n.stopOnFirstError&&r.length>0)return}if(e&&typeof e==="object"&&!Array.isArray(e)){let a=e;if(n.validateRequired&&t.required){for(let c of t.required)if(!(c in a)){if(r.push({path:s?`${s}.${c}`:c,message:`Missing required property '${c}'`,expected:"required",rule:"required"}),n.stopOnFirstError)return}}if(t.properties){for(let[c,o]of Object.entries(t.properties))if(c in a){let l=s?`${s}.${c}`:c;if(this.validateObjectAgainstSchema(a[c],o,l,r,i,n),n.stopOnFirstError&&r.length>0)return}}if(t.additionalProperties===!1){let c=new Set(Object.keys(t.properties||{}));for(let o of Object.keys(a))if(!c.has(o))i.push({path:s?`${s}.${o}`:o,message:`Additional property '${o}' is not allowed`,rule:"additionalProperties"})}}}validateWithRules(e,t,s){let r=[],i=[];for(let n of t)try{let a=this.getValueByPath(e,n.path),c=this.validateWithRule(a,n,n.path);if(r.push(...c),s.stopOnFirstError&&r.length>0)break}catch(a){r.push({path:n.path,message:`Rule validation failed: ${a}`,rule:"system"})}return{isValid:r.length===0,errors:r,warnings:i}}validateWithRule(e,t,s){let r=[];if(t.required&&(e===void 0||e===null))return r.push({path:s,message:t.message||`Property '${s}' is required`,expected:"required",rule:"required"}),r;if(e===void 0||e===null)return r;if(t.type){let i=Array.isArray(e)?"array":typeof e;if(i!==t.type)r.push({path:s,message:t.message||`Expected type ${t.type}, got ${i}`,expected:t.type,actual:i,rule:"type"})}if(t.min!==void 0){let i=Array.isArray(e)?e.length:typeof e==="string"?e.length:typeof e==="number"?e:0;if(i<t.min)r.push({path:s,message:t.message||`Value must be at least ${t.min}`,expected:`>= ${t.min}`,actual:i,rule:"min"})}if(t.max!==void 0){let i=Array.isArray(e)?e.length:typeof e==="string"?e.length:typeof e==="number"?e:0;if(i>t.max)r.push({path:s,message:t.message||`Value must not exceed ${t.max}`,expected:`<= ${t.max}`,actual:i,rule:"max"})}if(t.pattern&&typeof e==="string"){if(!t.pattern.test(e))r.push({path:s,message:t.message||`Value does not match pattern ${t.pattern}`,expected:t.pattern.toString(),actual:e,rule:"pattern"})}if(t.enum&&!t.enum.includes(e))r.push({path:s,message:t.message||`Value must be one of: ${t.enum.join(", ")}`,expected:t.enum.join(", "),actual:e,rule:"enum"});if(t.validator){let i=t.validator(e);if(i)r.push({path:s,message:t.message||i,rule:"custom"})}return r}getValueByPath(e,t){if(!t)return e;let s=t.split("."),r=e;for(let i of s)if(r&&typeof r==="object"&&i in r)r=r[i];else return;return r}generateRulesFromInterface(e){let t=[],s=e.matchAll(/(\w+)(\?)?:\s*(\w+)/g);for(let r of s){let[,i,n,a]=r;t.push({path:i,required:!n,type:this.mapTypeScriptType(a)})}return t}mapTypeScriptType(e){switch(e.toLowerCase()){case"string":return"string";case"number":return"number";case"boolean":return"boolean";case"array":return"array";case"object":return"object";default:return"object"}}static createCommonRules(){return{server:[{path:"port",required:!0,type:"number",min:1,max:65535},{path:"host",required:!0,type:"string",min:1},{path:"ssl",type:"boolean"}],database:[{path:"url",required:!0,type:"string",min:1},{path:"pool",type:"number",min:1,max:100},{path:"timeout",type:"number",min:0}],api:[{path:"baseUrl",required:!0,type:"string",pattern:os},{path:"timeout",type:"number",min:0},{path:"retries",type:"number",min:0,max:10}]}}}function xr(e){if(!e)return"";let t=Array.isArray(e)?e.filter(Boolean):[e];if(t.length===0)return"";if(t.length===1)return` or alias "${t[0]}"`;return` or aliases ${t.map((s)=>`"${s}"`).join(", ")}`}class mt{fileLoader=new Se;envProcessor=new Ee;validator=new gt;async loadConfig(e){let t=Date.now(),{cache:s,performance:r,schema:i,validate:n,...a}=e;try{if(s?.enabled){let o=this.checkCache(a.name||"",a);if(o)return o}let c;try{c=await this.loadConfigurationStrategies(a,!0,s)}catch(o){let l=a.__strictErrorHandling;if(o instanceof Error&&o.name==="ConfigNotFoundError"){if(l)throw o;c={...await this.applyEnvironmentVariables(a.name||"",a.defaultConfig,a.checkEnv!==!1,a.verbose||!1),warnings:[`No configuration file found for "${a.name||"config"}", using defaults with environment variables`]}}else if(o instanceof Error&&o.name==="ConfigLoadError"){let h=o.message.includes("EACCES")||o.message.includes("EPERM")||o.message.includes("permission denied"),f=!h&&(o.message.includes("syntax")||o.message.includes("Expected")||o.message.includes("Unexpected")||o.message.includes("BuildMessage")||o.message.includes("errors building")),d=o.message.includes("Configuration must export a valid object")||o.message.includes("Configuration file is empty and exports nothing");if(l&&(d||h))throw o;if(f&&(!l||!d))c={...await this.applyEnvironmentVariables(a.name||"",a.defaultConfig,a.checkEnv!==!1,a.verbose||!1),warnings:["Configuration file has syntax errors, using defaults with environment variables"]};else if(!l)c={...await this.applyEnvironmentVariables(a.name||"",a.defaultConfig,a.checkEnv!==!1,a.verbose||!1),warnings:[`Configuration loading error, using defaults: ${o.message}`]};else throw o}else c={...await this.applyEnvironmentVariables(a.name||"",a.defaultConfig,a.checkEnv!==!1,a.verbose||!1),warnings:[`Configuration loading failed, using defaults: ${o instanceof Error?o.message:String(o)}`]}}if(i||n)await this.validateConfiguration(c.config,i,n,a.name);if(s?.enabled&&c)this.cacheResult(a.name||"",c,s,a);if(r?.enabled){let o={operation:"loadConfig",duration:Date.now()-t,configName:a.name,timestamp:new Date};if(r.onMetrics)r.onMetrics(o);if(r.slowThreshold&&o.duration>r.slowThreshold)E.warn(`Slow configuration loading detected: ${o.duration}ms for ${a.name}`);c.metrics=o}return c}catch(c){let o=Date.now()-t;throw E.error(`Configuration loading failed after ${o}ms:`,[c instanceof Error?c:Error(String(c))]),c}}async loadConfigurationStrategies(e,t=!1,s){let{name:r="",alias:i,cwd:n,configDir:a,defaultConfig:c,checkEnv:o=!0,arrayStrategy:l="replace",verbose:h=!1}=e,f=n||N.cwd(),d=[],u=await this.loadLocalConfiguration(r,i,f,a,c,l,h,o,s);if(u)return d.push(...this.getLocalSearchPaths(r,i,f,a)),this.finalizeResult(u,d,o,r,h);let $=await this.loadHomeConfiguration(r,i,c,l,h,o);if($)return d.push(...this.getHomeSearchPaths(r,i)),this.finalizeResult($,d,o,r,h);let b=await this.loadPackageJsonConfiguration(r,i,f,c,l,h,o);if(b)return d.push(w(f,"package.json")),this.finalizeResult(b,d,o,r,h);if(d.push(...this.getAllSearchPaths(r,i,f,a)),t)throw O.configNotFound(r,d,i);return{...await this.applyEnvironmentVariables(r,c,o,h),warnings:[`No configuration file found for "${r}"${xr(i)}, using defaults with environment variables`]}}async loadLocalConfiguration(e,t,s,r,i,n,a,c,o){let l=c?H(e,i,a):i,h=this.getLocalDirectories(s,r);for(let f of h){if(a)E.info(`Searching for configuration in: ${f}`);let d=this.fileLoader.generateConfigPaths(e,f,t),u=await this.fileLoader.tryLoadFromPaths(d,l,{arrayStrategy:n,verbose:a,cacheTtl:o?.ttl,useCache:!o?.ttl||o.ttl>100});if(u){if(a)E.success(`Configuration loaded from: ${u.source.path}`);return u}}return null}async loadHomeConfiguration(e,t,s,r,i,n){if(!e)return null;let a=n?H(e,s,i):s,c=[w(F(),".config",e),w(F(),".config"),F()];for(let o of c){if(i)E.info(`Checking home directory: ${o}`);let l=this.fileLoader.generateConfigPaths(e,o,t),h=await this.fileLoader.tryLoadFromPaths(l,a,{arrayStrategy:r,verbose:i});if(h){if(i)E.success(`Configuration loaded from home directory: ${h.source.path}`);return h}}return null}async loadPackageJsonConfiguration(e,t,s,r,i,n,a){let c=a?H(e,r,n):r;try{let o=w(s,"package.json");if(!st(o))return null;let l={};try{l=JSON.parse(Ws(o,"utf8"))}catch(d){if(n)E.warn("Failed to parse package.json:",[d instanceof Error?d:Error(String(d))]);return null}let h=l[e],f=e;if(!h&&t){let d=Array.isArray(t)?t:[t];for(let u of d){if(!u)continue;if(l[u]){h=l[u],f=u;break}}}if(h&&typeof h==="object"&&!Array.isArray(h)){if(n)E.success(`Configuration loaded from package.json: ${f}`);return{config:ft(c,h,i),source:{type:"package.json",path:o,priority:30,timestamp:new Date}}}}catch(o){if(n)E.warn("Failed to load package.json:",[o instanceof Error?o:Error(String(o))])}return null}async applyEnvironmentVariables(e,t,s,r){if(!s||!e||typeof t!=="object"||t===null||Array.isArray(t))return{config:t,source:{type:"default",priority:10,timestamp:new Date}};return{config:H(e,t,r),source:{type:"environment",priority:20,timestamp:new Date}}}async finalizeResult(e,t,s,r,i){return{config:e.config,source:e.source,path:e.source.path}}async validateConfiguration(e,t,s,r){let i=[];if(s){let n=s(e);if(n)i.push(...n)}if(t){let n=await this.validator.validateConfiguration(e,t);if(!n.isValid)i.push(...n.errors.map((a)=>a.path?`${a.path}: ${a.message}`:a.message))}if(i.length>0)throw O.configValidation(r||"unknown",i,r)}checkCache(e,t){let s=this.generateCacheKey(e,t);return q.get(s)||null}cacheResult(e,t,s,r){let i=this.generateCacheKey(e,r);q.set(i,t,void 0,s.ttl)}generateCacheKey(e,t){let s=[e];if(t.alias){let r=Array.isArray(t.alias)?t.alias.join(","):t.alias;s.push(`alias:${r}`)}if(t.cwd)s.push(`cwd:${t.cwd}`);if(t.configDir)s.push(`configDir:${t.configDir}`);if("checkEnv"in t)s.push(`checkEnv:${t.checkEnv}`);return s.join("|")}getLocalDirectories(e,t){return Array.from(new Set([e,w(e,"config"),w(e,".config"),t?w(e,t):void 0].filter(Boolean)))}getAllSearchPaths(e,t,s,r){let i=[];return i.push(...this.getLocalSearchPaths(e,t,s,r)),i.push(...this.getHomeSearchPaths(e,t)),i.push(w(s,"package.json")),i}getLocalSearchPaths(e,t,s,r){let i=this.getLocalDirectories(s,r),n=[];for(let a of i)n.push(...this.fileLoader.generateConfigPaths(e,a,t));return n}getHomeSearchPaths(e,t){if(!e)return[];let s=[w(F(),".config",e),w(F(),".config"),F()],r=[];for(let i of s)r.push(...this.fileLoader.generateConfigPaths(e,i,t));return r}async loadConfigWithResult(e){return this.loadConfig(e)}}function Zt(e){let t=!(e.message.includes("EACCES")||e.message.includes("EPERM")||e.message.includes("permission denied"))&&(e.message.includes("syntax")||e.message.includes("Expected")||e.message.includes("Unexpected")||e.message.includes("BuildMessage")),s=e.message.includes("Configuration must export a valid object")||e.message.includes("Configuration file is empty and exports nothing");return t||s}async function _r(e){return A.loadConfig({...e,__strictErrorHandling:!0})}async function pt(e){let t="defaultConfig"in e&&e.defaultConfig!==void 0?e.defaultConfig:{},s="cache"in e||"performance"in e||"schema"in e||"validate"in e;try{let r;if(s)r=await A.loadConfig(e);else r=await A.loadConfig({...e,defaultConfig:t,cache:{enabled:!0},performance:{enabled:!1}});return r?.config??t}catch(r){let i=r instanceof Error?r.name:"UnknownError",n=r instanceof Error?r.message:String(r);if(!(i==="ConfigNotFoundError"||i==="ConfigLoadError"||i==="ConfigValidationError"||n.includes("config"))&&e.verbose)E.warn("Unexpected error loading config, using defaults:",[r instanceof Error?r:Error(String(r))]);let a=s?{...e,defaultConfig:t}:{...e,defaultConfig:t,cache:{enabled:!0},performance:{enabled:!1}};if("checkEnv"in e?e.checkEnv!==!1:!0)return(await A.applyEnvironmentVariables(a.name||"",t,!0,a.verbose||!1))?.config??t;return t}}async function Tr(e={defaultConfig:{}}){if(typeof e==="string"){let{cwd:t}=await import("process");try{return(await A.loadConfig({name:e,cwd:t(),generatedDir:"./generated",configDir:"./config",defaultConfig:{},checkEnv:!0,arrayStrategy:"replace"})).config}catch(s){if(s instanceof Error&&(s.name==="ConfigNotFoundError"||s.name==="ConfigLoadError"&&Zt(s)))return(await A.applyEnvironmentVariables(e,{},!0,!1)).config;throw s}}try{return(await A.loadConfig({...e,cwd:e.cwd||N.cwd(),cache:{enabled:!0},performance:{enabled:!1}})).config}catch(t){if(t instanceof Error&&(t.name==="ConfigNotFoundError"||t.name==="ConfigLoadError"&&Zt(t)))return(await A.applyEnvironmentVariables(e.name||"",e.defaultConfig||{},e.checkEnv!==!1,e.verbose||!1)).config;throw t}}async function Ar(e,t,s="replace"){let r=new Se;try{let i=await r.loadFromPath(e,t,{arrayStrategy:s,useCache:!1,trackPerformance:!1});return i?i.config:null}catch{return null}}function H(e,t,s=!1){let r=new Ee,i=e.toUpperCase().replace(/[^A-Z0-9]/g,"_");function n(a,c=[]){let o={...a};for(let[l,h]of Object.entries(a)){let f=[...c,l],d=[`${i}_${f.join("_").toUpperCase()}`,`${i}_${f.map((b)=>b.toUpperCase()).join("")}`,`${i}_${f.map((b)=>b.replace(/([A-Z])/g,"_$1").toUpperCase()).join("")}`],u,$;for(let b of d)if(u=N.env[b],u!==void 0){$=b;break}if(u!==void 0&&$)if(typeof h==="boolean")o[l]=["true","1","yes"].includes(u.toLowerCase());else if(typeof h==="number"){let b=Number(u);if(!Number.isNaN(b))o[l]=b}else if(Array.isArray(h))try{o[l]=JSON.parse(u)}catch{o[l]=u.split(",").map((b)=>b.trim())}else o[l]=u;else if(h&&typeof h==="object"&&!Array.isArray(h))o[l]=n(h,f)}return o}return n(t)}function Mr(e){let t=w(N.cwd(),e.configDir),s=w(N.cwd(),e.generatedDir),r=w(s,"config-types.ts");if(!st(Lt(r)))Ls(Lt(r),{recursive:!0,mode:511});let i=st(t)?Us(t).map((a)=>a.replace(/\.(ts|js|mjs|cjs|mts|cts|json)$/,"")).sort():[],n=`// Generated by bunfig v${yr}
|
|
24
|
+
`;return s}}function Tr(e,t){let s=ir("process");if(typeof s>"u"||!s.env)return t;let r=s.env[e];return r!==void 0?r:t}function os(e,t,s={}){return cs(e,t,s,new WeakMap)}function cs(e,t,s,r){let{arrayMergeMode:i="replace",skipNullish:n=!1,customMerger:a}=s;if(t===null||t===void 0)return n?e:t;if(a){let c=a(e,t);if(c!==void 0)return c}if(Array.isArray(t)||Array.isArray(e))return ls(e,t,i,r);if(!_(t)||!_(e))return t;return Ir(e,t,s,r)}function ls(e,t,s,r){if(Array.isArray(t)&&!Array.isArray(e))return t;if(Array.isArray(e)&&!Array.isArray(t))return t;if(Array.isArray(t)&&Array.isArray(e))switch(s){case"replace":return t;case"concat":return Ar(e,t);case"smart":return Mr(e,t,r);default:return t}return t}function Ar(e,t){let s=[...t];for(let r of e)if(!s.some((i)=>dt(i,r)))s.push(r);return s}function Mr(e,t,s){if(t.length===0)return e;if(e.length===0)return t;if(_(t[0])&&_(e[0]))return Pr(e,t,s);if(t.every((r)=>typeof r==="string")&&e.every((r)=>typeof r==="string")){let r=[...t];for(let i of e)if(!r.includes(i))r.push(i);return r}return t}function Pr(e,t,s){let r=[...t];for(let i of e){if(!_(i)){r.push(i);continue}let n=["id","name","key","path","type"],a=!1;for(let c of n)if(c in i){if(r.find((o)=>_(o)&&(c in o)&&o[c]===i[c])){a=!0;break}}if(!a)r.push(i)}return r}function Ir(e,t,s,r){let i=t;if(_(i)&&r.has(i))return r.get(i);let n={...e};if(_(i))r.set(i,n);for(let a in i){if(!Object.prototype.hasOwnProperty.call(i,a))continue;let c=i[a],o=n[a];if(s.skipNullish&&(c===null||c===void 0))continue;if(c===null||c===void 0){n[a]=c;continue}if(_(c)&&_(o))n[a]=cs(o,c,s,r);else if(Array.isArray(c)||Array.isArray(o))n[a]=ls(o,c,s.arrayMergeMode||"smart",r);else n[a]=c}return n}function pt(e,t,s="replace"){return os(e,t,{arrayMergeMode:s==="replace"?"replace":"smart",skipNullish:!0})}function dt(e,t){if(e===t)return!0;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let s=0;s<e.length;s++)if(!dt(e[s],t[s]))return!1;return!0}if(_(e)&&_(t)){let s=Object.keys(e),r=Object.keys(t);if(s.length!==r.length)return!1;for(let i of s){if(!Object.prototype.hasOwnProperty.call(t,i))return!1;if(!dt(e[i],t[i]))return!1}return!0}return!1}function _(e){return Boolean(e&&typeof e==="object"&&!Array.isArray(e))}class Te{extensions=[".ts",".js",".mjs",".cjs",".json",".mts",".cts"];async loadFromPath(e,t,s={}){let{arrayStrategy:r="replace",useCache:i=!0,cacheTtl:n,trackPerformance:a=!0,verbose:c=!1}=s;if(i){let l=K.getWithFileCheck("file",e);if(l){if(c)console.log(`Configuration loaded from cache: ${e}`);return l}}let o=async()=>{if(!fe(e))return null;try{let l=`?t=${Date.now()}`,h=await import(e+l),f=h.default||h,d="default"in h,u=Object.keys(h).length>0;if(!d&&!u)throw new ee(e,Error("Configuration file is empty and exports nothing"),"unknown");if(typeof f!=="object"||f===null||Array.isArray(f))throw new ee(e,Error("Configuration must export a valid object"),"unknown");let S={config:pt(t,f,r),source:{type:"file",path:e,priority:100,timestamp:new Date}};if(i)K.setWithFileCheck("file",S,e,n);return S}catch(l){throw l instanceof Error?D.configLoad(e,l):D.configLoad(e,Error(String(l)))}};if(a)return se.track("loadFromPath",o,{path:e});return o()}async tryLoadFromPaths(e,t,s={}){for(let r of e)try{let i=await this.loadFromPath(r,t,s);if(i)return i}catch(i){if(i instanceof Error&&i.name==="ConfigLoadError")throw i;if(s.verbose)console.warn(`Failed to load config from ${r}:`,i)}return null}generateConfigPaths(e,t,s){let r=this.generateNamePatterns(e,s),i=[];for(let n of r)for(let a of this.extensions)i.push(et(t,`${n}${a}`));return i}generateNamePatterns(e,t){let s=[];if(s.push("config",".config"),e)s.push(e,`.${e}.config`,`${e}.config`,`.${e}`);let r=t===void 0?[]:Array.isArray(t)?t:[t];for(let n of r){if(!n)continue;if(s.push(n,`.${n}.config`,`${n}.config`,`.${n}`),e)s.push(`${e}.${n}.config`,`.${e}.${n}.config`)}let i=new Set;return s.filter((n)=>{if(!n||i.has(n))return!1;return i.add(n),!0})}checkFileAccess(e){return is(async()=>{return fe(e)},{maxRetries:2,retryDelay:100,fallback:!1})}async discoverConfigFiles(e,t,s){let r=[];if(!fe(e))return r;if(t||s){let i=this.generateNamePatterns(t||"",s);for(let n of i)for(let a of this.extensions){let c=et(e,`${n}${a}`);if(await this.checkFileAccess(c))r.push(c)}}else try{let{readdirSync:i}=await import("fs"),n=i(e);for(let a of n)if(this.looksLikeConfigFile(a)){let c=et(e,a);if(await this.checkFileAccess(c))r.push(c)}}catch{return[]}return r}looksLikeConfigFile(e){return[/\.config\.(ts|js|mjs|cjs|json|mts|cts)$/,/^\..*\.(ts|js|mjs|cjs|json|mts|cts)$/,/config\.(ts|js|mjs|cjs|json|mts|cts)$/].some((t)=>t.test(e))}async validateConfigFile(e){let t=[];try{if(!fe(e))return t.push("Configuration file does not exist"),t;let s=await import(e),r=s.default||s;if(r===void 0)t.push("Configuration file must export a default value or named exports");else if(typeof r!=="object"||r===null)t.push("Configuration must be an object");else if(Array.isArray(r))t.push("Configuration cannot be an array at the root level");if(e.endsWith(".json"))try{let{readFileSync:i}=await import("fs"),n=i(e,"utf8");JSON.parse(n)}catch(i){t.push(`Invalid JSON syntax: ${i}`)}}catch(s){t.push(`Failed to load configuration file: ${s}`)}return t}async getFileModificationTime(e){try{let{statSync:t}=await import("fs");return t(e).mtime}catch{return null}}async preloadConfigurations(e,t={}){let s=new Map;return await Promise.allSettled(e.map(async(r)=>{try{let i=await this.loadFromPath(r,{},t);if(i)s.set(r,i.config)}catch(i){if(t.verbose)console.warn(`Failed to preload ${r}:`,i)}})),s}}class bt{async validateConfiguration(e,t,s={}){let{stopOnFirstError:r=!1,validateRequired:i=!0,validateTypes:n=!0,customRules:a=[],trackPerformance:c=!0,verbose:o=!1}=s,l=async()=>{let h=[],f=[],d={stopOnFirstError:r,validateRequired:i,validateTypes:n,customRules:a,trackPerformance:c,verbose:o};try{if(typeof t==="string")return await this.validateWithSchemaFile(e,t,d);else if(Array.isArray(t))return this.validateWithRules(e,[...t,...a],d);else return this.validateWithJSONSchema(e,t,d)}catch(u){return h.push({path:"",message:`Validation failed: ${u}`,rule:"system"}),{isValid:!1,errors:h,warnings:f}}};if(c)return await se.track("validateConfiguration",l);return l()}async validateWithSchemaFile(e,t,s){try{if(!Ks(t))throw new te(t,[{path:"",message:"Schema file does not exist"}]);let r=await import(t),i=r.default||r;if(Array.isArray(i))return this.validateWithRules(e,i,s);else return this.validateWithJSONSchema(e,i,s)}catch(r){throw new te(t,[{path:"",message:`Failed to load schema: ${r}`}])}}validateWithJSONSchema(e,t,s){let r=[],i=[];return this.validateObjectAgainstSchema(e,t,"",r,i,s),{isValid:r.length===0,errors:r,warnings:i}}validateObjectAgainstSchema(e,t,s,r,i,n){if(n.validateTypes&&t.type){let a=Array.isArray(e)?"array":typeof e,c=Array.isArray(t.type)?t.type:[t.type];if(!c.includes(a)){if(r.push({path:s,message:`Expected type ${c.join(" or ")}, got ${a}`,expected:c.join(" or "),actual:a,rule:"type"}),n.stopOnFirstError)return}}if(t.enum&&!t.enum.includes(e)){if(r.push({path:s,message:`Value must be one of: ${t.enum.join(", ")}`,expected:t.enum.join(", "),actual:e,rule:"enum"}),n.stopOnFirstError)return}if(typeof e==="string"){if(t.minLength!==void 0&&e.length<t.minLength)r.push({path:s,message:`String length must be at least ${t.minLength}`,expected:`>= ${t.minLength}`,actual:e.length,rule:"minLength"});if(t.maxLength!==void 0&&e.length>t.maxLength)r.push({path:s,message:`String length must not exceed ${t.maxLength}`,expected:`<= ${t.maxLength}`,actual:e.length,rule:"maxLength"});if(t.pattern){if(!new RegExp(t.pattern).test(e))r.push({path:s,message:`String does not match pattern ${t.pattern}`,expected:t.pattern,actual:e,rule:"pattern"})}}if(typeof e==="number"){if(t.minimum!==void 0&&e<t.minimum)r.push({path:s,message:`Value must be at least ${t.minimum}`,expected:`>= ${t.minimum}`,actual:e,rule:"minimum"});if(t.maximum!==void 0&&e>t.maximum)r.push({path:s,message:`Value must not exceed ${t.maximum}`,expected:`<= ${t.maximum}`,actual:e,rule:"maximum"})}if(Array.isArray(e)&&t.items)for(let a=0;a<e.length;a++){let c=s?`${s}[${a}]`:`[${a}]`;if(this.validateObjectAgainstSchema(e[a],t.items,c,r,i,n),n.stopOnFirstError&&r.length>0)return}if(e&&typeof e==="object"&&!Array.isArray(e)){let a=e;if(n.validateRequired&&t.required){for(let c of t.required)if(!(c in a)){if(r.push({path:s?`${s}.${c}`:c,message:`Missing required property '${c}'`,expected:"required",rule:"required"}),n.stopOnFirstError)return}}if(t.properties){for(let[c,o]of Object.entries(t.properties))if(c in a){let l=s?`${s}.${c}`:c;if(this.validateObjectAgainstSchema(a[c],o,l,r,i,n),n.stopOnFirstError&&r.length>0)return}}if(t.additionalProperties===!1){let c=new Set(Object.keys(t.properties||{}));for(let o of Object.keys(a))if(!c.has(o))i.push({path:s?`${s}.${o}`:o,message:`Additional property '${o}' is not allowed`,rule:"additionalProperties"})}}}validateWithRules(e,t,s){let r=[],i=[];for(let n of t)try{let a=this.getValueByPath(e,n.path),c=this.validateWithRule(a,n,n.path);if(r.push(...c),s.stopOnFirstError&&r.length>0)break}catch(a){r.push({path:n.path,message:`Rule validation failed: ${a}`,rule:"system"})}return{isValid:r.length===0,errors:r,warnings:i}}validateWithRule(e,t,s){let r=[];if(t.required&&(e===void 0||e===null))return r.push({path:s,message:t.message||`Property '${s}' is required`,expected:"required",rule:"required"}),r;if(e===void 0||e===null)return r;if(t.type){let i=Array.isArray(e)?"array":typeof e;if(i!==t.type)r.push({path:s,message:t.message||`Expected type ${t.type}, got ${i}`,expected:t.type,actual:i,rule:"type"})}if(t.min!==void 0){let i=Array.isArray(e)?e.length:typeof e==="string"?e.length:typeof e==="number"?e:0;if(i<t.min)r.push({path:s,message:t.message||`Value must be at least ${t.min}`,expected:`>= ${t.min}`,actual:i,rule:"min"})}if(t.max!==void 0){let i=Array.isArray(e)?e.length:typeof e==="string"?e.length:typeof e==="number"?e:0;if(i>t.max)r.push({path:s,message:t.message||`Value must not exceed ${t.max}`,expected:`<= ${t.max}`,actual:i,rule:"max"})}if(t.pattern&&typeof e==="string"){if(!t.pattern.test(e))r.push({path:s,message:t.message||`Value does not match pattern ${t.pattern}`,expected:t.pattern.toString(),actual:e,rule:"pattern"})}if(t.enum&&!t.enum.includes(e))r.push({path:s,message:t.message||`Value must be one of: ${t.enum.join(", ")}`,expected:t.enum.join(", "),actual:e,rule:"enum"});if(t.validator){let i=t.validator(e);if(i)r.push({path:s,message:t.message||i,rule:"custom"})}return r}getValueByPath(e,t){if(!t)return e;let s=t.split("."),r=e;for(let i of s)if(r&&typeof r==="object"&&i in r)r=r[i];else return;return r}generateRulesFromInterface(e){let t=[],s=e.matchAll(/(\w+)(\?)?:\s*(\w+)/g);for(let r of s){let[,i,n,a]=r;t.push({path:i,required:!n,type:this.mapTypeScriptType(a)})}return t}mapTypeScriptType(e){switch(e.toLowerCase()){case"string":return"string";case"number":return"number";case"boolean":return"boolean";case"array":return"array";case"object":return"object";default:return"object"}}static createCommonRules(){return{server:[{path:"port",required:!0,type:"number",min:1,max:65535},{path:"host",required:!0,type:"string",min:1},{path:"ssl",type:"boolean"}],database:[{path:"url",required:!0,type:"string",min:1},{path:"pool",type:"number",min:1,max:100},{path:"timeout",type:"number",min:0}],api:[{path:"baseUrl",required:!0,type:"string",pattern:fs},{path:"timeout",type:"number",min:0},{path:"retries",type:"number",min:0,max:10}]}}}function Or(e){if(!e)return"";let t=Array.isArray(e)?e.filter(Boolean):[e];if(t.length===0)return"";if(t.length===1)return` or alias "${t[0]}"`;return` or aliases ${t.map((s)=>`"${s}"`).join(", ")}`}class wt{fileLoader=new Te;envProcessor=new _e;validator=new bt;async loadConfig(e){let t=Date.now(),{cache:s,performance:r,schema:i,validate:n,...a}=e;try{if(s?.enabled){let o=this.checkCache(a.name||"",a);if(o)return o}let c;try{c=await this.loadConfigurationStrategies(a,!0,s)}catch(o){let l=a.__strictErrorHandling;if(o instanceof Error&&o.name==="ConfigNotFoundError"){if(l)throw o;c={...await this.applyEnvironmentVariables(a.name||"",a.defaultConfig,a.checkEnv!==!1,a.verbose||!1),warnings:[`No configuration file found for "${a.name||"config"}", using defaults with environment variables`]}}else if(o instanceof Error&&o.name==="ConfigLoadError"){let h=o.message.includes("EACCES")||o.message.includes("EPERM")||o.message.includes("permission denied"),f=!h&&(o.message.includes("syntax")||o.message.includes("Expected")||o.message.includes("Unexpected")||o.message.includes("BuildMessage")||o.message.includes("errors building")),d=o.message.includes("Configuration must export a valid object")||o.message.includes("Configuration file is empty and exports nothing");if(l&&(d||h))throw o;if(f&&(!l||!d))c={...await this.applyEnvironmentVariables(a.name||"",a.defaultConfig,a.checkEnv!==!1,a.verbose||!1),warnings:["Configuration file has syntax errors, using defaults with environment variables"]};else if(!l)c={...await this.applyEnvironmentVariables(a.name||"",a.defaultConfig,a.checkEnv!==!1,a.verbose||!1),warnings:[`Configuration loading error, using defaults: ${o.message}`]};else throw o}else c={...await this.applyEnvironmentVariables(a.name||"",a.defaultConfig,a.checkEnv!==!1,a.verbose||!1),warnings:[`Configuration loading failed, using defaults: ${o instanceof Error?o.message:String(o)}`]}}if(i||n)await this.validateConfiguration(c.config,i,n,a.name);if(s?.enabled&&c)this.cacheResult(a.name||"",c,s,a);if(r?.enabled){let o={operation:"loadConfig",duration:Date.now()-t,configName:a.name,timestamp:new Date};if(r.onMetrics)r.onMetrics(o);if(r.slowThreshold&&o.duration>r.slowThreshold)x.warn(`Slow configuration loading detected: ${o.duration}ms for ${a.name}`);c.metrics=o}return c}catch(c){let o=Date.now()-t;throw x.error(`Configuration loading failed after ${o}ms:`,[c instanceof Error?c:Error(String(c))]),c}}async loadConfigurationStrategies(e,t=!1,s){let{name:r="",alias:i,cwd:n,configDir:a,defaultConfig:c,checkEnv:o=!0,arrayStrategy:l="replace",verbose:h=!1}=e,f=n||j.cwd(),d=[],u=await this.loadLocalConfiguration(r,i,f,a,c,l,h,o,s);if(u)return d.push(...this.getLocalSearchPaths(r,i,f,a)),this.finalizeResult(u,d,o,r,h);let S=await this.loadHomeConfiguration(r,i,c,l,h,o);if(S)return d.push(...this.getHomeSearchPaths(r,i)),this.finalizeResult(S,d,o,r,h);let w=await this.loadPackageJsonConfiguration(r,i,f,c,l,h,o);if(w)return d.push(C(f,"package.json")),this.finalizeResult(w,d,o,r,h);if(d.push(...this.getAllSearchPaths(r,i,f,a)),t)throw D.configNotFound(r,d,i);return{...await this.applyEnvironmentVariables(r,c,o,h),warnings:[`No configuration file found for "${r}"${Or(i)}, using defaults with environment variables`]}}async loadLocalConfiguration(e,t,s,r,i,n,a,c,o){let l=c?Y(e,i,a):i,h=this.getLocalDirectories(s,r);for(let f of h){if(a)x.info(`Searching for configuration in: ${f}`);let d=this.fileLoader.generateConfigPaths(e,f,t),u=await this.fileLoader.tryLoadFromPaths(d,l,{arrayStrategy:n,verbose:a,cacheTtl:o?.ttl,useCache:!o?.ttl||o.ttl>100});if(u){if(a)x.success(`Configuration loaded from: ${u.source.path}`);return u}}return null}async loadHomeConfiguration(e,t,s,r,i,n){if(!e)return null;let a=n?Y(e,s,i):s,c=[C(z(),".config",e),C(z(),".config"),z()];for(let o of c){if(i)x.info(`Checking home directory: ${o}`);let l=this.fileLoader.generateConfigPaths(e,o,t),h=await this.fileLoader.tryLoadFromPaths(l,a,{arrayStrategy:r,verbose:i});if(h){if(i)x.success(`Configuration loaded from home directory: ${h.source.path}`);return h}}return null}async loadPackageJsonConfiguration(e,t,s,r,i,n,a){let c=a?Y(e,r,n):r;try{let o=C(s,"package.json");if(!at(o))return null;let l={};try{l=JSON.parse(Hs(o,"utf8"))}catch(d){if(n)x.warn("Failed to parse package.json:",[d instanceof Error?d:Error(String(d))]);return null}let h=l[e],f=e;if(!h&&t){let d=Array.isArray(t)?t:[t];for(let u of d){if(!u)continue;if(l[u]){h=l[u],f=u;break}}}if(h&&typeof h==="object"&&!Array.isArray(h)){if(n)x.success(`Configuration loaded from package.json: ${f}`);return{config:pt(c,h,i),source:{type:"package.json",path:o,priority:30,timestamp:new Date}}}}catch(o){if(n)x.warn("Failed to load package.json:",[o instanceof Error?o:Error(String(o))])}return null}async applyEnvironmentVariables(e,t,s,r){if(!s||!e||typeof t!=="object"||t===null||Array.isArray(t))return{config:t,source:{type:"default",priority:10,timestamp:new Date}};return{config:Y(e,t,r),source:{type:"environment",priority:20,timestamp:new Date}}}async finalizeResult(e,t,s,r,i){return{config:e.config,source:e.source,path:e.source.path}}async validateConfiguration(e,t,s,r){let i=[];if(s){let n=s(e);if(n)i.push(...n)}if(t){let n=await this.validator.validateConfiguration(e,t);if(!n.isValid)i.push(...n.errors.map((a)=>a.path?`${a.path}: ${a.message}`:a.message))}if(i.length>0)throw D.configValidation(r||"unknown",i,r)}checkCache(e,t){let s=this.generateCacheKey(e,t);return K.get(s)||null}cacheResult(e,t,s,r){let i=this.generateCacheKey(e,r);K.set(i,t,void 0,s.ttl)}generateCacheKey(e,t){let s=[e];if(t.alias){let r=Array.isArray(t.alias)?t.alias.join(","):t.alias;s.push(`alias:${r}`)}if(t.cwd)s.push(`cwd:${t.cwd}`);if(t.configDir)s.push(`configDir:${t.configDir}`);if("checkEnv"in t)s.push(`checkEnv:${t.checkEnv}`);return s.join("|")}getLocalDirectories(e,t){return Array.from(new Set([e,C(e,"config"),C(e,".config"),t?C(e,t):void 0].filter(Boolean)))}getAllSearchPaths(e,t,s,r){let i=[];return i.push(...this.getLocalSearchPaths(e,t,s,r)),i.push(...this.getHomeSearchPaths(e,t)),i.push(C(s,"package.json")),i}getLocalSearchPaths(e,t,s,r){let i=this.getLocalDirectories(s,r),n=[];for(let a of i)n.push(...this.fileLoader.generateConfigPaths(e,a,t));return n}getHomeSearchPaths(e,t){if(!e)return[];let s=[C(z(),".config",e),C(z(),".config"),z()],r=[];for(let i of s)r.push(...this.fileLoader.generateConfigPaths(e,i,t));return r}async loadConfigWithResult(e){return this.loadConfig(e)}}function Yt(e){let t=!(e.message.includes("EACCES")||e.message.includes("EPERM")||e.message.includes("permission denied"))&&(e.message.includes("syntax")||e.message.includes("Expected")||e.message.includes("Unexpected")||e.message.includes("BuildMessage")),s=e.message.includes("Configuration must export a valid object")||e.message.includes("Configuration file is empty and exports nothing");return t||s}async function Rr(e){return P.loadConfig({...e,__strictErrorHandling:!0})}async function vt(e){let t="defaultConfig"in e&&e.defaultConfig!==void 0?e.defaultConfig:{},s="cache"in e||"performance"in e||"schema"in e||"validate"in e;try{let r;if(s)r=await P.loadConfig(e);else r=await P.loadConfig({...e,defaultConfig:t,cache:{enabled:!0},performance:{enabled:!1}});return r?.config??t}catch(r){let i=r instanceof Error?r.name:"UnknownError",n=r instanceof Error?r.message:String(r);if(!(i==="ConfigNotFoundError"||i==="ConfigLoadError"||i==="ConfigValidationError"||n.includes("config"))&&e.verbose)x.warn("Unexpected error loading config, using defaults:",[r instanceof Error?r:Error(String(r))]);let a=s?{...e,defaultConfig:t}:{...e,defaultConfig:t,cache:{enabled:!0},performance:{enabled:!1}};if("checkEnv"in e?e.checkEnv!==!1:!0)return(await P.applyEnvironmentVariables(a.name||"",t,!0,a.verbose||!1))?.config??t;return t}}async function Dr(e={defaultConfig:{}}){if(typeof e==="string"){let{cwd:t}=await import("process");try{return(await P.loadConfig({name:e,cwd:t(),generatedDir:"./generated",configDir:"./config",defaultConfig:{},checkEnv:!0,arrayStrategy:"replace"})).config}catch(s){if(s instanceof Error&&(s.name==="ConfigNotFoundError"||s.name==="ConfigLoadError"&&Yt(s)))return(await P.applyEnvironmentVariables(e,{},!0,!1)).config;throw s}}try{return(await P.loadConfig({...e,cwd:e.cwd||j.cwd(),cache:{enabled:!0},performance:{enabled:!1}})).config}catch(t){if(t instanceof Error&&(t.name==="ConfigNotFoundError"||t.name==="ConfigLoadError"&&Yt(t)))return(await P.applyEnvironmentVariables(e.name||"",e.defaultConfig||{},e.checkEnv!==!1,e.verbose||!1)).config;throw t}}async function Br(e,t,s="replace"){let r=new Te;try{let i=await r.loadFromPath(e,t,{arrayStrategy:s,useCache:!1,trackPerformance:!1});return i?i.config:null}catch{return null}}function Y(e,t,s=!1){let r=new _e,i=e.toUpperCase().replace(/[^A-Z0-9]/g,"_");function n(a,c=[]){let o={...a};for(let[l,h]of Object.entries(a)){let f=[...c,l],d=[`${i}_${f.join("_").toUpperCase()}`,`${i}_${f.map((w)=>w.toUpperCase()).join("")}`,`${i}_${f.map((w)=>w.replace(/([A-Z])/g,"_$1").toUpperCase()).join("")}`],u,S;for(let w of d)if(u=j.env[w],u!==void 0){S=w;break}if(u!==void 0&&S)if(typeof h==="boolean")o[l]=["true","1","yes"].includes(u.toLowerCase());else if(typeof h==="number"){let w=Number(u);if(!Number.isNaN(w))o[l]=w}else if(Array.isArray(h))try{o[l]=JSON.parse(u)}catch{o[l]=u.split(",").map((w)=>w.trim())}else o[l]=u;else if(h&&typeof h==="object"&&!Array.isArray(h))o[l]=n(h,f)}return o}return n(t)}function Nr(e){let t=C(j.cwd(),e.configDir),s=C(j.cwd(),e.generatedDir),r=C(s,"config-types.ts");if(!at(zt(r)))Zs(zt(r),{recursive:!0,mode:511});let i=at(t)?Qs(t).map((a)=>a.replace(/\.(ts|js|mjs|cjs|mts|cts|json)$/,"")).sort():[],n=`// Generated by bunfig v${Er}
|
|
25
25
|
export type ConfigNames = ${i.length?`'${i.join("' | '")}'`:"string"}
|
|
26
|
-
`;
|
|
27
|
-
${i.map((o)=>{let l=
|
|
26
|
+
`;Vs(r,n,{mode:438})}function jr(e){let t=null,s=null,r=()=>{if(!s)s=vt(e).then((n)=>{return t=n,n},(n)=>{let a="defaultConfig"in e?e.defaultConfig:{};if(t=a,"verbose"in e&&e.verbose)x.warn("Config loading failed, using defaults:",[n instanceof Error?n:Error(String(n))]);return a});return s},i="defaultConfig"in e?e.defaultConfig:{};return t=i,r(),new Proxy({},{get(n,a){if(t)return t[a];let c=i[a];return r(),c},has(n,a){return a in(t||i)},ownKeys(){return Object.keys(t||i)},getOwnPropertyDescriptor(n,a){return Object.getOwnPropertyDescriptor(t||i,a)},set(n,a,c){if(!t)t={...i};return t[a]=c,!0}})}function Lr(e){let t=Kt(Xs.cwd(),e?.configDir||"./config");function s(){if(!Gs(t))return[];let i=new Set([".ts",".js",".mjs",".cjs",".mts",".cts",".json"]),n=[".ts",".mts",".cts",".js",".mjs",".cjs",".json"],a=Ys(t).filter((o)=>i.has(tt(o))).map((o)=>({base:o.replace(/\.(?:ts|js|mjs|cjs|mts|cts|json)$/i,""),file:o})),c=new Map;for(let{base:o,file:l}of a){let h=tt(l).toLowerCase(),f=c.get(o);if(!f){c.set(o,l);continue}let d=tt(f).toLowerCase();if(n.indexOf(h)<n.indexOf(d))c.set(o,l)}return Array.from(c.entries()).map(([o,l])=>({base:o,file:l})).sort((o,l)=>o.base.localeCompare(l.base))}function r(){let i=s(),n=i.map((o)=>o.base),a=n.length?n.map((o)=>`'${o}'`).join(" | "):"string",c=i.length?`{
|
|
27
|
+
${i.map((o)=>{let l=Kt(t,o.file).replace(/\\/g,"/");return` '${o.base}': typeof import('${l}').default`}).join(`,
|
|
28
28
|
`)}
|
|
29
29
|
}`:"Record<string, any>";return`export type ConfigNames = ${a}
|
|
30
30
|
export type ConfigByName = ${c}
|
|
31
31
|
export type Config<N extends ConfigNames> = N extends keyof ConfigByName ? ConfigByName[N] : unknown
|
|
32
32
|
export type ConfigOf = Config
|
|
33
|
-
`}return{name:"bunfig-plugin",setup(i){i.onResolve({filter:/^virtual:bunfig-types$/},(n)=>{return{path:n.path,namespace:"bunfig-virtual"}}),i.onLoad({filter:/^virtual:bunfig-types$/,namespace:"bunfig-virtual"},()=>{return{contents:r(),loader:"ts"}})}}}async function ds(){if(!tt)tt=await pt({name:"broadcast",alias:"realtime",defaultConfig:xe});return tt}class _e{config;keys=new Map;channelKeys=new Map;constructor(e={}){this.config={enabled:e.enabled??!1,algorithm:e.algorithm||"aes-256-gcm",keyRotationInterval:e.keyRotationInterval||86400000,channelKeys:e.channelKeys||new Map},this.channelKeys=new Map(this.config.channelKeys)}isEnabled(){return this.config.enabled}async setChannelKey(e,t){this.channelKeys.set(e,t);let s=he.from(t,"hex"),r=await crypto.subtle.importKey("raw",s,{name:"AES-GCM"},!1,["encrypt","decrypt"]);this.keys.set(e,r)}async generateChannelKey(e){let t=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),s=await crypto.subtle.exportKey("raw",t),r=he.from(s).toString("hex");return await this.setChannelKey(e,r),r}async encrypt(e,t){if(!this.config.enabled){if(t===void 0)return"undefined";return JSON.stringify(t)}let s=this.keys.get(e);if(!s)throw Error(`No encryption key found for channel: ${e}`);let r=t===void 0?"undefined":JSON.stringify(t),i=crypto.getRandomValues(new Uint8Array(12)),n=await crypto.subtle.encrypt({name:"AES-GCM",iv:i},s,new TextEncoder().encode(r)),a=new Uint8Array(i.length+n.byteLength);return a.set(i,0),a.set(new Uint8Array(n),i.length),he.from(a).toString("base64")}async decrypt(e,t){if(!this.config.enabled){if(t==="undefined")return;return JSON.parse(t)}let s=this.keys.get(e);if(!s)throw Error(`No encryption key found for channel: ${e}`);let r=he.from(t,"base64"),i=r.slice(0,12),n=r.slice(12),a=await crypto.subtle.decrypt({name:"AES-GCM",iv:i},s,n),c=new TextDecoder().decode(a);if(c==="undefined")return;return JSON.parse(c)}hasChannelKey(e){return this.channelKeys.has(e)}getChannelKey(e){return this.channelKeys.get(e)}async rotateChannelKey(e){return this.generateChannelKey(e)}removeChannelKey(e){this.channelKeys.delete(e),this.keys.delete(e)}}class te{server;broadcaster;constructor(e,t){this.server=e,this.broadcaster=t}toUser(e,t,s){this.broadcaster.send(`private-user.${e}`,t,s)}toUsers(e,t,s){let r=e.map((i)=>`private-user.${i}`);this.broadcaster.send(r,t,s)}exceptUsers(e,t,s,r){let i=this.server.channels.getSubscribers(t),n=new Set(e.map((a)=>`private-user.${a}`));for(let a of i)if(!Array.from(n).some((c)=>this.server.channels.getChannel(c).subscribers.has(a))){this.broadcaster.send(t,s,r);break}}toAll(e,t){this.broadcaster.send("broadcast",e,t)}toRole(e,t,s){this.broadcaster.send(`role.${e}`,t,s)}notify(e,t){this.toUser(e,"notification",t)}notifyUsers(e,t){this.toUsers(e,"notification",t)}systemMessage(e,t="info"){this.toAll("system.message",{message:e,type:t,timestamp:Date.now()})}modelUpdated(e,t,s){this.broadcaster.send(`model.${e}.${t}`,"updated",s)}modelCreated(e,t){this.broadcaster.send(`model.${e}`,"created",t)}modelDeleted(e,t){this.broadcaster.send(`model.${e}.${t}`,"deleted",{id:t})}getUserConnectionCount(e){return this.server.channels.getSubscriberCount(`private-user.${e}`)}isUserOnline(e){return this.getUserConnectionCount(e)>0}getOnlineUsers(e){let t=e.startsWith("presence-")?e:`presence-${e}`,s=this.server.channels.getPresenceMembers(t);if(!s)return[];return Array.from(s.values())}getPresenceCount(e){let t=e.startsWith("presence-")?e:`presence-${e}`;return this.server.channels.getSubscriberCount(t)}}function ms(e,t){return new te(e,t)}class Te{hooks=new Map;on(e,t){if(!this.hooks.has(e))this.hooks.set(e,new Set);this.hooks.get(e).add(t)}off(e,t){this.hooks.get(e)?.delete(t)}async fire(e){let t=this.hooks.get(e.event);if(t)for(let r of t)try{await r(e)}catch(i){console.error(`Error in lifecycle hook for ${e.event}:`,i)}let s=this.hooks.get("all");if(s)for(let r of s)try{await r(e)}catch(i){console.error("Error in 'all' lifecycle hook:",i)}}async channelCreated(e,t){await this.fire({channel:e,event:"created",timestamp:Date.now(),socketId:t})}async channelSubscribed(e,t,s){await this.fire({channel:e,event:"subscribed",timestamp:Date.now(),socketId:t,subscriberCount:s})}async channelUnsubscribed(e,t,s){await this.fire({channel:e,event:"unsubscribed",timestamp:Date.now(),socketId:t,subscriberCount:s})}async channelEmpty(e){await this.fire({channel:e,event:"empty",timestamp:Date.now(),subscriberCount:0})}async channelDestroyed(e){await this.fire({channel:e,event:"destroyed",timestamp:Date.now()})}}class Ae{config;connectionCount=0;channelCount=0;channelsPerConnection=new Map;constructor(e={}){this.config={maxConnections:e.maxConnections??1e4,maxChannelsPerConnection:e.maxChannelsPerConnection??100,maxGlobalChannels:e.maxGlobalChannels??50000,shedLoadAt:e.shedLoadAt??90,backpressureThreshold:e.backpressureThreshold??1048576}}canAcceptConnection(){return this.connectionCount<this.config.maxConnections}shouldShedLoad(){let e=this.connectionCount/this.config.maxConnections*100,t=this.channelCount/this.config.maxGlobalChannels*100;return e>=this.config.shedLoadAt||t>=this.config.shedLoadAt}registerConnection(e){this.connectionCount++,this.channelsPerConnection.set(e,0)}unregisterConnection(e){this.connectionCount=Math.max(0,this.connectionCount-1);let t=this.channelsPerConnection.get(e)||0;this.channelCount=Math.max(0,this.channelCount-t),this.channelsPerConnection.delete(e)}canSubscribe(e){if((this.channelsPerConnection.get(e)||0)>=this.config.maxChannelsPerConnection)return!1;if(this.channelCount>=this.config.maxGlobalChannels)return!1;return!0}registerSubscription(e){let t=this.channelsPerConnection.get(e)||0;this.channelsPerConnection.set(e,t+1),this.channelCount++}unregisterSubscription(e){let t=this.channelsPerConnection.get(e)||0;if(t>0)this.channelsPerConnection.set(e,t-1),this.channelCount=Math.max(0,this.channelCount-1)}shouldApplyBackpressure(e){return e>this.config.backpressureThreshold}getStats(){let e=Array.from(this.channelsPerConnection.values()).reduce((s,r)=>s+r,0),t=this.connectionCount>0?e/this.connectionCount:0;return{connections:this.connectionCount,channels:this.channelCount,averageChannelsPerConnection:t,memoryUsage:Dr.memoryUsage().heapUsed,isOverloaded:this.shouldShedLoad()}}getConnectionUsage(){return this.connectionCount/this.config.maxConnections*100}getChannelUsage(){return this.channelCount/this.config.maxGlobalChannels*100}}class Me{callback=null;config;constructor(e={}){this.config={enabled:e.enabled??!0,cookie:{name:e.cookie?.name||"auth_token",secure:e.cookie?.secure??!0},jwt:{secret:e.jwt?.secret||Nr.env.JWT_SECRET||"",algorithm:e.jwt?.algorithm||"HS256"},session:{key:e.session?.key||"session_id"}}}authenticate(e){this.callback=e}async authenticateRequest(e){if(!this.config.enabled)return null;if(this.callback)return await this.callback(e);let t=e.headers.get("cookie");if(t){let r=this.parseCookies(t)[this.config.cookie.name];if(r)return this.verifyToken(r)}let s=e.headers.get("authorization");if(s?.startsWith("Bearer ")){let r=s.slice(7);return this.verifyToken(r)}return null}parseCookies(e){let t={};for(let s of e.split(";")){let[r,...i]=s.split("=");t[r.trim()]=i.join("=").trim()}return t}async verifyToken(e){try{let t=e.split(".");if(t.length===3){let s=JSON.parse(atob(t[1]));return{id:s.sub||s.id,...s}}}catch(t){console.error("Error verifying token:",t)}return null}}class Pe{limits=new Map;config;cleanupTimer;constructor(e){this.config={max:e.max||100,window:e.window||60000,perChannel:e.perChannel??!1,perUser:e.perUser??!1},this.cleanupTimer=setInterval(()=>this.cleanup(),60000)}check(e,t){let s=this.getKey(e,t),r=Date.now(),i=this.limits.get(s);if(!i||i.resetAt<r)return this.limits.set(s,{count:1,resetAt:r+this.config.window}),!1;if(i.count>=this.config.max)return!0;return i.count++,!1}getRemaining(e,t){let s=this.getKey(e,t),r=this.limits.get(s);if(!r||r.resetAt<Date.now())return this.config.max;return Math.max(0,this.config.max-r.count)}getResetAt(e,t){let s=this.getKey(e,t);return this.limits.get(s)?.resetAt||Date.now()}getKey(e,t){let s=[];if(this.config.perUser&&e.data.user)s.push(`user:${e.data.user.id}`);else s.push(`socket:${e.data.socketId}`);if(this.config.perChannel&&t)s.push(`channel:${t}`);return s.join(":")}cleanup(){let e=Date.now();for(let[t,s]of this.limits.entries())if(s.resetAt<e)this.limits.delete(t)}clear(){this.limits.clear()}stop(){clearInterval(this.cleanupTimer)}}class Ie{validators=new Set;addValidator(e){this.validators.add(e)}removeValidator(e){this.validators.delete(e)}validate(e){for(let t of this.validators){let s=t(e);if(s===!1)return{valid:!1,error:"Validation failed"};if(typeof s==="string")return{valid:!1,error:s}}return{valid:!0}}}class Oe{callbacks=new Map;metrics=new Map;on(e,t){if(!this.callbacks.has(e))this.callbacks.set(e,new Set);this.callbacks.get(e).add(t)}off(e,t){let s=this.callbacks.get(e);if(s)s.delete(t)}emit(e){this.incrementMetric(e.type);let t=this.callbacks.get(e.type);if(t)for(let r of t)r(e);let s=this.callbacks.get("all");if(s)for(let r of s)r(e)}incrementMetric(e,t=1){let s=this.metrics.get(e)||0;this.metrics.set(e,s+t)}getMetric(e){return this.metrics.get(e)||0}getMetrics(){return Object.fromEntries(this.metrics)}resetMetrics(){this.metrics.clear()}}class Re{config;constructor(e={}){this.config={cors:{enabled:e.cors?.enabled??!0,origins:e.cors?.origins||["*"],credentials:e.cors?.credentials??!0},maxPayloadSize:e.maxPayloadSize||1048576,sanitizeMessages:e.sanitizeMessages??!0}}checkOrigin(e){if(!this.config.cors?.enabled)return!0;if(this.config.cors.origins?.includes("*"))return!0;return this.config.cors.origins?.includes(e)??!1}sanitize(e){if(!this.config.sanitizeMessages)return e;if(typeof e==="string")return e.replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/\x27/g,"'").replace(/\//g,"/");if(Array.isArray(e))return e.map((t)=>this.sanitize(t));if(e&&typeof e==="object"){let t={};for(let[s,r]of Object.entries(e))t[s]=this.sanitize(r);return t}return e}checkSize(e){return e.length<=this.config.maxPayloadSize}}class De{config;redis;inMemoryStore=new Map;constructor(e={},t){this.config={enabled:e.enabled??!1,ttl:e.ttl??3600,maxMessages:e.maxMessages??100,excludeEvents:e.excludeEvents||["ping","pong"]},this.redis=t}async store(e,t,s,r){if(!this.config.enabled)return;if(this.config.excludeEvents.includes(t))return;let i={id:crypto.randomUUID(),event:t,data:s,timestamp:Date.now(),socketId:r};if(this.redis)await this.storeInRedis(e,i);else this.storeInMemory(e,i)}async getHistory(e,t,s){if(!this.config.enabled)return[];if(this.redis)return this.getHistoryFromRedis(e,t,s);return this.getHistoryFromMemory(e,t,s)}async clear(e){if(this.redis){let t=this.getRedisKey(e),s=this.redis;if(s.publisher)await s.publisher.del(t)}else this.inMemoryStore.delete(e)}async storeInRedis(e,t){if(!this.redis)return;let s=this.getRedisKey(e),r=JSON.stringify(t),i=this.redis;if(!i.publisher)return;await i.publisher.zadd(s,t.timestamp,r);let n=-this.config.maxMessages-1;await i.publisher.send("ZREMRANGEBYRANK",[s,"0",n.toString()]),await i.publisher.expire(s,this.config.ttl)}async getHistoryFromRedis(e,t,s){if(!this.redis)return[];let r=this.getRedisKey(e),i=t?.toString()||"-inf",n="+inf",a=s||this.config.maxMessages,c=this.redis;if(!c.publisher)return[];return(await c.publisher.send("ZRANGEBYSCORE",[r,i,n,"LIMIT","0",a.toString()])).map((o)=>JSON.parse(o))}storeInMemory(e,t){if(!this.inMemoryStore.has(e))this.inMemoryStore.set(e,[]);let s=this.inMemoryStore.get(e);if(s.push(t),s.length>this.config.maxMessages)s.shift();let r=Date.now()-this.config.ttl*1000,i=s.filter((n)=>n.timestamp>r);this.inMemoryStore.set(e,i)}getHistoryFromMemory(e,t,s){let r=this.inMemoryStore.get(e)||[],i=r;if(t!==void 0)i=r.filter((n)=>n.timestamp>=t);if(s)i=i.slice(0,s);return i}getRedisKey(e){return`history:${e}`}async getStats(){if(this.redis){let s=this.redis;if(!s.publisher)return{totalChannels:0,totalMessages:0,channels:{}};let r=await s.publisher.send("KEYS",["history:*"]),i=0,n={};for(let a of r){let c=await s.publisher.send("ZCARD",[a]),o=a.replace("history:",""),l=Number(c);n[o]=l,i+=l}return{totalChannels:r.length,totalMessages:i,channels:n}}let e=0,t={};for(let[s,r]of this.inMemoryStore.entries())t[s]=r.length,e+=r.length;return{totalChannels:this.inMemoryStore.size,totalMessages:e,channels:t}}}class Ne{config;presenceUsers=new Map;heartbeatTimer;onRemove;constructor(e={}){this.config={enabled:e.enabled??!0,interval:e.interval??30000,timeout:e.timeout??60000,requireClientHeartbeat:e.requireClientHeartbeat??!0}}start(){if(!this.config.enabled)return;this.heartbeatTimer=setInterval(()=>{this.checkHeartbeats()},this.config.interval)}stop(){if(this.heartbeatTimer)clearInterval(this.heartbeatTimer)}onUserRemove(e){this.onRemove=e}heartbeat(e,t,s){if(!this.config.enabled)return;if(!this.presenceUsers.has(e))this.presenceUsers.set(e,new Map);let r=this.presenceUsers.get(e),i=r.get(t);r.set(t,{socketId:t,lastSeen:Date.now(),data:s||i?.data})}remove(e,t){let s=this.presenceUsers.get(e);if(s){if(s.delete(t),s.size===0)this.presenceUsers.delete(e)}}checkHeartbeats(){let e=Date.now(),t=this.config.timeout;for(let[s,r]of this.presenceUsers.entries()){let i=[];for(let[n,a]of r.entries())if(e-a.lastSeen>t)i.push(n);for(let n of i){let a=r.get(n);if(r.delete(n),this.onRemove&&a)this.onRemove(s,n,a.data)}if(r.size===0)this.presenceUsers.delete(s)}}getActiveUsers(e){let t=this.presenceUsers.get(e);if(!t)return[];return Array.from(t.values())}isActive(e,t){let s=this.presenceUsers.get(e)?.get(t);if(!s)return!1;return Date.now()-s.lastSeen<this.config.timeout}getStats(){let e=0;for(let t of this.presenceUsers.values())e+=t.size;return{channels:this.presenceUsers.size,totalUsers:e}}}class Be{publisher;subscriber;config;serverId;messageHandlers=new Set;get client(){return this.publisher}constructor(e){this.serverId=crypto.randomUUID(),this.config={host:e.host||Q.env.REDIS_HOST||"localhost",port:e.port||Number.parseInt(Q.env.REDIS_PORT||"6379"),password:e.password||Q.env.REDIS_PASSWORD||"",database:e.database||Number.parseInt(Q.env.REDIS_DB||"0"),url:e.url||Q.env.REDIS_URL||"",keyPrefix:e.keyPrefix||"broadcasting:"};let t=this.config.url||this.buildRedisUrl();this.publisher=new Qt(t||"redis://localhost:6379"),this.subscriber=new Qt(t||"redis://localhost:6379")}buildRedisUrl(){return`redis://${this.config.password?`:${this.config.password}@`:""}${this.config.host}:${this.config.port}/${this.config.database}`}async connect(){await Promise.all([this.publisher.connect(),this.subscriber.connect()]),await this.subscriber.subscribe(`${this.config.keyPrefix}channel`,(e)=>{this.handleRedisMessage(e)})}close(){this.publisher.close(),this.subscriber.close()}async broadcast(e,t,s,r){let i={type:"broadcast",channel:e,event:t,data:s,socketId:r,serverId:this.serverId};await this.publisher.publish(`${this.config.keyPrefix}channel`,JSON.stringify(i))}onMessage(e){this.messageHandlers.add(e)}offMessage(e){this.messageHandlers.delete(e)}handleRedisMessage(e){try{let t=JSON.parse(e);if(t.serverId===this.serverId)return;for(let s of this.messageHandlers)s(t)}catch(t){console.error("Error handling Redis message:",t)}}async storeChannel(e,t){let s=`${this.config.keyPrefix}channels:${e}`;await this.publisher.sadd(s,t),await this.publisher.expire(s,3600)}async removeChannel(e,t){let s=`${this.config.keyPrefix}channels:${e}`;await this.publisher.srem(s,t)}async getChannelSubscribers(e){let t=`${this.config.keyPrefix}channels:${e}`;return await this.publisher.smembers(t)}async storePresenceMember(e,t,s){let r=`${this.config.keyPrefix}presence:${e}`;await this.publisher.hmset(r,[t,JSON.stringify(s)]),await this.publisher.expire(r,3600)}async removePresenceMember(e,t){let s=`${this.config.keyPrefix}presence:${e}`;await this.publisher.send("HDEL",[s,t])}async getPresenceMembers(e){let t=`${this.config.keyPrefix}presence:${e}`,s=await this.publisher.send("HGETALL",[t]),r=new Map;for(let i=0;i<s.length;i+=2){let n=s[i],a=s[i+1];try{r.set(n,JSON.parse(a))}catch{console.error(`Error parsing presence member data for ${n}`)}}return r}async incrementStat(e){let t=`${this.config.keyPrefix}stats:${e}`;await this.publisher.incr(t)}async getStats(){let e=await this.publisher.send("KEYS",[`${this.config.keyPrefix}stats:*`]),t={};for(let s of e){let r=await this.publisher.get(s),i=s.replace(`${this.config.keyPrefix}stats:`,"");t[i]=Number.parseInt(r||"0")}return t}async storeConnection(e,t){let s=`${this.config.keyPrefix}connections:${e}`;await this.publisher.set(s,JSON.stringify(t)),await this.publisher.expire(s,7200)}async removeConnection(e){let t=`${this.config.keyPrefix}connections:${e}`;await this.publisher.del(t)}async getConnection(e){let t=`${this.config.keyPrefix}connections:${e}`,s=await this.publisher.get(t);if(!s)return null;try{return JSON.parse(s)}catch{return console.error(`Error parsing connection data for ${e}`),null}}async getTotalConnections(){return(await this.publisher.send("KEYS",[`${this.config.keyPrefix}connections:*`])).length}async getTotalChannels(){return(await this.publisher.send("KEYS",[`${this.config.keyPrefix}channels:*`])).length}async healthCheck(){try{return await this.publisher.send("PING",[]),!0}catch{return!1}}getServerId(){return this.serverId}}class je{config;endpoints;constructor(e={}){this.config={enabled:e.enabled??!1,endpoints:e.endpoints||[],retryAttempts:e.retryAttempts??3,retryDelay:e.retryDelay??1000,timeout:e.timeout??5000,secret:e.secret||""},this.endpoints=this.config.endpoints}register(e){this.endpoints.push(e)}async fire(e,t){if(!this.config.enabled)return;let s={event:e,timestamp:Date.now(),data:t};if(this.config.secret)s.signature=await this.generateSignature(s);let r=this.endpoints.filter((i)=>i.events.includes(e)).map((i)=>this.sendWebhook(i,s));await Promise.allSettled(r)}async sendWebhook(e,t,s=1){try{let r=new AbortController,i=setTimeout(()=>r.abort(),this.config.timeout),n=await fetch(e.url,{method:e.method||"POST",headers:{"Content-Type":"application/json","User-Agent":"ts-broadcasting/1.0","X-Webhook-Signature":t.signature||"",...e.headers},body:JSON.stringify(t),signal:r.signal});if(clearTimeout(i),!n.ok&&n.status>=500&&s<=this.config.retryAttempts)return await new Promise((a)=>setTimeout(a,this.config.retryDelay*s)),this.sendWebhook(e,t,s+1)}catch{if(s<=this.config.retryAttempts)return await new Promise((r)=>setTimeout(r,this.config.retryDelay*s)),this.sendWebhook(e,t,s+1)}}async generateSignature(e){let t=new TextEncoder,s=t.encode(JSON.stringify(e)),r=await crypto.subtle.importKey("raw",t.encode(this.config.secret),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),i=await crypto.subtle.sign("HMAC",r,s);return Br.from(i).toString("hex")}async verifySignature(e,t){if(!this.config.secret)return!0;let s=await this.generateSignature(e);return t===s}}class yt{server;connections=new Map;config;channels;broadcaster;helpers;redis;auth;rateLimit;monitoring;validator;security;encryption;webhooks;persistence;channelState;namespace;presenceHeartbeat;acknowledgments;batchOps;lifecycle;loadManager;queueManager;constructor(e){if(this.config=e,this.channels=new ke,this.broadcaster=new ye(this,e),this.helpers=new te(this,this.broadcaster),e.auth)this.auth=new Me(e.auth);if(e.rateLimit)this.rateLimit=new Pe(e.rateLimit);if(e.security)this.security=new Re(e.security);if(this.monitoring=new Oe,this.validator=new Ie,e.encryption)this.encryption=new _e(e.encryption);if(e.webhooks)this.webhooks=new je(e.webhooks);if(e.persistence)this.persistence=new De(e.persistence);if(this.channelState=new ve,this.namespace=new Ce,e.heartbeat)this.presenceHeartbeat=new Ne(e.heartbeat);if(e.acknowledgments)this.acknowledgments=new me(e.acknowledgments);if(e.batch)this.batchOps=new pe(e.batch,this.channels);if(this.lifecycle=new Te,e.loadManagement)this.loadManager=new Ae(e.loadManagement);if(e.queue?.enabled)this.initializeQueueManager();if(this.presenceHeartbeat)this.presenceHeartbeat.onUserRemove((t,s,r)=>{if(this.broadcast(t,"member_removed",{id:s,user:r},s),this.config.verbose)console.warn(`Removed inactive user ${s} from ${t}`)});this.setupDefaultValidators()}async initializeQueueManager(){try{let{BroadcastQueueManager:e}=await Tt().then(() => _t);if(this.queueManager=new e(this,this.config.queue),this.config.verbose)console.warn("Queue manager initialized")}catch(e){console.error("Failed to initialize queue manager:",e)}}async start(){if(this.presenceHeartbeat){if(this.presenceHeartbeat.start(),this.config.verbose)console.warn("Started presence heartbeat monitoring")}if(this.config.redis){if(this.redis=new Be(this.config.redis),await this.redis.connect(),this.redis.onMessage((r)=>{if(r.type==="broadcast")this.broadcast(r.channel,r.event,r.data,r.socketId)}),this.config.verbose)console.warn("Connected to Redis for horizontal scaling")}let e=this.config.connections?.[this.config.default||"bun"];if(!e)throw Error("No connection configuration found");let t=e.host||"0.0.0.0",s=e.port??6001;if(this.server=Bun.serve({hostname:t,port:s,fetch:async(r,i)=>{let n=new URL(r.url);if(n.pathname==="/health"){let a={status:"ok",redis:this.redis?await this.redis.healthCheck():null};return Response.json(a)}if(n.pathname==="/stats")return Response.json(await this.getStats());if(n.pathname==="/metrics"){let{PrometheusExporter:a}=await Promise.resolve().then(() => (Mt(),At)),c=await new a(this).export();return new Response(c,{headers:{"Content-Type":"text/plain; version=0.0.4"}})}if(n.pathname==="/app"||n.pathname==="/ws"){let a=null;if(this.auth)a=await this.auth.authenticateRequest(r);if(i.upgrade(r,{data:{id:crypto.randomUUID(),socketId:crypto.randomUUID(),channels:new Set,connectedAt:Date.now(),user:a??void 0}}))return;return new Response("WebSocket upgrade failed",{status:400})}return new Response("Not found",{status:404})},websocket:{open:(r)=>{this.handleOpen(r)},message:(r,i)=>{this.handleMessage(r,i)},close:(r,i,n)=>{this.handleClose(r,i,n)},drain:(r)=>{this.handleDrain(r)},idleTimeout:e.options?.idleTimeout,maxPayloadLength:e.options?.maxPayloadLength,backpressureLimit:e.options?.backpressureLimit,closeOnBackpressureLimit:e.options?.closeOnBackpressureLimit,sendPings:e.options?.sendPings,perMessageDeflate:e.options?.perMessageDeflate}}),this.config.verbose)console.warn(`Broadcasting server started on ${t}:${s}`);this.monitoring?.emit({type:"connection",timestamp:Date.now(),socketId:"server",data:{event:"server_start"}})}async stop(){if(this.rateLimit)this.rateLimit.stop();if(this.presenceHeartbeat)this.presenceHeartbeat.stop();if(this.acknowledgments)this.acknowledgments.clear();if(this.queueManager)await this.queueManager.close();if(this.redis)this.redis.close();if(this.server){if(this.server.stop(),this.connections.clear(),this.config.verbose)console.warn("Broadcasting server stopped")}this.monitoring?.emit({type:"disconnection",timestamp:Date.now(),socketId:"server",data:{event:"server_stop"}})}handleOpen(e){if(this.loadManager&&!this.loadManager.canAcceptConnection()){e.close(1008,"Server at capacity");return}if(this.loadManager?.shouldShedLoad()){e.close(1008,"Server load too high");return}if(this.loadManager)this.loadManager.registerConnection(e.data.socketId);if(this.connections.set(e.data.socketId,e),this.redis)this.redis.storeConnection(e.data.socketId,{connectedAt:e.data.connectedAt,channels:Array.from(e.data.channels),user:e.data.user}).catch((t)=>console.error("Redis store connection error:",t));if(this.webhooks)this.webhooks.fire("connection",{socketId:e.data.socketId,connectedAt:e.data.connectedAt,user:e.data.user}).catch((t)=>console.error("Webhook error:",t));if(this.send(e,{event:"connection_established",data:{socket_id:e.data.socketId,activity_timeout:this.config.connections?.[this.config.default||"bun"]?.options?.idleTimeout||120}}),this.monitoring?.emit({type:"connection",timestamp:Date.now(),socketId:e.data.socketId}),this.config.verbose)console.warn(`WebSocket connected: ${e.data.socketId}`)}async handleMessage(e,t){if(this.rateLimit&&this.rateLimit.check(e)){this.send(e,{event:"error",data:{type:"RateLimitExceeded",error:"Too many requests",retryAfter:this.rateLimit.getResetAt(e)}});return}let s=typeof t==="string"?t:t.toString();if(this.security&&!this.security.checkSize(s)){this.send(e,{event:"error",data:{type:"PayloadTooLarge",error:"Message size exceeds maximum allowed"}});return}try{let r=JSON.parse(s);if(this.validator){let n=this.validator.validate(r);if(!n.valid){this.send(e,{event:"error",data:{type:"ValidationError",error:n.error}});return}}let i=this.security?this.security.sanitize(r):r;switch(this.monitoring?.emit({type:"message",timestamp:Date.now(),socketId:e.data.socketId,data:{event:i.event}}),i.event){case"subscribe":await this.handleSubscribe(e,i);break;case"unsubscribe":await this.handleUnsubscribe(e,i);break;case"batch_subscribe":await this.handleBatchSubscribe(e,i);break;case"batch_unsubscribe":await this.handleBatchUnsubscribe(e,i);break;case"heartbeat":case"presence_heartbeat":await this.handleHeartbeat(e,i);break;case"ping":this.send(e,{event:"pong"});break;default:if(this.acknowledgments&&i.ack&&i.messageId)this.send(e,{event:"ack",messageId:i.messageId});if(i.event.startsWith("client-"))await this.handleClientEvent(e,i);break}}catch(r){if(this.monitoring?.emit({type:"error",timestamp:Date.now(),socketId:e.data.socketId,data:{error:r instanceof Error?r.message:"Unknown error"}}),this.config.verbose)console.error("Error handling message:",r)}}async handleSubscribe(e,t){let{channel:s,channel_data:r}=t;try{if(this.loadManager&&!this.loadManager.canSubscribe(e.data.socketId)){this.send(e,{event:"subscription_error",channel:s,data:{type:"CapacityError",error:"Subscription limit reached",status:429}});return}let i=await this.channels.subscribe(e,s,r);if(!i){this.send(e,{event:"subscription_error",channel:s,data:{type:"AuthError",error:"Unauthorized",status:401}});return}if(this.loadManager)this.loadManager.registerSubscription(e.data.socketId);if(this.redis){if(await this.redis.storeChannel(s,e.data.socketId),this.channels.getChannelType(s)==="presence"&&typeof i==="object")await this.redis.storePresenceMember(s,e.data.socketId,i)}let n=this.channels.getChannelType(s);if(this.lifecycle){if(this.channels.getSubscriberCount(s)===1)await this.lifecycle.channelCreated(s,e.data.socketId);await this.lifecycle.channelSubscribed(s,e.data.socketId,this.channels.getSubscriberCount(s))}if(n==="presence"){if(this.presenceHeartbeat&&typeof i==="object")this.presenceHeartbeat.heartbeat(s,e.data.socketId,i);let a=this.channels.getPresenceMembers(s),c={presence:{ids:Array.from(a?.keys()||[]),hash:Object.fromEntries(a||[]),count:a?.size||0}};if(this.send(e,{event:"subscription_succeeded",channel:s,data:c}),typeof i==="object")this.broadcast(s,"member_added",i,e.data.socketId)}else this.send(e,{event:"subscription_succeeded",channel:s});if(this.webhooks)this.webhooks.fire("subscribe",{socketId:e.data.socketId,channel:s,channelData:r}).catch((a)=>console.error("Webhook error:",a));if(this.monitoring?.emit({type:"subscribe",timestamp:Date.now(),socketId:e.data.socketId,channel:s}),this.config.verbose)console.warn(`Socket ${e.data.socketId} subscribed to ${s}`)}catch(i){this.send(e,{event:"subscription_error",channel:s,data:{type:"ServerError",error:i instanceof Error?i.message:"Internal server error",status:500}})}}async handleUnsubscribe(e,t){let{channel:s}=t,r=this.channels.getChannelType(s),i=null;if(r==="presence")i=this.channels.getPresenceMembers(s)?.get(e.data.socketId);if(this.redis){if(await this.redis.removeChannel(s,e.data.socketId),r==="presence")await this.redis.removePresenceMember(s,e.data.socketId)}if(this.channels.unsubscribe(e,s),r==="presence"&&i)this.broadcast(s,"member_removed",i,e.data.socketId);if(this.monitoring?.emit({type:"unsubscribe",timestamp:Date.now(),socketId:e.data.socketId,channel:s}),this.config.verbose)console.warn(`Socket ${e.data.socketId} unsubscribed from ${s}`)}async handleClientEvent(e,t){let{event:s,channel:r,data:i}=t;if(this.channels.getChannelType(r)==="public")return;this.broadcast(r,s,i,e.data.socketId)}handleClose(e,t,s){let r=new Map;for(let i of e.data.channels)if(this.channels.getChannelType(i)==="presence"){let n=this.channels.getPresenceMembers(i)?.get(e.data.socketId);if(n)r.set(i,n)}this.channels.unsubscribeAll(e);for(let[i,n]of r)this.broadcast(i,"member_removed",n,e.data.socketId);if(this.loadManager)this.loadManager.unregisterConnection(e.data.socketId);if(this.connections.delete(e.data.socketId),this.redis)this.redis.removeConnection(e.data.socketId).catch((i)=>console.error("Redis remove connection error:",i));if(this.webhooks)this.webhooks.fire("disconnection",{socketId:e.data.socketId,code:t,reason:s}).catch((i)=>console.error("Webhook error:",i));if(this.monitoring?.emit({type:"disconnection",timestamp:Date.now(),socketId:e.data.socketId,data:{code:t,reason:s}}),this.config.verbose)console.warn(`WebSocket closed: ${e.data.socketId} (${t}: ${s})`)}handleError(e,t){if(this.monitoring?.emit({type:"error",timestamp:Date.now(),socketId:e.data.socketId,data:{error:t.message}}),this.config.verbose)console.error(`WebSocket error for ${e.data.socketId}:`,t)}handleDrain(e){if(this.config.verbose)console.warn(`WebSocket drained: ${e.data.socketId}`)}send(e,t){return e.send(JSON.stringify(t))}broadcast(e,t,s,r){let i=JSON.stringify({event:t,channel:e,data:s});if(this.server)if(r){let n=this.channels.getSubscribers(e);for(let a of n)if(a!==r){let c=this.connections.get(a);if(c)c.send(i)}}else this.server.publish(e,i);if(this.redis)this.redis.broadcast(e,t,s,r).catch((n)=>{console.error("Redis broadcast error:",n)});this.monitoring?.emit({type:"broadcast",timestamp:Date.now(),socketId:r||"server",channel:e,data:{event:t,dataSize:JSON.stringify(s).length}})}getConnectionCount(){return this.connections.size}getSubscriberCount(e){return this.channels.getSubscriberCount(e)}async getStats(){let e={connections:this.getConnectionCount(),channels:this.channels.getChannelCount(),uptime:jr.uptime()};if(this.redis){let t={totalConnections:await this.redis.getTotalConnections(),totalChannels:await this.redis.getTotalChannels(),redisHealthy:await this.redis.healthCheck(),serverId:this.redis.getServerId()};return{...e,...t,metrics:this.monitoring?.getMetrics()||{}}}return{...e,metrics:this.monitoring?.getMetrics()||{}}}async handleBatchSubscribe(e,t){if(!this.batchOps){this.send(e,{event:"error",data:{type:"NotSupported",error:"Batch operations are not enabled"}});return}try{let s=await this.batchOps.batchSubscribe(e,{channels:t.channels,channelData:t.channelData});this.send(e,{event:"batch_subscribe_result",messageId:t.messageId,data:s})}catch(s){this.send(e,{event:"error",data:{type:"BatchError",error:s instanceof Error?s.message:"Batch subscribe failed"}})}}handleBatchUnsubscribe(e,t){if(!this.batchOps){this.send(e,{event:"error",data:{type:"NotSupported",error:"Batch operations are not enabled"}});return}try{let s=this.batchOps.batchUnsubscribe(e,t.channels);this.send(e,{event:"batch_unsubscribe_result",messageId:t.messageId,data:s})}catch(s){this.send(e,{event:"error",data:{type:"BatchError",error:s instanceof Error?s.message:"Batch unsubscribe failed"}})}}async handleHeartbeat(e,t){if(!this.presenceHeartbeat)return;if(t.channel)this.presenceHeartbeat.heartbeat(t.channel,e.data.socketId)}setupDefaultValidators(){if(!this.validator)return;this.validator.addValidator((e)=>{if(!e||typeof e!=="object")return"Invalid message format";if(!e.event||typeof e.event!=="string")return"Missing or invalid event name";if(e.channel&&typeof e.channel!=="string")return"Invalid channel name";return!0}),this.validator.addValidator((e)=>{let t=e.event;if(t.length>100)return"Event name too long";if(!/^[\w.-]+$/.test(t))return"Event name contains invalid characters";return!0})}}var Zs,Qs=(e)=>e,Vs=(e,t)=>{for(var s in t)Zs(e,s,{get:t[s],enumerable:!0,configurable:!0,set:Hs.bind(t,s)})},M=(e,t)=>()=>(e&&(t=e(e=0)),t),Gs,q,X,Vt,ee,Wt,Ye,V,rr,y,g,ir,Ft,nr,qt,ar,or,Xe,cr,zt,Kt,lr,et,hr,ur,fr,dr,gr,ue,Yt,mr,pr,yr="0.15.8",br=()=>{},C,de,G,rt,it,ge,nt,at,Y,ot,ct,O,z,ts,ns,dt,as,os,cs,E,A,ls,hs,Ir,Rr=()=>{},us,fs,xe,tt=null,gs,Qt;var ps=R(()=>{B();Zs=Object.defineProperty;Gs=import.meta.require;ee=M(()=>{q=new ht,X=new ut,Vt={createKey:Ys,isEquivalent:Xs,estimateMemoryUsage:er}});pr=M(()=>{Wt=fe.env.CLARITY_LOG_DIR||Ts(tr(),"logs"),Ye={level:"info",defaultName:"clarity",timestamp:!0,colors:!0,format:"text",maxLogSize:10485760,logDatePattern:"YYYY-MM-DD",logDirectory:Wt,rotation:{frequency:"daily",maxSize:10485760,maxFiles:5,compress:!1,rotateHour:0,rotateMinute:0,rotateDayOfWeek:0,rotateDayOfMonth:1,encrypt:!1},verbose:!1,writeToFile:!1},V={...Ye},rr=(async()=>{try{let{loadConfig:e}=await Promise.resolve().then(()=>(fs(),us)),t=await e({name:"clarity",alias:"logging",defaultConfig:Ye,cwd:fe.cwd()});if(t)Object.assign(V,t)}catch{}return V})(),y={red:(e)=>`\x1B[31m${e}\x1B[0m`,green:(e)=>`\x1B[32m${e}\x1B[0m`,yellow:(e)=>`\x1B[33m${e}\x1B[0m`,blue:(e)=>`\x1B[34m${e}\x1B[0m`,magenta:(e)=>`\x1B[35m${e}\x1B[0m`,cyan:(e)=>`\x1B[36m${e}\x1B[0m`,white:(e)=>`\x1B[37m${e}\x1B[0m`,gray:(e)=>`\x1B[90m${e}\x1B[0m`,bgRed:(e)=>`\x1B[41m${e}\x1B[0m`,bgYellow:(e)=>`\x1B[43m${e}\x1B[0m`,bgGray:(e)=>`\x1B[100m${e}\x1B[0m`,bold:(e)=>`\x1B[1m${e}\x1B[0m`,dim:(e)=>`\x1B[2m${e}\x1B[0m`,italic:(e)=>`\x1B[3m${e}\x1B[0m`,underline:(e)=>`\x1B[4m${e}\x1B[0m`,strikethrough:(e)=>`\x1B[9m${e}\x1B[0m`,reset:"\x1B[0m"},g=y,ir=y.red,Ft=y.green,nr=y.yellow,qt=y.blue,ar=y.magenta,or=y.cyan,Xe=y.white,cr=y.gray,zt=y.bgRed,Kt=y.bgYellow,lr=y.bgGray,et=y.bold,hr=y.dim,ur=y.italic,fr=y.underline,dr=y.strikethrough,gr=y.reset,ue={activationLevel:"error",bufferSize:50,flushOnDeactivation:!0,stopBuffering:!1},Yt={debug:"\uD83D\uDD0D",info:qt("\u2139"),success:Ft("\u2713"),warning:Kt(Xe(et(" WARN "))),error:zt(Xe(et(" ERROR ")))},mr=new $e("stacks")});z=M(()=>{C=class extends Error{timestamp;context;constructor(e,t={}){super(e);if(this.name=this.constructor.name,this.timestamp=new Date,this.context=t,Error.captureStackTrace)Error.captureStackTrace(this,this.constructor)}toJSON(){return{name:this.name,code:this.code,message:this.message,timestamp:this.timestamp.toISOString(),context:this.context,stack:this.stack}}toString(){let e=Object.keys(this.context).length>0?` (${Object.entries(this.context).map(([t,s])=>`${t}: ${s}`).join(", ")})`:"";return`${this.name} [${this.code}]: ${this.message}${e}`}},de=class extends C{code="CONFIG_NOT_FOUND";constructor(e,t,s){let r=s===void 0?[]:Array.isArray(s)?s.filter(Boolean):[s],i="";if(r.length===1)i=` or alias "${r[0]}"`;else if(r.length>1)i=` or aliases ${r.map((n)=>`"${n}"`).join(", ")}`;super(`Configuration "${e}"${i} not found`,{configName:e,alias:s,searchPaths:t,searchPathCount:t.length})}},G=class extends C{code="CONFIG_LOAD_ERROR";constructor(e,t,s){super(`Failed to load configuration from "${e}": ${t.message}`,{configPath:e,configName:s,originalError:t.name,originalMessage:t.message});this.cause=t}},rt=class extends C{code="CONFIG_VALIDATION_ERROR";constructor(e,t,s){super(`Configuration validation failed for "${e}"`,{configPath:e,configName:s,validationErrors:t,errorCount:t.length})}},it=class extends C{code="CONFIG_MERGE_ERROR";constructor(e,t,s,r){super(`Failed to merge configuration from "${e}" with "${t}": ${s.message}`,{sourcePath:e,targetPath:t,configName:r,originalError:s.name,originalMessage:s.message});this.cause=s}},ge=class extends C{code="ENV_VAR_ERROR";constructor(e,t,s,r){super(`Failed to parse environment variable "${e}" with value "${t}" as ${s}`,{envKey:e,envValue:t,expectedType:s,configName:r})}},nt=class extends C{code="FILE_SYSTEM_ERROR";constructor(e,t,s){super(`File system ${e} failed for "${t}": ${s.message}`,{operation:e,path:t,originalError:s.name,originalMessage:s.message});this.cause=s}},at=class extends C{code="TYPE_GENERATION_ERROR";constructor(e,t,s){super(`Failed to generate types from "${e}" to "${t}": ${s.message}`,{configDir:e,outputPath:t,originalError:s.name,originalMessage:s.message});this.cause=s}},Y=class extends C{code="SCHEMA_VALIDATION_ERROR";constructor(e,t,s){super(`Schema validation failed${s?` for config "${s}"`:""}`,{schemaPath:e,configName:s,validationErrors:t,errorCount:t.length})}},ot=class extends C{code="BROWSER_CONFIG_ERROR";constructor(e,t,s,r){super(`Failed to fetch configuration from "${e}": ${t} ${s}`,{endpoint:e,status:t,statusText:s,configName:r})}},ct=class extends C{code="PLUGIN_ERROR";constructor(e,t,s){super(`Plugin "${e}" failed during ${t}: ${s.message}`,{pluginName:e,operation:t,originalError:s.name,originalMessage:s.message});this.cause=s}},O={configNotFound(e,t,s){return new de(e,t,s)},configLoad(e,t,s){return new G(e,t,s)},configValidation(e,t,s){return new rt(e,t,s)},configMerge(e,t,s,r){return new it(e,t,s,r)},envVar(e,t,s,r){return new ge(e,t,s,r)},fileSystem(e,t,s){return new nt(e,t,s)},typeGeneration(e,t,s){return new at(e,t,s)},schemaValidation(e,t,s){return new Y(e,t,s)},browserConfig(e,t,s,r){return new ot(e,t,s,r)},plugin(e,t,s){return new ct(e,t,s)}}});ts=M(()=>{ee(),z()});dt=M(()=>{ns={replace:"replace",concat:"concat",smart:"smart"}});as=M(()=>{ee(),z(),dt()});cs=M(()=>{ee(),z(),os=/^https?:\/\//});Ir=M(()=>{pr(),br(),ee(),z(),ts(),as(),cs(),dt(),E=new $e("bunfig",{showTags:!0}),A=new mt,ls=w(N.cwd(),"config"),hs=w(N.cwd(),"src/generated")});us={};Vs(us,{withErrorRecovery:()=>Xt,tryLoadConfig:()=>Ar,loadConfigWithResult:()=>_r,loadConfig:()=>pt,isRetryableError:()=>vr,isConfigNotFoundError:()=>wr,isBunfigError:()=>es,globalPerformanceMonitor:()=>X,globalCache:()=>q,getEnvOrDefault:()=>Cr,generateConfigTypes:()=>Mr,defaultGeneratedDir:()=>hs,defaultConfigDir:()=>ls,deepMergeWithArrayStrategy:()=>ft,deepMerge:()=>ss,createLibraryConfig:()=>Pr,config:()=>Tr,bunfigPlugin:()=>Or,applyEnvVarsToConfig:()=>H,TypeGenerationError:()=>at,SchemaValidationError:()=>Y,PluginError:()=>ct,PerformanceMonitor:()=>ut,FileSystemError:()=>nt,ErrorFactory:()=>O,EnvVarError:()=>ge,EnvProcessor:()=>Ee,ConfigValidator:()=>gt,ConfigValidationError:()=>rt,ConfigNotFoundError:()=>de,ConfigMergeError:()=>it,ConfigLoader:()=>mt,ConfigLoadError:()=>G,ConfigFileLoader:()=>Se,ConfigCache:()=>ht,CacheUtils:()=>Vt,BunfigError:()=>C,BrowserConfigError:()=>ot,ArrayMergeStrategies:()=>ns});fs=M(()=>{Ir(),z(),ee(),z(),Rr(),ts(),as(),cs(),dt()});fs();xe={verbose:!1,driver:"bun",default:"bun",connections:{bun:{driver:"bun",host:"0.0.0.0",port:6001,scheme:"ws",options:{idleTimeout:120,maxPayloadLength:16777216,backpressureLimit:1048576,closeOnBackpressureLimit:!1,sendPings:!0,publishToSelf:!1,perMessageDeflate:!0}},reverb:{driver:"reverb",host:"127.0.0.1",port:8080,scheme:"ws",key:I.env.REVERB_APP_KEY,secret:I.env.REVERB_APP_SECRET,appId:I.env.REVERB_APP_ID,options:{idleTimeout:120,maxPayloadLength:16777216}},pusher:{driver:"pusher",key:I.env.PUSHER_APP_KEY,secret:I.env.PUSHER_APP_SECRET,appId:I.env.PUSHER_APP_ID,cluster:I.env.PUSHER_APP_CLUSTER||"mt1",useTLS:!0},ably:{driver:"ably",key:I.env.ABLY_KEY},log:{driver:"log"},null:{driver:"null"}}};gs=xe;({RedisClient:Qt}=globalThis.Bun)});var ws={};Fe(ws,{getConfig:()=>ds,defaultConfig:()=>xe,createHelpers:()=>ms,createEvent:()=>Ht,config:()=>gs,channel:()=>Wr,broadcastToUsers:()=>Ur,broadcastToUser:()=>Lr,broadcast:()=>Jr,WebhookManager:()=>je,SecurityManager:()=>Re,RedisAdapter:()=>Be,RecurringBroadcastJob:()=>J,RateLimiter:()=>Pe,PublicChannel:()=>Le,PrometheusExporter:()=>Z,PrivateChannel:()=>Ue,PresenceHeartbeatManager:()=>Ne,PresenceChannel:()=>kt,PersistenceManager:()=>De,MonitoringManager:()=>Oe,MessageValidationManager:()=>Ie,MessageDeduplicator:()=>bs,LoadManager:()=>Ae,EncryptionManager:()=>_e,Echo:()=>Fr,DelayedBroadcastJob:()=>j,Connector:()=>vt,Client:()=>Je,CircuitBreakerManager:()=>ys,CircuitBreakerError:()=>wt,CircuitBreaker:()=>bt,ChannelStateManager:()=>ve,ChannelNamespaceManager:()=>Ce,ChannelManager:()=>ke,ChannelLifecycleManager:()=>Te,ChannelInstance:()=>Ct,Broadcaster:()=>ye,BroadcastTo:()=>be,BroadcastServer:()=>yt,BroadcastQueueManager:()=>K,BroadcastJob:()=>D,BroadcastHelpers:()=>te,BroadcastClient:()=>qr,Broadcast:()=>v,BatchOperationsManager:()=>pe,AuthenticationManager:()=>Me,AnonymousEvent:()=>we,AcknowledgmentManager:()=>me});class v{static setServer(e){x=e}static getServer(){return x}static get broadcaster(){if(!x)throw Error("Broadcast server not initialized. Call Broadcast.setServer() first.");return x.broadcaster}static get channels(){if(!x)throw Error("Broadcast server not initialized. Call Broadcast.setServer() first.");return x.channels}static channel(e,t){if(!x)throw Error("Broadcast server not initialized. Call Broadcast.setServer() first.");return x.channels.channel(e,t),v}static async event(e){return v.broadcaster.broadcast(e)}static send(e,t,s){v.broadcaster.send(e,t,s)}static private(e,t,s){let r=e.startsWith("private-")?e:`private-${e}`;v.send(r,t,s)}static presence(e,t,s){let r=e.startsWith("presence-")?e:`presence-${e}`;v.send(r,t,s)}static toUser(e,t,s){v.private(`user.${e}`,t,s)}static toUsers(e,t,s){let r=e.map((i)=>`private-user.${i}`);v.send(r,t,s)}static toOthers(e){return v.broadcaster.toOthers(e)}static getConnectionCount(){if(!x)return 0;return x.getConnectionCount()}static getSubscriberCount(e){if(!x)return 0;return x.getSubscriberCount(e)}}function Jr(e,t,s){if(typeof e==="object"&&"broadcastOn"in e)return v.event(e);if(typeof e==="string"&&t)v.send(e,t,s)}function Lr(e,t,s){v.toUser(e,t,s)}function Ur(e,t,s){v.toUsers(e,t,s)}function Wr(e,t){v.channel(e,t)}class bt{name;state="CLOSED";failures=0;successes=0;totalRequests=0;lastFailureTime=null;lastSuccessTime=null;resetTimer=null;failureTimestamps=[];config;constructor(e,t){this.name=e,this.config={failureThreshold:t?.failureThreshold??5,failureWindow:t?.failureWindow??60000,resetTimeout:t?.resetTimeout??60000,successThreshold:t?.successThreshold??2,timeout:t?.timeout??30000}}async execute(e){if(this.state==="OPEN")throw new wt(`Circuit breaker is OPEN for ${this.name}`);this.totalRequests++;try{let t=await this.executeWithTimeout(e);return this.onSuccess(),t}catch(t){throw this.onFailure(),t}}async executeWithTimeout(e){return Promise.race([e(),new Promise((t,s)=>{setTimeout(()=>{s(Error(`Operation timed out after ${this.config.timeout}ms`))},this.config.timeout)})])}onSuccess(){if(this.failures=0,this.successes++,this.lastSuccessTime=Date.now(),this.state==="HALF_OPEN"){if(this.successes>=this.config.successThreshold)this.close()}}onFailure(){if(this.failures++,this.lastFailureTime=Date.now(),this.failureTimestamps.push(Date.now()),this.cleanOldFailures(),this.failureTimestamps.length>=this.config.failureThreshold)this.open()}cleanOldFailures(){let e=Date.now()-this.config.failureWindow;this.failureTimestamps=this.failureTimestamps.filter((t)=>t>e)}open(){if(this.state="OPEN",this.successes=0,console.warn(`Circuit breaker OPENED for ${this.name}`),this.resetTimer)clearTimeout(this.resetTimer);this.resetTimer=setTimeout(()=>{this.halfOpen()},this.config.resetTimeout)}halfOpen(){this.state="HALF_OPEN",this.successes=0,this.failures=0,this.failureTimestamps=[],console.warn(`Circuit breaker HALF_OPEN for ${this.name}`)}close(){if(this.state="CLOSED",this.failures=0,this.successes=0,this.failureTimestamps=[],this.resetTimer)clearTimeout(this.resetTimer),this.resetTimer=null;console.log(`Circuit breaker CLOSED for ${this.name}`)}reset(){this.close()}getState(){return this.state}isOpen(){return this.state==="OPEN"}getStats(){return this.cleanOldFailures(),{state:this.state,failures:this.failureTimestamps.length,successes:this.successes,totalRequests:this.totalRequests,lastFailureTime:this.lastFailureTime,lastSuccessTime:this.lastSuccessTime}}destroy(){if(this.resetTimer)clearTimeout(this.resetTimer),this.resetTimer=null}}class ys{breakers=new Map;defaultConfig;constructor(e){this.defaultConfig=e}getBreaker(e,t){if(!this.breakers.has(e))this.breakers.set(e,new bt(e,t||this.defaultConfig));return this.breakers.get(e)}async execute(e,t,s){return this.getBreaker(e,s).execute(t)}getStats(){let e={};for(let[t,s]of this.breakers)e[t]=s.getStats();return e}resetAll(){for(let e of this.breakers.values())e.reset()}destroy(){for(let e of this.breakers.values())e.destroy();this.breakers.clear()}}class vt{eventCallbacks=new Map;on(e,t){if(!this.eventCallbacks.has(e))this.eventCallbacks.set(e,new Set);this.eventCallbacks.get(e).add(t)}off(e,t){if(!t)this.eventCallbacks.delete(e);else this.eventCallbacks.get(e)?.delete(t)}emit(e,t){let s=this.eventCallbacks.get(e);if(s)for(let r of s)r(t)}}class Je{ws=null;config;channels=new Map;_socketId=null;reconnectAttempts=0;reconnectTimer=null;messageQueue=[];heartbeatTimer=null;pendingAcks=new Map;encryptionKeys=new Map;connector=new vt;constructor(e){if(this.config={broadcaster:e.broadcaster||"bun",host:e.host||"localhost",port:e.port||6001,scheme:e.scheme||"ws",key:e.key||"",cluster:e.cluster||"",encrypted:e.encrypted??!1,auth:e.auth||{},autoConnect:e.autoConnect??!0,reconnect:e.reconnect??e.autoReconnect??!0,autoReconnect:e.autoReconnect??e.reconnect??!0,reconnectDelay:(e.reconnectDelay??e.reconnectInterval)||1000,reconnectInterval:(e.reconnectInterval??e.reconnectDelay)||1000,maxReconnectAttempts:e.maxReconnectAttempts||10,encryption:{enabled:e.encryption?.enabled??!1,keys:e.encryption?.keys||{}},acknowledgments:{enabled:e.acknowledgments?.enabled??!1,timeout:e.acknowledgments?.timeout||5000},batch:{enabled:e.batch?.enabled??!0,maxBatchSize:e.batch?.maxBatchSize||50},heartbeat:{enabled:e.heartbeat?.enabled??!1,interval:e.heartbeat?.interval||30000},offlineQueue:{enabled:e.offlineQueue?.enabled??!0,maxSize:e.offlineQueue?.maxSize||100}},this.config.encryption.enabled&&this.config.encryption.keys)for(let[t,s]of Object.entries(this.config.encryption.keys))this.encryptionKeys.set(t,s);if(this.config.autoConnect)this.connect()}connect(){if(this.ws?.readyState===WebSocket.OPEN)return;let e=`${this.config.scheme}://${this.config.host}:${this.config.port}/ws`;this.ws=new WebSocket(e),this.ws.onopen=()=>{if(this.reconnectAttempts=0,this.connector.emit("connect"),this.config.heartbeat.enabled)this.startHeartbeat();while(this.messageQueue.length>0){let t=this.messageQueue.shift();if(t){if(this.ws?.send(t.message),t.ack&&t.messageId)this.waitForAck(t.messageId)}}},this.ws.onmessage=(t)=>{this.handleMessage(t.data)},this.ws.onclose=()=>{if(this._socketId=null,this.stopHeartbeat(),this.connector.emit("disconnect"),this.config.reconnect&&this.reconnectAttempts<this.config.maxReconnectAttempts){this.reconnectAttempts++;let t=Math.min(this.config.reconnectDelay*2**(this.reconnectAttempts-1),30000);this.reconnectTimer=setTimeout(()=>this.connect(),t)}},this.ws.onerror=(t)=>{this.connector.emit("error",t),console.error("WebSocket error:",t)}}disconnect(){if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;this.stopHeartbeat();for(let e of this.pendingAcks.values())clearTimeout(e.timeout),e.reject(Error("Connection closed"));this.pendingAcks.clear();for(let e of this.channels.values())e.unsubscribe();if(this.ws)this.ws.close(),this.ws=null;this.channels.clear(),this._socketId=null}isConnected(){return this.ws?.readyState===WebSocket.OPEN}socketId(){return this._socketId}channel(e){if(!this.channels.has(e)){let t=new Le(this,e);this.channels.set(e,t),t.subscribe()}return this.channels.get(e)}private(e){let t=e.startsWith("private-")?e:`private-${e}`;if(!this.channels.has(t)){let s=new Ue(this,t);this.channels.set(t,s),s.subscribe()}return this.channels.get(t)}join(e){let t=e.startsWith("presence-")?e:`presence-${e}`;if(!this.channels.has(t)){let s=new kt(this,t);this.channels.set(t,s),s.subscribe()}return this.channels.get(t)}leave(e){let t=this.channels.get(e);if(t)t.unsubscribe(),this.channels.delete(e)}leaveAll(){for(let e of this.channels.values())e.unsubscribe();this.channels.clear()}async batchSubscribe(e,t){if(!this.config.batch?.enabled)throw Error("Batch operations are disabled");if(e.length>(this.config.batch?.maxBatchSize??50))throw Error(`Batch size exceeds maximum: ${e.length} > ${this.config.batch.maxBatchSize}`);return new Promise((s,r)=>{let i=crypto.randomUUID();this.send({event:"batch_subscribe",channels:e,channelData:t,messageId:i});let n=setTimeout(()=>{r(Error("Batch subscribe timeout"))},1e4),a=(c)=>{if(c?.messageId===i)clearTimeout(n),s(c)};this.listen("batch_subscribe_result",a)})}async batchUnsubscribe(e){if(!this.config.batch?.enabled)throw Error("Batch operations are disabled");if(e.length>(this.config.batch?.maxBatchSize??50))throw Error(`Batch size exceeds maximum: ${e.length} > ${this.config.batch.maxBatchSize}`);return new Promise((t,s)=>{let r=crypto.randomUUID();this.send({event:"batch_unsubscribe",channels:e,messageId:r});let i=setTimeout(()=>{s(Error("Batch unsubscribe timeout"))},1e4),n=(a)=>{if(a?.messageId===r)clearTimeout(i),t(a)};this.listen("batch_unsubscribe_result",n)})}getSocketId(){return this._socketId}setEncryptionKey(e,t){this.encryptionKeys.set(e,t)}getEncryptionKey(e){return this.encryptionKeys.get(e)}async sendWithAck(e,t=!1){if(!t||!this.config.acknowledgments.enabled)return this.send(e),Promise.resolve(!0);let s=crypto.randomUUID(),r={...e,messageId:s,ack:!0};return new Promise((i,n)=>{this.send(r),this.waitForAck(s).then(i).catch(n)})}waitForAck(e){return new Promise((t,s)=>{let r=setTimeout(()=>{this.pendingAcks.delete(e),s(Error(`Acknowledgment timeout for message ${e}`))},this.config.acknowledgments.timeout);this.pendingAcks.set(e,{messageId:e,resolve:t,reject:s,timeout:r})})}handleAck(e){let t=this.pendingAcks.get(e);if(t)clearTimeout(t.timeout),t.resolve(!0),this.pendingAcks.delete(e)}startHeartbeat(){if(this.heartbeatTimer)return;this.heartbeatTimer=setInterval(()=>{this.send({event:"heartbeat",timestamp:Date.now()})},this.config.heartbeat.interval)}stopHeartbeat(){if(this.heartbeatTimer)clearInterval(this.heartbeatTimer),this.heartbeatTimer=null}globalCallbacks=new Map;listen(e,t){if(!this.globalCallbacks.has(e))this.globalCallbacks.set(e,new Set);this.globalCallbacks.get(e).add(t)}stopListening(e,t){if(!t)this.globalCallbacks.delete(e);else this.globalCallbacks.get(e)?.delete(t)}send(e){let t=JSON.stringify(e);if(this.ws?.readyState===WebSocket.OPEN)this.ws.send(t);else if(this.config.offlineQueue?.enabled)if(this.messageQueue.length<(this.config.offlineQueue.maxSize??100))this.messageQueue.push({message:t});else console.warn("Message queue is full, dropping message")}handleMessage(e){try{let t=JSON.parse(e);if(t.event==="connection_established"){this._socketId=t.data.socket_id;return}if(t.event==="ack"&&t.messageId){this.handleAck(t.messageId);return}let s=this.globalCallbacks.get(t.event);if(s)for(let r of s)r(t.data);if(t.channel){let r=this.channels.get(t.channel);if(r)r.handleEvent(t.event,t.data)}}catch(t){console.error("Error parsing message:",t)}}}class Ct{client;name;callbacks=new Map;isSubscribed=!1;constructor(e,t){this.client=e,this.name=t}subscribe(){if(this.isSubscribed)return;this.client.send({event:"subscribe",channel:this.name})}unsubscribe(){if(!this.isSubscribed)return;this.client.send({event:"unsubscribe",channel:this.name}),this.isSubscribed=!1,this.callbacks.clear()}listen(e,t){if(!this.callbacks.has(e))this.callbacks.set(e,new Set);return this.callbacks.get(e).add(t),this}stopListening(e,t){if(!t)this.callbacks.delete(e);else{let s=this.callbacks.get(e);if(s)s.delete(t)}return this}handleEvent(e,t){if(e==="subscription_succeeded")this.isSubscribed=!0;else if(e==="subscription_error")this.isSubscribed=!1;let s=this.callbacks.get(e);if(s)for(let r of s)r(t)}getName(){return this.name}}class bs{config;redis;seenMessages=new Map;cleanupInterval=null;constructor(e,t){if(this.config={enabled:e?.enabled??!0,ttl:e?.ttl??60,maxSize:e?.maxSize??1e4,hashFunction:e?.hashFunction||this.defaultHashFunction},this.redis=t,this.config.enabled&&!t)this.startCleanup()}defaultHashFunction(e,t,s){let r=`${e}:${t}:${JSON.stringify(s)}`;return this.simpleHash(r)}simpleHash(e){let t=0;for(let s=0;s<e.length;s++){let r=e.charCodeAt(s);t=(t<<5)-t+r,t=t&t}return t.toString(36)}async isDuplicate(e,t,s,r){if(!this.config.enabled)return!1;let i=r||this.config.hashFunction(e,t,s);if(this.redis)return this.checkRedis(i);return this.checkMemory(i)}async checkRedis(e){if(!this.redis)return!1;let t=`dedup:${e}`;try{if(await this.redis.client?.exists(t))return!0;return await this.redis.client?.setex(t,this.config.ttl,"1"),!1}catch(s){return console.error("Redis deduplication error:",s),this.checkMemory(e)}}checkMemory(e){let t=Date.now(),s=this.seenMessages.get(e);if(s){if(t-s<this.config.ttl*1000)return!0;this.seenMessages.delete(e)}if(this.seenMessages.set(e,t),this.seenMessages.size>this.config.maxSize){let r=Array.from(this.seenMessages.entries());r.sort((n,a)=>n[1]-a[1]);let i=r.slice(0,r.length-this.config.maxSize);for(let[n]of i)this.seenMessages.delete(n)}return!1}startCleanup(){this.cleanupInterval=setInterval(()=>{this.cleanup()},60000)}cleanup(){let e=Date.now(),t=this.config.ttl*1000;for(let[s,r]of this.seenMessages.entries())if(e-r>t)this.seenMessages.delete(s)}async clear(){if(this.redis)try{let e=await this.redis.client?.keys("dedup:*");if(e&&e.length>0)await this.redis.client?.del(...e)}catch(e){console.error("Error clearing Redis deduplication cache:",e)}this.seenMessages.clear()}getStats(){return{enabled:this.config.enabled,cacheSize:this.seenMessages.size,ttl:this.config.ttl,usingRedis:!!this.redis}}stop(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null}}var x=null,wt,Le,Ue,kt,Fr,qr;var $t=R(async()=>{ps();Ke();B();await ze();wt=class wt extends Error{constructor(e){super(e);this.name="CircuitBreakerError"}};Le=class Le extends Ct{subscribed(e){return this.listen("subscription_succeeded",e)}error(e){return this.listen("subscription_error",e)}};Ue=class Ue extends Le{whisper(e,t){return this.client.send({event:`client-${e}`,channel:this.name,data:t}),this}listenForWhisper(e,t){return this.listen(`client-${e}`,t)}};kt=class kt extends Ue{members=new Map;presenceHeartbeatTimer=null;subscribe(){super.subscribe(),this.startPresenceHeartbeat()}unsubscribe(){this.stopPresenceHeartbeat(),super.unsubscribe()}startPresenceHeartbeat(){this.presenceHeartbeatTimer=setInterval(()=>{this.client.send({event:"presence_heartbeat",channel:this.name,timestamp:Date.now()})},30000)}stopPresenceHeartbeat(){if(this.presenceHeartbeatTimer)clearInterval(this.presenceHeartbeatTimer),this.presenceHeartbeatTimer=null}handleEvent(e,t){if(e==="subscription_succeeded"&&t?.presence){for(let[r,i]of Object.entries(t.presence.hash))this.members.set(r,i);let s=this.callbacks.get("here");if(s){let r=Array.from(this.members.values());for(let i of s)i(r)}}else if(e==="member_added"){this.members.set(t.id,t);let s=this.callbacks.get("joining");if(s)for(let r of s)r(t)}else if(e==="member_removed"){this.members.delete(t.id);let s=this.callbacks.get("leaving");if(s)for(let r of s)r(t)}super.handleEvent(e,t)}here(e){return this.listen("here",e)}joining(e){return this.listen("joining",e)}leaving(e){return this.listen("leaving",e)}getMembers(){return Array.from(this.members.values())}getMember(e){return this.members.get(e)||null}};Fr=Je,qr=Je});$t();var se=null;function We(e){se=e}function k(){return se}async function zr(e){let r=new(await $t().then(() => ws)).BroadcastServer(e);return await r.start(),We(r),r}async function Kr(){if(se)await se.stop(),se=null}function vs(e,t,s,r){let i=k();if(!i){console.warn("[realtime] Server not initialized, cannot emit event");return}let n=e;if(r?.presence){if(!e.startsWith("presence-"))n=`presence-${e}`}else if(r?.private){if(!e.startsWith("private-"))n=`private-${e}`}let a=r?.exclude?Array.isArray(r.exclude)?r.exclude[0]:r.exclude:void 0;i.broadcast(n,t,s,a)}function Cs(e,t,s,r){vs(`private-user.${e}`,t,s,{...r,private:!0})}function Zr(e,t,s,r){for(let i of e)Cs(i,t,s,r)}var Qr=["private-","presence-"];function Et(e){for(let t of Qr)if(e.startsWith(t))return e.slice(t.length);return e}class St{channelName;constructor(e){this.channelName=e}async private(e,t){let s=k();if(!s)throw Error("Broadcast server not initialized");await s.broadcast(`private-${Et(this.channelName)}`,e,t)}async public(e,t){let s=k();if(!s)throw Error("Broadcast server not initialized");await s.broadcast(Et(this.channelName),e,t)}async presence(e,t){let s=k();if(!s)throw Error("Broadcast server not initialized");await s.broadcast(`presence-${Et(this.channelName)}`,e,t)}async broadcast(e,t,s="public"){switch(s){case"private":return this.private(e,t);case"presence":return this.presence(e,t);default:return this.public(e,t)}}}function Hr(e){return new St(e)}import{log as re}from"@stacksjs/logging";function Vr(e,t){try{if(typeof e.hasSubscribers==="function")return Boolean(e.hasSubscribers(t));if(typeof e.subscriberCount==="function")return e.subscriberCount(t)>0;let s=e.channels??e.clients;if(s&&typeof s.get==="function"){let r=s.get(t),i=(r&&(r.size??r.length))??null;if(typeof i==="number")return i>0}}catch{}return!0}class ks{async connect(){}async disconnect(){}subscribe(e,t){re.warn("Broadcast.subscribe() is a client-side operation. Use BroadcastClient instead.")}unsubscribe(e){re.warn("Broadcast.unsubscribe() is a client-side operation. Use BroadcastClient instead.")}broadcast(e,t,s,r="public"){let i=k();if(!i){re.warn("Broadcast server not initialized");return}let n=e;if(r==="private"&&!e.startsWith("private-"))n=`private-${e}`;else if(r==="presence"&&!e.startsWith("presence-"))n=`presence-${e}`;if(!Vr(i,n)){re.debug(`[Broadcast] Skipping '${t}' on '${n}' \u2014 no subscribers`);return}try{i.broadcast(n,t,s)}catch(a){re.error(`[Broadcast] Failed to broadcast event '${t}' to channel '${n}':`,a)}}isConnected(){return k()!==null}}async function $s(e,t){let{appPath:s}=await import("@stacksjs/path"),r=awaitPromise.resolve(globalThis.Bun),i;try{i=r.globSync([s("Broadcasts/**/*.ts")],{absolute:!0})}catch(u){throw Error(`Failed to scan broadcast files: ${u instanceof Error?u.message:String(u)}`)}let n=i.find((u)=>u.endsWith(`${e}.ts`));if(!n)throw Error(`Broadcast ${e} not found`);let a;try{a=await import(n)}catch(u){throw Error(`Failed to import broadcast '${e}': ${u instanceof Error?u.message:String(u)}`)}let c=a.default;if(c.handle){await c.handle(t);return}let o=k();if(!o)throw Error("Broadcast server not initialized");let l=c.broadcastOn?.()||c.channel?.()||[],h=c.broadcastAs?.()||c.event?.()||e,f=c.broadcastWith?.()||c.data?.()||t,d={shouldBroadcast:()=>!0,broadcastOn:()=>l,broadcastAs:()=>h,broadcastWith:()=>f};await o.broadcaster.broadcast(d)}async function Gr(e,t){if(typeof e!=="string"||e.trim().length===0)throw Error("[realtime] broadcast() requires a non-empty event name");await $s(e,t)}function Yr(e){if(e)We(e)}async function Xr(e,t,s){}async function ei(e,t){if(!k())return new Response("WebSocket server not initialized",{status:500});if(t.upgrade(e))return;return new Response("WebSocket upgrade failed",{status:400})}export{Xr as storeWebSocketEvent,Kr as stopServer,We as setServer,Yr as setBunSocket,$s as runBroadcast,ei as handleWebSocketRequest,k as getServer,ds as getConfig,Zr as emitToUsers,Cs as emitToUser,vs as emit,Gr as dispatchBroadcast,xe as defaultConfig,zr as createServer,ms as createHelpers,Ht as createEvent,Hr as createChannel,gs as config,Wr as channel,Ur as broadcastToUsers,Lr as broadcastToUser,Jr as broadcast,je as WebhookManager,St as StacksChannel,Re as SecurityManager,Be as RedisAdapter,J as RecurringBroadcastJob,Pe as RateLimiter,Le as PublicChannel,Z as PrometheusExporter,Ue as PrivateChannel,Ne as PresenceHeartbeatManager,kt as PresenceChannel,De as PersistenceManager,Oe as MonitoringManager,Ie as MessageValidationManager,bs as MessageDeduplicator,Ae as LoadManager,ks as LegacyBroadcast,_e as EncryptionManager,Fr as Echo,j as DelayedBroadcastJob,vt as Connector,Je as Client,ys as CircuitBreakerManager,wt as CircuitBreakerError,bt as CircuitBreaker,ve as ChannelStateManager,Ce as ChannelNamespaceManager,ke as ChannelManager,Te as ChannelLifecycleManager,Ct as ChannelInstance,ye as Broadcaster,be as BroadcastTo,yt as BroadcastServer,K as BroadcastQueueManager,D as BroadcastJob,te as BroadcastHelpers,qr as BroadcastClient,v as Broadcast,pe as BatchOperationsManager,Me as AuthenticationManager,we as AnonymousEvent,me as AcknowledgmentManager};
|
|
33
|
+
`}return{name:"bunfig-plugin",setup(i){i.onResolve({filter:/^virtual:bunfig-types$/},(n)=>{return{path:n.path,namespace:"bunfig-virtual"}}),i.onLoad({filter:/^virtual:bunfig-types$/,namespace:"bunfig-virtual"},()=>{return{contents:r(),loader:"ts"}})}}}async function bs(){if(!nt)nt=await vt({name:"broadcast",alias:"realtime",defaultConfig:Ae});return nt}class Me{config;keys=new Map;channelKeys=new Map;constructor(e={}){this.config={enabled:e.enabled??!1,algorithm:e.algorithm||"aes-256-gcm",keyRotationInterval:e.keyRotationInterval||86400000,channelKeys:e.channelKeys||new Map},this.channelKeys=new Map(this.config.channelKeys)}isEnabled(){return this.config.enabled}async setChannelKey(e,t){this.channelKeys.set(e,t);let s=de.from(t,"hex"),r=await crypto.subtle.importKey("raw",s,{name:"AES-GCM"},!1,["encrypt","decrypt"]);this.keys.set(e,r)}async generateChannelKey(e){let t=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),s=await crypto.subtle.exportKey("raw",t),r=de.from(s).toString("hex");return await this.setChannelKey(e,r),r}async encrypt(e,t){if(!this.config.enabled){if(t===void 0)return"undefined";return JSON.stringify(t)}let s=this.keys.get(e);if(!s)throw Error(`No encryption key found for channel: ${e}`);let r=t===void 0?"undefined":JSON.stringify(t),i=crypto.getRandomValues(new Uint8Array(12)),n=await crypto.subtle.encrypt({name:"AES-GCM",iv:i},s,new TextEncoder().encode(r)),a=new Uint8Array(i.length+n.byteLength);return a.set(i,0),a.set(new Uint8Array(n),i.length),de.from(a).toString("base64")}async decrypt(e,t){if(!this.config.enabled){if(t==="undefined")return;return JSON.parse(t)}let s=this.keys.get(e);if(!s)throw Error(`No encryption key found for channel: ${e}`);let r=de.from(t,"base64"),i=r.slice(0,12),n=r.slice(12),a=await crypto.subtle.decrypt({name:"AES-GCM",iv:i},s,n),c=new TextDecoder().decode(a);if(c==="undefined")return;return JSON.parse(c)}hasChannelKey(e){return this.channelKeys.has(e)}getChannelKey(e){return this.channelKeys.get(e)}async rotateChannelKey(e){return this.generateChannelKey(e)}removeChannelKey(e){this.channelKeys.delete(e),this.keys.delete(e)}}class ie{server;broadcaster;constructor(e,t){this.server=e,this.broadcaster=t}toUser(e,t,s){this.broadcaster.send(`private-user.${e}`,t,s)}toUsers(e,t,s){let r=e.map((i)=>`private-user.${i}`);this.broadcaster.send(r,t,s)}exceptUsers(e,t,s,r){let i=this.server.channels.getSubscribers(t),n=new Set(e.map((a)=>`private-user.${a}`));for(let a of i)if(!Array.from(n).some((c)=>this.server.channels.getChannel(c).subscribers.has(a))){this.broadcaster.send(t,s,r);break}}toAll(e,t){this.broadcaster.send("broadcast",e,t)}toRole(e,t,s){this.broadcaster.send(`role.${e}`,t,s)}notify(e,t){this.toUser(e,"notification",t)}notifyUsers(e,t){this.toUsers(e,"notification",t)}systemMessage(e,t="info"){this.toAll("system.message",{message:e,type:t,timestamp:Date.now()})}modelUpdated(e,t,s){this.broadcaster.send(`model.${e}.${t}`,"updated",s)}modelCreated(e,t){this.broadcaster.send(`model.${e}`,"created",t)}modelDeleted(e,t){this.broadcaster.send(`model.${e}.${t}`,"deleted",{id:t})}getUserConnectionCount(e){return this.server.channels.getSubscriberCount(`private-user.${e}`)}isUserOnline(e){return this.getUserConnectionCount(e)>0}getOnlineUsers(e){let t=e.startsWith("presence-")?e:`presence-${e}`,s=this.server.channels.getPresenceMembers(t);if(!s)return[];return Array.from(s.values())}getPresenceCount(e){let t=e.startsWith("presence-")?e:`presence-${e}`;return this.server.channels.getSubscriberCount(t)}}function vs(e,t){return new ie(e,t)}class Pe{hooks=new Map;on(e,t){if(!this.hooks.has(e))this.hooks.set(e,new Set);this.hooks.get(e).add(t)}off(e,t){this.hooks.get(e)?.delete(t)}async fire(e){let t=this.hooks.get(e.event);if(t)for(let r of t)try{await r(e)}catch(i){console.error(`Error in lifecycle hook for ${e.event}:`,i)}let s=this.hooks.get("all");if(s)for(let r of s)try{await r(e)}catch(i){console.error("Error in 'all' lifecycle hook:",i)}}async channelCreated(e,t){await this.fire({channel:e,event:"created",timestamp:Date.now(),socketId:t})}async channelSubscribed(e,t,s){await this.fire({channel:e,event:"subscribed",timestamp:Date.now(),socketId:t,subscriberCount:s})}async channelUnsubscribed(e,t,s){await this.fire({channel:e,event:"unsubscribed",timestamp:Date.now(),socketId:t,subscriberCount:s})}async channelEmpty(e){await this.fire({channel:e,event:"empty",timestamp:Date.now(),subscriberCount:0})}async channelDestroyed(e){await this.fire({channel:e,event:"destroyed",timestamp:Date.now()})}}class Ie{config;connectionCount=0;channelCount=0;channelsPerConnection=new Map;constructor(e={}){this.config={maxConnections:e.maxConnections??1e4,maxChannelsPerConnection:e.maxChannelsPerConnection??100,maxGlobalChannels:e.maxGlobalChannels??50000,shedLoadAt:e.shedLoadAt??90,backpressureThreshold:e.backpressureThreshold??1048576}}canAcceptConnection(){return this.connectionCount<this.config.maxConnections}shouldShedLoad(){let e=this.connectionCount/this.config.maxConnections*100,t=this.channelCount/this.config.maxGlobalChannels*100;return e>=this.config.shedLoadAt||t>=this.config.shedLoadAt}registerConnection(e){this.connectionCount++,this.channelsPerConnection.set(e,0)}unregisterConnection(e){this.connectionCount=Math.max(0,this.connectionCount-1);let t=this.channelsPerConnection.get(e)||0;this.channelCount=Math.max(0,this.channelCount-t),this.channelsPerConnection.delete(e)}canSubscribe(e){if((this.channelsPerConnection.get(e)||0)>=this.config.maxChannelsPerConnection)return!1;if(this.channelCount>=this.config.maxGlobalChannels)return!1;return!0}registerSubscription(e){let t=this.channelsPerConnection.get(e)||0;this.channelsPerConnection.set(e,t+1),this.channelCount++}unregisterSubscription(e){let t=this.channelsPerConnection.get(e)||0;if(t>0)this.channelsPerConnection.set(e,t-1),this.channelCount=Math.max(0,this.channelCount-1)}shouldApplyBackpressure(e){return e>this.config.backpressureThreshold}getStats(){let e=Array.from(this.channelsPerConnection.values()).reduce((s,r)=>s+r,0),t=this.connectionCount>0?e/this.connectionCount:0;return{connections:this.connectionCount,channels:this.channelCount,averageChannelsPerConnection:t,memoryUsage:Wr.memoryUsage().heapUsed,isOverloaded:this.shouldShedLoad()}}getConnectionUsage(){return this.connectionCount/this.config.maxConnections*100}getChannelUsage(){return this.channelCount/this.config.maxGlobalChannels*100}}class Oe{callback=null;config;constructor(e={}){this.config={enabled:e.enabled??!0,cookie:{name:e.cookie?.name||"auth_token",secure:e.cookie?.secure??!0},jwt:{secret:e.jwt?.secret||Fr.env.JWT_SECRET||"",algorithm:e.jwt?.algorithm||"HS256"},session:{key:e.session?.key||"session_id"}}}authenticate(e){this.callback=e}async authenticateRequest(e){if(!this.config.enabled)return null;if(this.callback)return await this.callback(e);let t=e.headers.get("cookie");if(t){let r=this.parseCookies(t)[this.config.cookie.name];if(r)return this.verifyToken(r)}let s=e.headers.get("authorization");if(s?.startsWith("Bearer ")){let r=s.slice(7);return this.verifyToken(r)}return null}parseCookies(e){let t={};for(let s of e.split(";")){let[r,...i]=s.split("=");t[r.trim()]=i.join("=").trim()}return t}async verifyToken(e){try{let t=e.split(".");if(t.length===3){let s=JSON.parse(atob(t[1]));return{id:s.sub||s.id,...s}}}catch(t){console.error("Error verifying token:",t)}return null}}class Re{limits=new Map;config;cleanupTimer;constructor(e){this.config={max:e.max||100,window:e.window||60000,perChannel:e.perChannel??!1,perUser:e.perUser??!1},this.cleanupTimer=setInterval(()=>this.cleanup(),60000)}check(e,t){let s=this.getKey(e,t),r=Date.now(),i=this.limits.get(s);if(!i||i.resetAt<r)return this.limits.set(s,{count:1,resetAt:r+this.config.window}),!1;if(i.count>=this.config.max)return!0;return i.count++,!1}getRemaining(e,t){let s=this.getKey(e,t),r=this.limits.get(s);if(!r||r.resetAt<Date.now())return this.config.max;return Math.max(0,this.config.max-r.count)}getResetAt(e,t){let s=this.getKey(e,t);return this.limits.get(s)?.resetAt||Date.now()}getKey(e,t){let s=[];if(this.config.perUser&&e.data.user)s.push(`user:${e.data.user.id}`);else s.push(`socket:${e.data.socketId}`);if(this.config.perChannel&&t)s.push(`channel:${t}`);return s.join(":")}cleanup(){let e=Date.now();for(let[t,s]of this.limits.entries())if(s.resetAt<e)this.limits.delete(t)}clear(){this.limits.clear()}stop(){clearInterval(this.cleanupTimer)}}class De{validators=new Set;addValidator(e){this.validators.add(e)}removeValidator(e){this.validators.delete(e)}validate(e){for(let t of this.validators){let s=t(e);if(s===!1)return{valid:!1,error:"Validation failed"};if(typeof s==="string")return{valid:!1,error:s}}return{valid:!0}}}class Be{callbacks=new Map;metrics=new Map;on(e,t){if(!this.callbacks.has(e))this.callbacks.set(e,new Set);this.callbacks.get(e).add(t)}off(e,t){let s=this.callbacks.get(e);if(s)s.delete(t)}emit(e){this.incrementMetric(e.type);let t=this.callbacks.get(e.type);if(t)for(let r of t)r(e);let s=this.callbacks.get("all");if(s)for(let r of s)r(e)}incrementMetric(e,t=1){let s=this.metrics.get(e)||0;this.metrics.set(e,s+t)}getMetric(e){return this.metrics.get(e)||0}getMetrics(){return Object.fromEntries(this.metrics)}resetMetrics(){this.metrics.clear()}}class Ne{config;constructor(e={}){this.config={cors:{enabled:e.cors?.enabled??!0,origins:e.cors?.origins||["*"],credentials:e.cors?.credentials??!0},maxPayloadSize:e.maxPayloadSize||1048576,sanitizeMessages:e.sanitizeMessages??!0}}checkOrigin(e){if(!this.config.cors?.enabled)return!0;if(this.config.cors.origins?.includes("*"))return!0;return this.config.cors.origins?.includes(e)??!1}sanitize(e){if(!this.config.sanitizeMessages)return e;if(typeof e==="string")return e.replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/\x27/g,"'").replace(/\//g,"/");if(Array.isArray(e))return e.map((t)=>this.sanitize(t));if(e&&typeof e==="object"){let t={};for(let[s,r]of Object.entries(e))t[s]=this.sanitize(r);return t}return e}checkSize(e){return e.length<=this.config.maxPayloadSize}}class je{config;redis;inMemoryStore=new Map;constructor(e={},t){this.config={enabled:e.enabled??!1,ttl:e.ttl??3600,maxMessages:e.maxMessages??100,excludeEvents:e.excludeEvents||["ping","pong"]},this.redis=t}async store(e,t,s,r){if(!this.config.enabled)return;if(this.config.excludeEvents.includes(t))return;let i={id:crypto.randomUUID(),event:t,data:s,timestamp:Date.now(),socketId:r};if(this.redis)await this.storeInRedis(e,i);else this.storeInMemory(e,i)}async getHistory(e,t,s){if(!this.config.enabled)return[];if(this.redis)return this.getHistoryFromRedis(e,t,s);return this.getHistoryFromMemory(e,t,s)}async clear(e){if(this.redis){let t=this.getRedisKey(e),s=this.redis;if(s.publisher)await s.publisher.del(t)}else this.inMemoryStore.delete(e)}async storeInRedis(e,t){if(!this.redis)return;let s=this.getRedisKey(e),r=JSON.stringify(t),i=this.redis;if(!i.publisher)return;await i.publisher.zadd(s,t.timestamp,r);let n=-this.config.maxMessages-1;await i.publisher.send("ZREMRANGEBYRANK",[s,"0",n.toString()]),await i.publisher.expire(s,this.config.ttl)}async getHistoryFromRedis(e,t,s){if(!this.redis)return[];let r=this.getRedisKey(e),i=t?.toString()||"-inf",n="+inf",a=s||this.config.maxMessages,c=this.redis;if(!c.publisher)return[];return(await c.publisher.send("ZRANGEBYSCORE",[r,i,n,"LIMIT","0",a.toString()])).map((o)=>JSON.parse(o))}storeInMemory(e,t){if(!this.inMemoryStore.has(e))this.inMemoryStore.set(e,[]);let s=this.inMemoryStore.get(e);if(s.push(t),s.length>this.config.maxMessages)s.shift();let r=Date.now()-this.config.ttl*1000,i=s.filter((n)=>n.timestamp>r);this.inMemoryStore.set(e,i)}getHistoryFromMemory(e,t,s){let r=this.inMemoryStore.get(e)||[],i=r;if(t!==void 0)i=r.filter((n)=>n.timestamp>=t);if(s)i=i.slice(0,s);return i}getRedisKey(e){return`history:${e}`}async getStats(){if(this.redis){let s=this.redis;if(!s.publisher)return{totalChannels:0,totalMessages:0,channels:{}};let r=await s.publisher.send("KEYS",["history:*"]),i=0,n={};for(let a of r){let c=await s.publisher.send("ZCARD",[a]),o=a.replace("history:",""),l=Number(c);n[o]=l,i+=l}return{totalChannels:r.length,totalMessages:i,channels:n}}let e=0,t={};for(let[s,r]of this.inMemoryStore.entries())t[s]=r.length,e+=r.length;return{totalChannels:this.inMemoryStore.size,totalMessages:e,channels:t}}}class Je{config;presenceUsers=new Map;heartbeatTimer;onRemove;constructor(e={}){this.config={enabled:e.enabled??!0,interval:e.interval??30000,timeout:e.timeout??60000,requireClientHeartbeat:e.requireClientHeartbeat??!0}}start(){if(!this.config.enabled)return;this.heartbeatTimer=setInterval(()=>{this.checkHeartbeats()},this.config.interval)}stop(){if(this.heartbeatTimer)clearInterval(this.heartbeatTimer)}onUserRemove(e){this.onRemove=e}heartbeat(e,t,s){if(!this.config.enabled)return;if(!this.presenceUsers.has(e))this.presenceUsers.set(e,new Map);let r=this.presenceUsers.get(e),i=r.get(t);r.set(t,{socketId:t,lastSeen:Date.now(),data:s||i?.data})}remove(e,t){let s=this.presenceUsers.get(e);if(s){if(s.delete(t),s.size===0)this.presenceUsers.delete(e)}}checkHeartbeats(){let e=Date.now(),t=this.config.timeout;for(let[s,r]of this.presenceUsers.entries()){let i=[];for(let[n,a]of r.entries())if(e-a.lastSeen>t)i.push(n);for(let n of i){let a=r.get(n);if(r.delete(n),this.onRemove&&a)this.onRemove(s,n,a.data)}if(r.size===0)this.presenceUsers.delete(s)}}getActiveUsers(e){let t=this.presenceUsers.get(e);if(!t)return[];return Array.from(t.values())}isActive(e,t){let s=this.presenceUsers.get(e)?.get(t);if(!s)return!1;return Date.now()-s.lastSeen<this.config.timeout}getStats(){let e=0;for(let t of this.presenceUsers.values())e+=t.size;return{channels:this.presenceUsers.size,totalUsers:e}}}class Le{publisher;subscriber;config;serverId;messageHandlers=new Set;get client(){return this.publisher}constructor(e){this.serverId=crypto.randomUUID(),this.config={host:e.host||G.env.REDIS_HOST||"localhost",port:e.port||Number.parseInt(G.env.REDIS_PORT||"6379"),password:e.password||G.env.REDIS_PASSWORD||"",database:e.database||Number.parseInt(G.env.REDIS_DB||"0"),url:e.url||G.env.REDIS_URL||"",keyPrefix:e.keyPrefix||"broadcasting:"};let t=this.config.url||this.buildRedisUrl();this.publisher=new Xt(t||"redis://localhost:6379"),this.subscriber=new Xt(t||"redis://localhost:6379")}buildRedisUrl(){return`redis://${this.config.password?`:${this.config.password}@`:""}${this.config.host}:${this.config.port}/${this.config.database}`}async connect(){await Promise.all([this.publisher.connect(),this.subscriber.connect()]),await this.subscriber.subscribe(`${this.config.keyPrefix}channel`,(e)=>{this.handleRedisMessage(e)})}close(){this.publisher.close(),this.subscriber.close()}async broadcast(e,t,s,r){let i={type:"broadcast",channel:e,event:t,data:s,socketId:r,serverId:this.serverId};await this.publisher.publish(`${this.config.keyPrefix}channel`,JSON.stringify(i))}onMessage(e){this.messageHandlers.add(e)}offMessage(e){this.messageHandlers.delete(e)}handleRedisMessage(e){try{let t=JSON.parse(e);if(t.serverId===this.serverId)return;for(let s of this.messageHandlers)s(t)}catch(t){console.error("Error handling Redis message:",t)}}async storeChannel(e,t){let s=`${this.config.keyPrefix}channels:${e}`;await this.publisher.sadd(s,t),await this.publisher.expire(s,3600)}async removeChannel(e,t){let s=`${this.config.keyPrefix}channels:${e}`;await this.publisher.srem(s,t)}async getChannelSubscribers(e){let t=`${this.config.keyPrefix}channels:${e}`;return await this.publisher.smembers(t)}async storePresenceMember(e,t,s){let r=`${this.config.keyPrefix}presence:${e}`;await this.publisher.hmset(r,[t,JSON.stringify(s)]),await this.publisher.expire(r,3600)}async removePresenceMember(e,t){let s=`${this.config.keyPrefix}presence:${e}`;await this.publisher.send("HDEL",[s,t])}async getPresenceMembers(e){let t=`${this.config.keyPrefix}presence:${e}`,s=await this.publisher.send("HGETALL",[t]),r=new Map;for(let i=0;i<s.length;i+=2){let n=s[i],a=s[i+1];try{r.set(n,JSON.parse(a))}catch{console.error(`Error parsing presence member data for ${n}`)}}return r}async incrementStat(e){let t=`${this.config.keyPrefix}stats:${e}`;await this.publisher.incr(t)}async getStats(){let e=await this.publisher.send("KEYS",[`${this.config.keyPrefix}stats:*`]),t={};for(let s of e){let r=await this.publisher.get(s),i=s.replace(`${this.config.keyPrefix}stats:`,"");t[i]=Number.parseInt(r||"0")}return t}async storeConnection(e,t){let s=`${this.config.keyPrefix}connections:${e}`;await this.publisher.set(s,JSON.stringify(t)),await this.publisher.expire(s,7200)}async removeConnection(e){let t=`${this.config.keyPrefix}connections:${e}`;await this.publisher.del(t)}async getConnection(e){let t=`${this.config.keyPrefix}connections:${e}`,s=await this.publisher.get(t);if(!s)return null;try{return JSON.parse(s)}catch{return console.error(`Error parsing connection data for ${e}`),null}}async getTotalConnections(){return(await this.publisher.send("KEYS",[`${this.config.keyPrefix}connections:*`])).length}async getTotalChannels(){return(await this.publisher.send("KEYS",[`${this.config.keyPrefix}channels:*`])).length}async healthCheck(){try{return await this.publisher.send("PING",[]),!0}catch{return!1}}getServerId(){return this.serverId}}class Ue{config;endpoints;constructor(e={}){this.config={enabled:e.enabled??!1,endpoints:e.endpoints||[],retryAttempts:e.retryAttempts??3,retryDelay:e.retryDelay??1000,timeout:e.timeout??5000,secret:e.secret||""},this.endpoints=this.config.endpoints}register(e){this.endpoints.push(e)}async fire(e,t){if(!this.config.enabled)return;let s={event:e,timestamp:Date.now(),data:t};if(this.config.secret)s.signature=await this.generateSignature(s);let r=this.endpoints.filter((i)=>i.events.includes(e)).map((i)=>this.sendWebhook(i,s));await Promise.allSettled(r)}async sendWebhook(e,t,s=1){try{let r=new AbortController,i=setTimeout(()=>r.abort(),this.config.timeout),n=await fetch(e.url,{method:e.method||"POST",headers:{"Content-Type":"application/json","User-Agent":"ts-broadcasting/1.0","X-Webhook-Signature":t.signature||"",...e.headers},body:JSON.stringify(t),signal:r.signal});if(clearTimeout(i),!n.ok&&n.status>=500&&s<=this.config.retryAttempts)return await new Promise((a)=>setTimeout(a,this.config.retryDelay*s)),this.sendWebhook(e,t,s+1)}catch{if(s<=this.config.retryAttempts)return await new Promise((r)=>setTimeout(r,this.config.retryDelay*s)),this.sendWebhook(e,t,s+1)}}async generateSignature(e){let t=new TextEncoder,s=t.encode(JSON.stringify(e)),r=await crypto.subtle.importKey("raw",t.encode(this.config.secret),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),i=await crypto.subtle.sign("HMAC",r,s);return qr.from(i).toString("hex")}async verifySignature(e,t){if(!this.config.secret)return!0;let s=await this.generateSignature(e);return t===s}}class Ct{server;connections=new Map;config;channels;broadcaster;helpers;redis;auth;rateLimit;monitoring;validator;security;encryption;webhooks;persistence;channelState;namespace;presenceHeartbeat;acknowledgments;batchOps;lifecycle;loadManager;queueManager;constructor(e){if(this.config=e,this.channels=new Se,this.broadcaster=new ve(this,e),this.helpers=new ie(this,this.broadcaster),e.auth)this.auth=new Oe(e.auth);if(e.rateLimit)this.rateLimit=new Re(e.rateLimit);if(e.security)this.security=new Ne(e.security);if(this.monitoring=new Be,this.validator=new De,e.encryption)this.encryption=new Me(e.encryption);if(e.webhooks)this.webhooks=new Ue(e.webhooks);if(e.persistence)this.persistence=new je(e.persistence);if(this.channelState=new ke,this.namespace=new Ee,e.heartbeat)this.presenceHeartbeat=new Je(e.heartbeat);if(e.acknowledgments)this.acknowledgments=new be(e.acknowledgments);if(e.batch)this.batchOps=new we(e.batch,this.channels);if(this.lifecycle=new Pe,e.loadManagement)this.loadManager=new Ie(e.loadManagement);if(e.queue?.enabled)this.initializeQueueManager();if(this.presenceHeartbeat)this.presenceHeartbeat.onUserRemove((t,s,r)=>{if(this.broadcast(t,"member_removed",{id:s,user:r},s),this.config.verbose)console.warn(`Removed inactive user ${s} from ${t}`)});this.setupDefaultValidators()}async initializeQueueManager(){try{let{BroadcastQueueManager:e}=await Ot().then(() => It);if(this.queueManager=new e(this,this.config.queue),this.config.verbose)console.warn("Queue manager initialized")}catch(e){console.error("Failed to initialize queue manager:",e)}}async start(){if(this.presenceHeartbeat){if(this.presenceHeartbeat.start(),this.config.verbose)console.warn("Started presence heartbeat monitoring")}if(this.config.redis){if(this.redis=new Le(this.config.redis),await this.redis.connect(),this.redis.onMessage((r)=>{if(r.type==="broadcast")this.broadcast(r.channel,r.event,r.data,r.socketId)}),this.config.verbose)console.warn("Connected to Redis for horizontal scaling")}let e=this.config.connections?.[this.config.default||"bun"];if(!e)throw Error("No connection configuration found");let t=e.host||"0.0.0.0",s=e.port??6001;if(this.server=Bun.serve({hostname:t,port:s,fetch:async(r,i)=>{let n=new URL(r.url);if(n.pathname==="/health"){let a={status:"ok",redis:this.redis?await this.redis.healthCheck():null};return Response.json(a)}if(n.pathname==="/stats")return Response.json(await this.getStats());if(n.pathname==="/metrics"){let{PrometheusExporter:a}=await Promise.resolve().then(() => (Dt(),Rt)),c=await new a(this).export();return new Response(c,{headers:{"Content-Type":"text/plain; version=0.0.4"}})}if(n.pathname==="/app"||n.pathname==="/ws"){let a=null;if(this.auth)a=await this.auth.authenticateRequest(r);if(i.upgrade(r,{data:{id:crypto.randomUUID(),socketId:crypto.randomUUID(),channels:new Set,connectedAt:Date.now(),user:a??void 0}}))return;return new Response("WebSocket upgrade failed",{status:400})}return new Response("Not found",{status:404})},websocket:{open:(r)=>{this.handleOpen(r)},message:(r,i)=>{this.handleMessage(r,i)},close:(r,i,n)=>{this.handleClose(r,i,n)},drain:(r)=>{this.handleDrain(r)},idleTimeout:e.options?.idleTimeout,maxPayloadLength:e.options?.maxPayloadLength,backpressureLimit:e.options?.backpressureLimit,closeOnBackpressureLimit:e.options?.closeOnBackpressureLimit,sendPings:e.options?.sendPings,perMessageDeflate:e.options?.perMessageDeflate}}),this.config.verbose)console.warn(`Broadcasting server started on ${t}:${s}`);this.monitoring?.emit({type:"connection",timestamp:Date.now(),socketId:"server",data:{event:"server_start"}})}async stop(){if(this.rateLimit)this.rateLimit.stop();if(this.presenceHeartbeat)this.presenceHeartbeat.stop();if(this.acknowledgments)this.acknowledgments.clear();if(this.queueManager)await this.queueManager.close();if(this.redis)this.redis.close();if(this.server){if(this.server.stop(),this.connections.clear(),this.config.verbose)console.warn("Broadcasting server stopped")}this.monitoring?.emit({type:"disconnection",timestamp:Date.now(),socketId:"server",data:{event:"server_stop"}})}handleOpen(e){if(this.loadManager&&!this.loadManager.canAcceptConnection()){e.close(1008,"Server at capacity");return}if(this.loadManager?.shouldShedLoad()){e.close(1008,"Server load too high");return}if(this.loadManager)this.loadManager.registerConnection(e.data.socketId);if(this.connections.set(e.data.socketId,e),this.redis)this.redis.storeConnection(e.data.socketId,{connectedAt:e.data.connectedAt,channels:Array.from(e.data.channels),user:e.data.user}).catch((t)=>console.error("Redis store connection error:",t));if(this.webhooks)this.webhooks.fire("connection",{socketId:e.data.socketId,connectedAt:e.data.connectedAt,user:e.data.user}).catch((t)=>console.error("Webhook error:",t));if(this.send(e,{event:"connection_established",data:{socket_id:e.data.socketId,activity_timeout:this.config.connections?.[this.config.default||"bun"]?.options?.idleTimeout||120}}),this.monitoring?.emit({type:"connection",timestamp:Date.now(),socketId:e.data.socketId}),this.config.verbose)console.warn(`WebSocket connected: ${e.data.socketId}`)}async handleMessage(e,t){if(this.rateLimit&&this.rateLimit.check(e)){this.send(e,{event:"error",data:{type:"RateLimitExceeded",error:"Too many requests",retryAfter:this.rateLimit.getResetAt(e)}});return}let s=typeof t==="string"?t:t.toString();if(this.security&&!this.security.checkSize(s)){this.send(e,{event:"error",data:{type:"PayloadTooLarge",error:"Message size exceeds maximum allowed"}});return}try{let r=JSON.parse(s);if(this.validator){let n=this.validator.validate(r);if(!n.valid){this.send(e,{event:"error",data:{type:"ValidationError",error:n.error}});return}}let i=this.security?this.security.sanitize(r):r;switch(this.monitoring?.emit({type:"message",timestamp:Date.now(),socketId:e.data.socketId,data:{event:i.event}}),i.event){case"subscribe":await this.handleSubscribe(e,i);break;case"unsubscribe":await this.handleUnsubscribe(e,i);break;case"batch_subscribe":await this.handleBatchSubscribe(e,i);break;case"batch_unsubscribe":await this.handleBatchUnsubscribe(e,i);break;case"heartbeat":case"presence_heartbeat":await this.handleHeartbeat(e,i);break;case"ping":this.send(e,{event:"pong"});break;default:if(this.acknowledgments&&i.ack&&i.messageId)this.send(e,{event:"ack",messageId:i.messageId});if(i.event.startsWith("client-"))await this.handleClientEvent(e,i);break}}catch(r){if(this.monitoring?.emit({type:"error",timestamp:Date.now(),socketId:e.data.socketId,data:{error:r instanceof Error?r.message:"Unknown error"}}),this.config.verbose)console.error("Error handling message:",r)}}async handleSubscribe(e,t){let{channel:s,channel_data:r}=t;try{if(this.loadManager&&!this.loadManager.canSubscribe(e.data.socketId)){this.send(e,{event:"subscription_error",channel:s,data:{type:"CapacityError",error:"Subscription limit reached",status:429}});return}let i=await this.channels.subscribe(e,s,r);if(!i){this.send(e,{event:"subscription_error",channel:s,data:{type:"AuthError",error:"Unauthorized",status:401}});return}if(this.loadManager)this.loadManager.registerSubscription(e.data.socketId);if(this.redis){if(await this.redis.storeChannel(s,e.data.socketId),this.channels.getChannelType(s)==="presence"&&typeof i==="object")await this.redis.storePresenceMember(s,e.data.socketId,i)}let n=this.channels.getChannelType(s);if(this.lifecycle){if(this.channels.getSubscriberCount(s)===1)await this.lifecycle.channelCreated(s,e.data.socketId);await this.lifecycle.channelSubscribed(s,e.data.socketId,this.channels.getSubscriberCount(s))}if(n==="presence"){if(this.presenceHeartbeat&&typeof i==="object")this.presenceHeartbeat.heartbeat(s,e.data.socketId,i);let a=this.channels.getPresenceMembers(s),c={presence:{ids:Array.from(a?.keys()||[]),hash:Object.fromEntries(a||[]),count:a?.size||0}};if(this.send(e,{event:"subscription_succeeded",channel:s,data:c}),typeof i==="object")this.broadcast(s,"member_added",i,e.data.socketId)}else this.send(e,{event:"subscription_succeeded",channel:s});if(this.webhooks)this.webhooks.fire("subscribe",{socketId:e.data.socketId,channel:s,channelData:r}).catch((a)=>console.error("Webhook error:",a));if(this.monitoring?.emit({type:"subscribe",timestamp:Date.now(),socketId:e.data.socketId,channel:s}),this.config.verbose)console.warn(`Socket ${e.data.socketId} subscribed to ${s}`)}catch(i){this.send(e,{event:"subscription_error",channel:s,data:{type:"ServerError",error:i instanceof Error?i.message:"Internal server error",status:500}})}}async handleUnsubscribe(e,t){let{channel:s}=t,r=this.channels.getChannelType(s),i=null;if(r==="presence")i=this.channels.getPresenceMembers(s)?.get(e.data.socketId);if(this.redis){if(await this.redis.removeChannel(s,e.data.socketId),r==="presence")await this.redis.removePresenceMember(s,e.data.socketId)}if(this.channels.unsubscribe(e,s),r==="presence"&&i)this.broadcast(s,"member_removed",i,e.data.socketId);if(this.monitoring?.emit({type:"unsubscribe",timestamp:Date.now(),socketId:e.data.socketId,channel:s}),this.config.verbose)console.warn(`Socket ${e.data.socketId} unsubscribed from ${s}`)}async handleClientEvent(e,t){let{event:s,channel:r,data:i}=t;if(this.channels.getChannelType(r)==="public")return;this.broadcast(r,s,i,e.data.socketId)}handleClose(e,t,s){let r=new Map;for(let i of e.data.channels)if(this.channels.getChannelType(i)==="presence"){let n=this.channels.getPresenceMembers(i)?.get(e.data.socketId);if(n)r.set(i,n)}this.channels.unsubscribeAll(e);for(let[i,n]of r)this.broadcast(i,"member_removed",n,e.data.socketId);if(this.loadManager)this.loadManager.unregisterConnection(e.data.socketId);if(this.connections.delete(e.data.socketId),this.redis)this.redis.removeConnection(e.data.socketId).catch((i)=>console.error("Redis remove connection error:",i));if(this.webhooks)this.webhooks.fire("disconnection",{socketId:e.data.socketId,code:t,reason:s}).catch((i)=>console.error("Webhook error:",i));if(this.monitoring?.emit({type:"disconnection",timestamp:Date.now(),socketId:e.data.socketId,data:{code:t,reason:s}}),this.config.verbose)console.warn(`WebSocket closed: ${e.data.socketId} (${t}: ${s})`)}handleError(e,t){if(this.monitoring?.emit({type:"error",timestamp:Date.now(),socketId:e.data.socketId,data:{error:t.message}}),this.config.verbose)console.error(`WebSocket error for ${e.data.socketId}:`,t)}handleDrain(e){if(this.config.verbose)console.warn(`WebSocket drained: ${e.data.socketId}`)}send(e,t){return e.send(JSON.stringify(t))}broadcast(e,t,s,r){let i=JSON.stringify({event:t,channel:e,data:s});if(this.server)if(r){let n=this.channels.getSubscribers(e);for(let a of n)if(a!==r){let c=this.connections.get(a);if(c)c.send(i)}}else this.server.publish(e,i);if(this.redis)this.redis.broadcast(e,t,s,r).catch((n)=>{console.error("Redis broadcast error:",n)});this.monitoring?.emit({type:"broadcast",timestamp:Date.now(),socketId:r||"server",channel:e,data:{event:t,dataSize:JSON.stringify(s).length}})}getConnectionCount(){return this.connections.size}getSubscriberCount(e){return this.channels.getSubscriberCount(e)}async getStats(){let e={connections:this.getConnectionCount(),channels:this.channels.getChannelCount(),uptime:zr.uptime()};if(this.redis){let t={totalConnections:await this.redis.getTotalConnections(),totalChannels:await this.redis.getTotalChannels(),redisHealthy:await this.redis.healthCheck(),serverId:this.redis.getServerId()};return{...e,...t,metrics:this.monitoring?.getMetrics()||{}}}return{...e,metrics:this.monitoring?.getMetrics()||{}}}async handleBatchSubscribe(e,t){if(!this.batchOps){this.send(e,{event:"error",data:{type:"NotSupported",error:"Batch operations are not enabled"}});return}try{let s=await this.batchOps.batchSubscribe(e,{channels:t.channels,channelData:t.channelData});this.send(e,{event:"batch_subscribe_result",messageId:t.messageId,data:s})}catch(s){this.send(e,{event:"error",data:{type:"BatchError",error:s instanceof Error?s.message:"Batch subscribe failed"}})}}handleBatchUnsubscribe(e,t){if(!this.batchOps){this.send(e,{event:"error",data:{type:"NotSupported",error:"Batch operations are not enabled"}});return}try{let s=this.batchOps.batchUnsubscribe(e,t.channels);this.send(e,{event:"batch_unsubscribe_result",messageId:t.messageId,data:s})}catch(s){this.send(e,{event:"error",data:{type:"BatchError",error:s instanceof Error?s.message:"Batch unsubscribe failed"}})}}async handleHeartbeat(e,t){if(!this.presenceHeartbeat)return;if(t.channel)this.presenceHeartbeat.heartbeat(t.channel,e.data.socketId)}setupDefaultValidators(){if(!this.validator)return;this.validator.addValidator((e)=>{if(!e||typeof e!=="object")return"Invalid message format";if(!e.event||typeof e.event!=="string")return"Missing or invalid event name";if(e.channel&&typeof e.channel!=="string")return"Invalid channel name";return!0}),this.validator.addValidator((e)=>{let t=e.event;if(t.length>100)return"Event name too long";if(!/^[\w.-]+$/.test(t))return"Event name contains invalid characters";return!0})}}var er,tr=(e)=>e,rr=(e,t)=>{for(var s in t)er(e,s,{get:t[s],enumerable:!0,configurable:!0,set:sr.bind(t,s)})},I=(e,t)=>()=>(e&&(t=e(e=0)),t),ir,K,se,ts,re,Zt,st,X,hr,y,g,ur,Qt,fr,Ht,dr,gr,rt,mr,Vt,Gt,pr,it,yr,br,wr,vr,Cr,ge,rs,$r,kr,Er="0.15.8",Sr=()=>{},E,pe,ee,ot,ct,ye,lt,ht,te,ut,ft,D,Z,as,hs,yt,us,fs,ds,x,P,gs,ms,Jr,Ur=()=>{},ps,ys,Ae,nt=null,ws,Xt;var Cs=B(()=>{J();er=Object.defineProperty;ir=import.meta.require;re=I(()=>{K=new gt,se=new mt,ts={createKey:nr,isEquivalent:ar,estimateMemoryUsage:or}});kr=I(()=>{Zt=me.env.CLARITY_LOG_DIR||Ds(cr(),"logs"),st={level:"info",defaultName:"clarity",timestamp:!0,colors:!0,format:"text",maxLogSize:10485760,logDatePattern:"YYYY-MM-DD",logDirectory:Zt,rotation:{frequency:"daily",maxSize:10485760,maxFiles:5,compress:!1,rotateHour:0,rotateMinute:0,rotateDayOfWeek:0,rotateDayOfMonth:1,encrypt:!1},verbose:!1,writeToFile:!1},X={...st},hr=(async()=>{try{let{loadConfig:e}=await Promise.resolve().then(()=>(ys(),ps)),t=await e({name:"clarity",alias:"logging",defaultConfig:st,cwd:me.cwd()});if(t)Object.assign(X,t)}catch{}return X})(),y={red:(e)=>`\x1B[31m${e}\x1B[0m`,green:(e)=>`\x1B[32m${e}\x1B[0m`,yellow:(e)=>`\x1B[33m${e}\x1B[0m`,blue:(e)=>`\x1B[34m${e}\x1B[0m`,magenta:(e)=>`\x1B[35m${e}\x1B[0m`,cyan:(e)=>`\x1B[36m${e}\x1B[0m`,white:(e)=>`\x1B[37m${e}\x1B[0m`,gray:(e)=>`\x1B[90m${e}\x1B[0m`,bgRed:(e)=>`\x1B[41m${e}\x1B[0m`,bgYellow:(e)=>`\x1B[43m${e}\x1B[0m`,bgGray:(e)=>`\x1B[100m${e}\x1B[0m`,bold:(e)=>`\x1B[1m${e}\x1B[0m`,dim:(e)=>`\x1B[2m${e}\x1B[0m`,italic:(e)=>`\x1B[3m${e}\x1B[0m`,underline:(e)=>`\x1B[4m${e}\x1B[0m`,strikethrough:(e)=>`\x1B[9m${e}\x1B[0m`,reset:"\x1B[0m"},g=y,ur=y.red,Qt=y.green,fr=y.yellow,Ht=y.blue,dr=y.magenta,gr=y.cyan,rt=y.white,mr=y.gray,Vt=y.bgRed,Gt=y.bgYellow,pr=y.bgGray,it=y.bold,yr=y.dim,br=y.italic,wr=y.underline,vr=y.strikethrough,Cr=y.reset,ge={activationLevel:"error",bufferSize:50,flushOnDeactivation:!0,stopBuffering:!1},rs={debug:"\uD83D\uDD0D",info:Ht("\u2139"),success:Qt("\u2713"),warning:Gt(rt(it(" WARN "))),error:Vt(rt(it(" ERROR ")))},$r=new xe("stacks")});Z=I(()=>{E=class extends Error{timestamp;context;constructor(e,t={}){super(e);if(this.name=this.constructor.name,this.timestamp=new Date,this.context=t,Error.captureStackTrace)Error.captureStackTrace(this,this.constructor)}toJSON(){return{name:this.name,code:this.code,message:this.message,timestamp:this.timestamp.toISOString(),context:this.context,stack:this.stack}}toString(){let e=Object.keys(this.context).length>0?` (${Object.entries(this.context).map(([t,s])=>`${t}: ${s}`).join(", ")})`:"";return`${this.name} [${this.code}]: ${this.message}${e}`}},pe=class extends E{code="CONFIG_NOT_FOUND";constructor(e,t,s){let r=s===void 0?[]:Array.isArray(s)?s.filter(Boolean):[s],i="";if(r.length===1)i=` or alias "${r[0]}"`;else if(r.length>1)i=` or aliases ${r.map((n)=>`"${n}"`).join(", ")}`;super(`Configuration "${e}"${i} not found`,{configName:e,alias:s,searchPaths:t,searchPathCount:t.length})}},ee=class extends E{code="CONFIG_LOAD_ERROR";constructor(e,t,s){super(`Failed to load configuration from "${e}": ${t.message}`,{configPath:e,configName:s,originalError:t.name,originalMessage:t.message});this.cause=t}},ot=class extends E{code="CONFIG_VALIDATION_ERROR";constructor(e,t,s){super(`Configuration validation failed for "${e}"`,{configPath:e,configName:s,validationErrors:t,errorCount:t.length})}},ct=class extends E{code="CONFIG_MERGE_ERROR";constructor(e,t,s,r){super(`Failed to merge configuration from "${e}" with "${t}": ${s.message}`,{sourcePath:e,targetPath:t,configName:r,originalError:s.name,originalMessage:s.message});this.cause=s}},ye=class extends E{code="ENV_VAR_ERROR";constructor(e,t,s,r){super(`Failed to parse environment variable "${e}" with value "${t}" as ${s}`,{envKey:e,envValue:t,expectedType:s,configName:r})}},lt=class extends E{code="FILE_SYSTEM_ERROR";constructor(e,t,s){super(`File system ${e} failed for "${t}": ${s.message}`,{operation:e,path:t,originalError:s.name,originalMessage:s.message});this.cause=s}},ht=class extends E{code="TYPE_GENERATION_ERROR";constructor(e,t,s){super(`Failed to generate types from "${e}" to "${t}": ${s.message}`,{configDir:e,outputPath:t,originalError:s.name,originalMessage:s.message});this.cause=s}},te=class extends E{code="SCHEMA_VALIDATION_ERROR";constructor(e,t,s){super(`Schema validation failed${s?` for config "${s}"`:""}`,{schemaPath:e,configName:s,validationErrors:t,errorCount:t.length})}},ut=class extends E{code="BROWSER_CONFIG_ERROR";constructor(e,t,s,r){super(`Failed to fetch configuration from "${e}": ${t} ${s}`,{endpoint:e,status:t,statusText:s,configName:r})}},ft=class extends E{code="PLUGIN_ERROR";constructor(e,t,s){super(`Plugin "${e}" failed during ${t}: ${s.message}`,{pluginName:e,operation:t,originalError:s.name,originalMessage:s.message});this.cause=s}},D={configNotFound(e,t,s){return new pe(e,t,s)},configLoad(e,t,s){return new ee(e,t,s)},configValidation(e,t,s){return new ot(e,t,s)},configMerge(e,t,s,r){return new ct(e,t,s,r)},envVar(e,t,s,r){return new ye(e,t,s,r)},fileSystem(e,t,s){return new lt(e,t,s)},typeGeneration(e,t,s){return new ht(e,t,s)},schemaValidation(e,t,s){return new te(e,t,s)},browserConfig(e,t,s,r){return new ut(e,t,s,r)},plugin(e,t,s){return new ft(e,t,s)}}});as=I(()=>{re(),Z()});yt=I(()=>{hs={replace:"replace",concat:"concat",smart:"smart"}});us=I(()=>{re(),Z(),yt()});ds=I(()=>{re(),Z(),fs=/^https?:\/\//});Jr=I(()=>{kr(),Sr(),re(),Z(),as(),us(),ds(),yt(),x=new xe("bunfig",{showTags:!0}),P=new wt,gs=C(j.cwd(),"config"),ms=C(j.cwd(),"src/generated")});ps={};rr(ps,{withErrorRecovery:()=>is,tryLoadConfig:()=>Br,loadConfigWithResult:()=>Rr,loadConfig:()=>vt,isRetryableError:()=>_r,isConfigNotFoundError:()=>xr,isBunfigError:()=>ns,globalPerformanceMonitor:()=>se,globalCache:()=>K,getEnvOrDefault:()=>Tr,generateConfigTypes:()=>Nr,defaultGeneratedDir:()=>ms,defaultConfigDir:()=>gs,deepMergeWithArrayStrategy:()=>pt,deepMerge:()=>os,createLibraryConfig:()=>jr,config:()=>Dr,bunfigPlugin:()=>Lr,applyEnvVarsToConfig:()=>Y,TypeGenerationError:()=>ht,SchemaValidationError:()=>te,PluginError:()=>ft,PerformanceMonitor:()=>mt,FileSystemError:()=>lt,ErrorFactory:()=>D,EnvVarError:()=>ye,EnvProcessor:()=>_e,ConfigValidator:()=>bt,ConfigValidationError:()=>ot,ConfigNotFoundError:()=>pe,ConfigMergeError:()=>ct,ConfigLoader:()=>wt,ConfigLoadError:()=>ee,ConfigFileLoader:()=>Te,ConfigCache:()=>gt,CacheUtils:()=>ts,BunfigError:()=>E,BrowserConfigError:()=>ut,ArrayMergeStrategies:()=>hs});ys=I(()=>{Jr(),Z(),re(),Z(),Ur(),as(),us(),ds(),yt()});ys();Ae={verbose:!1,driver:"bun",default:"bun",connections:{bun:{driver:"bun",host:"0.0.0.0",port:6001,scheme:"ws",options:{idleTimeout:120,maxPayloadLength:16777216,backpressureLimit:1048576,closeOnBackpressureLimit:!1,sendPings:!0,publishToSelf:!1,perMessageDeflate:!0}},reverb:{driver:"reverb",host:"127.0.0.1",port:8080,scheme:"ws",key:R.env.REVERB_APP_KEY,secret:R.env.REVERB_APP_SECRET,appId:R.env.REVERB_APP_ID,options:{idleTimeout:120,maxPayloadLength:16777216}},pusher:{driver:"pusher",key:R.env.PUSHER_APP_KEY,secret:R.env.PUSHER_APP_SECRET,appId:R.env.PUSHER_APP_ID,cluster:R.env.PUSHER_APP_CLUSTER||"mt1",useTLS:!0},ably:{driver:"ably",key:R.env.ABLY_KEY},log:{driver:"log"},null:{driver:"null"}}};ws=Ae;({RedisClient:Xt}=globalThis.Bun)});var Es={};Ze(Es,{getConfig:()=>bs,defaultConfig:()=>Ae,createHelpers:()=>vs,createEvent:()=>es,config:()=>ws,channel:()=>Hr,broadcastToUsers:()=>Qr,broadcastToUser:()=>Zr,broadcast:()=>Kr,WebhookManager:()=>Ue,SecurityManager:()=>Ne,RedisAdapter:()=>Le,RecurringBroadcastJob:()=>U,RateLimiter:()=>Re,PublicChannel:()=>Fe,PrometheusExporter:()=>V,PrivateChannel:()=>qe,PresenceHeartbeatManager:()=>Je,PresenceChannel:()=>xt,PersistenceManager:()=>je,MonitoringManager:()=>Be,MessageValidationManager:()=>De,MessageDeduplicator:()=>ks,LoadManager:()=>Ie,EncryptionManager:()=>Me,Echo:()=>Vr,DelayedBroadcastJob:()=>L,Connector:()=>Et,Client:()=>We,CircuitBreakerManager:()=>$s,CircuitBreakerError:()=>kt,CircuitBreaker:()=>$t,ChannelStateManager:()=>ke,ChannelNamespaceManager:()=>Ee,ChannelManager:()=>Se,ChannelLifecycleManager:()=>Pe,ChannelInstance:()=>St,Broadcaster:()=>ve,BroadcastTo:()=>Ce,BroadcastServer:()=>Ct,BroadcastQueueManager:()=>H,BroadcastJob:()=>N,BroadcastHelpers:()=>ie,BroadcastClient:()=>Gr,Broadcast:()=>$,BatchOperationsManager:()=>we,AuthenticationManager:()=>Oe,AnonymousEvent:()=>$e,AcknowledgmentManager:()=>be});class ${static setServer(e){T=e}static getServer(){return T}static get broadcaster(){if(!T)throw Error("Broadcast server not initialized. Call Broadcast.setServer() first.");return T.broadcaster}static get channels(){if(!T)throw Error("Broadcast server not initialized. Call Broadcast.setServer() first.");return T.channels}static channel(e,t){if(!T)throw Error("Broadcast server not initialized. Call Broadcast.setServer() first.");return T.channels.channel(e,t),$}static async event(e){return $.broadcaster.broadcast(e)}static send(e,t,s){$.broadcaster.send(e,t,s)}static private(e,t,s){let r=e.startsWith("private-")?e:`private-${e}`;$.send(r,t,s)}static presence(e,t,s){let r=e.startsWith("presence-")?e:`presence-${e}`;$.send(r,t,s)}static toUser(e,t,s){$.private(`user.${e}`,t,s)}static toUsers(e,t,s){let r=e.map((i)=>`private-user.${i}`);$.send(r,t,s)}static toOthers(e){return $.broadcaster.toOthers(e)}static getConnectionCount(){if(!T)return 0;return T.getConnectionCount()}static getSubscriberCount(e){if(!T)return 0;return T.getSubscriberCount(e)}}function Kr(e,t,s){if(typeof e==="object"&&"broadcastOn"in e)return $.event(e);if(typeof e==="string"&&t)$.send(e,t,s)}function Zr(e,t,s){$.toUser(e,t,s)}function Qr(e,t,s){$.toUsers(e,t,s)}function Hr(e,t){$.channel(e,t)}class $t{name;state="CLOSED";failures=0;successes=0;totalRequests=0;lastFailureTime=null;lastSuccessTime=null;resetTimer=null;failureTimestamps=[];config;constructor(e,t){this.name=e,this.config={failureThreshold:t?.failureThreshold??5,failureWindow:t?.failureWindow??60000,resetTimeout:t?.resetTimeout??60000,successThreshold:t?.successThreshold??2,timeout:t?.timeout??30000}}async execute(e){if(this.state==="OPEN")throw new kt(`Circuit breaker is OPEN for ${this.name}`);this.totalRequests++;try{let t=await this.executeWithTimeout(e);return this.onSuccess(),t}catch(t){throw this.onFailure(),t}}async executeWithTimeout(e){return Promise.race([e(),new Promise((t,s)=>{setTimeout(()=>{s(Error(`Operation timed out after ${this.config.timeout}ms`))},this.config.timeout)})])}onSuccess(){if(this.failures=0,this.successes++,this.lastSuccessTime=Date.now(),this.state==="HALF_OPEN"){if(this.successes>=this.config.successThreshold)this.close()}}onFailure(){if(this.failures++,this.lastFailureTime=Date.now(),this.failureTimestamps.push(Date.now()),this.cleanOldFailures(),this.failureTimestamps.length>=this.config.failureThreshold)this.open()}cleanOldFailures(){let e=Date.now()-this.config.failureWindow;this.failureTimestamps=this.failureTimestamps.filter((t)=>t>e)}open(){if(this.state="OPEN",this.successes=0,console.warn(`Circuit breaker OPENED for ${this.name}`),this.resetTimer)clearTimeout(this.resetTimer);this.resetTimer=setTimeout(()=>{this.halfOpen()},this.config.resetTimeout)}halfOpen(){this.state="HALF_OPEN",this.successes=0,this.failures=0,this.failureTimestamps=[],console.warn(`Circuit breaker HALF_OPEN for ${this.name}`)}close(){if(this.state="CLOSED",this.failures=0,this.successes=0,this.failureTimestamps=[],this.resetTimer)clearTimeout(this.resetTimer),this.resetTimer=null;console.log(`Circuit breaker CLOSED for ${this.name}`)}reset(){this.close()}getState(){return this.state}isOpen(){return this.state==="OPEN"}getStats(){return this.cleanOldFailures(),{state:this.state,failures:this.failureTimestamps.length,successes:this.successes,totalRequests:this.totalRequests,lastFailureTime:this.lastFailureTime,lastSuccessTime:this.lastSuccessTime}}destroy(){if(this.resetTimer)clearTimeout(this.resetTimer),this.resetTimer=null}}class $s{breakers=new Map;defaultConfig;constructor(e){this.defaultConfig=e}getBreaker(e,t){if(!this.breakers.has(e))this.breakers.set(e,new $t(e,t||this.defaultConfig));return this.breakers.get(e)}async execute(e,t,s){return this.getBreaker(e,s).execute(t)}getStats(){let e={};for(let[t,s]of this.breakers)e[t]=s.getStats();return e}resetAll(){for(let e of this.breakers.values())e.reset()}destroy(){for(let e of this.breakers.values())e.destroy();this.breakers.clear()}}class Et{eventCallbacks=new Map;on(e,t){if(!this.eventCallbacks.has(e))this.eventCallbacks.set(e,new Set);this.eventCallbacks.get(e).add(t)}off(e,t){if(!t)this.eventCallbacks.delete(e);else this.eventCallbacks.get(e)?.delete(t)}emit(e,t){let s=this.eventCallbacks.get(e);if(s)for(let r of s)r(t)}}class We{ws=null;config;channels=new Map;_socketId=null;reconnectAttempts=0;reconnectTimer=null;messageQueue=[];heartbeatTimer=null;pendingAcks=new Map;encryptionKeys=new Map;connector=new Et;constructor(e){if(this.config={broadcaster:e.broadcaster||"bun",host:e.host||"localhost",port:e.port||6001,scheme:e.scheme||"ws",key:e.key||"",cluster:e.cluster||"",encrypted:e.encrypted??!1,auth:e.auth||{},autoConnect:e.autoConnect??!0,reconnect:e.reconnect??e.autoReconnect??!0,autoReconnect:e.autoReconnect??e.reconnect??!0,reconnectDelay:(e.reconnectDelay??e.reconnectInterval)||1000,reconnectInterval:(e.reconnectInterval??e.reconnectDelay)||1000,maxReconnectAttempts:e.maxReconnectAttempts||10,encryption:{enabled:e.encryption?.enabled??!1,keys:e.encryption?.keys||{}},acknowledgments:{enabled:e.acknowledgments?.enabled??!1,timeout:e.acknowledgments?.timeout||5000},batch:{enabled:e.batch?.enabled??!0,maxBatchSize:e.batch?.maxBatchSize||50},heartbeat:{enabled:e.heartbeat?.enabled??!1,interval:e.heartbeat?.interval||30000},offlineQueue:{enabled:e.offlineQueue?.enabled??!0,maxSize:e.offlineQueue?.maxSize||100}},this.config.encryption.enabled&&this.config.encryption.keys)for(let[t,s]of Object.entries(this.config.encryption.keys))this.encryptionKeys.set(t,s);if(this.config.autoConnect)this.connect()}connect(){if(this.ws?.readyState===WebSocket.OPEN)return;let e=`${this.config.scheme}://${this.config.host}:${this.config.port}/ws`;this.ws=new WebSocket(e),this.ws.onopen=()=>{if(this.reconnectAttempts=0,this.connector.emit("connect"),this.config.heartbeat.enabled)this.startHeartbeat();while(this.messageQueue.length>0){let t=this.messageQueue.shift();if(t){if(this.ws?.send(t.message),t.ack&&t.messageId)this.waitForAck(t.messageId)}}},this.ws.onmessage=(t)=>{this.handleMessage(t.data)},this.ws.onclose=()=>{if(this._socketId=null,this.stopHeartbeat(),this.connector.emit("disconnect"),this.config.reconnect&&this.reconnectAttempts<this.config.maxReconnectAttempts){this.reconnectAttempts++;let t=Math.min(this.config.reconnectDelay*2**(this.reconnectAttempts-1),30000);this.reconnectTimer=setTimeout(()=>this.connect(),t)}},this.ws.onerror=(t)=>{this.connector.emit("error",t),console.error("WebSocket error:",t)}}disconnect(){if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;this.stopHeartbeat();for(let e of this.pendingAcks.values())clearTimeout(e.timeout),e.reject(Error("Connection closed"));this.pendingAcks.clear();for(let e of this.channels.values())e.unsubscribe();if(this.ws)this.ws.close(),this.ws=null;this.channels.clear(),this._socketId=null}isConnected(){return this.ws?.readyState===WebSocket.OPEN}socketId(){return this._socketId}channel(e){if(!this.channels.has(e)){let t=new Fe(this,e);this.channels.set(e,t),t.subscribe()}return this.channels.get(e)}private(e){let t=e.startsWith("private-")?e:`private-${e}`;if(!this.channels.has(t)){let s=new qe(this,t);this.channels.set(t,s),s.subscribe()}return this.channels.get(t)}join(e){let t=e.startsWith("presence-")?e:`presence-${e}`;if(!this.channels.has(t)){let s=new xt(this,t);this.channels.set(t,s),s.subscribe()}return this.channels.get(t)}leave(e){let t=this.channels.get(e);if(t)t.unsubscribe(),this.channels.delete(e)}leaveAll(){for(let e of this.channels.values())e.unsubscribe();this.channels.clear()}async batchSubscribe(e,t){if(!this.config.batch?.enabled)throw Error("Batch operations are disabled");if(e.length>(this.config.batch?.maxBatchSize??50))throw Error(`Batch size exceeds maximum: ${e.length} > ${this.config.batch.maxBatchSize}`);return new Promise((s,r)=>{let i=crypto.randomUUID();this.send({event:"batch_subscribe",channels:e,channelData:t,messageId:i});let n=setTimeout(()=>{r(Error("Batch subscribe timeout"))},1e4),a=(c)=>{if(c?.messageId===i)clearTimeout(n),s(c)};this.listen("batch_subscribe_result",a)})}async batchUnsubscribe(e){if(!this.config.batch?.enabled)throw Error("Batch operations are disabled");if(e.length>(this.config.batch?.maxBatchSize??50))throw Error(`Batch size exceeds maximum: ${e.length} > ${this.config.batch.maxBatchSize}`);return new Promise((t,s)=>{let r=crypto.randomUUID();this.send({event:"batch_unsubscribe",channels:e,messageId:r});let i=setTimeout(()=>{s(Error("Batch unsubscribe timeout"))},1e4),n=(a)=>{if(a?.messageId===r)clearTimeout(i),t(a)};this.listen("batch_unsubscribe_result",n)})}getSocketId(){return this._socketId}setEncryptionKey(e,t){this.encryptionKeys.set(e,t)}getEncryptionKey(e){return this.encryptionKeys.get(e)}async sendWithAck(e,t=!1){if(!t||!this.config.acknowledgments.enabled)return this.send(e),Promise.resolve(!0);let s=crypto.randomUUID(),r={...e,messageId:s,ack:!0};return new Promise((i,n)=>{this.send(r),this.waitForAck(s).then(i).catch(n)})}waitForAck(e){return new Promise((t,s)=>{let r=setTimeout(()=>{this.pendingAcks.delete(e),s(Error(`Acknowledgment timeout for message ${e}`))},this.config.acknowledgments.timeout);this.pendingAcks.set(e,{messageId:e,resolve:t,reject:s,timeout:r})})}handleAck(e){let t=this.pendingAcks.get(e);if(t)clearTimeout(t.timeout),t.resolve(!0),this.pendingAcks.delete(e)}startHeartbeat(){if(this.heartbeatTimer)return;this.heartbeatTimer=setInterval(()=>{this.send({event:"heartbeat",timestamp:Date.now()})},this.config.heartbeat.interval)}stopHeartbeat(){if(this.heartbeatTimer)clearInterval(this.heartbeatTimer),this.heartbeatTimer=null}globalCallbacks=new Map;listen(e,t){if(!this.globalCallbacks.has(e))this.globalCallbacks.set(e,new Set);this.globalCallbacks.get(e).add(t)}stopListening(e,t){if(!t)this.globalCallbacks.delete(e);else this.globalCallbacks.get(e)?.delete(t)}send(e){let t=JSON.stringify(e);if(this.ws?.readyState===WebSocket.OPEN)this.ws.send(t);else if(this.config.offlineQueue?.enabled)if(this.messageQueue.length<(this.config.offlineQueue.maxSize??100))this.messageQueue.push({message:t});else console.warn("Message queue is full, dropping message")}handleMessage(e){try{let t=JSON.parse(e);if(t.event==="connection_established"){this._socketId=t.data.socket_id;return}if(t.event==="ack"&&t.messageId){this.handleAck(t.messageId);return}let s=this.globalCallbacks.get(t.event);if(s)for(let r of s)r(t.data);if(t.channel){let r=this.channels.get(t.channel);if(r)r.handleEvent(t.event,t.data)}}catch(t){console.error("Error parsing message:",t)}}}class St{client;name;callbacks=new Map;isSubscribed=!1;constructor(e,t){this.client=e,this.name=t}subscribe(){if(this.isSubscribed)return;this.client.send({event:"subscribe",channel:this.name})}unsubscribe(){if(!this.isSubscribed)return;this.client.send({event:"unsubscribe",channel:this.name}),this.isSubscribed=!1,this.callbacks.clear()}listen(e,t){if(!this.callbacks.has(e))this.callbacks.set(e,new Set);return this.callbacks.get(e).add(t),this}stopListening(e,t){if(!t)this.callbacks.delete(e);else{let s=this.callbacks.get(e);if(s)s.delete(t)}return this}handleEvent(e,t){if(e==="subscription_succeeded")this.isSubscribed=!0;else if(e==="subscription_error")this.isSubscribed=!1;let s=this.callbacks.get(e);if(s)for(let r of s)r(t)}getName(){return this.name}}class ks{config;redis;seenMessages=new Map;cleanupInterval=null;constructor(e,t){if(this.config={enabled:e?.enabled??!0,ttl:e?.ttl??60,maxSize:e?.maxSize??1e4,hashFunction:e?.hashFunction||this.defaultHashFunction},this.redis=t,this.config.enabled&&!t)this.startCleanup()}defaultHashFunction(e,t,s){let r=`${e}:${t}:${JSON.stringify(s)}`;return this.simpleHash(r)}simpleHash(e){let t=0;for(let s=0;s<e.length;s++){let r=e.charCodeAt(s);t=(t<<5)-t+r,t=t&t}return t.toString(36)}async isDuplicate(e,t,s,r){if(!this.config.enabled)return!1;let i=r||this.config.hashFunction(e,t,s);if(this.redis)return this.checkRedis(i);return this.checkMemory(i)}async checkRedis(e){if(!this.redis)return!1;let t=`dedup:${e}`;try{if(await this.redis.client?.exists(t))return!0;return await this.redis.client?.setex(t,this.config.ttl,"1"),!1}catch(s){return console.error("Redis deduplication error:",s),this.checkMemory(e)}}checkMemory(e){let t=Date.now(),s=this.seenMessages.get(e);if(s){if(t-s<this.config.ttl*1000)return!0;this.seenMessages.delete(e)}if(this.seenMessages.set(e,t),this.seenMessages.size>this.config.maxSize){let r=Array.from(this.seenMessages.entries());r.sort((n,a)=>n[1]-a[1]);let i=r.slice(0,r.length-this.config.maxSize);for(let[n]of i)this.seenMessages.delete(n)}return!1}startCleanup(){this.cleanupInterval=setInterval(()=>{this.cleanup()},60000)}cleanup(){let e=Date.now(),t=this.config.ttl*1000;for(let[s,r]of this.seenMessages.entries())if(e-r>t)this.seenMessages.delete(s)}async clear(){if(this.redis)try{let e=await this.redis.client?.keys("dedup:*");if(e&&e.length>0)await this.redis.client?.del(...e)}catch(e){console.error("Error clearing Redis deduplication cache:",e)}this.seenMessages.clear()}getStats(){return{enabled:this.config.enabled,cacheSize:this.seenMessages.size,ttl:this.config.ttl,usingRedis:!!this.redis}}stop(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null}}var T=null,kt,Fe,qe,xt,Vr,Gr;var _t=B(async()=>{Cs();Ve();J();await He();kt=class kt extends Error{constructor(e){super(e);this.name="CircuitBreakerError"}};Fe=class Fe extends St{subscribed(e){return this.listen("subscription_succeeded",e)}error(e){return this.listen("subscription_error",e)}};qe=class qe extends Fe{whisper(e,t){return this.client.send({event:`client-${e}`,channel:this.name,data:t}),this}listenForWhisper(e,t){return this.listen(`client-${e}`,t)}};xt=class xt extends qe{members=new Map;presenceHeartbeatTimer=null;subscribe(){super.subscribe(),this.startPresenceHeartbeat()}unsubscribe(){this.stopPresenceHeartbeat(),super.unsubscribe()}startPresenceHeartbeat(){this.presenceHeartbeatTimer=setInterval(()=>{this.client.send({event:"presence_heartbeat",channel:this.name,timestamp:Date.now()})},30000)}stopPresenceHeartbeat(){if(this.presenceHeartbeatTimer)clearInterval(this.presenceHeartbeatTimer),this.presenceHeartbeatTimer=null}handleEvent(e,t){if(e==="subscription_succeeded"&&t?.presence){for(let[r,i]of Object.entries(t.presence.hash))this.members.set(r,i);let s=this.callbacks.get("here");if(s){let r=Array.from(this.members.values());for(let i of s)i(r)}}else if(e==="member_added"){this.members.set(t.id,t);let s=this.callbacks.get("joining");if(s)for(let r of s)r(t)}else if(e==="member_removed"){this.members.delete(t.id);let s=this.callbacks.get("leaving");if(s)for(let r of s)r(t)}super.handleEvent(e,t)}here(e){return this.listen("here",e)}joining(e){return this.listen("joining",e)}leaving(e){return this.listen("leaving",e)}getMembers(){return Array.from(this.members.values())}getMember(e){return this.members.get(e)||null}};Vr=We,Gr=We});_t();var ne=null;function ze(e){ne=e}function k(){return ne}async function Yr(e){let r=new(await _t().then(() => Es)).BroadcastServer(e);return await r.start(),ze(r),r}async function Xr(){if(ne)await ne.stop(),ne=null}function Ss(e,t,s,r){let i=k();if(!i){console.warn("[realtime] Server not initialized, cannot emit event");return}let n=e;if(r?.presence){if(!e.startsWith("presence-"))n=`presence-${e}`}else if(r?.private){if(!e.startsWith("private-"))n=`private-${e}`}let a=r?.exclude?Array.isArray(r.exclude)?r.exclude[0]:r.exclude:void 0;i.broadcast(n,t,s,a)}function xs(e,t,s,r){Ss(`private-user.${e}`,t,s,{...r,private:!0})}function ei(e,t,s,r){for(let i of e)xs(i,t,s,r)}var ti=["private-","presence-"];function Tt(e){for(let t of ti)if(e.startsWith(t))return e.slice(t.length);return e}class At{channelName;constructor(e){this.channelName=e}async private(e,t){let s=k();if(!s)throw Error("Broadcast server not initialized");await s.broadcast(`private-${Tt(this.channelName)}`,e,t)}async public(e,t){let s=k();if(!s)throw Error("Broadcast server not initialized");await s.broadcast(Tt(this.channelName),e,t)}async presence(e,t){let s=k();if(!s)throw Error("Broadcast server not initialized");await s.broadcast(`presence-${Tt(this.channelName)}`,e,t)}async broadcast(e,t,s="public"){switch(s){case"private":return this.private(e,t);case"presence":return this.presence(e,t);default:return this.public(e,t)}}}function si(e){return new At(e)}import{log as Q}from"@stacksjs/logging";var b=null;function ri(e){if(!e){b=null;return}b={channels:e.channels??[],maxPerChannel:e.maxPerChannel??100,ttlMs:e.ttlMs??300000,state:new Map}}function ii(){return b}function ni(e){if(!b||b.channels.length===0)return!1;for(let t of b.channels){if(t==="*")return!0;if(t===e)return!0;if(t.endsWith(".*")&&e.startsWith(t.slice(0,-1)))return!0}return!1}function Mt(e,t,s){if(!b||!ni(e))return null;let r=b.state.get(e);if(!r)r={messages:[],nextSeq:1},b.state.set(e,r);let i={seq:r.nextSeq++,ts:Date.now(),event:t,data:s};if(r.messages.push(i),r.messages.length>b.maxPerChannel)r.messages.splice(0,r.messages.length-b.maxPerChannel);return i.seq}function ai(e,t){if(!b)return[];let s=b.state.get(e);if(!s)return[];let r=Date.now(),i=b.ttlMs;while(s.messages.length>0&&r-s.messages[0].ts>i)s.messages.shift();if(s.messages.length===0)return[];return s.messages.filter((n)=>n.seq>t)}function oi(){if(!b)return;let e=Date.now(),t=b.ttlMs;for(let s of b.state.values())while(s.messages.length>0&&e-s.messages[0].ts>t)s.messages.shift()}function ci(){let e={};if(!b)return e;for(let[t,s]of b.state)e[t]={count:s.messages.length,firstSeq:s.messages[0]?.seq??null,lastSeq:s.messages[s.messages.length-1]?.seq??null};return e}var ae=null;function li(e){if(!e){ae=null;return}ae={maxPerSocketBytes:e.maxPerSocketBytes??1048576,onSlow:e.onSlow??((t)=>{Q.warn(`[realtime] slow consumer on '${t.channelName}': ${t.backpressure} bytes buffered`)})}}function hi(){return ae}function ui(e,t){if(!ae)return;try{let s=e.channels??e.clients,r=s&&typeof s.get==="function"?s.get(t):null;if(!r||typeof r[Symbol.iterator]!=="function")return;let{maxPerSocketBytes:i,onSlow:n}=ae;for(let a of r){let c=a&&typeof a==="object"&&"ws"in a?a.ws:a,o=c&&typeof c==="object"&&"backpressure"in c?c.backpressure:null;if(typeof o==="number"&&o>i)n({channelName:t,backpressure:o,socket:c})}}catch{}}function fi(e,t){try{if(typeof e.hasSubscribers==="function")return Boolean(e.hasSubscribers(t));if(typeof e.subscriberCount==="function")return e.subscriberCount(t)>0;let s=e.channels??e.clients;if(s&&typeof s.get==="function"){let r=s.get(t),i=(r&&(r.size??r.length))??null;if(typeof i==="number")return i>0}}catch{}return!0}class _s{async connect(){}async disconnect(){}subscribe(e,t){Q.warn("Broadcast.subscribe() is a client-side operation. Use BroadcastClient instead.")}unsubscribe(e){Q.warn("Broadcast.unsubscribe() is a client-side operation. Use BroadcastClient instead.")}broadcast(e,t,s,r="public"){let i=k();if(!i){Q.warn("Broadcast server not initialized");return}let n=e;if(r==="private"&&!e.startsWith("private-"))n=`private-${e}`;else if(r==="presence"&&!e.startsWith("presence-"))n=`presence-${e}`;if(!fi(i,n)){Q.debug(`[Broadcast] Skipping '${t}' on '${n}' \u2014 no subscribers`);return}ui(i,n),Mt(n,t,s);try{i.broadcast(n,t,s)}catch(a){Q.error(`[Broadcast] Failed to broadcast event '${t}' to channel '${n}':`,a)}}isConnected(){return k()!==null}}async function Ts(e,t){let{appPath:s}=await import("@stacksjs/path"),r=awaitPromise.resolve(globalThis.Bun),i;try{i=r.globSync([s("Broadcasts/**/*.ts")],{absolute:!0})}catch(u){throw Error(`Failed to scan broadcast files: ${u instanceof Error?u.message:String(u)}`)}let n=i.find((u)=>u.endsWith(`${e}.ts`));if(!n)throw Error(`Broadcast ${e} not found`);let a;try{a=await import(n)}catch(u){throw Error(`Failed to import broadcast '${e}': ${u instanceof Error?u.message:String(u)}`)}let c=a.default;if(c.handle){await c.handle(t);return}let o=k();if(!o)throw Error("Broadcast server not initialized");let l=c.broadcastOn?.()||c.channel?.()||[],h=c.broadcastAs?.()||c.event?.()||e,f=c.broadcastWith?.()||c.data?.()||t,d={shouldBroadcast:()=>!0,broadcastOn:()=>l,broadcastAs:()=>h,broadcastWith:()=>f};await o.broadcaster.broadcast(d)}async function di(e,t){if(typeof e!=="string"||e.trim().length===0)throw Error("[realtime] broadcast() requires a non-empty event name");await Ts(e,t)}import{log as As}from"@stacksjs/logging";var v=null;function gi(e){if(v?.timer)clearInterval(v.timer),v.timer=null;if(!e){v=null;return}let t=e.intervalMs??30000,s=e.maxMissedPongs??2,r=e.onDead??bi;v={intervalMs:t,maxMissedPongs:s,onDead:r,missed:new WeakMap,timer:null},v.timer=setInterval(()=>{if(!v)return;Ms()},t),v.timer.unref?.()}function mi(){return v}function Ms(){if(!v)return;let e=k();if(!e)return;let t=yi(e);for(let s of t){let r=s,i=v.missed.get(s)??0;if(i>=v.maxMissedPongs){As.warn(`[realtime] socket missed ${i} pongs \u2014 declaring dead`);try{v.onDead(s)}catch(n){As.warn(`[realtime] heartbeat onDead handler threw: ${n instanceof Error?n.message:String(n)}`)}v.missed.delete(s);continue}v.missed.set(s,i+1);try{if(typeof r.ping==="function")r.ping();else if(typeof r.send==="function")r.send("__stacks_ping__")}catch{}}}function pi(e){if(!v)return;v.missed.delete(e)}function yi(e){let t=new Set;try{let s=e.channels??e.clients;if(s&&typeof s.values==="function"){for(let r of s.values())if(r&&typeof r[Symbol.iterator]==="function")for(let i of r){let n=i&&typeof i==="object"&&"ws"in i?i.ws:i;if(n&&typeof n==="object")t.add(n)}}}catch{}return[...t]}function bi(e){let t=e;if(typeof t.close==="function")t.close(1011,"heartbeat timeout")}function wi(e){if(e)ze(e)}async function vi(e,t,s){}var Ke=null;function Ci(e){Ke=e}function $i(){return Ke}async function ki(e,t){if(!k())return new Response("WebSocket server not initialized",{status:500});if(Ke)try{let i=await Ke(e);if(!i.ok)return new Response(i.message??"Unauthorized",{status:i.status??401});if(t.upgrade(e,i.data?{data:i.data}:void 0))return;return new Response("WebSocket upgrade failed",{status:400})}catch(i){return console.error("[realtime] WebSocket authenticator threw:",i),new Response("WebSocket auth error",{status:500})}if(t.upgrade(e))return;return new Response("WebSocket upgrade failed",{status:400})}export{vi as storeWebSocketEvent,Xr as stopServer,Ci as setWsAuthenticator,ze as setServer,ri as setReplayBuffer,gi as setHeartbeatConfig,wi as setBunSocket,li as setBackpressureGuard,Ms as runOneTick,Ts as runBroadcast,ai as replaySince,Mt as recordBroadcast,oi as pruneExpired,pi as markPong,ki as handleWebSocketRequest,$i as getWsAuthenticator,k as getServer,ii as getReplayBuffer,mi as getHeartbeatConfig,bs as getConfig,hi as getBackpressureGuard,ei as emitToUsers,xs as emitToUser,Ss as emit,di as dispatchBroadcast,Ae as defaultConfig,ci as debugSnapshot,Yr as createServer,vs as createHelpers,es as createEvent,si as createChannel,ws as config,Hr as channel,Qr as broadcastToUsers,Zr as broadcastToUser,Kr as broadcast,Ue as WebhookManager,At as StacksChannel,Ne as SecurityManager,Le as RedisAdapter,U as RecurringBroadcastJob,Re as RateLimiter,Fe as PublicChannel,V as PrometheusExporter,qe as PrivateChannel,Je as PresenceHeartbeatManager,xt as PresenceChannel,je as PersistenceManager,Be as MonitoringManager,De as MessageValidationManager,ks as MessageDeduplicator,Ie as LoadManager,_s as LegacyBroadcast,Me as EncryptionManager,Vr as Echo,L as DelayedBroadcastJob,Et as Connector,We as Client,$s as CircuitBreakerManager,kt as CircuitBreakerError,$t as CircuitBreaker,ke as ChannelStateManager,Ee as ChannelNamespaceManager,Se as ChannelManager,Pe as ChannelLifecycleManager,St as ChannelInstance,ve as Broadcaster,Ce as BroadcastTo,Ct as BroadcastServer,H as BroadcastQueueManager,N as BroadcastJob,ie as BroadcastHelpers,Gr as BroadcastClient,$ as Broadcast,we as BatchOperationsManager,Oe as AuthenticationManager,$e as AnonymousEvent,be as AcknowledgmentManager};
|
package/dist/src/broadcast.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import type { ChannelType } from 'ts-broadcasting';
|
|
2
|
+
/**
|
|
3
|
+
* Install (or clear) the backpressure guard. Pass `null` to disable.
|
|
4
|
+
*/
|
|
5
|
+
export declare function setBackpressureGuard(cfg: BackpressureGuardConfig | null): void;
|
|
6
|
+
/**
|
|
7
|
+
* Read the currently-installed guard config (useful for tests).
|
|
8
|
+
*/
|
|
9
|
+
export declare function getBackpressureGuard(): Required<BackpressureGuardConfig> | null;
|
|
2
10
|
/**
|
|
3
11
|
* Run a broadcast from a broadcast file
|
|
4
12
|
*
|
|
@@ -13,6 +21,24 @@ export declare function runBroadcast(name: string, payload?: any): Promise<void>
|
|
|
13
21
|
* await broadcast('OrderCreated', { orderId: 123 })
|
|
14
22
|
*/
|
|
15
23
|
export declare function broadcast(name: string, payload?: any): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Backpressure guard config (stacksjs/stacks#1877 R-2). The default
|
|
26
|
+
* threshold is 1 MiB of buffered-bytes per socket — above this, the
|
|
27
|
+
* configured `onSlow` callback fires once per offending socket per
|
|
28
|
+
* broadcast. Apps install via `setBackpressureGuard({...})`; the
|
|
29
|
+
* default is "no guard" for backwards-compat, so existing callers
|
|
30
|
+
* see no behavior change until they opt in.
|
|
31
|
+
*
|
|
32
|
+
* Why opt-in: the underlying ts-broadcasting `server.broadcast()` is
|
|
33
|
+
* synchronous and we can't inject between message-serialize and
|
|
34
|
+
* socket-write. The best we can do at the Stacks layer is detect
|
|
35
|
+
* slow consumers AROUND the broadcast call and let the app decide
|
|
36
|
+
* what to do (close socket, drop client from channel, scale up).
|
|
37
|
+
*/
|
|
38
|
+
export declare interface BackpressureGuardConfig {
|
|
39
|
+
maxPerSocketBytes?: number
|
|
40
|
+
onSlow?: (info: { channelName: string, backpressure: number, socket: unknown }) => void
|
|
41
|
+
}
|
|
16
42
|
export declare interface BroadcastInstance {
|
|
17
43
|
channel?: () => string | string[]
|
|
18
44
|
broadcastOn?: () => string | string[]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install (or replace) the heartbeat config. Pass `null` to stop
|
|
3
|
+
* the heartbeat loop. Safe to call multiple times — the previous
|
|
4
|
+
* timer is cleared before the new one starts.
|
|
5
|
+
*/
|
|
6
|
+
export declare function setHeartbeatConfig(cfg: HeartbeatConfig | null): void;
|
|
7
|
+
/** Read the current config — useful for tests. */
|
|
8
|
+
export declare function getHeartbeatConfig(): Readonly<HeartbeatState> | null;
|
|
9
|
+
/**
|
|
10
|
+
* Manually fire a single heartbeat tick. Exposed for tests; in
|
|
11
|
+
* production it's invoked by the internal interval.
|
|
12
|
+
*/
|
|
13
|
+
export declare function runOneTick(): void;
|
|
14
|
+
/**
|
|
15
|
+
* Called from the server's pong handler (or message handler when
|
|
16
|
+
* fallback `__stacks_ping__` text frames are in use). Resets the
|
|
17
|
+
* missed-pong counter for the given socket so it doesn't get
|
|
18
|
+
* declared dead.
|
|
19
|
+
*/
|
|
20
|
+
export declare function markPong(socket: object): void;
|
|
21
|
+
export declare interface HeartbeatConfig {
|
|
22
|
+
intervalMs?: number
|
|
23
|
+
maxMissedPongs?: number
|
|
24
|
+
onDead?: (socket: unknown) => void
|
|
25
|
+
}
|
|
26
|
+
declare interface HeartbeatState {
|
|
27
|
+
intervalMs: number
|
|
28
|
+
maxMissedPongs: number
|
|
29
|
+
onDead: (socket: unknown) => void
|
|
30
|
+
missed: WeakMap<object, number>
|
|
31
|
+
timer: ReturnType<typeof setInterval> | null
|
|
32
|
+
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
export type { EmitOptions } from './emit';
|
|
2
2
|
export type { BroadcastInstance } from './broadcast';
|
|
3
|
+
export type { BackpressureGuardConfig } from './broadcast';
|
|
4
|
+
export type { HeartbeatConfig } from './heartbeat';
|
|
5
|
+
export type { BufferedMessage, ReplayBufferConfig } from './replay-buffer';
|
|
6
|
+
export type { WsAuthenticator, WsAuthResult } from './ws';
|
|
3
7
|
/**
|
|
4
8
|
* Stacks Realtime Module
|
|
5
9
|
*
|
|
@@ -16,4 +20,18 @@ export { getServer, setServer, createServer, stopServer } from './server-instanc
|
|
|
16
20
|
export { emit, emitToUser, emitToUsers } from './emit';
|
|
17
21
|
export { channel as createChannel, Channel as StacksChannel } from './channel';
|
|
18
22
|
export { broadcast as dispatchBroadcast, runBroadcast, Broadcast as LegacyBroadcast } from './broadcast';
|
|
23
|
+
// Backpressure guard for slow consumers (stacksjs/stacks#1877 R-2).
|
|
24
|
+
// Opt-in via setBackpressureGuard; default is no-op.
|
|
25
|
+
export { setBackpressureGuard, getBackpressureGuard } from './broadcast';
|
|
26
|
+
// Heartbeat ping/pong for detecting half-closed sockets
|
|
27
|
+
// (stacksjs/stacks#1877 R-5). Opt-in via setHeartbeatConfig.
|
|
28
|
+
export { getHeartbeatConfig, markPong, runOneTick, setHeartbeatConfig } from './heartbeat';
|
|
29
|
+
// At-least-once replay buffer for reconnect (stacksjs/stacks#1877 R-3).
|
|
30
|
+
// Opt-in via setReplayBuffer. Apps wire `replaySince(channel, seq)`
|
|
31
|
+
// into their reconnect handler to re-send missed messages.
|
|
32
|
+
export { debugSnapshot, getReplayBuffer, pruneExpired, recordBroadcast, replaySince, setReplayBuffer } from './replay-buffer';
|
|
19
33
|
export { setBunSocket, handleWebSocketRequest, storeWebSocketEvent } from './ws';
|
|
34
|
+
// WebSocket authenticator wiring (stacksjs/stacks#1877 R-1). Install
|
|
35
|
+
// once at server boot to require a valid token / cookie at the
|
|
36
|
+
// handshake boundary — without it, the upgrade proceeds unauthed.
|
|
37
|
+
export { setWsAuthenticator, getWsAuthenticator } from './ws';
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install (or replace) the replay-buffer config. Pass `null` to disable
|
|
3
|
+
* and drop all buffered state. Safe to call multiple times.
|
|
4
|
+
*/
|
|
5
|
+
export declare function setReplayBuffer(cfg: ReplayBufferConfig | null): void;
|
|
6
|
+
/** Read the current config — useful for tests. */
|
|
7
|
+
export declare function getReplayBuffer(): Readonly<BufferRegistry> | null;
|
|
8
|
+
/**
|
|
9
|
+
* Called by the broadcast wrapper for every outbound message on a
|
|
10
|
+
* matched channel. Records the message and assigns a monotonic seq.
|
|
11
|
+
* Returns the seq for the caller to optionally include in the
|
|
12
|
+
* outbound payload — clients store the latest seq locally and send
|
|
13
|
+
* it back on reconnect via `replaySince`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function recordBroadcast(channel: string, event: string, data: unknown): number | null;
|
|
16
|
+
/**
|
|
17
|
+
* Replay every buffered message on `channel` with `seq > sinceSeq`.
|
|
18
|
+
* Stale entries (older than `ttlMs`) are evicted on the way through
|
|
19
|
+
* so callers don't see them. Returns the array of messages the
|
|
20
|
+
* caller should re-send to the reconnecting client.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* // Inside the reconnect handler:
|
|
25
|
+
* const missed = replaySince('orders', lastSeenSeq)
|
|
26
|
+
* for (const msg of missed) {
|
|
27
|
+
* socket.send(JSON.stringify({ event: msg.event, data: msg.data, seq: msg.seq }))
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function replaySince(channel: string, sinceSeq: number): BufferedMessage[];
|
|
32
|
+
/**
|
|
33
|
+
* Drop expired entries across every tracked channel. Called by apps
|
|
34
|
+
* that want eager memory reclaim — the default lazy-on-read path is
|
|
35
|
+
* adequate for most workloads.
|
|
36
|
+
*/
|
|
37
|
+
export declare function pruneExpired(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Snapshot the buffer state — debugging only. Don't depend on this
|
|
40
|
+
* shape in production code; the internals may change.
|
|
41
|
+
*/
|
|
42
|
+
export declare function debugSnapshot(): Record<string, { count: number, firstSeq: number | null, lastSeq: number | null }>;
|
|
43
|
+
/**
|
|
44
|
+
* Per-channel message replay buffer (stacksjs/stacks#1877 R-3).
|
|
45
|
+
*
|
|
46
|
+
* Background: ts-broadcasting delivers messages at-most-once — a client
|
|
47
|
+
* that drops between two broadcasts loses everything in flight. For
|
|
48
|
+
* channels where the app needs every message (chat, presence, order
|
|
49
|
+
* updates), reconnect-after-network-blip becomes a silent data loss.
|
|
50
|
+
*
|
|
51
|
+
* Fix: opt-in per-channel ring buffer that retains the most-recent N
|
|
52
|
+
* messages with monotonic sequence IDs. On reconnect, the client sends
|
|
53
|
+
* its last-seen seq; the server replays everything stored after that
|
|
54
|
+
* point. Apps install via `setReplayBuffer({ channels, maxPerChannel,
|
|
55
|
+
* ttlMs })`. Buffer is in-process — for cross-instance replay, route
|
|
56
|
+
* through a shared store (Redis Streams, Postgres LISTEN/NOTIFY, etc.).
|
|
57
|
+
*
|
|
58
|
+
* Memory shape: `Map<channel, RingBuffer<BufferedMessage>>`. Bounded by
|
|
59
|
+
* `maxPerChannel` (default 100) so a chatty channel can't OOM the
|
|
60
|
+
* server. Entries past `ttlMs` are evicted lazily on read — apps that
|
|
61
|
+
* want eager eviction can call `pruneExpired()` from their own timer.
|
|
62
|
+
*/
|
|
63
|
+
export declare interface ReplayBufferConfig {
|
|
64
|
+
channels?: string[]
|
|
65
|
+
maxPerChannel?: number
|
|
66
|
+
ttlMs?: number
|
|
67
|
+
}
|
|
68
|
+
export declare interface BufferedMessage {
|
|
69
|
+
seq: number
|
|
70
|
+
ts: number
|
|
71
|
+
event: string
|
|
72
|
+
data: unknown
|
|
73
|
+
}
|
|
74
|
+
declare interface ChannelState {
|
|
75
|
+
messages: BufferedMessage[]
|
|
76
|
+
nextSeq: number
|
|
77
|
+
}
|
|
78
|
+
declare interface BufferRegistry {
|
|
79
|
+
channels: string[]
|
|
80
|
+
maxPerChannel: number
|
|
81
|
+
ttlMs: number
|
|
82
|
+
state: Map<string, ChannelState>
|
|
83
|
+
}
|
package/dist/src/ws.d.ts
CHANGED
|
@@ -11,9 +11,34 @@ export declare function setBunSocket(server: BroadcastServer | null): void;
|
|
|
11
11
|
*/
|
|
12
12
|
export declare function storeWebSocketEvent(_type: 'disconnection' | 'error' | 'success', _socket: string, _details: string): Promise<void>;
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
* Install (or clear) the global WebSocket authenticator. Called once
|
|
15
|
+
* at server boot; pass `null` to disable auth (the unauthed default).
|
|
16
|
+
*/
|
|
17
|
+
export declare function setWsAuthenticator(fn: WsAuthenticator | null): void;
|
|
18
|
+
/** Read the currently-installed authenticator. Useful for tests. */
|
|
19
|
+
export declare function getWsAuthenticator(): WsAuthenticator | null;
|
|
20
|
+
/**
|
|
21
|
+
* Handle WebSocket request upgrade. If an authenticator is installed
|
|
22
|
+
* (see `setWsAuthenticator`), it runs FIRST and a 401 is returned on
|
|
23
|
+
* failure (stacksjs/stacks#1877 R-1). Without an authenticator the
|
|
24
|
+
* upgrade proceeds for backwards-compat — the function still works
|
|
25
|
+
* the same way it did before.
|
|
18
26
|
*/
|
|
19
27
|
export declare function handleWebSocketRequest(req: Request, server: Server<any>): Promise<Response | undefined>;
|
|
28
|
+
/**
|
|
29
|
+
* Optional authenticator invoked at WebSocket handshake time.
|
|
30
|
+
*
|
|
31
|
+
* Apps install one via `setWsAuthenticator(fn)` to require a valid
|
|
32
|
+
* token / cookie / signed query param BEFORE the upgrade goes through
|
|
33
|
+
* (stacksjs/stacks#1877 R-1). Without an authenticator, the upgrade
|
|
34
|
+
* proceeds as before — useful for local-dev / public-broadcast apps,
|
|
35
|
+
* but production apps should always install one.
|
|
36
|
+
*
|
|
37
|
+
* The returned `data` is attached to the upgraded socket as `ws.data`
|
|
38
|
+
* so per-message authorization can read it back without re-parsing
|
|
39
|
+
* the auth token on every frame.
|
|
40
|
+
*/
|
|
41
|
+
export type WsAuthenticator = (req: Request) => Promise<WsAuthResult> | WsAuthResult;
|
|
42
|
+
/** Result returned from a `WsAuthenticator`. */
|
|
43
|
+
export type WsAuthResult = | { ok: true, data?: Record<string, unknown> }
|
|
44
|
+
| { ok: false, status?: number, message?: string }
|