fluxion-ts 0.9.6 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -453,140 +453,48 @@ fluxion({
453
453
 
454
454
  Relative paths are resolved relative to `moduleDir`. PEM content can be passed directly as strings.
455
455
 
456
- ### `dir`
457
-
458
- Dynamic directory root. Created automatically if missing.
459
-
460
- ### `host`
461
-
462
- Host passed to `server.listen`.
463
-
464
- ### `port`
465
-
466
- Business server port.
467
-
468
- ### `metaPort`
469
-
470
- Primary meta API port. Defaults to `port + 1` and must be different from `port`.
471
-
472
- ### `reloadDelay`
473
-
474
- Debounce delay for file re-registration. Defaults to `300` and must be at least `50`.
475
-
476
- ### `nativeWatcher`
477
-
478
- Use native file watcher (`fs.watch`) instead of chokidar. Defaults to `false`.
479
-
480
- When set to `true`, Fluxion uses Node.js built-in `fs.watch()` for file watching. When `false` (default), it uses `chokidar` for better cross-platform compatibility.
481
-
482
- **Trade-offs:**
483
-
484
- - `chokidar` (default): Better cross-platform support, more stable, handles edge cases
485
- - `fs.watch`: Native implementation, lighter weight, but may have platform-specific quirks
486
-
487
- Example:
488
-
489
- ```ts
490
- fluxion({
491
- dir: './dynamicDirectory',
492
- host: '127.0.0.1',
493
- port: 3000,
494
- nativeWatcher: true, // use native fs.watch instead of chokidar
495
- });
496
- ```
497
-
498
- ### `apiExts`
499
-
500
- Extensions registered as API handlers. Defaults to:
501
-
502
- ```ts
503
- ['.ts']
504
- ```
505
-
506
- Example:
507
-
508
- ```ts
509
- fluxion({
510
- dir: './dynamicDirectory',
511
- host: '127.0.0.1',
512
- port: 3000,
513
- apiExts: ['.ts', '.mjs'],
514
- });
515
- ```
456
+ ## Recent Updates
516
457
 
517
- ### `routerExclude`
518
-
519
- Extensions excluded from both API and static registration.
520
-
521
- Example:
458
+ ### v0.11.x
522
459
 
523
- ```ts
524
- routerExclude: ['.map']
525
- ```
460
+ **Middleware & Module System**
526
461
 
527
- ### `maxRequestBytes`
528
-
529
- Maximum accepted request body size. Defaults to `8_000_000`.
530
-
531
- ### `logger`
532
-
533
- Built-in modes:
462
+ - ✨ Added `defineMiddleware()` and `defineFluxionModule()` functions for enhanced type safety
463
+ - ✨ Middleware execution now supports timeout configuration via `MIDDLEWARE_TIMEOUT_FLAG`
464
+ - Module context now includes logger support
465
+ - ✨ Enhanced module type validation with more precise function checking
466
+ - ✨ Added `meta` field for extended metadata support
534
467
 
535
- - `one-line`
536
- - `json-line`
468
+ **Logging Improvements**
537
469
 
538
- A custom logger can be loaded through an injection config object whose module exports a function.
470
+ - 🔄 Unified logging interface: merged `event` and `message` fields into single `message` field
471
+ - ✨ Simplified logger API across all methods
539
472
 
540
- ### `injections`
473
+ **Handler Parameters**
541
474
 
542
- Worker startup injections. Each item is loaded with `require(modulePath)` and called as a factory. The resulting instances are stored on:
475
+ - 🔄 Adjusted handler parameter order for better ergonomics
543
476
 
544
- ```ts
545
- globalThis[Symbol.for('fluxion.injection')]
546
- ```
477
+ ### v0.10.x
547
478
 
548
- ### `workerOptions`
479
+ **HTTP Exception Handling**
549
480
 
550
- Worker pool tuning: how many workers to spawn, and when to proactively recycle one.
481
+ - 🔄 Refactored HTTP exception classes: renamed error types to exception types
482
+ - ✨ Expanded `HttpCode` enum with additional HTTP status codes
483
+ - ✨ Added `BadRequestError` and other HTTP exception classes
484
+ - 📦 Exported exception classes for user applications
485
+ - ✨ Handler catch blocks now directly send response ending
551
486
 
552
- ```ts
553
- interface WorkerOptions {
554
- maxWorkerCount?: number;
555
- restartWhen?: Partial<WorkerRestartWhen>;
556
- }
487
+ **Worker Management**
557
488
 
558
- interface WorkerRestartWhen {
559
- /** Recycle when RSS exceeds this many MB. Infinity (default) = disabled. */
560
- memoryUsageGreaterThan: number;
561
- /** Recycle when no Ping answer within this many ms. Default 30000. */
562
- healthzTimeout: number;
563
- /** Recycle after this many ms of uptime (scheduled rotation). Infinity (default) = disabled. */
564
- uptimeGreaterThan: number;
565
- }
566
- ```
489
+ - Added proactive worker recycling conditions (memory usage, health timeout, uptime)
490
+ - Enhanced worker pool tuning with `restartWhen` options
567
491
 
568
- - `maxWorkerCount` defaults to `4`, clamped to the CPU count (minimum 1).
569
- - `restartWhen` lets the primary proactively recycle an unhealthy worker. The worker is hard-killed and immediately respawned when **any** configured condition is met (OR semantics):
570
- - `memoryUsageGreaterThan` — RSS growth / native leak, caught before the OS OOM-killer. Disabled by default.
571
- - `healthzTimeout` — a wedged event loop (worker stopped answering Ping: infinite loop, deadlock, GC storm). **Defaults to `30000`ms.**
572
- - `uptimeGreaterThan` — scheduled rotation to reclaim slow growth / fragmentation. Disabled by default.
573
- - Conditions are evaluated by the primary against the telemetry it already collects (RSS from stats every ~2s, liveness from Ping every 5s, uptime).
574
- - A shared **anti-storm guard** bounds recycling: a given slot is restarted at most 3 times per rolling 60s, after which further restarts are suppressed and alerted instead of fork-bombing.
575
- - Independently of `restartWhen`, **any worker exit — crash, OOM, or proactive recycle — triggers a respawn**, so the pool stays at `maxWorkerCount`.
492
+ ### v0.9.x
576
493
 
577
- ```ts
578
- fluxion({
579
- // ...
580
- workerOptions: {
581
- maxWorkerCount: 4,
582
- restartWhen: {
583
- memoryUsageGreaterThan: 256, // MB; recycle a leaking worker at 256MB RSS
584
- // healthzTimeout defaults to 30000 — recycle wedged workers after 30s
585
- // uptimeGreaterThan: 6 * 3600_000, // optionally rotate every 6h
586
- },
587
- },
588
- });
589
- ```
494
+ - ✨ Added initial middleware support
495
+ - ✨ Added `defineMiddleware()` for middleware type safety
496
+ - ✨ Enhanced worker restart conditions for better memory management
497
+ - ✨ Restructured build and publish flow with build scripts
590
498
 
591
499
  ## Build and Test
592
500
 
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;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 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 Error(`[fluxion error] Certificate content must be a string or Buffer`)}function D(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: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){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: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){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<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){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}),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);if(!Q(e,n))if(Q(e,n.default))n=n.default;else throw Error(`[fluxion error] Invalid handler module '${t}', make sure it satisfies defineFluxionModule(...) helper`);return 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){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 ve(e){if(typeof e!=`function`)throw Error(`[fluxion error] Invalid FluxionMiddleware, expected a function but got ${typeof e}`);return e}exports.defineFluxionMiddleware=ve,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,message:r,...i}=e,a=`${x.darkGreen}[${n}]${x.reset}`,o=ee[t]??t,s=r,c=y(i).length>0?`${x.dim}${S(i)}${x.reset}`:``;console.log(`${a} ${o} ${s}${c}`)};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 ne(e){let t=C(e);return{write(e,n,r={}){let i={...r,timestamp:_(),level:e,message: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 re(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 w=typeof Error.isError==`function`?e=>Error.isError(e)?e.message:String(e):e=>e?.message||String(e);function ie(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 T(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 ae(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:T(e.key,t),cert:T(e.cert,t)};return e.ca!==void 0&&(Array.isArray(e.ca)?n.ca=e.ca.map(e=>T(e,t)):n.ca=T(e.ca,t)),n}function E(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:ie(d),maxRequestBytes:f,logger:y,include:m,apiInclude:h,exclude:g,nativeWatcher:v,https:ae(_,u)}}const D=e=>[100].includes(e?.type),O=e=>[202,200,201,203].includes(e?.type),k=e=>process.send?.(e),A=(e,t)=>e.send(t),j=Symbol.for(`fluxion.router.StaticHandled`),M=Symbol.for(`fluxion.handlerTimeout`),N=Symbol.for(`fluxion.middlewareTimeout`),oe={".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 se=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}({});function P(e,t,n=200){e.statusCode=n,e.setHeader(`Content-Type`,`application/json; charset=utf-8`),e.end(JSON.stringify(t))}function F(e,t,n=200){if(!e.writableEnded){if(e.headersSent){e.end();return}P(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{P(n,{message:`Bad Request: invalid url`},400);return}if(r===`GET`&&i===`/_fluxion/healthz`){P(n,{ok:!0,role:`primary`,pid:process.pid,now:Date.now(),uptimeSeconds:Number(process.uptime().toFixed(3))});return}if(r===`GET`&&i===`/_fluxion/workers`){P(n,{ok:!0,now:Date.now(),workers:t()});return}P(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:w(t)}),process.exit(1)}),n.listen(e.options.metaPort,e.options.host),n}const I=e=>Number((e/1024/1024).toFixed(2)),L=6e4;function R(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<L);return o.set(e,n),n.length},c=e=>{let t=Date.now(),n=(o.get(e)??[]).filter(e=>t-e<L);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:I(r.memory.rss),heapTotalMb:I(r.memory.heapTotal),heapUsedMb:I(r.memory.heapUsed),externalMb:I(r.memory.external),arrayBuffersMb:I(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:L,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=I(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(O(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:L,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{A(t.instance,{type:100,sentAt:e})}catch{}m(Date.now())},5e3).unref()}function z(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 B(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 V(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 H(e){if(e!==void 0)try{return new URL(e,`http://fluxion.local`)}catch{return}}function U(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 W=class extends Error{errno;code;constructor(e,t,n){super(e),this.name=`HttpException`,this.errno=t,this.code=n}},G=class extends W{constructor(e=`Bad Request`){super(e,400,`BAD_REQUEST`)}},le=class extends W{constructor(e=`Unauthorized`){super(e,401,`UNAUTHORIZED`)}},ue=class extends W{constructor(e=`Forbidden`){super(e,403,`FORBIDDEN`)}},de=class extends W{constructor(e=`Not Found`){super(e,404,`NOT_FOUND`)}},fe=class extends W{constructor(e=`Method Not Allowed`){super(e,405,`METHOD_NOT_ALLOWED`)}},pe=class extends W{constructor(e=`Not Acceptable`){super(e,406,`NOT_ACCEPTABLE`)}},me=class extends W{constructor(e=`Request Timeout`){super(e,408,`REQUEST_TIMEOUT`)}},he=class extends W{constructor(e=`Conflict`){super(e,409,`CONFLICT`)}},ge=class extends W{constructor(e=`Gone`){super(e,410,`GONE`)}},K=class extends W{constructor(e=`Payload Too Large`){super(e,413,`PAYLOAD_TOO_LARGE`)}},_e=class extends W{constructor(e=`Unsupported Media Type`){super(e,415,`UNSUPPORTED_MEDIA_TYPE`)}},ve=class extends W{constructor(e=`Unprocessable Entity`){super(e,422,`UNPROCESSABLE_ENTITY`)}},ye=class extends W{constructor(e=`Too Many Requests`){super(e,429,`TOO_MANY_REQUESTS`)}},be=class extends W{constructor(e=`Internal Server Error`){super(e,500,`INTERNAL_SERVER_ERROR`)}},xe=class extends W{constructor(e=`Not Implemented`){super(e,501,`NOT_IMPLEMENTED`)}},Se=class extends W{constructor(e=`Bad Gateway`){super(e,502,`BAD_GATEWAY`)}},Ce=class extends W{constructor(e=`Service Unavailable`){super(e,503,`SERVICE_UNAVAILABLE`)}},we=class extends W{constructor(e=`Gateway Timeout`){super(e,504,`GATEWAY_TIMEOUT`)}};function q(e,t){return new K(`request body too large: ${e.toString()} bytes exceeds ${t.toString()} bytes`)}function J(e){return Array.isArray(e)?e[0]:e}function Y(){return{exists:!1,bytes:0,truncated:!1}}function Te(e,t,n,r){return t===0?Y():V(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: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:Te(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 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=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:U(new URLSearchParams(r.toString(`utf8`))),preview:i}:V(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 X=(e,t,n)=>Promise.race([e,new Promise(e=>setTimeout(()=>e(n),t))]);function ke(e){let t=Object.freeze({logger:e.logger}),n=async(n,r)=>{let i=n.method??`GET`,a=B(n),o=H(n.url);if(o===void 0){F(r,{message:`Bad Request: req.url is undefined`},400);return}let s={method:i,ip:a,url:o,query:U(o.searchParams),body:{},headers:n.headers,cookie:Oe(n.headers.cookie),meta:{}},c={exists:!1,bytes:0,truncated:!1};e.logger.info(`Req`,{method:i,ip:a,path:o.pathname});let l=performance.now();r.once(`finish`,()=>{let t={workerId:process.env.WORKER_ID??`[primary]`,method:i,ip:a,path:o.pathname,status:r.statusCode,duration:(performance.now()-l).toFixed(4)};y(s.query).length>0&&(t.query=s.query),c.exists&&(t.body=c.value,t.bodyBytes=c.bytes,t.bodyTruncated=c.truncated),e.logger.info(`Res`,t)});try{if(s.url.pathname.startsWith(`/_fluxion/`)){F(r,{message:`Not Found`},404);return}let i=await De(n,s.method,e.options.maxRequestBytes);s.body=i.body,c=i.preview;let a=await e.router.getModule(o);if(!a){F(r,{message:`Not Found`},404);return}if(n.method&&a.methods&&!a.methods.includes(n.method)){F(r,{message:`Method Not Allowed`},405);return}let l=a.type===0?a.handlerTimeoutMs??e.options.handlerTimeoutMs:e.options.staticResourceTimeoutMs;if(a.middlewares)for(let i=0;i<a.middlewares.length;i++){if(await X(z(a.middlewares[i],s,t,n,r),e.options.middlewareTimeoutMs,N)===N){e.logger.warn(`MiddlewareTimeout`,{method:s.method,ip:s.ip}),F(r,{message:`Internal Server Error`},500);return}if(r.writableEnded)return;if(r.headersSent){r.end();return}}let u=await X(z(a.handler,s,t,n,r),l,M);if(u===M){e.logger.warn(`HandlerTimeout`,{method:s.method,ip:s.ip}),F(r,{message:`Handler timed out`},500);return}u!==j&&F(r,u)}catch(t){t instanceof W?(e.logger.error(`RequestFailed`,{method:s.method,ip:s.ip,path:s.url.pathname,error:t.message}),F(r,{message:t.message},t.errno)):(e.logger.error(`RequestFailed`,{method:s.method,ip:s.ip,path:s.url.pathname,error:w(t)}),F(r,{message:w(t)},t.errno??500))}},r=e.options.https?p.default.createServer({key:e.options.https.key,cert:e.options.https.cert,ca:e.options.https.ca},n):f.default.createServer(n);return r.on(`close`,()=>{e.logger.info(`ServerClosed`,{host:e.options.host,port:e.options.port})}),r.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})}),r.on(`error`,t=>{e.logger.error(`ServerError`,{error:w(t)})}),r}const Z=()=>{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();k({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 Ae(e){if(u.default.isPrimary)throw Error(`[fluxion error] createWorker should only be called in worker process`);process.on(`message`,e=>{if(D(e)&&e.type===100){k({type:202,pid:process.pid,sentAt:e.sentAt,receivedAt:Date.now()});return}}),k({type:200,pid:process.pid}),Z();try{ke(e),k({type:201,pid:process.pid})}catch(t){e.logger.error(`WorkerBootstrapFailed`,{pid:process.pid,error:w(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()}},je=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}},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=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 Ne(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 Pe=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=oe[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(j)),i.pipe(r)})}}}async register(e,t){let n=this.handlers.get(t)?.disposer;if(n&&await z(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=Ne(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 Fe(e){let t={options:E(e)};t.logger=ne(t),t.router=new Pe(t),u.default.isPrimary?R(t):(t.logger=re(t.logger,process.pid),t.watcher=await new(t.options.nativeWatcher?Me:je)(t).start(),Ae(t))}function Ie(e,t){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 Le(e){if(typeof e!=`function`)throw Error(`[fluxion error] Invalid FluxionMiddleware, expected a function but got ${typeof e}`);return e}function Re(e){if(typeof e!=`function`)throw Error(`[fluxion error] Invalid FluxionLoggerFn, expected a function but got ${typeof e}`);return e}exports.BadGatewayException=Se,exports.BadRequestException=G,exports.ConflictException=he,exports.ForbiddenException=ue,exports.GatewayTimeoutException=we,exports.GoneException=ge,exports.HttpCode=se,exports.HttpException=W,exports.InternalServerErrorException=be,exports.MethodNotAllowedException=fe,exports.NotAcceptableException=pe,exports.NotFoundException=de,exports.NotImplementedException=xe,exports.PayloadTooLargeException=K,exports.RequestTimeoutException=me,exports.ServiceUnavailableException=Ce,exports.TooManyRequestsException=ye,exports.UnauthorizedException=le,exports.UnprocessableEntityException=ve,exports.UnsupportedMediaTypeException=_e,exports.defineFluxionLogger=Re,exports.defineFluxionMiddleware=Le,exports.defineFluxionModule=Ie,exports.fluxion=Fe;
2
2
  //# sourceMappingURL=index.cjs.map