fnlb 1.1.17 → 1.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -94,7 +94,7 @@ await fnlb.start({
94
94
 
95
95
  ## 🎯 Starting Specific Bots by ID
96
96
 
97
- Run exact bots without filtering by category using the `bots` array. Get bot IDs from [app.fnlb.net/bots](https://app.fnlb.net/bots) select a bot **About this bot** **FNLB ID**.
97
+ Use the `bots` array to include specific bots by ID. Get bot IDs from [app.fnlb.net/bots](https://app.fnlb.net/bots) > select a bot > **About this bot** > **FNLB ID**.
98
98
 
99
99
  ```ts
100
100
  import FNLB from 'fnlb';
@@ -108,9 +108,36 @@ await fnlb.start({
108
108
  });
109
109
  ```
110
110
 
111
- Multiple shards can share the same `bots` list, the gateway distributes IDs across shards with no duplicates. You can combine `bots` and `categories` to narrow selection further.
111
+ ## 🔀 Bot and Category Selection
112
112
 
113
- Omit `categories` (or pass `[]`) to allow bots from any category. When `categories` is set, bots without a category are still included.
113
+ `categories` and `bots` define which bots a shard can pick from. They work as an **include list**.
114
+
115
+ - **Categories only** - bots in those categories, plus unassigned bots.
116
+ - **Bots only** - only the listed bot IDs.
117
+ - **Both** - bots from the listed categories **or** the listed bot IDs (union).
118
+ - **Neither** - your full bot pool.
119
+
120
+ Invalid category or bot IDs are ignored at startup.
121
+
122
+ Multiple shards can share the same `bots` list - the gateway distributes IDs across shards with no duplicates.
123
+
124
+ Example - start bots from two categories **and** two specific bots from elsewhere:
125
+
126
+ ```ts
127
+ import FNLB from 'fnlb';
128
+
129
+ const fnlb = new FNLB();
130
+
131
+ await fnlb.start({
132
+ apiToken: 'your-api-token',
133
+ categories: ['category-id-1', 'category-id-2'],
134
+ bots: ['bot-id-1', 'bot-id-2'],
135
+ numberOfShards: 2,
136
+ botsPerShard: 10
137
+ });
138
+ ```
139
+
140
+ Omit `categories` (or pass `[]`) to allow bots from any category when using `bots` alone. When `categories` is set, bots without a category are still included.
114
141
 
115
142
  ## ⛔ Stopping All Bots
116
143
 
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{fork as R}from"node:child_process";import{resolve as f}from"node:path";import{createHash as p}from"node:crypto";import{mkdir as v,readFile as y,writeFile as D}from"node:fs/promises";import{resolve as b}from"node:path";import{createPublicKey as k,verify as S}from"node:crypto";class m{lockPromise;constructor(){this.lockPromise=void 0}get isLocked(){return!!this.lockPromise}wait(){return this.lockPromise?.promise||Promise.resolve()}lock(){let e,t=new Promise((o)=>{e=o});this.lockPromise={promise:t,resolve:e}}unlock(){this.lockPromise?.resolve(),this.lockPromise=void 0}}class g{static wait(e){return new Promise((t)=>setTimeout(t,e))}}function N(e){return Buffer.from(JSON.stringify({fileName:e.fileName,hash:e.hash,url:e.url,version:e.version}))}function P(e,t){if(!e.signature||!e.signatureKeyId)return"invalid";let o=t[e.signatureKeyId];if(!o)return"invalid";let n=k({key:Buffer.from(o,"base64"),format:"der",type:"spki"}),s=e.fileName??E(e.url);if(!s)return"invalid";return S(null,N({version:e.version,hash:e.hash,fileName:s,url:e.url}),n,Buffer.from(e.signature,"base64"))?"verified":"invalid"}function L(e,t){let o=t.replace(/\/$/,""),n=new URL(e.url),s="/dist/",a=n.pathname.indexOf("/dist/");if(a===-1)throw Error("Invalid release url: missing /dist/ path");let i=n.pathname.slice(a+6);return`${o}/dist/${i}`}function E(e){try{let t=new URL(e).pathname.split("/").pop();return t?decodeURIComponent(t):null}catch{return null}}class c{storageDir;targetFileName;displayName;releaseUrl;releaseProvider;releasePublicKeys;trustedDownloadOrigin;maxDownloadRetries;maxBackoffMs;initialDelayMs;staleMs;log;success;warn;error;isLoaded=!1;lastLoadedTime=0;lock=new m;constructor(e){this.storageDir=e.storageDir,this.targetFileName=e.targetFileName,this.displayName=e.displayName??e.targetFileName,this.releaseUrl=e.releaseUrl,this.releaseProvider=e.releaseProvider,this.releasePublicKeys=e.releasePublicKeys,this.trustedDownloadOrigin=e.trustedDownloadOrigin,this.maxDownloadRetries=e.maxDownloadRetries??1/0,this.maxBackoffMs=e.maxBackoffMs??60000,this.initialDelayMs=e.initialDelayMs??1000,this.staleMs=e.staleMs??0,this.log=e.log,this.success=e.success,this.warn=e.warn,this.error=e.error}async ensureUpToDate(e){await this.lock.wait(),this.lock.lock();try{let t=this.getFilePath(),o=e||!this.isLoaded;if(this.isLoaded&&!e&&this.staleMs>0){let r=Date.now()-this.lastLoadedTime;if(r>=this.staleMs)o=!0,this.log?.(`${this.displayName} is stale (${Math.round(r/1000)}s old), checking for updates...`)}if(!o)return t;let n=await y(t).catch(()=>null),s,a=0,i=this.initialDelayMs;this.log?.(n?"Checking for updates...":`Downloading ${this.displayName}...`);while(a<this.maxDownloadRetries)try{s=await this.fetchReleaseInfo();break}catch(r){let l=Math.min(i*2,this.maxBackoffMs);if(a++,this.error?.("Update error:",r),this.warn?.(`Check for updates attempt ${a} failed: ${r.message}. Retrying in ${l>=60000?`${~~(l/60000)}m`:`${~~(l/1000)}s`}...`),a>=this.maxDownloadRetries)break;await new Promise((h)=>setTimeout(h,i)),i=l}if(!s){if(n)return this.warn?.("Failed to check for updates. Using existing local version."),this.isLoaded=!0,this.lastLoadedTime=Date.now(),this.success?.(`Loaded existing ${this.displayName} version`),t;throw Error("[AutoUpdater] Failed to check for updates and no local file found.")}if(this.validateReleaseInfo(s),n){if(p("sha256").update(n).digest("hex")===s.hash)return this.success?.(`${this.displayName} v${s.version} is up to date`),this.isLoaded=!0,this.lastLoadedTime=Date.now(),this.success?.(`Finished loading ${this.displayName} v${s.version}`),t;this.log?.(`Downloading update for ${this.displayName} v${s.version}`)}a=0,i=this.initialDelayMs;while(a<this.maxDownloadRetries)try{let r=this.resolveDownloadUrl(s),l=await fetch(r);if(!l.ok)throw Error(`Download failed with status ${l.status}`);let h=Buffer.from(await l.arrayBuffer());if(p("sha256").update(h).digest("hex")!==s.hash)throw Error("Downloaded file hash mismatch...");return await v(this.storageDir,{recursive:!0}).catch(()=>{throw Error(`Failed to create the target directory on ${this.storageDir}`)}),await D(t,h),this.isLoaded=!0,this.lastLoadedTime=Date.now(),this.success?.(`Finished loading ${this.displayName} v${s.version}`),t}catch(r){let l=Math.min(i*2,this.maxBackoffMs);a++,this.error?.("Download error:",r),this.warn?.(`Download attempt ${a} failed: ${r.message}. Retrying in ${l>=60000?`${~~(l/60000)}m`:`${~~(l/1000)}s`}...`),await g.wait(i),i=l}if(n)return this.warn?.("Max retries reached. Using existing local version."),this.isLoaded=!0,this.lastLoadedTime=Date.now(),this.success?.(`Loaded existing ${this.displayName} version`),t;throw Error(`[AutoUpdater] Failed to download and verify update after ${a} attempts`)}finally{this.lock.unlock()}}getFilePath(){return b(this.storageDir,this.targetFileName)}async fetchReleaseInfo(){if(this.releaseProvider)return this.releaseProvider();if(!this.releaseUrl)throw Error("No release provider configured");let e=await fetch(this.releaseUrl);if(!e.ok)throw Error(`Status code: ${e.status}`);return await e.json()}validateReleaseInfo(e){if(!this.releasePublicKeys||Object.keys(this.releasePublicKeys).length===0)return;if(P(e,this.releasePublicKeys)!=="verified")throw Error("Invalid release signature");this.log?.(`Verified release signature for v${e.version}`)}resolveDownloadUrl(e){if(!this.trustedDownloadOrigin)return e.url;let t=L(e,this.trustedDownloadOrigin);if(t!==e.url)this.warn?.("Release url mismatch, using trusted origin path");return t}}var w={"fnlb-release-key-2026-06":"MCowBQYDK2VwAyEA2TWIe/P4JlHT4sK1jJn1o52fsCUqUXAfCH1xK71TMuE="};class u{static wait(e){return new Promise((t)=>setTimeout(t,e))}}class d{config;activeProcesses=new Map;packageName=`${process.versions.bun?"zenith-bun":"zenith"}`;fnlbDir;updater;lastChannel;shouldRestart=!0;runId=0;constructor(e){this.config=e,this.fnlbDir=e?.fnlbPath?f(e?.fnlbPath,".fnlb"):f(process.cwd(),".fnlb"),this.setupUpdater(e?.channel??"stable")}setupUpdater(e){this.updater=new c({storageDir:this.fnlbDir,targetFileName:`${this.packageName}.mjs`,displayName:"FNLB",releaseUrl:`https://dist.fnlb.net/packages/${this.packageName}/release?channel=${encodeURIComponent(e)}`,releasePublicKeys:w,trustedDownloadOrigin:"https://cdn.fnlb.net",maxDownloadRetries:this.config?.maxDownloadRetries??1/0,maxBackoffMs:this.config?.maxBackoffMs??60000,staleMs:this.config?.updateIntervalMs??3600000,log:(...t)=>this.log(...t),success:(...t)=>this.success(...t),warn:(...t)=>this.warn(...t),error:(...t)=>this.error(...t)}),this.lastChannel=e}async start(e){await this.stop(),this.shouldRestart=!0,this.runId++;let t=this.runId,o=this.resolveAuthToken(e);if(!o)throw Error("[FNLB ShardingManager] Please provide an auth token.");let n=e.channel??this.config?.channel??"stable";if(n!==this.lastChannel)this.setupUpdater(n),await this.update(!0);else await this.update();let s=e.numberOfShards??1,a=(~~(Math.random()*1e4)).toString(36)+"fnlb"+(~~(Date.now()/1000)).toString(36);for(let i=0;i<s;i++){let r=`${a}-${i.toString().padStart(2,"0")}`,l=await this.startShard(e,r,t,o);this.activeProcesses.set(r,l)}}async stop(){if(this.shouldRestart=!1,this.runId++,this.activeProcesses.size===0)return;this.log("Stopping all active shards...");for(let[e,t]of this.activeProcesses)this.log(`Stopping shard with ID: ${e}`),t.kill();this.activeProcesses.clear(),this.log("All shards stopped.")}async startShard(e,t,o,n){let s=n??this.resolveAuthToken(e);if(!s||s.length<10)throw Error("[FNLB ShardingManager] Please provide a valid auth token.");this.log("Starting shard with ID:",t);let a=R(f(this.fnlbDir,`${this.packageName}.mjs`),[],{env:{...process.env,FORCE_COLOR:"1",SHARD_ID:t,API_TOKEN:s,...e.categories?.length?{CATEGORIES:e.categories.join(",")}:{},...e.bots?.length?{BOTS:e.bots.join(",")}:{},BOTS_PER_SHARD:(e.botsPerShard??1).toString(),HIDE_USERNAMES:e.hideUsernames?"true":"false",HIDE_EMAILS:e.hideEmails?"true":"false",LOG_LEVEL:e.logLevel,CLUSTER_ID:this.config?.clusterName?.trim().replace(/ +(?= )/g,"").toLowerCase().replaceAll(" ","-")??"unknown",CLUSTER_NAME:this.config?.clusterName?.trim(),FNLB_DIR:this.fnlbDir,...e.extraEnv},stdio:["inherit","pipe","pipe","ipc"]});if(!this.config?.disableSubProcessLogs)a.stdout?.on("data",(i)=>{let r=i.toString("utf8");process.stdout.write(r),this.config?.onSubProcessLogMessage?.({timestamp:Date.now(),content:r,format:0})});if(!this.config?.disableSubProcessErrorLogs)a.stderr?.on("data",(i)=>{let r=i.toString("utf8");process.stderr.write(r),this.config?.onSubProcessLogMessage?.({timestamp:Date.now(),content:r,format:4})});return a.on("close",async(i)=>{if(this.activeProcesses.delete(t),this.shouldRestart&&o===this.runId){if(i===0)this.warn("Shard exited with code:",i);else this.error("Shard exited with code:",i?.toString()??"none");this.log("Trying to restart shard..."),await this.update(!0),await u.wait(1e4);let r=await this.startShard(e,t,o,s);this.activeProcesses.set(t,r)}else this.log(`Shard ${t} stopped.`)}),a}async update(e){await this.updater.ensureUpToDate(e)}resolveAuthToken(e){return(e.token??e.apiToken)?.trim()||void 0}log(...e){if(!this.config?.disableLogs)console.log("[FNLB ShardingManager]",...e),this.config?.onLogMessage?.({timestamp:Date.now(),content:e.join(" "),format:0})}success(...e){if(!this.config?.disableLogs)console.log("[FNLB ShardingManager] [OK]",...e),this.config?.onLogMessage?.({timestamp:Date.now(),content:e.join(" "),format:1})}warn(...e){if(!this.config?.disableErrorLogs)console.warn("[FNLB ShardingManager] [WRN]",...e),this.config?.onLogMessage?.({timestamp:Date.now(),content:e.join(" "),format:3})}error(...e){if(!this.config?.disableErrorLogs)console.error("[FNLB ShardingManager] [ERR]",...e),this.config?.onLogMessage?.({timestamp:Date.now(),content:e.join(" "),format:4})}}var $;((o)=>{o.Info="INFO";o.Debug="DEBUG"})($||={});var V=d;export{V as default,$ as LogLevel};
1
+ import{fork as U}from"node:child_process";import{resolve as f}from"node:path";import{createHash as p}from"node:crypto";import{mkdir as D,readFile as y,writeFile as b}from"node:fs/promises";import{resolve as N}from"node:path";import{createPublicKey as S,verify as k}from"node:crypto";class m{lockPromise;constructor(){this.lockPromise=void 0}get isLocked(){return!!this.lockPromise}wait(){return this.lockPromise?.promise||Promise.resolve()}lock(){let e,t=new Promise((o)=>{e=o});this.lockPromise={promise:t,resolve:e}}unlock(){this.lockPromise?.resolve(),this.lockPromise=void 0}}class g{static wait(e){return new Promise((t)=>setTimeout(t,e))}}function L(e){return new TextEncoder().encode(JSON.stringify({fileName:e.fileName,hash:e.hash,url:e.url,version:e.version}))}function P(e){return e.fileName??R(e.url)}function E(e,t){let o=t.replace(/\/$/,""),n=new URL(e.url),s="/dist/",a=n.pathname.indexOf("/dist/");if(a===-1)throw Error("Invalid release url: missing /dist/ path");let r=n.pathname.slice(a+6);return`${o}/dist/${r}`}function R(e){try{let t=new URL(e).pathname.split("/").pop();return t?decodeURIComponent(t):null}catch{return null}}function x(e,t){if(!e.signature||!e.signatureKeyId)return"invalid";let o=t[e.signatureKeyId];if(!o)return"invalid";let n=S({key:Buffer.from(o,"base64"),format:"der",type:"spki"}),s=P(e);if(!s)return"invalid";return k(null,L({version:e.version,hash:e.hash,fileName:s,url:e.url}),n,Buffer.from(e.signature,"base64"))?"verified":"invalid"}class c{storageDir;targetFileName;displayName;releaseUrl;releaseProvider;releasePublicKeys;trustedDownloadOrigin;maxDownloadRetries;maxBackoffMs;initialDelayMs;staleMs;log;success;warn;error;isLoaded=!1;lastLoadedTime=0;lock=new m;constructor(e){this.storageDir=e.storageDir,this.targetFileName=e.targetFileName,this.displayName=e.displayName??e.targetFileName,this.releaseUrl=e.releaseUrl,this.releaseProvider=e.releaseProvider,this.releasePublicKeys=e.releasePublicKeys,this.trustedDownloadOrigin=e.trustedDownloadOrigin,this.maxDownloadRetries=e.maxDownloadRetries??1/0,this.maxBackoffMs=e.maxBackoffMs??60000,this.initialDelayMs=e.initialDelayMs??1000,this.staleMs=e.staleMs??0,this.log=e.log,this.success=e.success,this.warn=e.warn,this.error=e.error}async ensureUpToDate(e){await this.lock.wait(),this.lock.lock();try{let t=this.getFilePath(),o=e||!this.isLoaded;if(this.isLoaded&&!e&&this.staleMs>0){let i=Date.now()-this.lastLoadedTime;if(i>=this.staleMs)o=!0,this.log?.(`${this.displayName} is stale (${Math.round(i/1000)}s old), checking for updates...`)}if(!o)return t;let n=await y(t).catch(()=>null),s,a=0,r=this.initialDelayMs;this.log?.(n?"Checking for updates...":`Downloading ${this.displayName}...`);while(a<this.maxDownloadRetries)try{s=await this.fetchReleaseInfo();break}catch(i){let l=Math.min(r*2,this.maxBackoffMs);if(a++,this.error?.("Update error:",i),this.warn?.(`Check for updates attempt ${a} failed: ${i.message}. Retrying in ${l>=60000?`${~~(l/60000)}m`:`${~~(l/1000)}s`}...`),a>=this.maxDownloadRetries)break;await new Promise((h)=>setTimeout(h,r)),r=l}if(!s){if(n)return this.warn?.("Failed to check for updates. Using existing local version."),this.isLoaded=!0,this.lastLoadedTime=Date.now(),this.success?.(`Loaded existing ${this.displayName} version`),t;throw Error("[AutoUpdater] Failed to check for updates and no local file found.")}if(this.validateReleaseInfo(s),n){if(p("sha256").update(n).digest("hex")===s.hash)return this.success?.(`${this.displayName} v${s.version} is up to date`),this.isLoaded=!0,this.lastLoadedTime=Date.now(),this.success?.(`Finished loading ${this.displayName} v${s.version}`),t;this.log?.(`Downloading update for ${this.displayName} v${s.version}`)}a=0,r=this.initialDelayMs;while(a<this.maxDownloadRetries)try{let i=this.resolveDownloadUrl(s),l=await fetch(i);if(!l.ok)throw Error(`Download failed with status ${l.status}`);let h=Buffer.from(await l.arrayBuffer());if(p("sha256").update(h).digest("hex")!==s.hash)throw Error("Downloaded file hash mismatch...");return await D(this.storageDir,{recursive:!0}).catch(()=>{throw Error(`Failed to create the target directory on ${this.storageDir}`)}),await b(t,h),this.isLoaded=!0,this.lastLoadedTime=Date.now(),this.success?.(`Finished loading ${this.displayName} v${s.version}`),t}catch(i){let l=Math.min(r*2,this.maxBackoffMs);a++,this.error?.("Download error:",i),this.warn?.(`Download attempt ${a} failed: ${i.message}. Retrying in ${l>=60000?`${~~(l/60000)}m`:`${~~(l/1000)}s`}...`),await g.wait(r),r=l}if(n)return this.warn?.("Max retries reached. Using existing local version."),this.isLoaded=!0,this.lastLoadedTime=Date.now(),this.success?.(`Loaded existing ${this.displayName} version`),t;throw Error(`[AutoUpdater] Failed to download and verify update after ${a} attempts`)}finally{this.lock.unlock()}}getFilePath(){return N(this.storageDir,this.targetFileName)}async fetchReleaseInfo(){if(this.releaseProvider)return this.releaseProvider();if(!this.releaseUrl)throw Error("No release provider configured");let e=await fetch(this.releaseUrl);if(!e.ok)throw Error(`Status code: ${e.status}`);return await e.json()}validateReleaseInfo(e){if(!this.releasePublicKeys||Object.keys(this.releasePublicKeys).length===0)return;if(x(e,this.releasePublicKeys)!=="verified")throw Error("Invalid release signature");this.log?.(`Verified release signature for v${e.version}`)}resolveDownloadUrl(e){if(!this.trustedDownloadOrigin)return e.url;let t=E(e,this.trustedDownloadOrigin);if(t!==e.url)this.warn?.("Release url mismatch, using trusted origin path");return t}}var w="https://cdn.fnlb.net",v={"fnlb-release-key-2026-06":"MCowBQYDK2VwAyEA2TWIe/P4JlHT4sK1jJn1o52fsCUqUXAfCH1xK71TMuE="};class u{static wait(e){return new Promise((t)=>setTimeout(t,e))}}class d{config;activeProcesses=new Map;packageName=`${process.versions.bun?"zenith-bun":"zenith"}`;fnlbDir;updater;lastChannel;shouldRestart=!0;runId=0;constructor(e){this.config=e,this.fnlbDir=e?.fnlbPath?f(e?.fnlbPath,".fnlb"):f(process.cwd(),".fnlb"),this.setupUpdater(e?.channel??"stable")}setupUpdater(e){this.updater=new c({storageDir:this.fnlbDir,targetFileName:`${this.packageName}.mjs`,displayName:"FNLB",releaseUrl:`https://dist.fnlb.net/packages/${this.packageName}/release?channel=${encodeURIComponent(e)}`,releasePublicKeys:v,trustedDownloadOrigin:w,maxDownloadRetries:this.config?.maxDownloadRetries??1/0,maxBackoffMs:this.config?.maxBackoffMs??60000,staleMs:this.config?.updateIntervalMs??3600000,log:(...t)=>this.log(...t),success:(...t)=>this.success(...t),warn:(...t)=>this.warn(...t),error:(...t)=>this.error(...t)}),this.lastChannel=e}async start(e){await this.stop(),this.shouldRestart=!0,this.runId++;let t=this.runId,o=this.resolveAuthToken(e);if(!o)throw Error("[FNLB ShardingManager] Please provide an auth token.");let n=e.channel??this.config?.channel??"stable";if(n!==this.lastChannel)this.setupUpdater(n),await this.update(!0);else await this.update();let s=e.numberOfShards??1,a=(~~(Math.random()*1e4)).toString(36)+"fnlb"+(~~(Date.now()/1000)).toString(36);for(let r=0;r<s;r++){let i=`${a}-${r.toString().padStart(2,"0")}`,l=await this.startShard(e,i,t,o);this.activeProcesses.set(i,l)}}async stop(){if(this.shouldRestart=!1,this.runId++,this.activeProcesses.size===0)return;this.log("Stopping all active shards...");for(let[e,t]of this.activeProcesses)this.log(`Stopping shard with ID: ${e}`),t.kill();this.activeProcesses.clear(),this.log("All shards stopped.")}async startShard(e,t,o,n){let s=n??this.resolveAuthToken(e);if(!s||s.length<10)throw Error("[FNLB ShardingManager] Please provide a valid auth token.");this.log("Starting shard with ID:",t);let a=U(f(this.fnlbDir,`${this.packageName}.mjs`),[],{env:{...process.env,FORCE_COLOR:"1",SHARD_ID:t,API_TOKEN:s,...e.categories?.length?{CATEGORIES:e.categories.join(",")}:{},...e.bots?.length?{BOTS:e.bots.join(",")}:{},BOTS_PER_SHARD:(e.botsPerShard??1).toString(),HIDE_USERNAMES:e.hideUsernames?"true":"false",HIDE_EMAILS:e.hideEmails?"true":"false",LOG_LEVEL:e.logLevel,CLUSTER_ID:this.config?.clusterName?.trim().replace(/ +(?= )/g,"").toLowerCase().replaceAll(" ","-")??"unknown",CLUSTER_NAME:this.config?.clusterName?.trim(),FNLB_DIR:this.fnlbDir,...e.extraEnv},stdio:["inherit","pipe","pipe","ipc"]});if(!this.config?.disableSubProcessLogs)a.stdout?.on("data",(r)=>{let i=r.toString("utf8");process.stdout.write(i),this.config?.onSubProcessLogMessage?.({timestamp:Date.now(),content:i,format:0})});if(!this.config?.disableSubProcessErrorLogs)a.stderr?.on("data",(r)=>{let i=r.toString("utf8");process.stderr.write(i),this.config?.onSubProcessLogMessage?.({timestamp:Date.now(),content:i,format:4})});return a.on("close",async(r)=>{if(this.activeProcesses.delete(t),this.shouldRestart&&o===this.runId){if(r===0)this.warn("Shard exited with code:",r);else this.error("Shard exited with code:",r?.toString()??"none");this.log("Trying to restart shard..."),await this.update(!0),await u.wait(1e4);let i=await this.startShard(e,t,o,s);this.activeProcesses.set(t,i)}else this.log(`Shard ${t} stopped.`)}),a}async update(e){await this.updater.ensureUpToDate(e)}resolveAuthToken(e){return(e.token??e.apiToken)?.trim()||void 0}log(...e){if(!this.config?.disableLogs)console.log("[FNLB ShardingManager]",...e),this.config?.onLogMessage?.({timestamp:Date.now(),content:e.join(" "),format:0})}success(...e){if(!this.config?.disableLogs)console.log("[FNLB ShardingManager] [OK]",...e),this.config?.onLogMessage?.({timestamp:Date.now(),content:e.join(" "),format:1})}warn(...e){if(!this.config?.disableErrorLogs)console.warn("[FNLB ShardingManager] [WRN]",...e),this.config?.onLogMessage?.({timestamp:Date.now(),content:e.join(" "),format:3})}error(...e){if(!this.config?.disableErrorLogs)console.error("[FNLB ShardingManager] [ERR]",...e),this.config?.onLogMessage?.({timestamp:Date.now(),content:e.join(" "),format:4})}}var $;((o)=>{o.Info="INFO";o.Debug="DEBUG"})($||={});var q=d;export{q as default,$ as LogLevel};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fnlb",
3
- "version": "1.1.17",
3
+ "version": "1.1.19",
4
4
  "author": "FNLB",
5
5
  "main": "dist/index.js",
6
6
  "homepage": "https://fnlb.net",
@@ -38,6 +38,6 @@
38
38
  "type": "module",
39
39
  "types": "dist/index.d.ts",
40
40
  "dependencies": {
41
- "@fnlb-project/shared": "^1.5.138"
41
+ "@fnlb-project/shared": "^1.5.142"
42
42
  }
43
43
  }