fluxion-ts 0.9.5 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require("node:fs");c=s(c);let l=require("node:path");l=s(l);let u=require("node:cluster");u=s(u);let d=require("node:os");d=s(d);let f=require("node:http");f=s(f);let p=require("node:https");p=s(p);let m=require("chokidar");m=s(m);let h=require("minimatch"),g=require("type-narrow");function _(e=new Date){return`${e.getFullYear()}.${String(e.getMonth()+1).padStart(2,`0`)}.${String(e.getDate()).padStart(2,`0`)} ${String(e.getHours()).padStart(2,`0`)}:${String(e.getMinutes()).padStart(2,`0`)}:${String(e.getSeconds()).padStart(2,`0`)}.${String(e.getMilliseconds()).padStart(3,`0`)}`}const v=JSON.stringify,y=Object.keys,b=process.env.FLUXION_COLORS!==`0`;let x;(function(e){e.reset=b?`\x1B[0m`:``,e.bold=b?`\x1B[1m`:``,e.dim=b?`\x1B[2m`:``,e.italic=b?`\x1B[3m`:``,e.underline=b?`\x1B[4m`:``,e.blink=b?`\x1B[5m`:``,e.inverse=b?`\x1B[7m`:``,e.black=b?`\x1B[30m`:``,e.red=b?`\x1B[31m`:``,e.green=b?`\x1B[32m`:``,e.yellow=b?`\x1B[33m`:``,e.blue=b?`\x1B[34m`:``,e.magenta=b?`\x1B[35m`:``,e.cyan=b?`\x1B[36m`:``,e.white=b?`\x1B[37m`:``,e.brightBlack=b?`\x1B[90m`:``,e.brightRed=b?`\x1B[91m`:``,e.brightGreen=b?`\x1B[92m`:``,e.brightYellow=b?`\x1B[93m`:``,e.brightBlue=b?`\x1B[94m`:``,e.brightMagenta=b?`\x1B[95m`:``,e.brightCyan=b?`\x1B[96m`:``,e.brightWhite=b?`\x1B[97m`:``,e.bgBlack=b?`\x1B[40m`:``,e.bgRed=b?`\x1B[41m`:``,e.bgGreen=b?`\x1B[42m`:``,e.bgYellow=b?`\x1B[43m`:``,e.bgBlue=b?`\x1B[44m`:``,e.bgMagenta=b?`\x1B[45m`:``,e.bgCyan=b?`\x1B[46m`:``,e.bgWhite=b?`\x1B[47m`:``,e.bgBrightBlack=b?`\x1B[100m`:``,e.bgBrightRed=b?`\x1B[101m`:``,e.bgBrightGreen=b?`\x1B[102m`:``,e.bgBrightYellow=b?`\x1B[103m`:``,e.bgBrightBlue=b?`\x1B[104m`:``,e.bgBrightMagenta=b?`\x1B[105m`:``,e.bgBrightCyan=b?`\x1B[106m`:``,e.bgBrightWhite=b?`\x1B[107m`:``,e.purple=b?`\x1B[38;2;225;16;248m`:``,e.orange=b?`\x1B[38;2;248;147;16m`:``,e.darkGreen=b?`\x1B[38;2;22;101;52m`:``,e.claude=b?`\x1B[38;2;217;119;87m`:``,e.deepseek=b?`\x1B[38;2;57;100;254m`:``,e.gpt=b?`\x1B[38;2;41;60;77m`:``})(x||={});const S=e=>{try{return v(e)}catch{return`[unserializable]`}},ee={INFO:`${x.cyan}INFO${x.reset}`,WARN:`${x.orange}WARN${x.reset}`,ERROR:`${x.red}ERROR${x.reset}`,SUCC:`${x.green}SUCC${x.reset}`,DEBUG:`${x.blue}DEBUG${x.reset}`,VERBOSE:`${x.purple}VERBOSE${x.reset}`},C=e=>{let{level:t,timestamp:n,event:r,message:i,...a}=e,o=`${x.darkGreen}[${n}]${x.reset}`,s=ee[t]??t,c=i??r,l=y(a).length>0?`${x.dim}${S(a)}${x.reset}`:``;console.log(`${o} ${s} ${c}${l}`)};function w(e){let t=e.options.logger;return t===void 0||t===`one-line`?C:t===`json-line`?e=>console.log(S(e)):t}function te(e){let t=w(e);return{write(e,n,r={}){let i={...r,timestamp:_(),level:e,event:n};try{t(i)}catch{}},info(e,t){this.write(`INFO`,e,t)},warn(e,t){this.write(`WARN`,e,t)},error(e,t){this.write(`ERROR`,e,t)},succ(e,t){this.write(`SUCC`,e,t)},debug(e,t){this.write(`DEBUG`,e,t)},verbose(e,t){this.write(`VERBOSE`,e,t)}}}function ne(e,t){let n=`[${t}]`;return{write(t,r,i){e.write(t,`${n} ${r}`,i)},info(t,r){e.info(`${n} ${t}`,r)},warn(t,r){e.warn(`${n} ${t}`,r)},error(t,r){e.error(`${n} ${t}`,r)},succ(t,r){e.succ(`${n} ${t}`,r)},debug(t,r){e.debug(`${n} ${t}`,r)},verbose(t,r){e.verbose(`${n} ${t}`,r)}}}const T=typeof Error.isError==`function`?e=>Error.isError(e)?e.message:String(e):e=>e?.message||String(e);function re(e={}){let t=e.restartWhen??{},n=t.healthzTimeout??3e4;return n!==1/0&&(!Number.isFinite(n)||n<1e4)&&$throw(`workerOptions.restartWhen.healthzTimeout must be a finite number >= 10000 (ms) or Infinity`),{maxWorkerCount:e.maxWorkerCount??4,restartWhen:{memoryUsageGreaterThan:t.memoryUsageGreaterThan??1/0,healthzTimeout:n,uptimeGreaterThan:t.uptimeGreaterThan??1/0}}}function E(e,t){if(Buffer.isBuffer(e))return e;if(typeof e==`string`){if(!e.startsWith(`-----BEGIN`)){let n=l.default.isAbsolute(e)?e:l.default.join(t,e);if(c.default.existsSync(n))return c.default.readFileSync(n)}return Buffer.from(e)}$throw(`Certificate content must be a string or Buffer`)}function D(e,t){if(!e)return;(typeof e!=`object`||!e||Array.isArray(e))&&$throw(`FluxionOptions.https must be an object`),typeof e.key!=`string`&&$throw(`FluxionOptions.https.key must be a string`),typeof e.cert!=`string`&&$throw(`FluxionOptions.https.cert must be a string`);let n={key:E(e.key,t),cert:E(e.cert,t)};return e.ca!==void 0&&(Array.isArray(e.ca)?n.ca=e.ca.map(e=>E(e,t)):n.ca=E(e.ca,t)),n}function O(e){(typeof e!=`object`||!e||Array.isArray(e))&&$throw(`FluxionOptions must be an object`);let{dir:t=l.default.isAbsolute(e.dir)?e.dir:l.default.join(process.cwd(),e.dir),host:n,port:r,handlerTimeoutMs:i=5e3,middlewareTimeoutMs:a=3e3,staticResourceTimeoutMs:o=10*6e5,metaPort:s=r+1,moduleDir:u=process.cwd(),workerOptions:d={},maxRequestBytes:f=8e6,reloadDelay:p=500,include:m=[`**/*`],apiInclude:h=[`**/*.ts`],exclude:g=[`**/node_modules/**`,`**/.git/**`,`**/dist/**`,`**/build/**`,`**/.vscode/**`,`**/.idea/**`,`**/*.log`,`**/.DS_Store`,`**/coverage/**`,`**/.nyc_output/**`,`**/*.tmp`,`**/*.temp`],https:_,nativeWatcher:v=!1}=e,y=e.logger??`one-line`;return y!==`one-line`&&y!==`json-line`&&typeof y!=`function`&&$throw(`Invalid logger option, Must be 'one-line', 'json-line' or a custom logger function`),typeof t!=`string`&&$throw(`FluxionOptions.dir must be a string`),typeof u!=`string`&&$throw(`FluxionOptions.moduleDir must be a string`),typeof n!=`string`&&$throw(`FluxionOptions.host must be a string`),(!Number.isSafeInteger(i)||i<=100)&&$throw(`FluxionOptions.handlerTimeoutMs must be an integer greater than 100`),(!Number.isSafeInteger(a)||a<=100)&&$throw(`FluxionOptions.middlewareTimeoutMs must be an integer greater than 100`),(typeof p!=`number`||p<=0||!Number.isSafeInteger(p))&&$throw(`FluxionOptions.reloadDelay must be a positive integer`),p<50&&$throw(`FluxionOptions.reloadDelay must be greater than or equal to 50`),(typeof r!=`number`||!Number.isSafeInteger(r))&&$throw(`FluxionOptions.port must be a positive integer`),(r<=1||r>65535)&&$throw(`FluxionOptions.port must be 1 ~ 65535`),(typeof s!=`number`||!Number.isSafeInteger(s))&&$throw(`FluxionOptions.metaPort must be a positive integer`),(s<=1||s>65535)&&$throw(`FluxionOptions.metaPort must be 1 ~ 65535`),s===r&&$throw(`FluxionOptions.metaPort must be different from FluxionOptions.port`),(typeof d!=`object`||!d||Array.isArray(d))&&$throw(`FluxionOptions.workerOptions must be an object`),(typeof f!=`number`||f<=0||!Number.isSafeInteger(f))&&$throw(`FluxionOptions.maxRequestBytes must be a positive integer`),c.default.existsSync(t)||c.default.mkdirSync(t,{recursive:!0}),{dir:t,host:n,port:r,handlerTimeoutMs:i,middlewareTimeoutMs:a,staticResourceTimeoutMs:o,reloadDelay:p,metaPort:s,moduleDir:u,workerOptions:re(d),maxRequestBytes:f,logger:y,include:m,apiInclude:h,exclude:g,nativeWatcher:v,https:D(_,u)}}const k=e=>[100].includes(e?.type),A=e=>[202,200,201,203].includes(e?.type),j=e=>process.send?.(e),M=(e,t)=>e.send(t),N=Symbol.for(`fluxion.router.StaticHandled`),P=Symbol.for(`fluxion.handlerTimeout`),F=Symbol.for(`fluxion.middlewareTimeout`),ie={".css":`text/css; charset=utf-8`,".html":`text/html; charset=utf-8`,".ico":`image/x-icon`,".js":`text/javascript; charset=utf-8`,".json":`application/json; charset=utf-8`,".map":`application/json; charset=utf-8`,".png":`image/png`,".jpg":`image/jpeg`,".jpeg":`image/jpeg`,".svg":`image/svg+xml`,".txt":`text/plain; charset=utf-8`,".webp":`image/webp`},ae=()=>{};function I(e,t,n=200){e.statusCode=n,e.setHeader(`Content-Type`,`application/json; charset=utf-8`),e.end(JSON.stringify(t))}function L(e,t,n=200){if(!e.writableEnded){if(e.headersSent){e.end();return}I(e,t,n)}}function R(e,t){let n=f.default.createServer((e,n)=>{let r=e.method??`GET`,i=`/`;try{i=new URL(e.url??`/`,`http://fluxion.local`).pathname}catch{I(n,{message:`Bad Request: invalid url`},400);return}if(r===`GET`&&i===`/_fluxion/healthz`){I(n,{ok:!0,role:`primary`,pid:process.pid,now:Date.now(),uptimeSeconds:Number(process.uptime().toFixed(3))});return}if(r===`GET`&&i===`/_fluxion/workers`){I(n,{ok:!0,now:Date.now(),workers:t()});return}I(n,{message:`Not Found`},404)});return n.on(`listening`,()=>{e.logger.info(`MetaApiStarted`,{pid:process.pid,host:e.options.host,port:e.options.metaPort,prefix:`/_fluxion`})}),n.on(`error`,t=>{e.logger.error(`MetaApiError`,{host:e.options.host,port:e.options.metaPort,error:T(t)}),process.exit(1)}),n.listen(e.options.metaPort,e.options.host),n}const z=e=>Number((e/1024/1024).toFixed(2)),B=6e4;function V(e){u.default.isPrimary||$throw(`createPrimary should only be called in primary process`);let{workerOptions:t}=e.options,n=t.restartWhen,r=Math.max(1,d.default.cpus().length),i=Math.max(1,Math.min(t.maxWorkerCount??Math.min(2,r),r));e.logger.info(`PrimaryStarted`,{pid:process.pid,workers:i,host:e.options.host,port:e.options.port,metaPort:e.options.metaPort});let a=new Map,o=new Map,s=e=>{let t=Date.now(),n=(o.get(e)??[]).filter(e=>t-e<B);return o.set(e,n),n.length},c=e=>{let t=Date.now(),n=(o.get(e)??[]).filter(e=>t-e<B);n.push(t),o.set(e,n)},l=e=>s(e)>=3;R(e,()=>({primaryPid:process.pid,host:e.options.host,port:e.options.port,metaPort:e.options.metaPort,uptimeSeconds:Number(process.uptime().toFixed(3)),workers:Array.from(a.entries()).map(([e,t])=>{let{instance:n}=t,r=t.lastStats;return{workerId:e,slot:t.slot,pid:t.pid??n.process.pid??null,state:t.state,restartReason:t.restartReason??null,createdAt:t.createdAt,readyAt:t.readyAt??null,connected:n.isConnected(),dead:n.isDead(),exitedAfterDisconnect:n.exitedAfterDisconnect,lastPongAt:t.lastPongAt??null,lastRttMs:t.lastRttMs??null,stats:r===void 0?null:{at:r.at,uptimeSeconds:r.uptimeSeconds,cpu:r.cpu,memory:{...r.memory,rssMb:z(r.memory.rss),heapTotalMb:z(r.memory.heapTotal),heapUsedMb:z(r.memory.heapUsed),externalMb:z(r.memory.external),arrayBuffersMb:z(r.memory.arrayBuffers)}}}})}));let f=(t,n)=>{for(let e of a.values())if(e.state===`restarting`)return;if(l(t.slot)){e.logger.warn(`WorkerRecycleSuppressed`,{slot:t.slot,pid:t.pid,reason:n,windowMs:B,max:3});return}c(t.slot),t.state=`restarting`,t.restartReason=n,e.logger.warn(`WorkerRecycling`,{slot:t.slot,pid:t.pid,reason:n}),t.instance.kill()},p=(e,t)=>{let r=z(t.memory.rss);if(r>n.memoryUsageGreaterThan){f(e,`memoryUsageGreaterThan: rss ${r}MB > ${n.memoryUsageGreaterThan}MB`);return}let i=t.uptimeSeconds*1e3;i>n.uptimeGreaterThan&&f(e,`uptimeGreaterThan: ${Math.round(i/1e3)}s > ${Math.round(n.uptimeGreaterThan/1e3)}s`)},m=e=>{for(let t of a.values()){if(t.state!==`ready`||t.lastPongAt===void 0)continue;let r=e-t.lastPongAt;r>n.healthzTimeout&&f(t,`healthzTimeout: no pong for ${Math.round(r/1e3)}s > ${Math.round(n.healthzTimeout/1e3)}s`)}},h=e=>{g(u.default.fork({WORKER_ID:String(e)}),e)},g=(t,n)=>{let r={state:`creating`,pid:t.process.pid,slot:n,createdAt:Date.now(),instance:t};a.set(t.id,r),t.on(`message`,i=>{if(A(i)){if(i.type===202){let e=Date.now()-i.sentAt;r.pid=i.pid,r.lastPongAt=Date.now(),r.lastRttMs=e;return}if(i.type===201){r.state=`ready`,r.pid=i.pid,r.readyAt=Date.now(),e.logger.info(`WorkerReady`,{workerId:t.id,slot:n,pid:i.pid});return}if(i.type===200){r.state=`created`,r.pid=i.pid,e.logger.info(`WorkerCreated`,{workerId:t.id,slot:n,pid:i.pid});return}i.type===203&&(r.pid=i.pid,r.lastStats=i.stats,r.state===`ready`&&p(r,i.stats))}}),t.on(`exit`,(n,r)=>{let i=a.get(t.id);a.delete(t.id);let o=i?.slot,s=i?.state===`restarting`,u=i?.restartReason??null;if(e.logger.warn(`WorkerExited`,{workerId:t.id,slot:o??null,pid:t.process.pid??`unknown`,code:n,signal:r??`none`,expected:s,reason:u}),o!==void 0){if(s){h(o);return}if(c(o),l(o)){e.logger.error(`WorkerRespawnSuppressed`,{slot:o,windowMs:B,max:3});return}h(o)}})};for(let e=0;e<i;e++)h(e+1);setInterval(()=>{let e=Date.now();for(let t of a.values())if(t.instance.isConnected())try{M(t.instance,{type:100,sentAt:e})}catch{}m(Date.now())},5e3).unref()}function H(e,...t){return new Promise((n,r)=>{try{let i=e(...t);i instanceof Promise?i.then(n).catch(r):n(i)}catch(e){r(e)}})}function U(e){let t=e.headersDistinct[`x-forwarded-for`];if(t){let e=t[0]?.split(`,`)[0]?.trim();if(e&&e.length>0)return e}let n=e.headersDistinct[`x-real-ip`]?.[0].trim();return n===void 0?e.socket.remoteAddress??`unknown`:n}function W(e){if(e===void 0)return!1;let t=e.toLowerCase();return t.startsWith(`text/`)||t.includes(`json`)||t.includes(`xml`)||t.includes(`x-www-form-urlencoded`)||t.includes(`javascript`)}function G(e){if(e!==void 0)try{return new URL(e,`http://fluxion.local`)}catch{return}}function K(e){let t={};for(let[n,r]of e.entries()){let e=t[n];if(e===void 0){t[n]=r;continue}if(Array.isArray(e)){e.push(r);continue}t[n]=[e,r]}return t}function q(e,t){let n=Error(`request body too large: ${e.toString()} bytes exceeds ${t.toString()} bytes`);return n.code=`REQUEST_BODY_TOO_LARGE`,n}function J(e){return Array.isArray(e)?e[0]:e}function Y(){return{exists:!1,bytes:0,truncated:!1}}function oe(e,t,n,r){return t===0?Y():W(n)?{exists:!0,value:e.toString(`utf8`),bytes:t,truncated:r}:{exists:!0,value:`<binary body: ${t} bytes>`,bytes:t,truncated:r}}async function se(e,t,n,r=8192){if(t===`GET`||t===`HEAD`||e.readableEnded)return{rawBody:void 0,preview:Y()};let i=J(e.headers[`content-length`]),a=i===void 0?NaN:Number.parseInt(i,10);if(Number.isFinite(a)&&a>n)throw q(a,n);return new Promise((t,i)=>{let a=[],o=[],s=0,c=0,l=!1,u=!1,d=()=>{e.off(`data`,p),e.off(`end`,m),e.off(`error`,h),e.off(`aborted`,g)},f=e=>{u||(u=!0,e())},p=t=>{let u=Buffer.isBuffer(t)?t:Buffer.from(t);if(s+=u.byteLength,s>n){d(),e.resume(),f(()=>{i(q(s,n))});return}if(a.push(u),c<r){let e=r-c,t=u.subarray(0,e);o.push(t),c+=t.length,t.length<u.length&&(l=!0)}else l=!0},m=()=>{d(),f(()=>{let n=a.length>0?Buffer.concat(a):void 0;t({rawBody:n,preview:oe(o.length>0?Buffer.concat(o):Buffer.alloc(0),n?.byteLength??0,J(e.headers[`content-type`]),l)})})},h=e=>{d(),f(()=>{i(e)})},g=()=>{d(),f(()=>{i(Error(`request aborted while reading body`))})};e.on(`data`,p),e.once(`end`,m),e.once(`error`,h),e.once(`aborted`,g)})}async function ce(e,t,n){let{rawBody:r,preview:i}=await se(e,t,n);if(r===void 0||r.byteLength===0)return{body:{},preview:i};let a=J(e.headers[`content-type`])?.toLowerCase()??``;if(a.includes(`json`)){let e=r.toString(`utf8`).trim();if(e.length===0)return{body:{},preview:i};try{let t=JSON.parse(e);return typeof t==`object`&&t&&!Array.isArray(t)?{body:t,preview:i}:{body:{value:t},preview:i}}catch{return{body:{raw:e},preview:i}}}return a.includes(`x-www-form-urlencoded`)?{body:K(new URLSearchParams(r.toString(`utf8`))),preview:i}:W(a)?{body:{raw:r.toString(`utf8`)},preview:i}:{body:{},preview:i}}function le(e){if(!e)return{};let t={},n=e.split(`;`);for(let e of n){let[n,...r]=e.split(`=`);if(!n)continue;let i=n.trim(),a=r.join(`=`).trim();t[i]=decodeURIComponent(a)}return t}const X=(e,t,n)=>Promise.race([e,new Promise(e=>setTimeout(()=>e(n),t))]);function ue(e){let t=async(t,n)=>{let r=t.method??`GET`,i=U(t),a=G(t.url);if(a===void 0){L(n,{message:`Bad Request: req.url is undefined`},400);return}let o={method:r,ip:i,url:a,query:K(a.searchParams),body:{},headers:t.headers,cookie:le(t.headers.cookie)},s={exists:!1,bytes:0,truncated:!1};e.logger.info(`Req`,{method:r,ip:i,path:a.pathname});let c=performance.now();n.once(`finish`,()=>{let t={workerId:process.env.WORKER_ID??`[primary]`,method:r,ip:i,path:a.pathname,status:n.statusCode,duration:(performance.now()-c).toFixed(4)};y(o.query).length>0&&(t.query=o.query),s.exists&&(t.body=s.value,t.bodyBytes=s.bytes,t.bodyTruncated=s.truncated),e.logger.info(`Res`,t)});try{if(o.url.pathname.startsWith(`/_fluxion/`)){L(n,{message:`Not Found`},404);return}let r=await ce(t,o.method,e.options.maxRequestBytes);o.body=r.body,s=r.preview;let i=await e.router.getModule(a);if(!i){L(n,{message:`Not Found`},404);return}if(t.method&&i.methods&&!i.methods.includes(t.method)){L(n,{message:`Method Not Allowed`},405);return}let c=i.type===0?i.handlerTimeoutMs??e.options.handlerTimeoutMs:e.options.staticResourceTimeoutMs;if(i.middlewares)for(let r=0;r<i.middlewares.length;r++){if(await X(H(i.middlewares[r],o,t,n),e.options.middlewareTimeoutMs,F)===F){e.logger.warn(`MiddlewareTimeout`,{method:o.method,ip:o.ip}),L(n,{message:`Internal Server Error`},500);return}if(n.writableEnded)return;if(n.headersSent){n.end();return}}let l=await X(H(i.handler,o,t,n),c,P);if(l===P){e.logger.warn(`HandlerTimeout`,{method:o.method,ip:o.ip}),L(n,{message:`Handler timed out`},500);return}l!==N&&L(n,l)}catch(t){e.logger.error(`RequestFailed`,{method:o.method,ip:o.ip,path:o.url.pathname,error:T(t)}),t.code===`REQUEST_BODY_TOO_LARGE`?L(n,{message:T(t)},413):L(n,{message:T(t)},500)}},n=e.options.https?p.default.createServer({key:e.options.https.key,cert:e.options.https.cert,ca:e.options.https.ca},t):f.default.createServer(t);return n.on(`close`,()=>{e.logger.info(`ServerClosed`,{host:e.options.host,port:e.options.port})}),n.listen(e.options.port,e.options.host,()=>{e.logger.info(`ServerStarted`,{pid:process.pid,protocol:e.options.https?`https`:`http`,host:e.options.host,port:e.options.port}),e.logger.info(`DynamicDirectory`,{directory:e.options.dir})}),n.on(`error`,t=>{e.logger.error(`ServerError`,{error:T(t)})}),n}const de=()=>{let e=process.cpuUsage(),t=Date.now();setInterval(()=>{let n=Date.now(),r=Math.max(1,(n-t)*1e3),i=process.cpuUsage(e),a=Number(((i.user+i.system)/r*100).toFixed(2));e=process.cpuUsage(),t=n;let o=process.memoryUsage();j({type:203,pid:process.pid,stats:{at:n,pid:process.pid,uptimeSeconds:Number(process.uptime().toFixed(3)),cpu:{userMicros:i.user,systemMicros:i.system,percent:a},memory:{rss:o.rss,heapTotal:o.heapTotal,heapUsed:o.heapUsed,external:o.external,arrayBuffers:o.arrayBuffers}}})},2e3).unref()};function fe(e){u.default.isPrimary&&$throw(`createWorker should only be called in worker process`),process.on(`message`,e=>{if(k(e)&&e.type===100){j({type:202,pid:process.pid,sentAt:e.sentAt,receivedAt:Date.now()});return}}),j({type:200,pid:process.pid}),de();try{ue(e),j({type:201,pid:process.pid})}catch(t){e.logger.error(`WorkerBootstrapFailed`,{pid:process.pid,error:T(t)}),process.exit(1)}}var Z=class{cx;timer=null;filesChanged=new Map;constructor(e){this.cx=e}async init(){let e=this.cx.options.dir;if(!c.default.existsSync(e))return this.cx.logger.warn(`Directory does not exist: ${e}`),this;let t=[],n=(e,r)=>{let i=c.default.readdirSync(e,{withFileTypes:!0});for(let a=0;a<i.length;a++){let o=i[a],s=l.default.join(e,o.name),c=l.default.join(r,o.name);if(o.isDirectory())n(s,c);else if(o.isFile()){let e=this.cx.router.register(s,c).catch(e=>{this.cx.logger.error(`Error registering file ${c}: ${e.message}`)});t.push(e)}}};return n(e,``),await Promise.all(t),this.cx.logger.info(`Initial registration complete for directory: ${e}`),this}queueUp(e,t){this.filesChanged.set(e,t),!this.timer&&(this.timer=setTimeout(async()=>{let e=[...this.filesChanged].map(([e,t])=>this.cx.router.register(e,t).catch(e=>this.cx.logger.error(`Error refreshing handlers: ${e.message}`)).finally(()=>this.filesChanged.delete(e)));await Promise.all(e),this.timer=null},this.cx.options.reloadDelay))}stopCore(){this.timer&&=(clearTimeout(this.timer),null),this.filesChanged.clear()}},pe=class extends Z{watcher=null;constructor(e){super(e)}async start(){this.stop(),await this.init();let e=this.cx.options.dir;return this.watcher=m.default.watch(e,{persistent:!0,ignoreInitial:!0,usePolling:!1,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}}).on(`all`,(t,n)=>{n&&this.queueUp(n,l.default.relative(e,n))}).on(`error`,e=>{let t=e instanceof Error?e:Error(String(e));this.cx.logger.error(`Watcher error: ${t.message}`),this.cx.logger.error(`Restarting watcher...`),this.start()}).on(`ready`,()=>{this.cx.logger.info(`Watcher ready and watching directory: ${e}`)}),this.cx.logger.info(`Watcher started on directory: ${e}`),this}stop(){return this.watcher&&=(this.watcher.close(),null),this.stopCore(),this}},me=class extends Z{watcher=null;constructor(e){super(e)}async start(){this.stop(),await this.init();let e=this.cx.options.dir;return this.watcher=c.default.watch(e,{recursive:!0},(t,n)=>{n&&this.queueUp(l.default.join(e,n),n)}).on(`error`,e=>{this.cx.logger.error(`Watcher error: ${e.message}`),this.cx.logger.error(`Restarting watcher...`),this.start()}),this.cx.logger.info(`Watcher started on directory: ${e}`),this}stop(){return this.watcher&&=(this.watcher.close(),null),this.stopCore(),this}};function Q(e,t){if(typeof t!=`object`||!t)return!1;if((0,g.static_cast)(t),typeof t.handler!=`function`)return e.logger.error(`handler must be a function`),!1;if(t.disposer!==void 0&&typeof t.disposer!=`function`)return e.logger.error(`disposer must be a function if provided`),!1;let n=t.handlerTimeoutMs;return n!==void 0&&(!Number.isSafeInteger(n)||n<100)?(e.logger.error(`handlerTimeoutMs must be an integer >= 100 if provided`),!1):t.type===0?!0:(e.logger.error(`You must use defineFluxionModule to create module`),!1)}function he(e,t){delete require.cache[t];let n=require(t);return Q(e,n)||(Q(e,n.default)?n=n.default:$throw(`Invalid handler module '${t}', make sure it satisfies defineFluxionModule(...) helper`)),n}var ge=class{cx;handlers=new Map;constructor(e){this.cx=e}makeStaticResource(e){return{type:1,handler:async(t,n,r)=>{if(t.method!==`GET`&&t.method!==`HEAD`){r.statusCode=405,r.setHeader(`Allow`,`GET, HEAD`),r.end();return}if(!c.default.existsSync(e)){r.statusCode=404,r.end(`Not Found`);return}let i=c.default.statSync(e);if(!i.isFile()){r.statusCode=404,r.end(`Not Found`);return}let a=ie[l.default.extname(e).toLowerCase()]??`application/octet-stream`;if(r.statusCode=200,r.setHeader(`Content-Type`,a),r.setHeader(`Content-Length`,String(i.size)),t.method===`HEAD`){r.end();return}return new Promise((t,n)=>{let i=c.default.createReadStream(e);i.on(`error`,n),i.on(`end`,()=>t(N)),i.pipe(r)})}}}async register(e,t){let n=this.handlers.get(t)?.disposer;if(n&&await H(n),!c.default.existsSync(e)){this.handlers.delete(t),this.cx.logger.info(`${x.red}Deleted ${x.reset} - ${t}`);return}if(!this.cx.options.include.some(e=>(0,h.minimatch)(t,e))){this.handlers.delete(t),this.cx.logger.info(`${x.yellow}Skipped ${x.reset} - ${t}`);return}if(this.cx.options.exclude.some(e=>(0,h.minimatch)(t,e))){this.handlers.delete(t),this.cx.logger.info(`${x.orange}Excluded${x.reset} - ${t}`);return}if(this.cx.options.apiInclude.some(e=>(0,h.minimatch)(t,e))){let n=he(this.cx,e);this.handlers.set(t,n),this.cx.logger.info(`${x.green}Api ${x.reset} - ${t}`);return}this.handlers.set(t,this.makeStaticResource(t)),this.cx.logger.info(`${x.brightBlue}Static ${x.reset} - ${t}`)}getModule(e){let t=e.pathname.replace(/^[/]+/,``).replace(/[/]+$/,``);return this.handlers.get(t)}remove(e){this.handlers.has(e)&&(this.handlers.delete(e),this.cx.logger.info(`${x.red}Deleted ${x.reset} - ${e}`));let t=e.endsWith(`/`)?e:e+`/`;for(let e of this.handlers.keys())e.startsWith(t)&&(this.handlers.delete(e),this.cx.logger.info(`${x.red}Deleted ${x.reset} - ${e}`))}};async function $(e){let t={options:O(e)};t.logger=te(t),t.router=new ge(t),u.default.isPrimary?V(t):(t.logger=ne(t.logger,process.pid),t.watcher=await new(t.options.nativeWatcher?me:pe)(t).start(),fe(t))}function _e(e,t=ae){return typeof e==`function`?(typeof t!=`function`&&$throw(`Invalid disposer, expected a function but got ${typeof t}`),{handler:e,disposer:t,type:0}):((typeof e!=`object`||!e)&&$throw(`Invalid argument, expected a FluxionModule object or a handler function, but got ${typeof e}`),typeof e.handler!=`function`&&$throw(`Invalid FluxionModule, "handler" must be a function`),e.disposer!==void 0&&typeof e.disposer!=`function`&&$throw(`Invalid FluxionModule, "disposer" must be a function if provided`),e.methods!==void 0&&(!Array.isArray(e.methods)||e.methods.some(e=>typeof e!=`string`))&&$throw(`Invalid FluxionModule, "methods" must be an array of strings if provided`),e.middlewares!==void 0&&(!Array.isArray(e.middlewares)||e.middlewares.some(e=>typeof e!=`function`))&&$throw(`Invalid FluxionModule, "middlewares" must be an array of functions if provided`),{...e,type:0})}exports.defineFluxionModule=_e,exports.fluxion=$;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require("node:fs");c=s(c);let l=require("node:path");l=s(l);let u=require("node:cluster");u=s(u);let d=require("node:os");d=s(d);let f=require("node:http");f=s(f);let p=require("node:https");p=s(p);let m=require("chokidar");m=s(m);let h=require("minimatch"),g=require("type-narrow");function _(e=new Date){return`${e.getFullYear()}.${String(e.getMonth()+1).padStart(2,`0`)}.${String(e.getDate()).padStart(2,`0`)} ${String(e.getHours()).padStart(2,`0`)}:${String(e.getMinutes()).padStart(2,`0`)}:${String(e.getSeconds()).padStart(2,`0`)}.${String(e.getMilliseconds()).padStart(3,`0`)}`}const v=JSON.stringify,y=Object.keys,b=process.env.FLUXION_COLORS!==`0`;let x;(function(e){e.reset=b?`\x1B[0m`:``,e.bold=b?`\x1B[1m`:``,e.dim=b?`\x1B[2m`:``,e.italic=b?`\x1B[3m`:``,e.underline=b?`\x1B[4m`:``,e.blink=b?`\x1B[5m`:``,e.inverse=b?`\x1B[7m`:``,e.black=b?`\x1B[30m`:``,e.red=b?`\x1B[31m`:``,e.green=b?`\x1B[32m`:``,e.yellow=b?`\x1B[33m`:``,e.blue=b?`\x1B[34m`:``,e.magenta=b?`\x1B[35m`:``,e.cyan=b?`\x1B[36m`:``,e.white=b?`\x1B[37m`:``,e.brightBlack=b?`\x1B[90m`:``,e.brightRed=b?`\x1B[91m`:``,e.brightGreen=b?`\x1B[92m`:``,e.brightYellow=b?`\x1B[93m`:``,e.brightBlue=b?`\x1B[94m`:``,e.brightMagenta=b?`\x1B[95m`:``,e.brightCyan=b?`\x1B[96m`:``,e.brightWhite=b?`\x1B[97m`:``,e.bgBlack=b?`\x1B[40m`:``,e.bgRed=b?`\x1B[41m`:``,e.bgGreen=b?`\x1B[42m`:``,e.bgYellow=b?`\x1B[43m`:``,e.bgBlue=b?`\x1B[44m`:``,e.bgMagenta=b?`\x1B[45m`:``,e.bgCyan=b?`\x1B[46m`:``,e.bgWhite=b?`\x1B[47m`:``,e.bgBrightBlack=b?`\x1B[100m`:``,e.bgBrightRed=b?`\x1B[101m`:``,e.bgBrightGreen=b?`\x1B[102m`:``,e.bgBrightYellow=b?`\x1B[103m`:``,e.bgBrightBlue=b?`\x1B[104m`:``,e.bgBrightMagenta=b?`\x1B[105m`:``,e.bgBrightCyan=b?`\x1B[106m`:``,e.bgBrightWhite=b?`\x1B[107m`:``,e.purple=b?`\x1B[38;2;225;16;248m`:``,e.orange=b?`\x1B[38;2;248;147;16m`:``,e.darkGreen=b?`\x1B[38;2;22;101;52m`:``,e.claude=b?`\x1B[38;2;217;119;87m`:``,e.deepseek=b?`\x1B[38;2;57;100;254m`:``,e.gpt=b?`\x1B[38;2;41;60;77m`:``})(x||={});const S=e=>{try{return v(e)}catch{return`[unserializable]`}},ee={INFO:`${x.cyan}INFO${x.reset}`,WARN:`${x.orange}WARN${x.reset}`,ERROR:`${x.red}ERROR${x.reset}`,SUCC:`${x.green}SUCC${x.reset}`,DEBUG:`${x.blue}DEBUG${x.reset}`,VERBOSE:`${x.purple}VERBOSE${x.reset}`},te=e=>{let{level:t,timestamp:n,event:r,message:i,...a}=e,o=`${x.darkGreen}[${n}]${x.reset}`,s=ee[t]??t,c=i??r,l=y(a).length>0?`${x.dim}${S(a)}${x.reset}`:``;console.log(`${o} ${s} ${c}${l}`)};function C(e){let t=e.options.logger;return t===void 0||t===`one-line`?te:t===`json-line`?e=>console.log(S(e)):t}function w(e){let t=C(e);return{write(e,n,r={}){let i={...r,timestamp:_(),level:e,event:n};try{t(i)}catch{}},info(e,t){this.write(`INFO`,e,t)},warn(e,t){this.write(`WARN`,e,t)},error(e,t){this.write(`ERROR`,e,t)},succ(e,t){this.write(`SUCC`,e,t)},debug(e,t){this.write(`DEBUG`,e,t)},verbose(e,t){this.write(`VERBOSE`,e,t)}}}function T(e,t){let n=`[${t}]`;return{write(t,r,i){e.write(t,`${n} ${r}`,i)},info(t,r){e.info(`${n} ${t}`,r)},warn(t,r){e.warn(`${n} ${t}`,r)},error(t,r){e.error(`${n} ${t}`,r)},succ(t,r){e.succ(`${n} ${t}`,r)},debug(t,r){e.debug(`${n} ${t}`,r)},verbose(t,r){e.verbose(`${n} ${t}`,r)}}}const E=typeof Error.isError==`function`?e=>Error.isError(e)?e.message:String(e):e=>e?.message||String(e);function D(e={}){let t=e.restartWhen??{},n=t.healthzTimeout??3e4;if(n!==1/0&&(!Number.isFinite(n)||n<1e4))throw Error(`[fluxion error] workerOptions.restartWhen.healthzTimeout must be a finite number >= 10000 (ms) or Infinity`);return{maxWorkerCount:e.maxWorkerCount??4,restartWhen:{memoryUsageGreaterThan:t.memoryUsageGreaterThan??1/0,healthzTimeout:n,uptimeGreaterThan:t.uptimeGreaterThan??1/0}}}function O(e,t){if(Buffer.isBuffer(e))return e;if(typeof e==`string`){if(!e.startsWith(`-----BEGIN`)){let n=l.default.isAbsolute(e)?e:l.default.join(t,e);if(c.default.existsSync(n))return c.default.readFileSync(n)}return Buffer.from(e)}throw Error(`[fluxion error] Certificate content must be a string or Buffer`)}function ne(e,t){if(!e)return;if(typeof e!=`object`||!e||Array.isArray(e))throw Error(`[fluxion error] FluxionOptions.https must be an object`);if(typeof e.key!=`string`)throw Error(`[fluxion error] FluxionOptions.https.key must be a string`);if(typeof e.cert!=`string`)throw Error(`[fluxion error] FluxionOptions.https.cert must be a string`);let n={key:O(e.key,t),cert:O(e.cert,t)};return e.ca!==void 0&&(Array.isArray(e.ca)?n.ca=e.ca.map(e=>O(e,t)):n.ca=O(e.ca,t)),n}function re(e){if(typeof e!=`object`||!e||Array.isArray(e))throw Error(`[fluxion error] FluxionOptions must be an object`);let{dir:t=l.default.isAbsolute(e.dir)?e.dir:l.default.join(process.cwd(),e.dir),host:n,port:r,handlerTimeoutMs:i=5e3,middlewareTimeoutMs:a=3e3,staticResourceTimeoutMs:o=10*6e5,metaPort:s=r+1,moduleDir:u=process.cwd(),workerOptions:d={},maxRequestBytes:f=8e6,reloadDelay:p=500,include:m=[`**/*`],apiInclude:h=[`**/*.ts`],exclude:g=[`**/node_modules/**`,`**/.git/**`,`**/dist/**`,`**/build/**`,`**/.vscode/**`,`**/.idea/**`,`**/*.log`,`**/.DS_Store`,`**/coverage/**`,`**/.nyc_output/**`,`**/*.tmp`,`**/*.temp`],https:_,nativeWatcher:v=!1}=e,y=e.logger??`one-line`;if(y!==`one-line`&&y!==`json-line`&&typeof y!=`function`)throw Error(`[fluxion error] Invalid logger option, Must be 'one-line', 'json-line' or a custom logger function`);if(typeof t!=`string`)throw Error(`[fluxion error] FluxionOptions.dir must be a string`);if(typeof u!=`string`)throw Error(`[fluxion error] FluxionOptions.moduleDir must be a string`);if(typeof n!=`string`)throw Error(`[fluxion error] FluxionOptions.host must be a string`);if(!Number.isSafeInteger(i)||i<=100)throw Error(`[fluxion error] FluxionOptions.handlerTimeoutMs must be an integer greater than 100`);if(!Number.isSafeInteger(a)||a<=100)throw Error(`[fluxion error] FluxionOptions.middlewareTimeoutMs must be an integer greater than 100`);if(typeof p!=`number`||p<=0||!Number.isSafeInteger(p))throw Error(`[fluxion error] FluxionOptions.reloadDelay must be a positive integer`);if(p<50)throw Error(`[fluxion error] FluxionOptions.reloadDelay must be greater than or equal to 50`);if(typeof r!=`number`||!Number.isSafeInteger(r))throw Error(`[fluxion error] FluxionOptions.port must be a positive integer`);if(r<=1||r>65535)throw Error(`[fluxion error] FluxionOptions.port must be 1 ~ 65535`);if(typeof s!=`number`||!Number.isSafeInteger(s))throw Error(`[fluxion error] FluxionOptions.metaPort must be a positive integer`);if(s<=1||s>65535)throw Error(`[fluxion error] FluxionOptions.metaPort must be 1 ~ 65535`);if(s===r)throw Error(`[fluxion error] FluxionOptions.metaPort must be different from FluxionOptions.port`);if(typeof d!=`object`||!d||Array.isArray(d))throw Error(`[fluxion error] FluxionOptions.workerOptions must be an object`);if(typeof f!=`number`||f<=0||!Number.isSafeInteger(f))throw Error(`[fluxion error] FluxionOptions.maxRequestBytes must be a positive integer`);return c.default.existsSync(t)||c.default.mkdirSync(t,{recursive:!0}),{dir:t,host:n,port:r,handlerTimeoutMs:i,middlewareTimeoutMs:a,staticResourceTimeoutMs:o,reloadDelay:p,metaPort:s,moduleDir:u,workerOptions:D(d),maxRequestBytes:f,logger:y,include:m,apiInclude:h,exclude:g,nativeWatcher:v,https:ne(_,u)}}const k=e=>[100].includes(e?.type),A=e=>[202,200,201,203].includes(e?.type),j=e=>process.send?.(e),ie=(e,t)=>e.send(t),M=Symbol.for(`fluxion.router.StaticHandled`),N=Symbol.for(`fluxion.handlerTimeout`),P=Symbol.for(`fluxion.middlewareTimeout`),ae={".css":`text/css; charset=utf-8`,".html":`text/html; charset=utf-8`,".ico":`image/x-icon`,".js":`text/javascript; charset=utf-8`,".json":`application/json; charset=utf-8`,".map":`application/json; charset=utf-8`,".png":`image/png`,".jpg":`image/jpeg`,".jpeg":`image/jpeg`,".svg":`image/svg+xml`,".txt":`text/plain; charset=utf-8`,".webp":`image/webp`};let oe=function(e){return e[e.Ok=200]=`Ok`,e[e.Created=201]=`Created`,e[e.Accepted=202]=`Accepted`,e[e.NoContent=204]=`NoContent`,e[e.PartialContent=206]=`PartialContent`,e[e.MovedPermanently=301]=`MovedPermanently`,e[e.Found=302]=`Found`,e[e.NotModified=304]=`NotModified`,e[e.TemporaryRedirect=307]=`TemporaryRedirect`,e[e.PermanentRedirect=308]=`PermanentRedirect`,e[e.BadRequest=400]=`BadRequest`,e[e.Unauthorized=401]=`Unauthorized`,e[e.Forbidden=403]=`Forbidden`,e[e.NotFound=404]=`NotFound`,e[e.MethodNotAllowed=405]=`MethodNotAllowed`,e[e.NotAcceptable=406]=`NotAcceptable`,e[e.RequestTimeout=408]=`RequestTimeout`,e[e.Conflict=409]=`Conflict`,e[e.Gone=410]=`Gone`,e[e.PayloadTooLarge=413]=`PayloadTooLarge`,e[e.UnsupportedMediaType=415]=`UnsupportedMediaType`,e[e.UnprocessableEntity=422]=`UnprocessableEntity`,e[e.TooManyRequests=429]=`TooManyRequests`,e[e.InternalServerError=500]=`InternalServerError`,e[e.NotImplemented=501]=`NotImplemented`,e[e.BadGateway=502]=`BadGateway`,e[e.ServiceUnavailable=503]=`ServiceUnavailable`,e[e.GatewayTimeout=504]=`GatewayTimeout`,e}({});const se=()=>{};function F(e,t,n=200){e.statusCode=n,e.setHeader(`Content-Type`,`application/json; charset=utf-8`),e.end(JSON.stringify(t))}function I(e,t,n=200){if(!e.writableEnded){if(e.headersSent){e.end();return}F(e,t,n)}}function ce(e,t){let n=f.default.createServer((e,n)=>{let r=e.method??`GET`,i=`/`;try{i=new URL(e.url??`/`,`http://fluxion.local`).pathname}catch{F(n,{message:`Bad Request: invalid url`},400);return}if(r===`GET`&&i===`/_fluxion/healthz`){F(n,{ok:!0,role:`primary`,pid:process.pid,now:Date.now(),uptimeSeconds:Number(process.uptime().toFixed(3))});return}if(r===`GET`&&i===`/_fluxion/workers`){F(n,{ok:!0,now:Date.now(),workers:t()});return}F(n,{message:`Not Found`},404)});return n.on(`listening`,()=>{e.logger.info(`MetaApiStarted`,{pid:process.pid,host:e.options.host,port:e.options.metaPort,prefix:`/_fluxion`})}),n.on(`error`,t=>{e.logger.error(`MetaApiError`,{host:e.options.host,port:e.options.metaPort,error:E(t)}),process.exit(1)}),n.listen(e.options.metaPort,e.options.host),n}const L=e=>Number((e/1024/1024).toFixed(2)),R=6e4;function z(e){if(!u.default.isPrimary)throw Error(`[fluxion error] createPrimary should only be called in primary process`);let{workerOptions:t}=e.options,n=t.restartWhen,r=Math.max(1,d.default.cpus().length),i=Math.max(1,Math.min(t.maxWorkerCount??Math.min(2,r),r));e.logger.info(`PrimaryStarted`,{pid:process.pid,workers:i,host:e.options.host,port:e.options.port,metaPort:e.options.metaPort});let a=new Map,o=new Map,s=e=>{let t=Date.now(),n=(o.get(e)??[]).filter(e=>t-e<R);return o.set(e,n),n.length},c=e=>{let t=Date.now(),n=(o.get(e)??[]).filter(e=>t-e<R);n.push(t),o.set(e,n)},l=e=>s(e)>=3;ce(e,()=>({primaryPid:process.pid,host:e.options.host,port:e.options.port,metaPort:e.options.metaPort,uptimeSeconds:Number(process.uptime().toFixed(3)),workers:Array.from(a.entries()).map(([e,t])=>{let{instance:n}=t,r=t.lastStats;return{workerId:e,slot:t.slot,pid:t.pid??n.process.pid??null,state:t.state,restartReason:t.restartReason??null,createdAt:t.createdAt,readyAt:t.readyAt??null,connected:n.isConnected(),dead:n.isDead(),exitedAfterDisconnect:n.exitedAfterDisconnect,lastPongAt:t.lastPongAt??null,lastRttMs:t.lastRttMs??null,stats:r===void 0?null:{at:r.at,uptimeSeconds:r.uptimeSeconds,cpu:r.cpu,memory:{...r.memory,rssMb:L(r.memory.rss),heapTotalMb:L(r.memory.heapTotal),heapUsedMb:L(r.memory.heapUsed),externalMb:L(r.memory.external),arrayBuffersMb:L(r.memory.arrayBuffers)}}}})}));let f=(t,n)=>{for(let e of a.values())if(e.state===`restarting`)return;if(l(t.slot)){e.logger.warn(`WorkerRecycleSuppressed`,{slot:t.slot,pid:t.pid,reason:n,windowMs:R,max:3});return}c(t.slot),t.state=`restarting`,t.restartReason=n,e.logger.warn(`WorkerRecycling`,{slot:t.slot,pid:t.pid,reason:n}),t.instance.kill()},p=(e,t)=>{let r=L(t.memory.rss);if(r>n.memoryUsageGreaterThan){f(e,`memoryUsageGreaterThan: rss ${r}MB > ${n.memoryUsageGreaterThan}MB`);return}let i=t.uptimeSeconds*1e3;i>n.uptimeGreaterThan&&f(e,`uptimeGreaterThan: ${Math.round(i/1e3)}s > ${Math.round(n.uptimeGreaterThan/1e3)}s`)},m=e=>{for(let t of a.values()){if(t.state!==`ready`||t.lastPongAt===void 0)continue;let r=e-t.lastPongAt;r>n.healthzTimeout&&f(t,`healthzTimeout: no pong for ${Math.round(r/1e3)}s > ${Math.round(n.healthzTimeout/1e3)}s`)}},h=e=>{g(u.default.fork({WORKER_ID:String(e)}),e)},g=(t,n)=>{let r={state:`creating`,pid:t.process.pid,slot:n,createdAt:Date.now(),instance:t};a.set(t.id,r),t.on(`message`,i=>{if(A(i)){if(i.type===202){let e=Date.now()-i.sentAt;r.pid=i.pid,r.lastPongAt=Date.now(),r.lastRttMs=e;return}if(i.type===201){r.state=`ready`,r.pid=i.pid,r.readyAt=Date.now(),e.logger.info(`WorkerReady`,{workerId:t.id,slot:n,pid:i.pid});return}if(i.type===200){r.state=`created`,r.pid=i.pid,e.logger.info(`WorkerCreated`,{workerId:t.id,slot:n,pid:i.pid});return}i.type===203&&(r.pid=i.pid,r.lastStats=i.stats,r.state===`ready`&&p(r,i.stats))}}),t.on(`exit`,(n,r)=>{let i=a.get(t.id);a.delete(t.id);let o=i?.slot,s=i?.state===`restarting`,u=i?.restartReason??null;if(e.logger.warn(`WorkerExited`,{workerId:t.id,slot:o??null,pid:t.process.pid??`unknown`,code:n,signal:r??`none`,expected:s,reason:u}),o!==void 0){if(s){h(o);return}if(c(o),l(o)){e.logger.error(`WorkerRespawnSuppressed`,{slot:o,windowMs:R,max:3});return}h(o)}})};for(let e=0;e<i;e++)h(e+1);setInterval(()=>{let e=Date.now();for(let t of a.values())if(t.instance.isConnected())try{ie(t.instance,{type:100,sentAt:e})}catch{}m(Date.now())},5e3).unref()}function B(e,...t){return new Promise((n,r)=>{try{let i=e(...t);i instanceof Promise?i.then(n).catch(r):n(i)}catch(e){r(e)}})}function V(e){let t=e.headersDistinct[`x-forwarded-for`];if(t){let e=t[0]?.split(`,`)[0]?.trim();if(e&&e.length>0)return e}let n=e.headersDistinct[`x-real-ip`]?.[0].trim();return n===void 0?e.socket.remoteAddress??`unknown`:n}function H(e){if(e===void 0)return!1;let t=e.toLowerCase();return t.startsWith(`text/`)||t.includes(`json`)||t.includes(`xml`)||t.includes(`x-www-form-urlencoded`)||t.includes(`javascript`)}function U(e){if(e!==void 0)try{return new URL(e,`http://fluxion.local`)}catch{return}}function W(e){let t={};for(let[n,r]of e.entries()){let e=t[n];if(e===void 0){t[n]=r;continue}if(Array.isArray(e)){e.push(r);continue}t[n]=[e,r]}return t}var G=class extends Error{errno;code;constructor(e,t,n){super(e),this.name=`HttpException`,this.errno=t,this.code=n}},le=class extends G{constructor(e=`Bad Request`){super(e,400,`BAD_REQUEST`)}},ue=class extends G{constructor(e=`Unauthorized`){super(e,401,`UNAUTHORIZED`)}},de=class extends G{constructor(e=`Forbidden`){super(e,403,`FORBIDDEN`)}},fe=class extends G{constructor(e=`Not Found`){super(e,404,`NOT_FOUND`)}},K=class extends G{constructor(e=`Method Not Allowed`){super(e,405,`METHOD_NOT_ALLOWED`)}},pe=class extends G{constructor(e=`Not Acceptable`){super(e,406,`NOT_ACCEPTABLE`)}},me=class extends G{constructor(e=`Request Timeout`){super(e,408,`REQUEST_TIMEOUT`)}},he=class extends G{constructor(e=`Conflict`){super(e,409,`CONFLICT`)}},ge=class extends G{constructor(e=`Gone`){super(e,410,`GONE`)}},q=class extends G{constructor(e=`Payload Too Large`){super(e,413,`PAYLOAD_TOO_LARGE`)}},_e=class extends G{constructor(e=`Unsupported Media Type`){super(e,415,`UNSUPPORTED_MEDIA_TYPE`)}},ve=class extends G{constructor(e=`Unprocessable Entity`){super(e,422,`UNPROCESSABLE_ENTITY`)}},ye=class extends G{constructor(e=`Too Many Requests`){super(e,429,`TOO_MANY_REQUESTS`)}},be=class extends G{constructor(e=`Internal Server Error`){super(e,500,`INTERNAL_SERVER_ERROR`)}},xe=class extends G{constructor(e=`Not Implemented`){super(e,501,`NOT_IMPLEMENTED`)}},Se=class extends G{constructor(e=`Bad Gateway`){super(e,502,`BAD_GATEWAY`)}},Ce=class extends G{constructor(e=`Service Unavailable`){super(e,503,`SERVICE_UNAVAILABLE`)}},we=class extends G{constructor(e=`Gateway Timeout`){super(e,504,`GATEWAY_TIMEOUT`)}};function J(e,t){return new q(`request body too large: ${e.toString()} bytes exceeds ${t.toString()} bytes`)}function Y(e){return Array.isArray(e)?e[0]:e}function X(){return{exists:!1,bytes:0,truncated:!1}}function Te(e,t,n,r){return t===0?X():H(n)?{exists:!0,value:e.toString(`utf8`),bytes:t,truncated:r}:{exists:!0,value:`<binary body: ${t} bytes>`,bytes:t,truncated:r}}async function Ee(e,t,n,r=8192){if(t===`GET`||t===`HEAD`||e.readableEnded)return{rawBody:void 0,preview:X()};let i=Y(e.headers[`content-length`]),a=i===void 0?NaN:Number.parseInt(i,10);if(Number.isFinite(a)&&a>n)throw J(a,n);return new Promise((t,i)=>{let a=[],o=[],s=0,c=0,l=!1,u=!1,d=()=>{e.off(`data`,p),e.off(`end`,m),e.off(`error`,h),e.off(`aborted`,g)},f=e=>{u||(u=!0,e())},p=t=>{let u=Buffer.isBuffer(t)?t:Buffer.from(t);if(s+=u.byteLength,s>n){d(),e.resume(),f(()=>{i(J(s,n))});return}if(a.push(u),c<r){let e=r-c,t=u.subarray(0,e);o.push(t),c+=t.length,t.length<u.length&&(l=!0)}else l=!0},m=()=>{d(),f(()=>{let n=a.length>0?Buffer.concat(a):void 0;t({rawBody:n,preview:Te(o.length>0?Buffer.concat(o):Buffer.alloc(0),n?.byteLength??0,Y(e.headers[`content-type`]),l)})})},h=e=>{d(),f(()=>{i(e)})},g=()=>{d(),f(()=>{i(Error(`request aborted while reading body`))})};e.on(`data`,p),e.once(`end`,m),e.once(`error`,h),e.once(`aborted`,g)})}async function De(e,t,n){let{rawBody:r,preview:i}=await Ee(e,t,n);if(r===void 0||r.byteLength===0)return{body:{},preview:i};let a=Y(e.headers[`content-type`])?.toLowerCase()??``;if(a.includes(`json`)){let e=r.toString(`utf8`).trim();if(e.length===0)return{body:{},preview:i};try{let t=JSON.parse(e);return typeof t==`object`&&t&&!Array.isArray(t)?{body:t,preview:i}:{body:{value:t},preview:i}}catch{return{body:{raw:e},preview:i}}}return a.includes(`x-www-form-urlencoded`)?{body:W(new URLSearchParams(r.toString(`utf8`))),preview:i}:H(a)?{body:{raw:r.toString(`utf8`)},preview:i}:{body:{},preview:i}}function Oe(e){if(!e)return{};let t={},n=e.split(`;`);for(let e of n){let[n,...r]=e.split(`=`);if(!n)continue;let i=n.trim(),a=r.join(`=`).trim();t[i]=decodeURIComponent(a)}return t}const Z=(e,t,n)=>Promise.race([e,new Promise(e=>setTimeout(()=>e(n),t))]);function ke(e){let t=async(t,n)=>{let r=t.method??`GET`,i=V(t),a=U(t.url);if(a===void 0){I(n,{message:`Bad Request: req.url is undefined`},400);return}let o={method:r,ip:i,url:a,query:W(a.searchParams),body:{},headers:t.headers,cookie:Oe(t.headers.cookie)},s={exists:!1,bytes:0,truncated:!1};e.logger.info(`Req`,{method:r,ip:i,path:a.pathname});let c=performance.now();n.once(`finish`,()=>{let t={workerId:process.env.WORKER_ID??`[primary]`,method:r,ip:i,path:a.pathname,status:n.statusCode,duration:(performance.now()-c).toFixed(4)};y(o.query).length>0&&(t.query=o.query),s.exists&&(t.body=s.value,t.bodyBytes=s.bytes,t.bodyTruncated=s.truncated),e.logger.info(`Res`,t)});try{if(o.url.pathname.startsWith(`/_fluxion/`)){I(n,{message:`Not Found`},404);return}let r=await De(t,o.method,e.options.maxRequestBytes);o.body=r.body,s=r.preview;let i=await e.router.getModule(a);if(!i){I(n,{message:`Not Found`},404);return}if(t.method&&i.methods&&!i.methods.includes(t.method)){I(n,{message:`Method Not Allowed`},405);return}let c=i.type===0?i.handlerTimeoutMs??e.options.handlerTimeoutMs:e.options.staticResourceTimeoutMs;if(i.middlewares)for(let r=0;r<i.middlewares.length;r++){if(await Z(B(i.middlewares[r],o,t,n),e.options.middlewareTimeoutMs,P)===P){e.logger.warn(`MiddlewareTimeout`,{method:o.method,ip:o.ip}),I(n,{message:`Internal Server Error`},500);return}if(n.writableEnded)return;if(n.headersSent){n.end();return}}let l=await Z(B(i.handler,o,t,n),c,N);if(l===N){e.logger.warn(`HandlerTimeout`,{method:o.method,ip:o.ip}),I(n,{message:`Handler timed out`},500);return}l!==M&&I(n,l)}catch(t){t instanceof G?(e.logger.error(`RequestFailed`,{method:o.method,ip:o.ip,path:o.url.pathname,error:t.message}),I(n,{message:t.message},t.errno)):(e.logger.error(`RequestFailed`,{method:o.method,ip:o.ip,path:o.url.pathname,error:E(t)}),I(n,{message:E(t)},t.errno??500))}},n=e.options.https?p.default.createServer({key:e.options.https.key,cert:e.options.https.cert,ca:e.options.https.ca},t):f.default.createServer(t);return n.on(`close`,()=>{e.logger.info(`ServerClosed`,{host:e.options.host,port:e.options.port})}),n.listen(e.options.port,e.options.host,()=>{e.logger.info(`ServerStarted`,{pid:process.pid,protocol:e.options.https?`https`:`http`,host:e.options.host,port:e.options.port}),e.logger.info(`DynamicDirectory`,{directory:e.options.dir})}),n.on(`error`,t=>{e.logger.error(`ServerError`,{error:E(t)})}),n}const Ae=()=>{let e=process.cpuUsage(),t=Date.now();setInterval(()=>{let n=Date.now(),r=Math.max(1,(n-t)*1e3),i=process.cpuUsage(e),a=Number(((i.user+i.system)/r*100).toFixed(2));e=process.cpuUsage(),t=n;let o=process.memoryUsage();j({type:203,pid:process.pid,stats:{at:n,pid:process.pid,uptimeSeconds:Number(process.uptime().toFixed(3)),cpu:{userMicros:i.user,systemMicros:i.system,percent:a},memory:{rss:o.rss,heapTotal:o.heapTotal,heapUsed:o.heapUsed,external:o.external,arrayBuffers:o.arrayBuffers}}})},2e3).unref()};function je(e){if(u.default.isPrimary)throw Error(`[fluxion error] createWorker should only be called in worker process`);process.on(`message`,e=>{if(k(e)&&e.type===100){j({type:202,pid:process.pid,sentAt:e.sentAt,receivedAt:Date.now()});return}}),j({type:200,pid:process.pid}),Ae();try{ke(e),j({type:201,pid:process.pid})}catch(t){e.logger.error(`WorkerBootstrapFailed`,{pid:process.pid,error:E(t)}),process.exit(1)}}var Q=class{cx;timer=null;filesChanged=new Map;constructor(e){this.cx=e}async init(){let e=this.cx.options.dir;if(!c.default.existsSync(e))return this.cx.logger.warn(`Directory does not exist: ${e}`),this;let t=[],n=(e,r)=>{let i=c.default.readdirSync(e,{withFileTypes:!0});for(let a=0;a<i.length;a++){let o=i[a],s=l.default.join(e,o.name),c=l.default.join(r,o.name);if(o.isDirectory())n(s,c);else if(o.isFile()){let e=this.cx.router.register(s,c).catch(e=>{this.cx.logger.error(`Error registering file ${c}: ${e.message}`)});t.push(e)}}};return n(e,``),await Promise.all(t),this.cx.logger.info(`Initial registration complete for directory: ${e}`),this}queueUp(e,t){this.filesChanged.set(e,t),!this.timer&&(this.timer=setTimeout(async()=>{let e=[...this.filesChanged].map(([e,t])=>this.cx.router.register(e,t).catch(e=>this.cx.logger.error(`Error refreshing handlers: ${e.message}`)).finally(()=>this.filesChanged.delete(e)));await Promise.all(e),this.timer=null},this.cx.options.reloadDelay))}stopCore(){this.timer&&=(clearTimeout(this.timer),null),this.filesChanged.clear()}},Me=class extends Q{watcher=null;constructor(e){super(e)}async start(){this.stop(),await this.init();let e=this.cx.options.dir;return this.watcher=m.default.watch(e,{persistent:!0,ignoreInitial:!0,usePolling:!1,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}}).on(`all`,(t,n)=>{n&&this.queueUp(n,l.default.relative(e,n))}).on(`error`,e=>{let t=e instanceof Error?e:Error(String(e));this.cx.logger.error(`Watcher error: ${t.message}`),this.cx.logger.error(`Restarting watcher...`),this.start()}).on(`ready`,()=>{this.cx.logger.info(`Watcher ready and watching directory: ${e}`)}),this.cx.logger.info(`Watcher started on directory: ${e}`),this}stop(){return this.watcher&&=(this.watcher.close(),null),this.stopCore(),this}},Ne=class extends Q{watcher=null;constructor(e){super(e)}async start(){this.stop(),await this.init();let e=this.cx.options.dir;return this.watcher=c.default.watch(e,{recursive:!0},(t,n)=>{n&&this.queueUp(l.default.join(e,n),n)}).on(`error`,e=>{this.cx.logger.error(`Watcher error: ${e.message}`),this.cx.logger.error(`Restarting watcher...`),this.start()}),this.cx.logger.info(`Watcher started on directory: ${e}`),this}stop(){return this.watcher&&=(this.watcher.close(),null),this.stopCore(),this}};function $(e,t){if(typeof t!=`object`||!t)return!1;if((0,g.static_cast)(t),typeof t.handler!=`function`)return e.logger.error(`handler must be a function`),!1;if(t.disposer!==void 0&&typeof t.disposer!=`function`)return e.logger.error(`disposer must be a function if provided`),!1;let n=t.handlerTimeoutMs;return n!==void 0&&(!Number.isSafeInteger(n)||n<100)?(e.logger.error(`handlerTimeoutMs must be an integer >= 100 if provided`),!1):t.type===0?!0:(e.logger.error(`You must use defineFluxionModule to create module`),!1)}function Pe(e,t){delete require.cache[t];let n=require(t);if(!$(e,n))if($(e,n.default))n=n.default;else throw Error(`[fluxion error] Invalid handler module '${t}', make sure it satisfies defineFluxionModule(...) helper`);return n}var Fe=class{cx;handlers=new Map;constructor(e){this.cx=e}makeStaticResource(e){return{type:1,handler:async(t,n,r)=>{if(t.method!==`GET`&&t.method!==`HEAD`){r.statusCode=405,r.setHeader(`Allow`,`GET, HEAD`),r.end();return}if(!c.default.existsSync(e)){r.statusCode=404,r.end(`Not Found`);return}let i=c.default.statSync(e);if(!i.isFile()){r.statusCode=404,r.end(`Not Found`);return}let a=ae[l.default.extname(e).toLowerCase()]??`application/octet-stream`;if(r.statusCode=200,r.setHeader(`Content-Type`,a),r.setHeader(`Content-Length`,String(i.size)),t.method===`HEAD`){r.end();return}return new Promise((t,n)=>{let i=c.default.createReadStream(e);i.on(`error`,n),i.on(`end`,()=>t(M)),i.pipe(r)})}}}async register(e,t){let n=this.handlers.get(t)?.disposer;if(n&&await B(n),!c.default.existsSync(e)){this.handlers.delete(t),this.cx.logger.info(`${x.red}Deleted ${x.reset} - ${t}`);return}if(!this.cx.options.include.some(e=>(0,h.minimatch)(t,e))){this.handlers.delete(t),this.cx.logger.info(`${x.yellow}Skipped ${x.reset} - ${t}`);return}if(this.cx.options.exclude.some(e=>(0,h.minimatch)(t,e))){this.handlers.delete(t),this.cx.logger.info(`${x.orange}Excluded${x.reset} - ${t}`);return}if(this.cx.options.apiInclude.some(e=>(0,h.minimatch)(t,e))){let n=Pe(this.cx,e);this.handlers.set(t,n),this.cx.logger.info(`${x.green}Api ${x.reset} - ${t}`);return}this.handlers.set(t,this.makeStaticResource(t)),this.cx.logger.info(`${x.brightBlue}Static ${x.reset} - ${t}`)}getModule(e){let t=e.pathname.replace(/^[/]+/,``).replace(/[/]+$/,``);return this.handlers.get(t)}remove(e){this.handlers.has(e)&&(this.handlers.delete(e),this.cx.logger.info(`${x.red}Deleted ${x.reset} - ${e}`));let t=e.endsWith(`/`)?e:e+`/`;for(let e of this.handlers.keys())e.startsWith(t)&&(this.handlers.delete(e),this.cx.logger.info(`${x.red}Deleted ${x.reset} - ${e}`))}};async function Ie(e){let t={options:re(e)};t.logger=w(t),t.router=new Fe(t),u.default.isPrimary?z(t):(t.logger=T(t.logger,process.pid),t.watcher=await new(t.options.nativeWatcher?Ne:Me)(t).start(),je(t))}function Le(e,t=se){if(typeof e==`function`){if(typeof t!=`function`)throw Error(`[fluxion error] Invalid disposer, expected a function but got ${typeof t}`);return{handler:e,disposer:t,type:0}}if(typeof e!=`object`||!e)throw Error(`[fluxion error] Invalid argument, expected a FluxionModule object or a handler function, but got ${typeof e}`);if(typeof e.handler!=`function`)throw Error(`[fluxion error] Invalid FluxionModule, "handler" must be a function`);if(e.disposer!==void 0&&typeof e.disposer!=`function`)throw Error(`[fluxion error] Invalid FluxionModule, "disposer" must be a function if provided`);if(e.methods!==void 0&&(!Array.isArray(e.methods)||e.methods.some(e=>typeof e!=`string`)))throw Error(`[fluxion error] Invalid FluxionModule, "methods" must be an array of strings if provided`);if(e.middlewares!==void 0&&(!Array.isArray(e.middlewares)||e.middlewares.some(e=>typeof e!=`function`)))throw Error(`[fluxion error] Invalid FluxionModule, "middlewares" must be an array of functions if provided`);return{...e,type:0}}function Re(e){if(typeof e!=`function`)throw Error(`[fluxion error] Invalid FluxionMiddleware, expected a function but got ${typeof e}`);return e}exports.BadGatewayException=Se,exports.BadRequestException=le,exports.ConflictException=he,exports.ForbiddenException=de,exports.GatewayTimeoutException=we,exports.GoneException=ge,exports.HttpCode=oe,exports.HttpException=G,exports.InternalServerErrorException=be,exports.MethodNotAllowedException=K,exports.NotAcceptableException=pe,exports.NotFoundException=fe,exports.NotImplementedException=xe,exports.PayloadTooLargeException=q,exports.RequestTimeoutException=me,exports.ServiceUnavailableException=Ce,exports.TooManyRequestsException=ye,exports.UnauthorizedException=ue,exports.UnprocessableEntityException=ve,exports.UnsupportedMediaTypeException=_e,exports.defineFluxionMiddleware=Re,exports.defineFluxionModule=Le,exports.fluxion=Ie;
2
2
  //# sourceMappingURL=index.cjs.map