fluxion-vio 0.1.2 → 0.1.3

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
@@ -139,6 +139,19 @@ await fluxion({ dir: './dynamic', host: '127.0.0.1', port: 3000, logger: oneLine
139
139
 
140
140
  Setting `FLUXION_INSTANCE_LOG=/path/to/file.log` additionally writes the same JSON lines to that file.
141
141
 
142
+ ### Redirecting all output to a file
143
+
144
+ Set `logOutputFile` to send everything the process prints — the framework's JSON lines and your own `console.log` / `console.error` — to a file instead of the terminal:
145
+
146
+ ```ts
147
+ await fluxion({ dir: './dynamic', host: '127.0.0.1', port: 3000, logOutputFile: './logs/server.log' });
148
+ ```
149
+
150
+ - Relative paths are resolved against `process.cwd()`; missing parent directories are created. The file is appended to, never truncated.
151
+ - The redirect starts when `fluxion()` is called, before it opens the port, so a startup failure (a busy port, for instance) lands in the file too. Output printed *before* that call has already gone to the terminal — call `fluxion()` as early as possible.
152
+ - On an in-place restart the same file is reopened in append mode, so the log continues across restarts.
153
+ - `SIGINT` / `SIGTERM` flush the file before exiting.
154
+
142
155
  ## HTTP exceptions
143
156
 
144
157
  ```ts
@@ -198,6 +211,7 @@ interface FluxionOptions {
198
211
 
199
212
  maxRequestBytes?: number; // 8_000_000
200
213
  logger?: 'json-line' | ((entry) => void); // 'json-line'
214
+ logOutputFile?: string; // redirect stdout/stderr here (relative to cwd)
201
215
  target?: string | string[]; // esbuild target, default 'node<major>'
202
216
  https?: { key: string | Buffer; cert: string | Buffer; ca?: string | Buffer | Array<string | Buffer> };
203
217
  csp?: string | false; // "default-src 'self'"; false omits the header
package/dist/index.cjs CHANGED
@@ -1,9 +1,9 @@
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,1);let l=require("node:path");l=s(l,1);let u=require("node:http");u=s(u,1);let d=require("node:https");d=s(d,1);let f=require("node:fs/promises");f=s(f,1);let p=require("minimatch"),m=require("esbuild"),h=require("node:vm"),g=require("node:module"),_=require("node:url");const v=e=>typeof e==`object`&&!!e&&!Array.isArray(e),y=e=>typeof Error.isError==`function`?Error.isError(e):e instanceof Error;function b(e){if(typeof e==`object`&&e){let{message:t,stack:n}=e,r=``;if(typeof t==`string`&&t.length>0&&(r=t),typeof n==`string`&&n.length>0&&(r+=(r.length>0?`
2
- `:``)+n),r.length>0)return r}return String(e)}const x=(e,t)=>typeof t==`bigint`?t.toString():y(t)?b(t):t,S=e=>JSON.stringify({timestamp:typeof e.timestamp==`string`?e.timestamp:String(e.timestamp),level:typeof e.level==`string`?e.level:`INFO`,event:`[unserializable]`}),C=e=>{try{return JSON.stringify(e,x)??S(e)}catch{return S(e)}},ee=e=>{console.log(C(e))};function te(e){return new Promise(t=>{if(e.destroyed||e.writableEnded){t();return}let n=()=>{clearTimeout(r),e.off(`error`,n),t()},r=setTimeout(n,2e3);r.unref(),e.once(`error`,n);try{e.write(``,n)}catch{n()}})}function ne(e,t){if(!(0,c.existsSync)(e)){let t=(0,l.dirname)(e);(0,c.existsSync)(t)||(0,c.mkdirSync)(t,{recursive:!0})}let n=(0,c.createWriteStream)(e,{flags:`a`,autoClose:!t});return{sink:e=>{try{n.write(C(e)+`
3
- `)}catch{}},flush:async()=>{await te(n),t&&await new Promise(e=>n.close(()=>e()))}}}function re(e,t){let n=process.env.FLUXION_INSTANCE_LOG,r=n?ne(n,t):null,i=e.options.logger,a=typeof i==`function`?i:ee;if(!r)return a;let o=e=>{a(e),r.sink(e)};return o.flush=r.flush,o}function ie(e,t={}){let n=re(e,t.deferClose===!0);return{write(e,t){let r=new Date().toISOString(),i=v(t)?{timestamp:r,level:e,event:t.event,...t}:{timestamp:r,level:e,event:t};try{n(i)}catch{}},info(e){this.write(`INFO`,e)},warn(e){this.write(`WARN`,e)},error(e){this.write(`ERROR`,e)},succ(e){this.write(`SUCC`,e)},debug(e){this.write(`DEBUG`,e)},verbose(e){this.write(`VERBOSE`,e)},core(e){this.write(`CORE`,e)},flush(){return n.flush?.()??Promise.resolve()}}}let w;(function(e){e.OptionsNormalized=Symbol(`fluxion.options.normalized`),e.StaticHandled=Symbol(`fluxion.router.StaticHandled`),e.HandlerTimeout=Symbol(`fluxion.handlerTimeout`),e.MiddlewareTimeout=Symbol(`fluxion.middlewareTimeout`)})(w||={});const T={".css":`text/css; charset=utf-8`,".html":`text/html; charset=utf-8`,".htm":`text/html; charset=utf-8`,".js":`text/javascript; charset=utf-8`,".mjs":`text/javascript; charset=utf-8`,".cjs":`text/javascript; charset=utf-8`,".json":`application/json; charset=utf-8`,".jsonld":`application/ld+json; charset=utf-8`,".map":`application/json; charset=utf-8`,".txt":`text/plain; charset=utf-8`,".md":`text/markdown; charset=utf-8`,".xml":`application/xml; charset=utf-8`,".csv":`text/csv; charset=utf-8`,".yaml":`application/yaml; charset=utf-8`,".yml":`application/yaml; charset=utf-8`,".toml":`application/toml; charset=utf-8`,".ico":`image/x-icon`,".png":`image/png`,".jpg":`image/jpeg`,".jpeg":`image/jpeg`,".gif":`image/gif`,".webp":`image/webp`,".avif":`image/avif`,".svg":`image/svg+xml`,".bmp":`image/bmp`,".tif":`image/tiff`,".tiff":`image/tiff`,".woff":`font/woff`,".woff2":`font/woff2`,".ttf":`font/ttf`,".otf":`font/otf`,".eot":`application/vnd.ms-fontobject`,".mp3":`audio/mpeg`,".wav":`audio/wav`,".ogg":`audio/ogg`,".oga":`audio/ogg`,".m4a":`audio/mp4`,".aac":`audio/aac`,".flac":`audio/flac`,".mp4":`video/mp4`,".webm":`video/webm`,".ogv":`video/ogg`,".mov":`video/quicktime`,".m4v":`video/mp4`,".pdf":`application/pdf`,".wasm":`application/wasm`,".zip":`application/zip`,".gz":`application/gzip`,".tar":`application/x-tar`,".rar":`application/vnd.rar`,".7z":`application/x-7z-compressed`,".webmanifest":`application/manifest+json; charset=utf-8`,".exe":`application/octet-stream`};let E=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 D=e=>e/(1024*1024),ae=()=>typeof process.execve==`function`;function oe(e,t=5e3){return new Promise(n=>{let r=!1,i=()=>{r||(r=!0,clearTimeout(a),n())},a=setTimeout(()=>{e.closeAllConnections(),i()},t);a.unref(),e.close(i),e.closeIdleConnections()})}const se=()=>[process.execPath,...process.execArgv,...process.argv.slice(1)];async function ce(e,t,n={}){typeof process.execve!=`function`&&(t.error({event:`RestartFailed`,pid:process.pid,error:`process.execve is not available`}),process.exit(1)),t.warn({event:`Restarting`,pid:process.pid,...n}),await oe(e),await t.flush();try{process.execve(process.execPath,se(),process.env)}catch(e){t.error({event:`RestartFailed`,pid:process.pid,error:b(e)})}process.exit(1)}function le(e){let{restartMemoryMB:t,server:n,logger:r,startupGraceMs:i=5e3,checkIntervalMs:a=1e4}=e;if(t===!1)return{start:()=>{},stop:()=>{}};let o=!1,s,c=()=>{if(o)return;let e=D(process.memoryUsage.rss());e<=t||(o=!0,s!==void 0&&(clearInterval(s),s=void 0),ce(n,r,{reason:`memory`,rssMB:Math.round(e)}))};return{start(){s!==void 0||o||(s=setTimeout(()=>{s=setInterval(c,a),s.unref(),c()},i),s.unref())},stop(){s!==void 0&&(clearInterval(s),s=void 0)}}}var O=class extends Error{constructor(e){super(e),this.name=`FluxionVioError`}};function k(e){if(Buffer.isBuffer(e))return e;if(typeof e==`string`){if(!e.startsWith(`-----BEGIN`)){let t=l.default.resolve(e);if(c.default.existsSync(t))return c.default.readFileSync(t)}return Buffer.from(e)}throw new O(`Certificate content must be a string or Buffer`)}function ue(e){if(!e)return;if(typeof e!=`object`||!e||Array.isArray(e))throw new O(`FluxionOptions.https must be an object`);if(typeof e.key!=`string`&&!Buffer.isBuffer(e.key))throw new O(`FluxionOptions.https.key must be a string or Buffer`);if(typeof e.cert!=`string`&&!Buffer.isBuffer(e.cert))throw new O(`FluxionOptions.https.cert must be a string or Buffer`);let t={key:k(e.key),cert:k(e.cert)};return e.ca!==void 0&&(Array.isArray(e.ca)?t.ca=e.ca.map(e=>k(e)):t.ca=k(e.ca)),t}function A(e){if(typeof e!=`object`||!e||Array.isArray(e))throw new O(`FluxionOptions must be an object`);if(`include`in e)throw new O(`The "include" option has been removed. Please use:
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,1);let l=require("node:path");l=s(l,1);let u=require("node:fs/promises");u=s(u,1);let d=require("node:http");d=s(d,1);let f=require("node:https");f=s(f,1);let p=require("minimatch"),m=require("esbuild"),h=require("node:vm"),g=require("node:module"),_=require("node:url");const v=e=>typeof e==`object`&&!!e&&!Array.isArray(e),y=e=>typeof Error.isError==`function`?Error.isError(e):e instanceof Error;function b(e){if(typeof e==`object`&&e){let{message:t,stack:n}=e,r=``;if(typeof t==`string`&&t.length>0&&(r=t),typeof n==`string`&&n.length>0&&(r+=(r.length>0?`
2
+ `:``)+n),r.length>0)return r}return String(e)}const x=(e,t)=>typeof t==`bigint`?t.toString():y(t)?b(t):t,S=e=>JSON.stringify({timestamp:typeof e.timestamp==`string`?e.timestamp:String(e.timestamp),level:typeof e.level==`string`?e.level:`INFO`,event:`[unserializable]`}),C=e=>{try{return JSON.stringify(e,x)??S(e)}catch{return S(e)}},ee=e=>{console.log(C(e))};function w(e){return new Promise(t=>{if(e.destroyed||e.writableEnded){t();return}let n=()=>{clearTimeout(r),e.off(`error`,n),t()},r=setTimeout(n,2e3);r.unref(),e.once(`error`,n);try{e.write(``,n)}catch{n()}})}function te(e,t){if(!(0,c.existsSync)(e)){let t=(0,l.dirname)(e);(0,c.existsSync)(t)||(0,c.mkdirSync)(t,{recursive:!0})}let n=(0,c.createWriteStream)(e,{flags:`a`,autoClose:!t});return{sink:e=>{try{n.write(C(e)+`
3
+ `)}catch{}},flush:async()=>{await w(n),t&&await new Promise(e=>n.close(()=>e()))}}}function ne(e,t){let n=process.env.FLUXION_INSTANCE_LOG,r=n?te(n,t):null,i=e.options.logger,a=typeof i==`function`?i:ee;if(!r)return a;let o=e=>{a(e),r.sink(e)};return o.flush=r.flush,o}function T(e,t={}){let n=ne(e,t.deferClose===!0);return{write(e,t){let r=new Date().toISOString(),i=v(t)?{timestamp:r,level:e,event:t.event,...t}:{timestamp:r,level:e,event:t};try{n(i)}catch{}},info(e){this.write(`INFO`,e)},warn(e){this.write(`WARN`,e)},error(e){this.write(`ERROR`,e)},succ(e){this.write(`SUCC`,e)},debug(e){this.write(`DEBUG`,e)},verbose(e){this.write(`VERBOSE`,e)},core(e){this.write(`CORE`,e)},flush(){return n.flush?.()??Promise.resolve()}}}async function E(e){await(0,u.mkdir)((0,l.dirname)(e),{recursive:!0});let t=await(0,u.open)(e,`a`),n=(e,n,r)=>{(0,c.writeSync)(t.fd,Buffer.from(e));let i=typeof n==`function`?n:r;return typeof i==`function`&&i(),!0};process.stdout.write=n,process.stderr.write=n}let D;(function(e){e.OptionsNormalized=Symbol(`fluxion.options.normalized`),e.StaticHandled=Symbol(`fluxion.router.StaticHandled`),e.HandlerTimeout=Symbol(`fluxion.handlerTimeout`),e.MiddlewareTimeout=Symbol(`fluxion.middlewareTimeout`)})(D||={});const re={".css":`text/css; charset=utf-8`,".html":`text/html; charset=utf-8`,".htm":`text/html; charset=utf-8`,".js":`text/javascript; charset=utf-8`,".mjs":`text/javascript; charset=utf-8`,".cjs":`text/javascript; charset=utf-8`,".json":`application/json; charset=utf-8`,".jsonld":`application/ld+json; charset=utf-8`,".map":`application/json; charset=utf-8`,".txt":`text/plain; charset=utf-8`,".md":`text/markdown; charset=utf-8`,".xml":`application/xml; charset=utf-8`,".csv":`text/csv; charset=utf-8`,".yaml":`application/yaml; charset=utf-8`,".yml":`application/yaml; charset=utf-8`,".toml":`application/toml; charset=utf-8`,".ico":`image/x-icon`,".png":`image/png`,".jpg":`image/jpeg`,".jpeg":`image/jpeg`,".gif":`image/gif`,".webp":`image/webp`,".avif":`image/avif`,".svg":`image/svg+xml`,".bmp":`image/bmp`,".tif":`image/tiff`,".tiff":`image/tiff`,".woff":`font/woff`,".woff2":`font/woff2`,".ttf":`font/ttf`,".otf":`font/otf`,".eot":`application/vnd.ms-fontobject`,".mp3":`audio/mpeg`,".wav":`audio/wav`,".ogg":`audio/ogg`,".oga":`audio/ogg`,".m4a":`audio/mp4`,".aac":`audio/aac`,".flac":`audio/flac`,".mp4":`video/mp4`,".webm":`video/webm`,".ogv":`video/ogg`,".mov":`video/quicktime`,".m4v":`video/mp4`,".pdf":`application/pdf`,".wasm":`application/wasm`,".zip":`application/zip`,".gz":`application/gzip`,".tar":`application/x-tar`,".rar":`application/vnd.rar`,".7z":`application/x-7z-compressed`,".webmanifest":`application/manifest+json; charset=utf-8`,".exe":`application/octet-stream`};let ie=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 ae=e=>e/(1024*1024),oe=()=>typeof process.execve==`function`;function se(e,t=5e3){return new Promise(n=>{let r=!1,i=()=>{r||(r=!0,clearTimeout(a),n())},a=setTimeout(()=>{e.closeAllConnections(),i()},t);a.unref(),e.close(i),e.closeIdleConnections()})}const ce=()=>[process.execPath,...process.execArgv,...process.argv.slice(1)];async function le(e,t,n={}){typeof process.execve!=`function`&&(t.error({event:`RestartFailed`,pid:process.pid,error:`process.execve is not available`}),process.exit(1)),t.warn({event:`Restarting`,pid:process.pid,...n}),await se(e),await t.flush();try{process.execve(process.execPath,ce(),process.env)}catch(e){t.error({event:`RestartFailed`,pid:process.pid,error:b(e)})}process.exit(1)}function O(e){let{restartMemoryMB:t,server:n,logger:r,startupGraceMs:i=5e3,checkIntervalMs:a=1e4}=e;if(t===!1)return{start:()=>{},stop:()=>{}};let o=!1,s,c=()=>{if(o)return;let e=ae(process.memoryUsage.rss());e<=t||(o=!0,s!==void 0&&(clearInterval(s),s=void 0),le(n,r,{reason:`memory`,rssMB:Math.round(e)}))};return{start(){s!==void 0||o||(s=setTimeout(()=>{s=setInterval(c,a),s.unref(),c()},i),s.unref())},stop(){s!==void 0&&(clearInterval(s),s=void 0)}}}var k=class extends Error{constructor(e){super(e),this.name=`FluxionVioError`}};function A(e){if(Buffer.isBuffer(e))return e;if(typeof e==`string`){if(!e.startsWith(`-----BEGIN`)){let t=l.default.resolve(e);if(c.default.existsSync(t))return c.default.readFileSync(t)}return Buffer.from(e)}throw new k(`Certificate content must be a string or Buffer`)}function ue(e){if(!e)return;if(typeof e!=`object`||!e||Array.isArray(e))throw new k(`FluxionOptions.https must be an object`);if(typeof e.key!=`string`&&!Buffer.isBuffer(e.key))throw new k(`FluxionOptions.https.key must be a string or Buffer`);if(typeof e.cert!=`string`&&!Buffer.isBuffer(e.cert))throw new k(`FluxionOptions.https.cert must be a string or Buffer`);let t={key:A(e.key),cert:A(e.cert)};return e.ca!==void 0&&(Array.isArray(e.ca)?t.ca=e.ca.map(e=>A(e)):t.ca=A(e.ca)),t}function j(e){if(typeof e!=`object`||!e||Array.isArray(e))throw new k(`FluxionOptions must be an object`);if(`include`in e)throw new k(`The "include" option has been removed. Please use:
4
4
  - "apiInclude" for API handler patterns (default: ["**/*.ts"])
5
5
  - "staticInclude" for static resource patterns (default: ["**/*"])
6
6
  Example migration:
7
7
  OLD: { include: ["**/*.ts", "**/*.js"], apiInclude: ["**/*.ts"] }
8
- NEW: { apiInclude: ["**/*.ts"], staticInclude: ["**/*.js"] }`);let{dir:t,host:n,port:r,handlerTimeoutMs:i=5e3,middlewareTimeoutMs:a=3e3,staticResourceTimeoutMs:o=180*1e3,target:s=`node${process.versions.node.split(`.`)[0]}`,maxRequestBytes:u=8e6,apiInclude:d=[`**/*.ts`],staticInclude:f=[`**/*`],exclude:p=[`**/node_modules/**`,`**/.git/**`,`**/dist/**`,`**/build/**`,`**/.vscode/**`,`**/.idea/**`,`**/*.log`,`**/.DS_Store`,`**/coverage/**`,`**/.nyc_output/**`,`**/*.tmp`,`**/*.temp`],https:m,csp:h=`default-src 'self'`,restartMemoryMB:g=!1}=e,_=r,v=e.logger??`json-line`;if(v!==`json-line`&&typeof v!=`function`)throw new O(`Invalid logger option, Must be 'json-line' or a custom logger function (write a one-line logger yourself)`);if(typeof t!=`string`)throw new O(`FluxionOptions.dir must be a string`);let y=l.default.resolve(process.cwd(),t),b=y.endsWith(l.default.sep)?y:y+l.default.sep;if(typeof s!=`string`&&!(Array.isArray(s)&&s.every(e=>typeof e==`string`)))throw new O(`FluxionOptions.target must be a string or an array of strings`);if(typeof n!=`string`)throw new O(`FluxionOptions.host must be a string`);if(!Number.isSafeInteger(i)||i<=100)throw new O(`FluxionOptions.handlerTimeoutMs must be an integer greater than 100`);if(!Number.isSafeInteger(a)||a<=100)throw new O(`FluxionOptions.middlewareTimeoutMs must be an integer greater than 100`);if(typeof _!=`number`||!Number.isSafeInteger(_))throw new O(`FluxionOptions.port must be a positive integer`);if(_<=1||_>65535)throw new O(`FluxionOptions.port must be 1 ~ 65535`);if(typeof u!=`number`||u<=0||!Number.isSafeInteger(u))throw new O(`FluxionOptions.maxRequestBytes must be a positive integer`);if(h!==!1&&typeof h!=`string`)throw new O(`FluxionOptions.csp must be a string or false`);if(g!==!1&&(typeof g!=`number`||!Number.isFinite(g)||g<=0))throw new O(`FluxionOptions.restartMemoryMB must be a positive number of MB, or false`);c.default.existsSync(b)||c.default.mkdirSync(b,{recursive:!0});let x={dir:b,host:n,port:_,handlerTimeoutMs:i,middlewareTimeoutMs:a,staticResourceTimeoutMs:o,target:s,maxRequestBytes:u,logger:v,apiInclude:d,staticInclude:f,exclude:p,https:ue(m),csp:h,restartMemoryMB:g,normalizedFlag:w.OptionsNormalized};return process.argv.includes(`--verbose`)&&console.log(`normalized options`,{...x,https:x.https?`set`:`unset`}),x}function j(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 de(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 M(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 N(e){if(e!==void 0)try{return new URL(e,`http://fluxion.local`)}catch{return}}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 I(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 L=class extends Error{errno;code;constructor(e,t,n){super(e),this.name=`HttpException`,this.errno=t,this.code=n}},R=class extends L{constructor(e=`Bad Request`){super(e,400,`BAD_REQUEST`)}},z=class extends L{constructor(e=`Unauthorized`){super(e,401,`UNAUTHORIZED`)}},B=class extends L{constructor(e=`Forbidden`){super(e,403,`FORBIDDEN`)}},V=class extends L{constructor(e=`Not Found`){super(e,404,`NOT_FOUND`)}},H=class extends L{constructor(e=`Method Not Allowed`){super(e,405,`METHOD_NOT_ALLOWED`)}},fe=class extends L{constructor(e=`Not Acceptable`){super(e,406,`NOT_ACCEPTABLE`)}},pe=class extends L{constructor(e=`Request Timeout`){super(e,408,`REQUEST_TIMEOUT`)}},me=class extends L{constructor(e=`Conflict`){super(e,409,`CONFLICT`)}},he=class extends L{constructor(e=`Gone`){super(e,410,`GONE`)}},U=class extends L{constructor(e=`Payload Too Large`){super(e,413,`PAYLOAD_TOO_LARGE`)}},ge=class extends L{constructor(e=`Unsupported Media Type`){super(e,415,`UNSUPPORTED_MEDIA_TYPE`)}},_e=class extends L{constructor(e=`Unprocessable Entity`){super(e,422,`UNPROCESSABLE_ENTITY`)}},ve=class extends L{constructor(e=`Too Many Requests`){super(e,429,`TOO_MANY_REQUESTS`)}},ye=class extends L{constructor(e=`Internal Server Error`){super(e,500,`INTERNAL_SERVER_ERROR`)}},be=class extends L{constructor(e=`Not Implemented`){super(e,501,`NOT_IMPLEMENTED`)}},xe=class extends L{constructor(e=`Bad Gateway`){super(e,502,`BAD_GATEWAY`)}},Se=class extends L{constructor(e=`Service Unavailable`){super(e,503,`SERVICE_UNAVAILABLE`)}},Ce=class extends L{constructor(e=`Gateway Timeout`){super(e,504,`GATEWAY_TIMEOUT`)}};function W(e,t){return new U(`request body too large: ${e.toString()} bytes exceeds ${t.toString()} bytes`)}function G(e){return Array.isArray(e)?e[0]:e}function K(){return{exists:!1,bytes:0,truncated:!1}}function we(e,t,n,r){return t===0?K():M(n)?{exists:!0,value:e.toString(`utf8`),bytes:t,truncated:r}:{exists:!0,value:`<binary body: ${t} bytes>`,bytes:t,truncated:r}}async function Te(e,t,n,r=8192){if(t===`GET`||t===`HEAD`||e.readableEnded)return{rawBody:void 0,preview:K()};let i=G(e.headers[`content-length`]),a=i===void 0?NaN:Number.parseInt(i,10);return new Promise((t,i)=>{let o=[],s=[],c=0,l=0,u=!1,d=!1,f=()=>{e.off(`data`,m),e.off(`end`,h),e.off(`error`,g),e.off(`aborted`,_)},p=e=>{d||(d=!0,e())};if(Number.isFinite(a)&&a>n){f(),e.resume(),p(()=>i(W(a,n)));return}let m=t=>{let a=Buffer.isBuffer(t)?t:Buffer.from(t);if(c+=a.byteLength,c>n){f(),e.resume(),p(()=>i(W(c,n)));return}if(o.push(a),l<r){let e=r-l,t=a.subarray(0,e);s.push(t),l+=t.length,t.length<a.length&&(u=!0)}else u=!0},h=()=>{f(),p(()=>{let n=o.length>0?Buffer.concat(o):void 0;t({rawBody:n,preview:we(s.length>0?Buffer.concat(s):Buffer.alloc(0),n?.byteLength??0,G(e.headers[`content-type`]),u)})})},g=e=>{f(),p(()=>i(e))},_=()=>{f(),p(()=>i(Error(`request aborted while reading body`)))};e.on(`data`,m),e.once(`end`,h),e.once(`error`,g),e.once(`aborted`,_)})}async function Ee(e,t,n){let{rawBody:r,preview:i}=await Te(e,t,n);if(r===void 0||r.byteLength===0)return{body:{},preview:i};let a=G(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:I(new URLSearchParams(r.toString(`utf8`))),preview:i}:M(a)?{body:{raw:r.toString(`utf8`)},preview:i}:{body:{},preview:i}}function De(e){if(!e)return{};let t={},n=e.split(`;`),r=0;for(let e of n){if(r>=100)break;let[n,...i]=e.split(`=`);if(!n)continue;let a=n.trim(),o=i.join(`=`).trim();t[a]=decodeURIComponent(o),r++}return t}const q=(e,t,n)=>Promise.race([e,new Promise(e=>setTimeout(()=>e(n),t))]);function Oe(e,t,n){if(typeof n.disposer!=`function`)return;let r=n.disposer;t.once(`close`,()=>{j(r).catch(t=>{e.logger.error({event:`DisposerFailed`,url:n.absolutePath,error:b(t)})})})}function ke(e){let t=Object.freeze({logger:e.logger}),n=async(n,r)=>{let i=n.method??`GET`,a=de(n),o=N(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:I(o.searchParams),body:{},headers:n.headers,cookie:De(n.headers.cookie),meta:{}};r.setHeader(`X-Content-Type-Options`,`nosniff`),r.setHeader(`X-Frame-Options`,`DENY`),r.setHeader(`X-XSS-Protection`,`1; mode=block`),e.options.csp!==!1&&r.setHeader(`Content-Security-Policy`,e.options.csp);let c={exists:!1,bytes:0,truncated:!1};e.logger.core({event:`request`,method:i,ip:a,path:o.pathname});let l=performance.now();r.once(`finish`,()=>{let t={event:`response`,method:i,ip:a,path:o.pathname,status:r.statusCode,duration:(performance.now()-l).toFixed(4)};Object.keys(s.query).length>0&&(t.query=s.query),c.exists&&(t.body=c.value,t.bodyBytes=c.bytes,t.bodyTruncated=c.truncated),e.logger.core(t)});try{let i=await Ee(n,s.method,e.options.maxRequestBytes);s.body=i.body,c=i.preview;let a=await e.router(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}Oe(e,r,a);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 q(j(a.middlewares[i],s,t,n,r),e.options.middlewareTimeoutMs,w.MiddlewareTimeout)===w.MiddlewareTimeout){e.logger.warn({event:`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 q(j(a.handler,s,t,n,r),l,w.HandlerTimeout);if(u===w.HandlerTimeout){e.logger.warn({event:`HandlerTimeout`,method:s.method,ip:s.ip}),F(r,{message:`Handler timed out`},500);return}u!==w.StaticHandled&&F(r,u)}catch(t){t instanceof L?(e.logger.error({...s,event:`RequestFailed`,error:t.message}),F(r,{message:t.message},t.errno)):(e.logger.error({...s,event:`RequestFailed`,error:b(t)}),F(r,{message:`Internal Server Error`},500))}},r=e.options.https?d.default.createServer({key:e.options.https.key,cert:e.options.https.cert,ca:e.options.https.ca},n):u.default.createServer(n);return new Promise((t,n)=>{let i=!1;r.on(`close`,()=>{e.logger.core({event:`ServerClosed`,host:e.options.host,port:e.options.port})}),r.once(`listening`,()=>{i=!0,e.logger.core({event:`FluxionStarted`,version:`0.1.1`,pid:process.pid,protocol:e.options.https?`https`:`http`,host:e.options.host,port:e.options.port}),e.logger.core({event:`DynamicDirectory`,directory:e.options.dir}),t(r)}),r.on(`error`,t=>{e.logger.error({event:`ServerError`,error:b(t)}),!i&&n(t)}),r.listen(e.options.port,e.options.host)})}function Ae(e){}const je=Ae,J=new Map,Me=`${l.sep}node_modules${l.sep}`,Y=new Set([`.ts`,`.tsx`,`.mts`,`.cts`,`.js`,`.jsx`,`.mjs`,`.cjs`]),X=[...Y,`.json`],Ne={".js":[`.ts`,`.tsx`],".jsx":[`.tsx`],".mjs":[`.mts`],".cjs":[`.cts`]},Pe=e=>!e.startsWith(`.`)&&!(0,l.isAbsolute)(e),Fe=e=>{try{let t=(0,c.statSync)(e.filename);return t.mtimeMs!==e.mtimeMs||t.size!==e.size}catch{return!0}},Z=e=>{try{return(0,c.statSync)(e).isFile()}catch{return!1}},Q=e=>{if(Z(e))return e;let t=(0,l.extname)(e),n=e.slice(0,e.length-t.length);for(let e of Ne[t]??[])if(Z(n+e))return n+e;for(let t of X)if(Z(e+t))return e+t;for(let t of X)if(Z((0,l.join)(e,`index`+t)))return(0,l.join)(e,`index`+t)};var Ie=class{opts;constructor(e){this.opts=e}compile(e){let{outputFiles:t}=(0,m.buildSync)({entryPoints:[e],bundle:!1,write:!1,platform:`node`,format:`cjs`,target:this.opts.target,sourcemap:`inline`,sourcesContent:!1,logLevel:`silent`,supported:{"dynamic-import":!1},define:{"import.meta.url":JSON.stringify((0,_.pathToFileURL)(e).href),"import.meta.filename":JSON.stringify(e),"import.meta.dirname":JSON.stringify((0,l.dirname)(e))}});return t[0].text}require(e){return this.load((0,l.resolve)(e)).exports}isHot(e){let t=(0,l.extname)(e);return e.startsWith(this.opts.dir)&&!e.includes(Me)&&(Y.has(t)||t===`.json`)}load(e){let t=J.get(e);if(t===void 0)return this.loadFresh(e);let n=this.collectChain(t);if(!this.anyStale(n))return t;for(let e of n)J.get(e.filename)===e&&J.delete(e.filename);return this.loadFresh(e)}collectChain(e){let t=new Set([e]);for(let e of t)for(let n of e.deps.values())t.add(n);return t}anyStale(e){for(let t of e)if(J.get(t.filename)!==t||Fe(t))return!0;return!1}loadFresh(e){let{mtimeMs:t,size:n}=(0,c.statSync)(e),r={id:e,filename:e,exports:{},mtimeMs:t,size:n,deps:new Map};J.set(e,r);try{this.evaluate(e,r)}catch(t){throw J.delete(e),t}return r}evaluate(e,t){let n=(0,l.extname)(e);if(n===`.json`){t.exports=JSON.parse((0,c.readFileSync)(e,`utf8`));return}if(!Y.has(n))throw Error(`FluxionLoader: unsupported file type "${n}" (${e})`);(0,h.compileFunction)(this.compile(e),[`exports`,`require`,`module`,`__filename`,`__dirname`],{filename:e}).call(t.exports,t.exports,this.createModuleRequire(t),t,e,(0,l.dirname)(e))}createModuleRequire(e){let t=(0,g.createRequire)(e.filename),n=t=>Pe(t)?void 0:Q((0,l.resolve)((0,l.dirname)(e.filename),t)),r=r=>{let i=n(r);if(i===void 0)return t(r);if(!this.isHot(i))return t(i);let a=this.load(i);return e.deps.set(i,a),a.exports};return r.resolve=e=>n(e)??t.resolve(e),r.cache=t.cache,r}};function $(e,t){if(typeof t!=`object`||!t)return!1;if(je(t),typeof t.handler!=`function`)return e.logger.error({event:`InvalidModule`,error:`handler must be a function`}),!1;if(t.disposer!==void 0&&typeof t.disposer!=`function`)return e.logger.error({event:`InvalidModule`,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({event:`InvalidModule`,error:`handlerTimeoutMs must be an integer >= 100 if provided`}),!1):t.type===0?!0:(e.logger.error({event:`InvalidModule`,error:`You must use defineFluxionModule to create module`}),!1)}function Le(e,t,n){let r=new Ie(e.options).require(t);if($(e,r.default))r=r.default;else if(!$(e,r))throw new O(`Invalid handler module '${t}', make sure it satisfies defineFluxionModule(...) helper`);return r.absolutePath=t,r.mtimeMs=n.mtimeMs,r}function Re(e){return async t=>{let n=t.pathname.replace(/^[/]+/,``).replace(/[/]+$/,``),r=l.default.join(e.options.dir,n),i=l.default.relative(e.options.dir,r);if(i.startsWith(`..`)||l.default.isAbsolute(i)||e.options.exclude.some(e=>(0,p.minimatch)(n,e)))return;let a=await f.default.stat(r).catch(()=>void 0);if(!(!a||!a.isFile())){if(e.options.apiInclude.some(e=>(0,p.minimatch)(n,e)))return Le(e,r,a);if(e.options.staticInclude.some(e=>(0,p.minimatch)(n,e)))return ze(r)}}}function ze(e){return{type:1,mtimeMs:NaN,absolutePath:e,handler:async(t,n,r,i)=>{if(t.method!==`GET`&&t.method!==`HEAD`){i.statusCode=405,i.setHeader(`Allow`,`GET, HEAD`),i.end();return}let a=await f.default.stat(e).catch(e=>e);if(a instanceof Error)return i.statusCode=404,i.end(`Not Accessible`),n.logger.error({event:`StaticResourceError`,url:t.url.pathname,error:a.message}),null;if(!a.isFile()){i.statusCode=404,i.end(`Not Found`);return}let o=T[l.default.extname(e).toLowerCase()]??`application/octet-stream`;if(i.statusCode=200,i.setHeader(`Content-Type`,o),i.setHeader(`Content-Length`,String(a.size)),t.method===`HEAD`){i.end();return}return new Promise((t,n)=>{let a=(0,c.createReadStream)(e),o=()=>{a.off(`error`,s),a.off(`end`,l),i.off(`close`,u),r.off(`aborted`,u)},s=e=>{o(),n(e)},l=()=>{o(),t(w.StaticHandled)},u=()=>{o(),a.destroy(),t(w.StaticHandled)};a.on(`error`,s),a.on(`end`,l),i.on(`close`,u),r.on(`aborted`,u),a.pipe(i)})}}}async function Be(e){let t={options:e.normalizedFlag===w.OptionsNormalized?e:A(e)},n=t.options.restartMemoryMB!==!1&&ae();t.logger=ie(t,{deferClose:n}),t.router=Re(t);let r=await ke(t);t.options.restartMemoryMB!==!1&&!n&&t.logger.warn({event:`RestartDisabled`,reason:`process.execve is not available on this Node.js version`,requiredVersion:`22.15`,nodeVersion:process.version,restartMemoryMB:t.options.restartMemoryMB});let i=le({restartMemoryMB:n?t.options.restartMemoryMB:!1,server:r,logger:t.logger}),a=e=>{i.stop(),t.logger.warn({event:`ShuttingDown`,pid:process.pid,signal:e}),r.close(async()=>{await t.logger.flush(),process.exit(0)})};process.once(`SIGINT`,()=>a(`SIGINT`)),process.once(`SIGTERM`,()=>a(`SIGTERM`)),i.start()}function Ve(e,t){if(typeof e==`function`){if(t!==void 0&&typeof t!=`function`)throw new O(`Invalid disposer, expected a function but got ${typeof t}`);return{handler:e,disposer:t,type:0}}if(typeof e!=`object`||!e)throw new O(`Invalid argument, expected a FluxionModule object or a handler function, but got ${typeof e}`);if(typeof e.handler!=`function`)throw new O(`Invalid FluxionModule, "handler" must be a function`);if(e.disposer!==void 0&&typeof e.disposer!=`function`)throw new O(`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 new O(`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 new O(`Invalid FluxionModule, "middlewares" must be an array of functions if provided`);return{...e,type:0}}function He(e){if(typeof e!=`function`)throw new O(`Invalid FluxionMiddleware, expected a function but got ${typeof e}`);return e}function Ue(e){if(typeof e!=`function`)throw new O(`Invalid FluxionLoggerFn, expected a function but got ${typeof e}`);return e}exports.BadGatewayException=xe,exports.BadRequestException=R,exports.ConflictException=me,exports.ForbiddenException=B,exports.GatewayTimeoutException=Ce,exports.GoneException=he,exports.HttpCode=E,exports.HttpException=L,exports.InternalServerErrorException=ye,exports.MethodNotAllowedException=H,exports.NotAcceptableException=fe,exports.NotFoundException=V,exports.NotImplementedException=be,exports.PayloadTooLargeException=U,exports.RequestTimeoutException=pe,exports.ServiceUnavailableException=Se,exports.TooManyRequestsException=ve,exports.UnauthorizedException=z,exports.UnprocessableEntityException=_e,exports.UnsupportedMediaTypeException=ge,exports.VERSION=`0.1.1`,exports.defineFluxionLogger=Ue,exports.defineFluxionMiddleware=He,exports.defineFluxionModule=Ve,exports.defineFluxionOptions=A,exports.fluxion=Be;
8
+ NEW: { apiInclude: ["**/*.ts"], staticInclude: ["**/*.js"] }`);let{dir:t,host:n,port:r,handlerTimeoutMs:i=5e3,middlewareTimeoutMs:a=3e3,staticResourceTimeoutMs:o=180*1e3,target:s=`node${process.versions.node.split(`.`)[0]}`,maxRequestBytes:u=8e6,apiInclude:d=[`**/*.ts`],staticInclude:f=[`**/*`],exclude:p=[`**/node_modules/**`,`**/.git/**`,`**/dist/**`,`**/build/**`,`**/.vscode/**`,`**/.idea/**`,`**/*.log`,`**/.DS_Store`,`**/coverage/**`,`**/.nyc_output/**`,`**/*.tmp`,`**/*.temp`],https:m,csp:h=`default-src 'self'`,restartMemoryMB:g=!1,logOutputFile:_}=e,v=r,y=e.logger??`json-line`;if(y!==`json-line`&&typeof y!=`function`)throw new k(`Invalid logger option, Must be 'json-line' or a custom logger function (write a one-line logger yourself)`);if(typeof t!=`string`)throw new k(`FluxionOptions.dir must be a string`);let b=l.default.resolve(process.cwd(),t),x=b.endsWith(l.default.sep)?b:b+l.default.sep;if(typeof s!=`string`&&!(Array.isArray(s)&&s.every(e=>typeof e==`string`)))throw new k(`FluxionOptions.target must be a string or an array of strings`);if(typeof n!=`string`)throw new k(`FluxionOptions.host must be a string`);if(!Number.isSafeInteger(i)||i<=100)throw new k(`FluxionOptions.handlerTimeoutMs must be an integer greater than 100`);if(!Number.isSafeInteger(a)||a<=100)throw new k(`FluxionOptions.middlewareTimeoutMs must be an integer greater than 100`);if(typeof v!=`number`||!Number.isSafeInteger(v))throw new k(`FluxionOptions.port must be a positive integer`);if(v<=1||v>65535)throw new k(`FluxionOptions.port must be 1 ~ 65535`);if(typeof u!=`number`||u<=0||!Number.isSafeInteger(u))throw new k(`FluxionOptions.maxRequestBytes must be a positive integer`);if(h!==!1&&typeof h!=`string`)throw new k(`FluxionOptions.csp must be a string or false`);if(g!==!1&&(typeof g!=`number`||!Number.isFinite(g)||g<=0))throw new k(`FluxionOptions.restartMemoryMB must be a positive number of MB, or false`);if(_!==void 0&&(typeof _!=`string`||_.length===0))throw new k(`FluxionOptions.logOutputFile must be a non-empty string path`);let S=_===void 0?void 0:l.default.resolve(process.cwd(),_);c.default.existsSync(x)||c.default.mkdirSync(x,{recursive:!0});let C={dir:x,host:n,port:v,handlerTimeoutMs:i,middlewareTimeoutMs:a,staticResourceTimeoutMs:o,target:s,maxRequestBytes:u,logger:y,logOutputFile:S,apiInclude:d,staticInclude:f,exclude:p,https:ue(m),csp:h,restartMemoryMB:g,normalizedFlag:D.OptionsNormalized};return process.argv.includes(`--verbose`)&&console.log(`normalized options`,{...C,https:C.https?`set`:`unset`}),C}function M(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 de(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 N(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 P(e){if(e!==void 0)try{return new URL(e,`http://fluxion.local`)}catch{return}}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 L(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 R=class extends Error{errno;code;constructor(e,t,n){super(e),this.name=`HttpException`,this.errno=t,this.code=n}},z=class extends R{constructor(e=`Bad Request`){super(e,400,`BAD_REQUEST`)}},B=class extends R{constructor(e=`Unauthorized`){super(e,401,`UNAUTHORIZED`)}},V=class extends R{constructor(e=`Forbidden`){super(e,403,`FORBIDDEN`)}},H=class extends R{constructor(e=`Not Found`){super(e,404,`NOT_FOUND`)}},fe=class extends R{constructor(e=`Method Not Allowed`){super(e,405,`METHOD_NOT_ALLOWED`)}},pe=class extends R{constructor(e=`Not Acceptable`){super(e,406,`NOT_ACCEPTABLE`)}},me=class extends R{constructor(e=`Request Timeout`){super(e,408,`REQUEST_TIMEOUT`)}},he=class extends R{constructor(e=`Conflict`){super(e,409,`CONFLICT`)}},ge=class extends R{constructor(e=`Gone`){super(e,410,`GONE`)}},U=class extends R{constructor(e=`Payload Too Large`){super(e,413,`PAYLOAD_TOO_LARGE`)}},_e=class extends R{constructor(e=`Unsupported Media Type`){super(e,415,`UNSUPPORTED_MEDIA_TYPE`)}},ve=class extends R{constructor(e=`Unprocessable Entity`){super(e,422,`UNPROCESSABLE_ENTITY`)}},ye=class extends R{constructor(e=`Too Many Requests`){super(e,429,`TOO_MANY_REQUESTS`)}},be=class extends R{constructor(e=`Internal Server Error`){super(e,500,`INTERNAL_SERVER_ERROR`)}},xe=class extends R{constructor(e=`Not Implemented`){super(e,501,`NOT_IMPLEMENTED`)}},Se=class extends R{constructor(e=`Bad Gateway`){super(e,502,`BAD_GATEWAY`)}},Ce=class extends R{constructor(e=`Service Unavailable`){super(e,503,`SERVICE_UNAVAILABLE`)}},we=class extends R{constructor(e=`Gateway Timeout`){super(e,504,`GATEWAY_TIMEOUT`)}};function W(e,t){return new U(`request body too large: ${e.toString()} bytes exceeds ${t.toString()} bytes`)}function G(e){return Array.isArray(e)?e[0]:e}function K(){return{exists:!1,bytes:0,truncated:!1}}function Te(e,t,n,r){return t===0?K():N(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:K()};let i=G(e.headers[`content-length`]),a=i===void 0?NaN:Number.parseInt(i,10);return new Promise((t,i)=>{let o=[],s=[],c=0,l=0,u=!1,d=!1,f=()=>{e.off(`data`,m),e.off(`end`,h),e.off(`error`,g),e.off(`aborted`,_)},p=e=>{d||(d=!0,e())};if(Number.isFinite(a)&&a>n){f(),e.resume(),p(()=>i(W(a,n)));return}let m=t=>{let a=Buffer.isBuffer(t)?t:Buffer.from(t);if(c+=a.byteLength,c>n){f(),e.resume(),p(()=>i(W(c,n)));return}if(o.push(a),l<r){let e=r-l,t=a.subarray(0,e);s.push(t),l+=t.length,t.length<a.length&&(u=!0)}else u=!0},h=()=>{f(),p(()=>{let n=o.length>0?Buffer.concat(o):void 0;t({rawBody:n,preview:Te(s.length>0?Buffer.concat(s):Buffer.alloc(0),n?.byteLength??0,G(e.headers[`content-type`]),u)})})},g=e=>{f(),p(()=>i(e))},_=()=>{f(),p(()=>i(Error(`request aborted while reading body`)))};e.on(`data`,m),e.once(`end`,h),e.once(`error`,g),e.once(`aborted`,_)})}async function q(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=G(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:L(new URLSearchParams(r.toString(`utf8`))),preview:i}:N(a)?{body:{raw:r.toString(`utf8`)},preview:i}:{body:{},preview:i}}function De(e){if(!e)return{};let t={},n=e.split(`;`),r=0;for(let e of n){if(r>=100)break;let[n,...i]=e.split(`=`);if(!n)continue;let a=n.trim(),o=i.join(`=`).trim();t[a]=decodeURIComponent(o),r++}return t}const J=(e,t,n)=>Promise.race([e,new Promise(e=>setTimeout(()=>e(n),t))]);function Oe(e,t,n){if(typeof n.disposer!=`function`)return;let r=n.disposer;t.once(`close`,()=>{M(r).catch(t=>{e.logger.error({event:`DisposerFailed`,url:n.absolutePath,error:b(t)})})})}function ke(e){let t=Object.freeze({logger:e.logger}),n=async(n,r)=>{let i=n.method??`GET`,a=de(n),o=P(n.url);if(o===void 0){I(r,{message:`Bad Request: req.url is undefined`},400);return}let s={method:i,ip:a,url:o,query:L(o.searchParams),body:{},headers:n.headers,cookie:De(n.headers.cookie),meta:{}};r.setHeader(`X-Content-Type-Options`,`nosniff`),r.setHeader(`X-Frame-Options`,`DENY`),r.setHeader(`X-XSS-Protection`,`1; mode=block`),e.options.csp!==!1&&r.setHeader(`Content-Security-Policy`,e.options.csp);let c={exists:!1,bytes:0,truncated:!1};e.logger.core({event:`request`,method:i,ip:a,path:o.pathname});let l=performance.now();r.once(`finish`,()=>{let t={event:`response`,method:i,ip:a,path:o.pathname,status:r.statusCode,duration:(performance.now()-l).toFixed(4)};Object.keys(s.query).length>0&&(t.query=s.query),c.exists&&(t.body=c.value,t.bodyBytes=c.bytes,t.bodyTruncated=c.truncated),e.logger.core(t)});try{let i=await q(n,s.method,e.options.maxRequestBytes);s.body=i.body,c=i.preview;let a=await e.router(o);if(!a){I(r,{message:`Not Found`},404);return}if(n.method&&a.methods&&!a.methods.includes(n.method)){I(r,{message:`Method Not Allowed`},405);return}Oe(e,r,a);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 J(M(a.middlewares[i],s,t,n,r),e.options.middlewareTimeoutMs,D.MiddlewareTimeout)===D.MiddlewareTimeout){e.logger.warn({event:`MiddlewareTimeout`,method:s.method,ip:s.ip}),I(r,{message:`Internal Server Error`},500);return}if(r.writableEnded)return;if(r.headersSent){r.end();return}}let u=await J(M(a.handler,s,t,n,r),l,D.HandlerTimeout);if(u===D.HandlerTimeout){e.logger.warn({event:`HandlerTimeout`,method:s.method,ip:s.ip}),I(r,{message:`Handler timed out`},500);return}u!==D.StaticHandled&&I(r,u)}catch(t){t instanceof R?(e.logger.error({...s,event:`RequestFailed`,error:t.message}),I(r,{message:t.message},t.errno)):(e.logger.error({...s,event:`RequestFailed`,error:b(t)}),I(r,{message:`Internal Server Error`},500))}},r=e.options.https?f.default.createServer({key:e.options.https.key,cert:e.options.https.cert,ca:e.options.https.ca},n):d.default.createServer(n);return new Promise((t,n)=>{let i=!1;r.on(`close`,()=>{e.logger.core({event:`ServerClosed`,host:e.options.host,port:e.options.port})}),r.once(`listening`,()=>{i=!0,e.logger.core({event:`FluxionStarted`,version:`0.1.2`,pid:process.pid,protocol:e.options.https?`https`:`http`,host:e.options.host,port:e.options.port}),e.logger.core({event:`DynamicDirectory`,directory:e.options.dir}),t(r)}),r.on(`error`,t=>{e.logger.error({event:`ServerError`,error:b(t)}),!i&&n(t)}),r.listen(e.options.port,e.options.host)})}function Ae(e){}const je=Ae,Y=new Map,Me=`${l.sep}node_modules${l.sep}`,X=new Set([`.ts`,`.tsx`,`.mts`,`.cts`,`.js`,`.jsx`,`.mjs`,`.cjs`]),Z=[...X,`.json`],Ne={".js":[`.ts`,`.tsx`],".jsx":[`.tsx`],".mjs":[`.mts`],".cjs":[`.cts`]},Pe=e=>!e.startsWith(`.`)&&!(0,l.isAbsolute)(e),Fe=e=>{try{let t=(0,c.statSync)(e.filename);return t.mtimeMs!==e.mtimeMs||t.size!==e.size}catch{return!0}},Q=e=>{try{return(0,c.statSync)(e).isFile()}catch{return!1}},Ie=e=>{if(Q(e))return e;let t=(0,l.extname)(e),n=e.slice(0,e.length-t.length);for(let e of Ne[t]??[])if(Q(n+e))return n+e;for(let t of Z)if(Q(e+t))return e+t;for(let t of Z)if(Q((0,l.join)(e,`index`+t)))return(0,l.join)(e,`index`+t)};var Le=class{opts;constructor(e){this.opts=e}compile(e){let{outputFiles:t}=(0,m.buildSync)({entryPoints:[e],bundle:!1,write:!1,platform:`node`,format:`cjs`,target:this.opts.target,sourcemap:`inline`,sourcesContent:!1,logLevel:`silent`,supported:{"dynamic-import":!1},define:{"import.meta.url":JSON.stringify((0,_.pathToFileURL)(e).href),"import.meta.filename":JSON.stringify(e),"import.meta.dirname":JSON.stringify((0,l.dirname)(e))}});return t[0].text}require(e){return this.load((0,l.resolve)(e)).exports}isHot(e){let t=(0,l.extname)(e);return e.startsWith(this.opts.dir)&&!e.includes(Me)&&(X.has(t)||t===`.json`)}load(e){let t=Y.get(e);if(t===void 0)return this.loadFresh(e);let n=this.collectChain(t);if(!this.anyStale(n))return t;for(let e of n)Y.get(e.filename)===e&&Y.delete(e.filename);return this.loadFresh(e)}collectChain(e){let t=new Set([e]);for(let e of t)for(let n of e.deps.values())t.add(n);return t}anyStale(e){for(let t of e)if(Y.get(t.filename)!==t||Fe(t))return!0;return!1}loadFresh(e){let{mtimeMs:t,size:n}=(0,c.statSync)(e),r={id:e,filename:e,exports:{},mtimeMs:t,size:n,deps:new Map};Y.set(e,r);try{this.evaluate(e,r)}catch(t){throw Y.delete(e),t}return r}evaluate(e,t){let n=(0,l.extname)(e);if(n===`.json`){t.exports=JSON.parse((0,c.readFileSync)(e,`utf8`));return}if(!X.has(n))throw Error(`FluxionLoader: unsupported file type "${n}" (${e})`);(0,h.compileFunction)(this.compile(e),[`exports`,`require`,`module`,`__filename`,`__dirname`],{filename:e}).call(t.exports,t.exports,this.createModuleRequire(t),t,e,(0,l.dirname)(e))}createModuleRequire(e){let t=(0,g.createRequire)(e.filename),n=t=>Pe(t)?void 0:Ie((0,l.resolve)((0,l.dirname)(e.filename),t)),r=r=>{let i=n(r);if(i===void 0)return t(r);if(!this.isHot(i))return t(i);let a=this.load(i);return e.deps.set(i,a),a.exports};return r.resolve=e=>n(e)??t.resolve(e),r.cache=t.cache,r}};function $(e,t){if(typeof t!=`object`||!t)return!1;if(je(t),typeof t.handler!=`function`)return e.logger.error({event:`InvalidModule`,error:`handler must be a function`}),!1;if(t.disposer!==void 0&&typeof t.disposer!=`function`)return e.logger.error({event:`InvalidModule`,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({event:`InvalidModule`,error:`handlerTimeoutMs must be an integer >= 100 if provided`}),!1):t.type===0?!0:(e.logger.error({event:`InvalidModule`,error:`You must use defineFluxionModule to create module`}),!1)}function Re(e,t,n){let r=new Le(e.options).require(t);if($(e,r.default))r=r.default;else if(!$(e,r))throw new k(`Invalid handler module '${t}', make sure it satisfies defineFluxionModule(...) helper`);return r.absolutePath=t,r.mtimeMs=n.mtimeMs,r}function ze(e){return async t=>{let n=t.pathname.replace(/^[/]+/,``).replace(/[/]+$/,``),r=l.default.join(e.options.dir,n),i=l.default.relative(e.options.dir,r);if(i.startsWith(`..`)||l.default.isAbsolute(i)||e.options.exclude.some(e=>(0,p.minimatch)(n,e)))return;let a=await u.default.stat(r).catch(()=>void 0);if(!(!a||!a.isFile())){if(e.options.apiInclude.some(e=>(0,p.minimatch)(n,e)))return Re(e,r,a);if(e.options.staticInclude.some(e=>(0,p.minimatch)(n,e)))return Be(r)}}}function Be(e){return{type:1,mtimeMs:NaN,absolutePath:e,handler:async(t,n,r,i)=>{if(t.method!==`GET`&&t.method!==`HEAD`){i.statusCode=405,i.setHeader(`Allow`,`GET, HEAD`),i.end();return}let a=await u.default.stat(e).catch(e=>e);if(a instanceof Error)return i.statusCode=404,i.end(`Not Accessible`),n.logger.error({event:`StaticResourceError`,url:t.url.pathname,error:a.message}),null;if(!a.isFile()){i.statusCode=404,i.end(`Not Found`);return}let o=re[l.default.extname(e).toLowerCase()]??`application/octet-stream`;if(i.statusCode=200,i.setHeader(`Content-Type`,o),i.setHeader(`Content-Length`,String(a.size)),t.method===`HEAD`){i.end();return}return new Promise((t,n)=>{let a=(0,c.createReadStream)(e),o=()=>{a.off(`error`,s),a.off(`end`,l),i.off(`close`,u),r.off(`aborted`,u)},s=e=>{o(),n(e)},l=()=>{o(),t(D.StaticHandled)},u=()=>{o(),a.destroy(),t(D.StaticHandled)};a.on(`error`,s),a.on(`end`,l),i.on(`close`,u),r.on(`aborted`,u),a.pipe(i)})}}}async function Ve(e){let t={options:e.normalizedFlag===D.OptionsNormalized?e:j(e)};t.options.logOutputFile&&await E(t.options.logOutputFile);let n=t.options.restartMemoryMB!==!1&&oe();t.logger=T(t,{deferClose:n}),t.router=ze(t);let r=await ke(t);t.options.restartMemoryMB!==!1&&!n&&t.logger.warn({event:`RestartDisabled`,reason:`process.execve is not available on this Node.js version`,requiredVersion:`22.15`,nodeVersion:process.version,restartMemoryMB:t.options.restartMemoryMB});let i=O({restartMemoryMB:n?t.options.restartMemoryMB:!1,server:r,logger:t.logger}),a=e=>{i.stop(),t.logger.warn({event:`ShuttingDown`,pid:process.pid,signal:e}),r.close(async()=>{await t.logger.flush(),process.exit(0)})};process.once(`SIGINT`,()=>a(`SIGINT`)),process.once(`SIGTERM`,()=>a(`SIGTERM`)),i.start()}function He(e,t){if(typeof e==`function`){if(t!==void 0&&typeof t!=`function`)throw new k(`Invalid disposer, expected a function but got ${typeof t}`);return{handler:e,disposer:t,type:0}}if(typeof e!=`object`||!e)throw new k(`Invalid argument, expected a FluxionModule object or a handler function, but got ${typeof e}`);if(typeof e.handler!=`function`)throw new k(`Invalid FluxionModule, "handler" must be a function`);if(e.disposer!==void 0&&typeof e.disposer!=`function`)throw new k(`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 new k(`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 new k(`Invalid FluxionModule, "middlewares" must be an array of functions if provided`);return{...e,type:0}}function Ue(e){if(typeof e!=`function`)throw new k(`Invalid FluxionMiddleware, expected a function but got ${typeof e}`);return e}function We(e){if(typeof e!=`function`)throw new k(`Invalid FluxionLoggerFn, expected a function but got ${typeof e}`);return e}exports.BadGatewayException=Se,exports.BadRequestException=z,exports.ConflictException=he,exports.ForbiddenException=V,exports.GatewayTimeoutException=we,exports.GoneException=ge,exports.HttpCode=ie,exports.HttpException=R,exports.InternalServerErrorException=be,exports.MethodNotAllowedException=fe,exports.NotAcceptableException=pe,exports.NotFoundException=H,exports.NotImplementedException=xe,exports.PayloadTooLargeException=U,exports.RequestTimeoutException=me,exports.ServiceUnavailableException=Ce,exports.TooManyRequestsException=ye,exports.UnauthorizedException=B,exports.UnprocessableEntityException=ve,exports.UnsupportedMediaTypeException=_e,exports.VERSION=`0.1.2`,exports.defineFluxionLogger=We,exports.defineFluxionMiddleware=Ue,exports.defineFluxionModule=He,exports.defineFluxionOptions=j,exports.fluxion=Ve;
9
9
  //# sourceMappingURL=index.cjs.map