molnos 1.1.0 → 1.2.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/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0
1
+ 1.2.0
@@ -1,11 +1,11 @@
1
1
  // MolnOS Core - See LICENSE file for copyright and license details.
2
- var N=class{requests=new Map;limit;windowMs;constructor(e=100,t=60){this.limit=e,this.windowMs=t*1e3,setInterval(()=>this.cleanup(),this.windowMs)}getLimit(){return this.limit}isAllowed(e){let t=Date.now(),s=e||"unknown",r=this.requests.get(s);return(!r||r.resetTime<t)&&(r={count:0,resetTime:t+this.windowMs},this.requests.set(s,r)),r.count++,r.count<=this.limit}getRemainingRequests(e){let t=Date.now(),s=e||"unknown",r=this.requests.get(s);return!r||r.resetTime<t?this.limit:Math.max(0,this.limit-r.count)}getResetTime(e){let t=Date.now(),s=e||"unknown",r=this.requests.get(s);return!r||r.resetTime<t?Math.floor((t+this.windowMs)/1e3):Math.floor(r.resetTime/1e3)}cleanup(){let e=Date.now();for(let[t,s]of this.requests.entries())s.resetTime<e&&this.requests.delete(t)}};import{URL as ue}from"url";var D=class{routes=[];globalMiddlewares=[];pathPatterns=new Map;use(e){return this.globalMiddlewares.push(e),this}get(e,...t){let s=t.pop();return this.register("GET",e,s,t)}post(e,...t){let s=t.pop();return this.register("POST",e,s,t)}put(e,...t){let s=t.pop();return this.register("PUT",e,s,t)}delete(e,...t){let s=t.pop();return this.register("DELETE",e,s,t)}patch(e,...t){let s=t.pop();return this.register("PATCH",e,s,t)}any(e,...t){let s=t.pop(),r=t;return this.register("GET",e,s,r),this.register("POST",e,s,r),this.register("PUT",e,s,r),this.register("DELETE",e,s,r),this.register("PATCH",e,s,r),this.register("OPTIONS",e,s,r),this}options(e,...t){let s=t.pop();return this.register("OPTIONS",e,s,t)}match(e,t){for(let s of this.routes){if(s.method!==e)continue;let r=this.pathPatterns.get(s.path);if(!r)continue;let i=r.pattern.exec(t);if(!i)continue;let n={};return r.paramNames.forEach((o,a)=>{n[o]=i[a+1]||""}),{route:s,params:n}}return null}async handle(e,t){let s=e.method||"GET",r=new ue(e.url||"/",`http://${e.headers.host}`),i=r.pathname,n=this.match(s,i);if(!n)return null;let{route:o,params:a}=n,l={};r.searchParams.forEach((c,u)=>{l[u]=c});let d={req:e,res:t,params:a,query:l,body:e.body||{},headers:e.headers,path:i,state:{},raw:()=>t,binary:(c,u="application/octet-stream",y=200)=>({statusCode:y,body:c,headers:{"Content-Type":u,"Content-Length":c.length.toString()},isRaw:!0}),text:(c,u=200)=>({statusCode:u,body:c,headers:{"Content-Type":"text/plain"}}),form:(c,u=200)=>({statusCode:u,body:c,headers:{"Content-Type":"application/x-www-form-urlencoded"}}),json:(c,u=200)=>({statusCode:u,body:c,headers:{"Content-Type":"application/json"}}),html:(c,u=200)=>({statusCode:u,body:c,headers:{"Content-Type":"text/html"}}),redirect:(c,u=302)=>({statusCode:u,body:null,headers:{Location:c}}),status:function(c){return{raw:()=>t,binary:(u,y="application/octet-stream")=>({statusCode:c,body:u,headers:{"Content-Type":y,"Content-Length":u.length.toString()},isRaw:!0}),text:u=>({statusCode:c,body:u,headers:{"Content-Type":"text/plain"}}),json:u=>({statusCode:c,body:u,headers:{"Content-Type":"application/json"}}),html:u=>({statusCode:c,body:u,headers:{"Content-Type":"text/html"}}),form:u=>({statusCode:c,body:u,headers:{"Content-Type":"application/x-www-form-urlencoded"}}),redirect:(u,y=302)=>({statusCode:y,body:null,headers:{Location:u}}),status:u=>this.status(u)}}},f=[...this.globalMiddlewares,...o.middlewares];return this.executeMiddlewareChain(d,f,o.handler)}register(e,t,s,r=[]){return this.routes.push({method:e,path:t,handler:s,middlewares:r}),this.pathPatterns.set(t,this.createPathPattern(t)),this}createPathPattern(e){let t=[],s=e.replace(/\/:[^/]+/g,r=>{let i=r.slice(2);return t.push(i),"/([^/]+)"});return s.endsWith("/*")?(s=`${s.slice(0,-2)}(?:/(.*))?`,t.push("wildcard")):s=s.replace(/\/$/,"/?"),{pattern:new RegExp(`^${s}$`),paramNames:t}}async executeMiddlewareChain(e,t,s){let r=0,i=async()=>{if(r<t.length){let n=t[r++];return n(e,i)}return s(e)};return i()}};var E=()=>({port:Number(process.env.PORT)||3e3,host:process.env.HOST||"0.0.0.0",useHttps:!1,useHttp2:!1,sslCert:"",sslKey:"",sslCa:"",debug:fe(process.env.DEBUG)||!1,maxBodySize:1048576,requestTimeout:3e4,rateLimit:{enabled:!0,requestsPerMinute:100},allowedDomains:["*"]});function fe(e){return e==="true"||e===!0}var A=class extends Error{constructor(e){super(e),this.name="ValidationError",this.message=e||"Validation did not pass",this.cause={statusCode:400}}};import{existsSync as he,readFileSync as pe}from"node:fs";var O=class{config={};options=[];validators=[];autoValidate=!0;constructor(e){let t=e?.configFilePath,s=e?.args||[],r=e?.config||{};this.options=e?.options||[],this.validators=e?.validators||[],e?.autoValidate!==void 0&&(this.autoValidate=e.autoValidate),this.config=this.createConfig(t,s,r)}deepMerge(e,t){let s={...e};for(let r in t)t[r]!==void 0&&(t[r]!==null&&typeof t[r]=="object"&&!Array.isArray(t[r])&&r in e&&e[r]!==null&&typeof e[r]=="object"&&!Array.isArray(e[r])?s[r]=this.deepMerge(e[r],t[r]):t[r]!==void 0&&(s[r]=t[r]));return s}setValueAtPath(e,t,s){let r=t.split("."),i=e;for(let o=0;o<r.length-1;o++){let a=r[o];!(a in i)||i[a]===null?i[a]={}:typeof i[a]!="object"&&(i[a]={}),i=i[a]}let n=r[r.length-1];i[n]=s}getValueAtPath(e,t){let s=t.split("."),r=e;for(let i of s){if(r==null)return;r=r[i]}return r}createConfig(e,t=[],s={}){let r={};for(let a of this.options)a.defaultValue!==void 0&&this.setValueAtPath(r,a.path,a.defaultValue);let i={};if(e&&he(e))try{let a=pe(e,"utf8");i=JSON.parse(a),console.log(`Loaded configuration from ${e}`)}catch(a){console.error(`Error reading config file: ${a instanceof Error?a.message:String(a)}`)}let n=this.parseCliArgs(t),o=this.deepMerge({},r);return o=this.deepMerge(o,i),o=this.deepMerge(o,s),o=this.deepMerge(o,n),o}parseCliArgs(e){let t={},s=e[0]?.endsWith("node")||e[0]?.endsWith("node.exe")?2:0;for(;s<e.length;){let r=e[s++],i=this.options.find(n=>n.flag===r);if(i)if(i.isFlag)this.setValueAtPath(t,i.path,!0);else if(s<e.length&&!e[s].startsWith("-")){let n=e[s++];if(i.parser)try{n=i.parser(n)}catch(o){console.error(`Error parsing value for ${i.flag}: ${o instanceof Error?o.message:String(o)}`);continue}if(i.validator){let o=i.validator(n);if(o!==!0&&typeof o=="string"){console.error(`Invalid value for ${i.flag}: ${o}`);continue}if(o===!1){console.error(`Invalid value for ${i.flag}`);continue}}this.setValueAtPath(t,i.path,n)}else console.error(`Missing value for option ${r}`)}return t}validate(){for(let e of this.validators){let t=this.getValueAtPath(this.config,e.path),s=e.validator(t,this.config);if(s===!1)throw new A(e.message);if(typeof s=="string")throw new A(s)}}get(){return this.autoValidate&&this.validate(),this.config}getValue(e,t){let s=this.getValueAtPath(this.config,e);return s!==void 0?s:t}setValue(e,t){if(typeof t=="object"&&t!==null&&!Array.isArray(t)){let s=this.getValueAtPath(this.config,e)||{};if(typeof s=="object"&&!Array.isArray(s)){let r=this.deepMerge(s,t);this.setValueAtPath(this.config,e,r);return}}this.setValueAtPath(this.config,e,t)}getHelpText(){let e=`Available configuration options:
2
+ var D=class{requests=new Map;limit;windowMs;constructor(t=100,e=60){this.limit=t,this.windowMs=e*1e3,setInterval(()=>this.cleanup(),this.windowMs)}getLimit(){return this.limit}isAllowed(t){let e=Date.now(),s=t||"unknown",r=this.requests.get(s);return(!r||r.resetTime<e)&&(r={count:0,resetTime:e+this.windowMs},this.requests.set(s,r)),r.count++,r.count<=this.limit}getRemainingRequests(t){let e=Date.now(),s=t||"unknown",r=this.requests.get(s);return!r||r.resetTime<e?this.limit:Math.max(0,this.limit-r.count)}getResetTime(t){let e=Date.now(),s=t||"unknown",r=this.requests.get(s);return!r||r.resetTime<e?Math.floor((e+this.windowMs)/1e3):Math.floor(r.resetTime/1e3)}cleanup(){let t=Date.now();for(let[e,s]of this.requests.entries())s.resetTime<t&&this.requests.delete(e)}};import{URL as ht}from"url";var q=class{routes=[];globalMiddlewares=[];pathPatterns=new Map;use(t){return this.globalMiddlewares.push(t),this}get(t,...e){let s=e.pop();return this.register("GET",t,s,e)}post(t,...e){let s=e.pop();return this.register("POST",t,s,e)}put(t,...e){let s=e.pop();return this.register("PUT",t,s,e)}delete(t,...e){let s=e.pop();return this.register("DELETE",t,s,e)}patch(t,...e){let s=e.pop();return this.register("PATCH",t,s,e)}any(t,...e){let s=e.pop(),r=e;return this.register("GET",t,s,r),this.register("POST",t,s,r),this.register("PUT",t,s,r),this.register("DELETE",t,s,r),this.register("PATCH",t,s,r),this.register("OPTIONS",t,s,r),this}options(t,...e){let s=e.pop();return this.register("OPTIONS",t,s,e)}match(t,e){for(let s of this.routes){if(s.method!==t)continue;let r=this.pathPatterns.get(s.path);if(!r)continue;let i=r.pattern.exec(e);if(!i)continue;let n={};return r.paramNames.forEach((o,a)=>{n[o]=i[a+1]||""}),{route:s,params:n}}return null}async handle(t,e){let s=t.method||"GET",r=new ht(t.url||"/",`http://${t.headers.host}`),i=r.pathname,n=this.match(s,i);if(!n)return null;let{route:o,params:a}=n,c={};r.searchParams.forEach((d,u)=>{c[u]=d});let l={req:t,res:e,params:a,query:c,body:t.body||{},headers:t.headers,path:i,state:{},raw:()=>e,binary:(d,u="application/octet-stream",y=200)=>({statusCode:y,body:d,headers:{"Content-Type":u,"Content-Length":d.length.toString()},isRaw:!0}),text:(d,u=200)=>({statusCode:u,body:d,headers:{"Content-Type":"text/plain"}}),form:(d,u=200)=>({statusCode:u,body:d,headers:{"Content-Type":"application/x-www-form-urlencoded"}}),json:(d,u=200)=>({statusCode:u,body:d,headers:{"Content-Type":"application/json"}}),html:(d,u=200)=>({statusCode:u,body:d,headers:{"Content-Type":"text/html"}}),redirect:(d,u=302)=>({statusCode:u,body:null,headers:{Location:d}}),status:function(d){return{raw:()=>e,binary:(u,y="application/octet-stream")=>({statusCode:d,body:u,headers:{"Content-Type":y,"Content-Length":u.length.toString()},isRaw:!0}),text:u=>({statusCode:d,body:u,headers:{"Content-Type":"text/plain"}}),json:u=>({statusCode:d,body:u,headers:{"Content-Type":"application/json"}}),html:u=>({statusCode:d,body:u,headers:{"Content-Type":"text/html"}}),form:u=>({statusCode:d,body:u,headers:{"Content-Type":"application/x-www-form-urlencoded"}}),redirect:(u,y=302)=>({statusCode:y,body:null,headers:{Location:u}}),status:u=>this.status(u)}}},f=[...this.globalMiddlewares,...o.middlewares];return this.executeMiddlewareChain(l,f,o.handler)}register(t,e,s,r=[]){return this.routes.push({method:t,path:e,handler:s,middlewares:r}),this.pathPatterns.set(e,this.createPathPattern(e)),this}createPathPattern(t){let e=[],s=t.replace(/\/:[^/]+/g,r=>{let i=r.slice(2);return e.push(i),"/([^/]+)"});return s.endsWith("/*")?(s=`${s.slice(0,-2)}(?:/(.*))?`,e.push("wildcard")):s=s.replace(/\/$/,"/?"),{pattern:new RegExp(`^${s}$`),paramNames:e}}async executeMiddlewareChain(t,e,s){let r=0,i=async()=>{if(r<e.length){let n=e[r++];return n(t,i)}return s(t)};return i()}};var E=()=>({port:Number(process.env.PORT)||3e3,host:process.env.HOST||"0.0.0.0",useHttps:!1,useHttp2:!1,sslCert:"",sslKey:"",sslCa:"",debug:pt(process.env.DEBUG)||!1,maxBodySize:1048576,requestTimeout:3e4,rateLimit:{enabled:!0,requestsPerMinute:100},allowedDomains:["*"]});function pt(t){return t==="true"||t===!0}var $=class extends Error{constructor(t){super(t),this.name="ValidationError",this.message=t||"Validation did not pass",this.cause={statusCode:400}}};import{existsSync as mt,readFileSync as yt}from"node:fs";var I=class{config={};options=[];validators=[];autoValidate=!0;constructor(t){let e=t?.configFilePath,s=t?.args||[],r=t?.config||{};this.options=t?.options||[],this.validators=t?.validators||[],t?.autoValidate!==void 0&&(this.autoValidate=t.autoValidate),this.config=this.createConfig(e,s,r)}deepMerge(t,e){let s={...t};for(let r in e)e[r]!==void 0&&(e[r]!==null&&typeof e[r]=="object"&&!Array.isArray(e[r])&&r in t&&t[r]!==null&&typeof t[r]=="object"&&!Array.isArray(t[r])?s[r]=this.deepMerge(t[r],e[r]):e[r]!==void 0&&(s[r]=e[r]));return s}setValueAtPath(t,e,s){let r=e.split("."),i=t;for(let o=0;o<r.length-1;o++){let a=r[o];!(a in i)||i[a]===null?i[a]={}:typeof i[a]!="object"&&(i[a]={}),i=i[a]}let n=r[r.length-1];i[n]=s}getValueAtPath(t,e){let s=e.split("."),r=t;for(let i of s){if(r==null)return;r=r[i]}return r}createConfig(t,e=[],s={}){let r={};for(let a of this.options)a.defaultValue!==void 0&&this.setValueAtPath(r,a.path,a.defaultValue);let i={};if(t&&mt(t))try{let a=yt(t,"utf8");i=JSON.parse(a),console.log(`Loaded configuration from ${t}`)}catch(a){console.error(`Error reading config file: ${a instanceof Error?a.message:String(a)}`)}let n=this.parseCliArgs(e),o=this.deepMerge({},r);return o=this.deepMerge(o,i),o=this.deepMerge(o,s),o=this.deepMerge(o,n),o}parseCliArgs(t){let e={},s=t[0]?.endsWith("node")||t[0]?.endsWith("node.exe")?2:0;for(;s<t.length;){let r=t[s++],i=this.options.find(n=>n.flag===r);if(i)if(i.isFlag)this.setValueAtPath(e,i.path,!0);else if(s<t.length&&!t[s].startsWith("-")){let n=t[s++];if(i.parser)try{n=i.parser(n)}catch(o){console.error(`Error parsing value for ${i.flag}: ${o instanceof Error?o.message:String(o)}`);continue}if(i.validator){let o=i.validator(n);if(o!==!0&&typeof o=="string"){console.error(`Invalid value for ${i.flag}: ${o}`);continue}if(o===!1){console.error(`Invalid value for ${i.flag}`);continue}}this.setValueAtPath(e,i.path,n)}else console.error(`Missing value for option ${r}`)}return e}validate(){for(let t of this.validators){let e=this.getValueAtPath(this.config,t.path),s=t.validator(e,this.config);if(s===!1)throw new $(t.message);if(typeof s=="string")throw new $(s)}}get(){return this.autoValidate&&this.validate(),this.config}getValue(t,e){let s=this.getValueAtPath(this.config,t);return s!==void 0?s:e}setValue(t,e){if(typeof e=="object"&&e!==null&&!Array.isArray(e)){let s=this.getValueAtPath(this.config,t)||{};if(typeof s=="object"&&!Array.isArray(s)){let r=this.deepMerge(s,e);this.setValueAtPath(this.config,t,r);return}}this.setValueAtPath(this.config,t,e)}getHelpText(){let t=`Available configuration options:
3
3
 
4
- `;for(let t of this.options)e+=`${t.flag}${t.isFlag?"":" <value>"}
5
- `,t.description&&(e+=` ${t.description}
6
- `),t.defaultValue!==void 0&&(e+=` Default: ${JSON.stringify(t.defaultValue)}
7
- `),e+=`
8
- `;return e}};var I={int:e=>{let t=e.trim();if(!/^[+-]?\d+$/.test(t))throw new Error(`Cannot parse "${e}" as an integer`);let s=Number.parseInt(t,10);if(Number.isNaN(s))throw new Error(`Cannot parse "${e}" as an integer`);return s},float:e=>{let t=e.trim();if(!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(t)){if(t==="Infinity"||t==="-Infinity")return t==="Infinity"?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY;throw new Error(`Cannot parse "${e}" as a number`)}let s=Number.parseFloat(t);if(Number.isNaN(s))throw new Error(`Cannot parse "${e}" as a number`);return s},boolean:e=>{let t=e.trim().toLowerCase();if(["true","yes","1","y"].includes(t))return!0;if(["false","no","0","n"].includes(t))return!1;throw new Error(`Cannot parse "${e}" as a boolean`)},array:e=>e.split(",").map(t=>t.trim()),json:e=>{try{return JSON.parse(e)}catch{throw new Error(`Cannot parse "${e}" as JSON`)}}};var g=E(),q=e=>({configFilePath:"mikroserve.config.json",args:process.argv,options:[{flag:"--port",path:"port",defaultValue:g.port},{flag:"--host",path:"host",defaultValue:g.host},{flag:"--https",path:"useHttps",defaultValue:g.useHttps,isFlag:!0},{flag:"--http2",path:"useHttp2",defaultValue:g.useHttp2,isFlag:!0},{flag:"--cert",path:"sslCert",defaultValue:g.sslCert},{flag:"--key",path:"sslKey",defaultValue:g.sslKey},{flag:"--ca",path:"sslCa",defaultValue:g.sslCa},{flag:"--ratelimit",path:"rateLimit.enabled",defaultValue:g.rateLimit.enabled,isFlag:!0},{flag:"--rps",path:"rateLimit.requestsPerMinute",defaultValue:g.rateLimit.requestsPerMinute},{flag:"--allowed",path:"allowedDomains",defaultValue:g.allowedDomains,parser:I.array},{flag:"--debug",path:"debug",defaultValue:g.debug,isFlag:!0},{flag:"--max-body-size",path:"maxBodySize",defaultValue:g.maxBodySize},{flag:"--request-timeout",path:"requestTimeout",defaultValue:g.requestTimeout}],config:e});function z(e,t){let s=t.match(/boundary=(?:"([^"]+)"|([^;]+))/i);if(!s)throw new Error("Invalid multipart/form-data: missing boundary");let r=s[1]||s[2],i=Buffer.from(`--${r}`),n=Buffer.from(`--${r}--`),o={},a={},l=me(e,i);for(let d of l){if(d.length===0||d.equals(n.subarray(i.length)))continue;let f=ye(d);if(!f)continue;let{name:c,filename:u,contentType:y,data:w}=f;if(u){let b={filename:u,contentType:y||"application/octet-stream",data:w,size:w.length};a[c]?Array.isArray(a[c])?a[c].push(b):a[c]=[a[c],b]:a[c]=b}else{let b=w.toString("utf8");o[c]?Array.isArray(o[c])?o[c].push(b):o[c]=[o[c],b]:o[c]=b}}return{fields:o,files:a}}function me(e,t){let s=[],r=0;for(;r<e.length;){let i=e.indexOf(t,r);if(i===-1)break;r!==i&&s.push(e.subarray(r,i)),r=i+t.length,r<e.length&&e[r]===13&&e[r+1]===10&&(r+=2)}return s}function ye(e){let t=Buffer.from(`\r
4
+ `;for(let e of this.options)t+=`${e.flag}${e.isFlag?"":" <value>"}
5
+ `,e.description&&(t+=` ${e.description}
6
+ `),e.defaultValue!==void 0&&(t+=` Default: ${JSON.stringify(e.defaultValue)}
7
+ `),t+=`
8
+ `;return t}};var O={int:t=>{let e=t.trim();if(!/^[+-]?\d+$/.test(e))throw new Error(`Cannot parse "${t}" as an integer`);let s=Number.parseInt(e,10);if(Number.isNaN(s))throw new Error(`Cannot parse "${t}" as an integer`);return s},float:t=>{let e=t.trim();if(!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(e)){if(e==="Infinity"||e==="-Infinity")return e==="Infinity"?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY;throw new Error(`Cannot parse "${t}" as a number`)}let s=Number.parseFloat(e);if(Number.isNaN(s))throw new Error(`Cannot parse "${t}" as a number`);return s},boolean:t=>{let e=t.trim().toLowerCase();if(["true","yes","1","y"].includes(e))return!0;if(["false","no","0","n"].includes(e))return!1;throw new Error(`Cannot parse "${t}" as a boolean`)},array:t=>t.split(",").map(e=>e.trim()),json:t=>{try{return JSON.parse(t)}catch{throw new Error(`Cannot parse "${t}" as JSON`)}}};var g=E(),z=t=>({configFilePath:"mikroserve.config.json",args:process.argv,options:[{flag:"--port",path:"port",defaultValue:g.port},{flag:"--host",path:"host",defaultValue:g.host},{flag:"--https",path:"useHttps",defaultValue:g.useHttps,isFlag:!0},{flag:"--http2",path:"useHttp2",defaultValue:g.useHttp2,isFlag:!0},{flag:"--cert",path:"sslCert",defaultValue:g.sslCert},{flag:"--key",path:"sslKey",defaultValue:g.sslKey},{flag:"--ca",path:"sslCa",defaultValue:g.sslCa},{flag:"--ratelimit",path:"rateLimit.enabled",defaultValue:g.rateLimit.enabled,isFlag:!0},{flag:"--rps",path:"rateLimit.requestsPerMinute",defaultValue:g.rateLimit.requestsPerMinute},{flag:"--allowed",path:"allowedDomains",defaultValue:g.allowedDomains,parser:O.array},{flag:"--debug",path:"debug",defaultValue:g.debug,isFlag:!0},{flag:"--max-body-size",path:"maxBodySize",defaultValue:g.maxBodySize},{flag:"--request-timeout",path:"requestTimeout",defaultValue:g.requestTimeout}],config:t});function B(t,e){let s=e.match(/boundary=(?:"([^"]+)"|([^;]+))/i);if(!s)throw new Error("Invalid multipart/form-data: missing boundary");let r=s[1]||s[2],i=Buffer.from(`--${r}`),n=Buffer.from(`--${r}--`),o={},a={},c=gt(t,i);for(let l of c){if(l.length===0||l.equals(n.subarray(i.length)))continue;let f=bt(l);if(!f)continue;let{name:d,filename:u,contentType:y,data:w}=f;if(u){let b={filename:u,contentType:y||"application/octet-stream",data:w,size:w.length};a[d]?Array.isArray(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b}else{let b=w.toString("utf8");o[d]?Array.isArray(o[d])?o[d].push(b):o[d]=[o[d],b]:o[d]=b}}return{fields:o,files:a}}function gt(t,e){let s=[],r=0;for(;r<t.length;){let i=t.indexOf(e,r);if(i===-1)break;r!==i&&s.push(t.subarray(r,i)),r=i+e.length,r<t.length&&t[r]===13&&t[r+1]===10&&(r+=2)}return s}function bt(t){let e=Buffer.from(`\r
9
9
  \r
10
- `),s=e.indexOf(t);if(s===-1)return null;let r=e.subarray(0,s),i=e.subarray(s+4),o=r.toString("utf8").split(`\r
11
- `),a="",l="",d,f;for(let u of o){let y=u.toLowerCase();if(y.startsWith("content-disposition:")){a=u.substring(20).trim();let w=a.match(/name="([^"]+)"/);w&&(l=w[1]);let b=a.match(/filename="([^"]+)"/);b&&(d=b[1])}else y.startsWith("content-type:")&&(f=u.substring(13).trim())}if(!l)return null;let c=i;return c.length>=2&&c[c.length-2]===13&&c[c.length-1]===10&&(c=c.subarray(0,c.length-2)),{disposition:a,name:l,filename:d,contentType:f,data:c}}import{readFileSync as S}from"fs";import $ from"http";import ge from"http2";import be from"https";var k=class{config;rateLimiter;router;shutdownHandlers=[];constructor(e){let t=new O(q(e||{})).get();t.debug&&console.log("Using configuration:",t),this.config=t,this.router=new D;let s=t.rateLimit.requestsPerMinute||E().rateLimit.requestsPerMinute;this.rateLimiter=new N(s,60),t.rateLimit.enabled===!0&&this.use(this.rateLimitMiddleware.bind(this))}use(e){return this.router.use(e),this}get(e,...t){return this.router.get(e,...t),this}post(e,...t){return this.router.post(e,...t),this}put(e,...t){return this.router.put(e,...t),this}delete(e,...t){return this.router.delete(e,...t),this}patch(e,...t){return this.router.patch(e,...t),this}any(e,...t){return this.router.any(e,...t),this}options(e,...t){return this.router.options(e,...t),this}start(){let e=this.createServer(),{port:t,host:s}=this.config;return this.setupGracefulShutdown(e),e.listen(t,s,()=>{let r=e.address(),i=this.config.useHttps||this.config.useHttp2?"https":"http";console.log(`MikroServe running at ${i}://${r.address!=="::"?r.address:"localhost"}:${r.port}`)}),e}createServer(){let e=this.requestHandler.bind(this);if(this.config.useHttp2){if(!this.config.sslCert||!this.config.sslKey)throw new Error("SSL certificate and key paths are required when useHttp2 is true");try{let t={key:S(this.config.sslKey),cert:S(this.config.sslCert),...this.config.sslCa?{ca:S(this.config.sslCa)}:{}};return ge.createSecureServer(t,e)}catch(t){throw t.message.includes("key values mismatch")?new Error(`SSL certificate and key do not match: ${t.message}`):t}}else if(this.config.useHttps){if(!this.config.sslCert||!this.config.sslKey)throw new Error("SSL certificate and key paths are required when useHttps is true");try{let t={key:S(this.config.sslKey),cert:S(this.config.sslCert),...this.config.sslCa?{ca:S(this.config.sslCa)}:{}};return be.createServer(t,e)}catch(t){throw t.message.includes("key values mismatch")?new Error(`SSL certificate and key do not match: ${t.message}`):t}}return $.createServer(e)}async rateLimitMiddleware(e,t){let s=e.req.socket.remoteAddress||"unknown";return e.res.setHeader("X-RateLimit-Limit",this.rateLimiter.getLimit().toString()),e.res.setHeader("X-RateLimit-Remaining",this.rateLimiter.getRemainingRequests(s).toString()),e.res.setHeader("X-RateLimit-Reset",this.rateLimiter.getResetTime(s).toString()),this.rateLimiter.isAllowed(s)?t():{statusCode:429,body:{error:"Too Many Requests",message:"Rate limit exceeded, please try again later"},headers:{"Content-Type":"application/json"}}}async requestHandler(e,t){let s=Date.now(),r=e.method||"UNKNOWN",i=e.url||"/unknown",n=this.config.debug;try{if(this.setCorsHeaders(t,e),this.setSecurityHeaders(t,this.config.useHttps),n&&console.log(`${r} ${i}`),e.method==="OPTIONS"){if(t instanceof $.ServerResponse)t.statusCode=204,t.end();else{let a=t;a.writeHead(204),a.end()}return}try{e.body=await this.parseBody(e)}catch(a){return n&&console.error("Body parsing error:",a.message),this.respond(t,{statusCode:400,body:{error:"Bad Request",message:a.message}})}let o=await this.router.handle(e,t);return o?o._handled?void 0:this.respond(t,o):this.respond(t,{statusCode:404,body:{error:"Not Found",message:"The requested endpoint does not exist"}})}catch(o){return console.error("Server error:",o),this.respond(t,{statusCode:500,body:{error:"Internal Server Error",message:n?o.message:"An unexpected error occurred"}})}finally{n&&this.logDuration(s,r,i)}}logDuration(e,t,s){let r=Date.now()-e;console.log(`${t} ${s} completed in ${r}ms`)}async parseBody(e){return new Promise((t,s)=>{let r=[],i=0,n=this.config.maxBodySize,o=!1,a=null,l=this.config.debug,d=e.headers["content-type"]||"";l&&console.log("Content-Type:",d),this.config.requestTimeout>0&&(a=setTimeout(()=>{o||(o=!0,l&&console.log("Request timeout exceeded"),s(new Error("Request timeout")))},this.config.requestTimeout));let f=()=>{a&&(clearTimeout(a),a=null)};e.on("data",c=>{if(!o){if(i+=c.length,l&&console.log(`Received chunk: ${c.length} bytes, total size: ${i}`),i>n){o=!0,f(),l&&console.log(`Body size exceeded limit: ${i} > ${n}`),s(new Error("Request body too large"));return}r.push(c)}}),e.on("end",()=>{if(!o){o=!0,f(),l&&console.log(`Request body complete: ${i} bytes`);try{if(r.length>0){let c=Buffer.concat(r);if(d.includes("application/json"))try{let u=c.toString("utf8");t(JSON.parse(u))}catch(u){s(new Error(`Invalid JSON in request body: ${u.message}`))}else if(d.includes("application/x-www-form-urlencoded")){let u=c.toString("utf8"),y={};new URLSearchParams(u).forEach((w,b)=>{y[b]=w}),t(y)}else if(d.includes("multipart/form-data"))try{let u=z(c,d);t(u)}catch(u){s(new Error(`Invalid multipart form data: ${u.message}`))}else this.isBinaryContentType(d)?t(c):t(c.toString("utf8"))}else t({})}catch(c){s(new Error(`Invalid request body: ${c}`))}}}),e.on("error",c=>{o||(o=!0,f(),s(new Error(`Error reading request body: ${c.message}`)))}),e.on("close",()=>{f()})})}isBinaryContentType(e){return["application/octet-stream","application/pdf","application/zip","application/gzip","application/x-tar","application/x-rar-compressed","application/x-7z-compressed","image/","video/","audio/","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument","application/msword","application/vnd.ms-powerpoint"].some(s=>e.includes(s))}setCorsHeaders(e,t){let s=t.headers.origin,{allowedDomains:r=["*"]}=this.config;!s||r.length===0||r.includes("*")?e.setHeader("Access-Control-Allow-Origin","*"):r.includes(s)&&(e.setHeader("Access-Control-Allow-Origin",s),e.setHeader("Vary","Origin")),e.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, PATCH, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization"),e.setHeader("Access-Control-Max-Age","86400")}setSecurityHeaders(e,t=!1){let s={"X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","Content-Security-Policy":"default-src 'self'; script-src 'self'; object-src 'none'","X-XSS-Protection":"1; mode=block"};if((t||this.config.useHttp2)&&(s["Strict-Transport-Security"]="max-age=31536000; includeSubDomains"),e instanceof $.ServerResponse)Object.entries(s).forEach(([r,i])=>{e.setHeader(r,i)});else{let r=e;Object.entries(s).forEach(([i,n])=>{r.setHeader(i,n)})}}respond(e,t){let s={...t.headers||{}};(i=>typeof i.writeHead=="function"&&typeof i.end=="function")(e)?(e.writeHead(t.statusCode,s),t.body===null||t.body===void 0?e.end():t.isRaw||typeof t.body=="string"?e.end(t.body):e.end(JSON.stringify(t.body))):(console.warn("Unexpected response object type without writeHead/end methods"),e.writeHead?.(t.statusCode,s),t.body===null||t.body===void 0?e.end?.():t.isRaw||typeof t.body=="string"?e.end?.(t.body):e.end?.(JSON.stringify(t.body)))}setupGracefulShutdown(e){let t=o=>{console.log("Shutting down MikroServe server..."),o&&console.error("Error:",o),this.cleanupShutdownHandlers(),e.close(()=>{console.log("Server closed successfully"),process.env.NODE_ENV!=="test"&&process.env.VITEST!=="true"&&setImmediate(()=>process.exit(o?1:0))})},s=()=>t(),r=()=>t(),i=o=>t(o),n=o=>t(o);this.shutdownHandlers=[s,r,i,n],process.on("SIGINT",s),process.on("SIGTERM",r),process.on("uncaughtException",i),process.on("unhandledRejection",n)}cleanupShutdownHandlers(){if(this.shutdownHandlers.length>0){let[e,t,s,r]=this.shutdownHandlers;process.removeListener("SIGINT",e),process.removeListener("SIGTERM",t),process.removeListener("uncaughtException",s),process.removeListener("unhandledRejection",r),this.shutdownHandlers=[]}}};function P(e){if(!e.deflate&&!e.inflate)throw new Error("Dictionary must provide either deflate or inflate mapping");if(e.deflate&&e.inflate)throw new Error("Dictionary should provide only one of deflate or inflate (not both). The inverse will be auto-generated.");return e.deflate?{deflate:e.deflate,inflate:F(e.deflate)}:{deflate:F(e.inflate),inflate:e.inflate}}function F(e){let t={};for(let[s,r]of Object.entries(e))t[r]=s;return t}function T(e,t){if(e==null||typeof e!="object")return e;if(Array.isArray(e))return e.map(r=>T(r,t));let s={};for(let[r,i]of Object.entries(e)){let n=t[r]||r;s[n]=T(i,t)}return s}function C(e){if(!e||typeof e!="string")throw new Error("Table name must be a non-empty string");if(e.length>255)throw new Error("Table name must not exceed 255 characters");if(e.includes("/")||e.includes("\\"))throw new Error("Table name must not contain path separators");if(e.includes(".."))throw new Error('Table name must not contain ".."');if(e.startsWith("."))throw new Error('Table name must not start with "."');if(e.includes("\0"))throw new Error("Table name must not contain null bytes");if(["CON","PRN","AUX","NUL","COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9","LPT1","LPT2","LPT3","LPT4","LPT5","LPT6","LPT7","LPT8","LPT9"].includes(e.toUpperCase()))throw new Error(`Table name "${e}" is reserved by the filesystem`)}function R(e){if(e==null)throw new Error("Key must be defined");if(typeof e!="string")throw new Error("Key must be a string");if(e.length===0)throw new Error("Key must not be empty");if(e.length>1024)throw new Error("Key must not exceed 1024 characters");if(e.includes("\0"))throw new Error("Key must not contain null bytes")}function B(e){if(e===void 0)throw new Error("Value must not be undefined (use null instead)");let t=typeof e;if(t==="function")throw new Error("Value must be JSON-serializable: functions are not supported");if(t==="symbol")throw new Error("Value must be JSON-serializable: symbols are not supported");try{if(JSON.stringify(e)===void 0)throw new Error("Value must be JSON-serializable: value cannot be serialized")}catch(s){throw new Error(`Value must be JSON-serializable: ${s instanceof Error?s.message:String(s)}`)}}import{existsSync as L,mkdirSync as we,readdirSync as ve,openSync as Ce,closeSync as Se}from"fs";import{readFile as Te,writeFile as xe,rename as Ee,unlink as U,open as Pe}from"fs/promises";import{join as H,dirname as Re}from"path";var V=class{data=new Map;databaseDirectory;dictionaries=new Map;useFsync;constructor(e){this.databaseDirectory=e.databaseDirectory,this.useFsync=e.durableWrites??!1,e.dictionaries&&Object.entries(e.dictionaries).forEach(([t,s])=>{let r=P(s);this.dictionaries.set(t,r)}),L(this.databaseDirectory)||we(this.databaseDirectory,{recursive:!0})}async start(){try{let e=ve(this.databaseDirectory);for(let t of e)!t.endsWith(".tmp")&&!t.startsWith(".")&&await this.loadTable(t)}catch(e){throw console.error("Failed to start database:",e),e}}async write(e,t,s,r,i){if(C(e),R(t),B(s),i&&!this.dictionaries.has(i))throw new Error(`Dictionary "${i}" not found. Available dictionaries: ${Array.from(this.dictionaries.keys()).join(", ")||"none"}`);try{this.data.has(e)||this.data.set(e,new Map);let n=this.data.get(e),a=(n.get(t)?.version||0)+1,l={value:s,version:a,timestamp:Date.now(),expiration:r||null,dictionaryName:i||void 0};return n.set(t,l),await this.persistTable(e),!0}catch(n){return console.error(`Write failed for ${e}:${t}:`,n),!1}}async get(e,t){C(e),t!==void 0&&R(t);try{this.data.has(e)||await this.loadTable(e);let s=this.data.get(e);if(!s)return t?void 0:[];if(t!==void 0){let n=s.get(t);if(!n)return;if(this.isExpired(n)){s.delete(t),await this.persistTable(e);return}return n.value}let r=[],i=[];for(let[n,o]of s.entries())this.isExpired(o)?i.push(n):r.push([n,o.value]);if(i.length>0){for(let n of i)s.delete(n);await this.persistTable(e)}return r}catch(s){return console.error(`Read failed for ${e}:${t}:`,s),t?void 0:[]}}async delete(e,t){C(e),R(t);try{this.data.has(e)||await this.loadTable(e);let s=this.data.get(e);if(!s||!s.has(t))return!1;let r=s.get(t);return r?this.isExpired(r)?(s.delete(t),await this.persistTable(e),!1):(s.delete(t),await this.persistTable(e),!0):!1}catch(s){return console.error(`Delete failed for ${e}:${t}:`,s),!1}}async getTableSize(e){C(e);try{this.data.has(e)||await this.loadTable(e);let t=this.data.get(e);if(!t)return 0;let s=0,r=[];for(let[i,n]of t.entries())this.isExpired(n)?r.push(i):s++;if(r.length>0){for(let i of r)t.delete(i);await this.persistTable(e)}return s}catch(t){return console.error(`Get table size failed for ${e}:`,t),0}}isExpired(e){return e.expiration===null?!1:Date.now()>e.expiration}async cleanupExpired(e){C(e);try{this.data.has(e)||await this.loadTable(e);let t=this.data.get(e);if(!t)return 0;let s=[];for(let[r,i]of t.entries())this.isExpired(i)&&s.push(r);for(let r of s)t.delete(r);return s.length>0&&await this.persistTable(e),s.length}catch(t){return console.error(`Cleanup failed for ${e}:`,t),0}}async cleanupAllExpired(){let e=0;for(let t of this.data.keys())e+=await this.cleanupExpired(t);return e}async deleteTable(e){C(e);try{this.data.delete(e);let t=H(this.databaseDirectory,e);return L(t)&&await U(t),!0}catch(t){return console.error(`Delete table failed for ${e}:`,t),!1}}listTables(){return Array.from(this.data.keys())}async flush(){try{let e=Array.from(this.data.keys()).map(t=>this.persistTable(t));await Promise.all(e)}catch(e){throw console.error("Flush failed:",e),e}}async close(){await this.flush()}addDictionary(e,t){let s=P(t);this.dictionaries.set(e,s)}removeDictionary(e){return this.dictionaries.delete(e)}listDictionaries(){return Array.from(this.dictionaries.keys())}async loadTable(e){let t=H(this.databaseDirectory,e);if(!L(t)){this.data.set(e,new Map);return}try{let s=await Te(t);if(s.length===0){this.data.set(e,new Map);return}let r=this.deserializeTable(s);this.data.set(e,r)}catch(s){console.error(`Failed to load table ${e}:`,s),this.data.set(e,new Map)}}async persistTable(e){let t=this.data.get(e);if(!t)return;let s=this.serializeTable(t),r=H(this.databaseDirectory,e),i=`${r}.tmp.${Date.now()}.${Math.random().toString(36).substring(7)}`;try{if(await xe(i,s),this.useFsync){let n=await Pe(i,"r+");try{await n.sync()}finally{await n.close()}}if(await Ee(i,r),this.useFsync){let n=Re(r),o=Ce(n,"r");try{Se(o)}catch{}}}catch(n){try{await U(i)}catch{}throw n}}serializeTable(e){let t=Array.from(e.entries()).map(([s,r])=>{let i=r.dictionaryName?this.dictionaries.get(r.dictionaryName):void 0,n={d:i?T(r.value,i.deflate):r.value,v:r.version,t:r.timestamp,x:r.expiration};return r.dictionaryName&&(n.n=r.dictionaryName),[s,n]});return Buffer.from(JSON.stringify(t),"utf8")}deserializeTable(e){let s=JSON.parse(e.toString("utf8")).map(([r,i])=>{let n=i.n,o=n?this.dictionaries.get(n):void 0;return[r,{value:o?T(i.d,o.inflate):i.d,version:i.v,timestamp:i.t,expiration:i.x,dictionaryName:n||void 0}]});return new Map(s)}};import{join as de}from"node:path";import{statSync as ze}from"node:fs";var m=class{isSilent;propertyPath="";constructor(e=!1){this.isSilent=e}test(e,t){if(!t)throw new Error("Missing input!");this.updatePropertyPath();let{results:s,errors:r}=this.validate(e.properties,t),i=this.compileErrors(s,r),n=this.isSuccessful(s,i);return{errors:i,success:n}}compileErrors(e,t){let s=e.filter(r=>r.success===!1);return[...t,...s].flatMap(r=>r)}isSuccessful(e,t){return e.every(s=>s.success===!0)&&t.length===0}validate(e,t,s=[],r=[]){let i=e?.additionalProperties??!0,n=e?.required||[];r=this.checkForRequiredKeysErrors(n,t,r),r=this.checkForDisallowedProperties(Object.keys(t),Object.keys(e),r,i);for(let o in e){let a=n.includes(o)&&o!=="required",l=e[o],d=t[o],f=l.additionalProperties??!0;a&&(r=this.checkForRequiredKeysErrors(l.required||[],d,r)),this.isDefined(d)&&(this.handleValidation(o,d,l,s),r=this.checkForDisallowedProperties(Object.keys(d),Object.keys(l),r,f),this.handleNestedObject(d,l,s,r))}return{results:s,errors:r}}updatePropertyPath(e,t=""){if(!e){this.propertyPath="";return}t&&(this.propertyPath=t),this.propertyPath=`${this.propertyPath}.${e}`,this.propertyPath.startsWith(".")&&(this.propertyPath=this.propertyPath.substring(1,this.propertyPath.length))}isDefined(e){return!!(typeof e=="number"&&e===0||e||e===""||typeof e=="boolean")}checkForRequiredKeysErrors(e,t,s){if(!this.areRequiredKeysPresent(e,t)){let r=t?Object.keys(t):[],i=this.findNonOverlappingElements(e,r),n=i.length>0?`Missing the required key: '${i.join(", ")}'!`:`Missing values for required keys: '${r.filter(o=>!t[o]).join(", ")}'!`;s.push({key:"",value:t,success:!1,error:n})}return s}checkForDisallowedProperties(e,t,s,r){if(!r){let i=this.findNonOverlappingElements(e,t);i.length>0&&s.push({key:`${t}`,value:e,success:!1,error:`Has additional (disallowed) properties: '${i.join(", ")}'!`})}return s}handleValidation(e,t,s,r){this.updatePropertyPath(e);let i=this.validateProperty(this.propertyPath,s,t);r.push(...i);let n=(a,l)=>{a.forEach(d=>{let f=this.validateProperty(this.propertyPath,l.items,d);r.push(...f)}),this.updatePropertyPath()},o=a=>{let l=Object.keys(a),d=this.propertyPath;l.forEach(f=>{if(this.updatePropertyPath(f,d),this.isArray(a[f])&&s[f]?.items!=null)n(a[f],s[f]);else{let c=this.validateProperty(this.propertyPath,s[f],a[f]);r.push(...c)}})};this.isArray(t)&&s.items!=null?n(t,s):this.isObject(t)?o(t):this.updatePropertyPath()}handleNestedObject(e,t,s,r){if(this.isObject(e)){let i=this.getNestedObjects(e);for(let n of i){let o=t[n],a=e[n];o&&typeof a=="object"&&this.validate(o,a,s,r)}}}getNestedObjects(e){return Object.keys(e).filter(t=>{if(this.isObject(e))return t})}findNonOverlappingElements(e,t){return e.filter(s=>!t.includes(s))}areRequiredKeysPresent(e,t=[]){return e.every(s=>Object.keys(t).includes(s)?this.isDefined(t[s]):!1)}validateProperty(e,t,s){return this.validateInput(t,s).map(i=>{let{success:n,error:o}=i;return{key:e,value:s,success:n,error:o??""}})}validateInput(e,t){if(e){let s=[{condition:()=>e.type,validator:()=>this.isCorrectType(e.type,t),error:"Invalid type"},{condition:()=>e.format,validator:()=>this.isCorrectFormat(e.format,t),error:"Invalid format"},{condition:()=>e.minLength,validator:()=>this.isMinimumLength(e.minLength,t),error:"Length too short"},{condition:()=>e.maxLength,validator:()=>this.isMaximumLength(e.maxLength,t),error:"Length too long"},{condition:()=>e.minValue,validator:()=>this.isMinimumValue(e.minValue,t),error:"Value too small"},{condition:()=>e.maxValue,validator:()=>this.isMaximumValue(e.maxValue,t),error:"Value too large"},{condition:()=>e.matchesPattern,validator:()=>this.matchesPattern(e.matchesPattern,t),error:"Pattern does not match"}],r=[];for(let i of s)i.condition()&&!i.validator()&&r.push({success:!1,error:i.error});return r}else this.isSilent||console.warn(`Missing property '${e}' for match '${t}'. Skipping...`);return[{success:!0}]}isCorrectType(e,t){return Array.isArray(e)||(e=[e]),e.some(s=>{switch(s){case"string":return typeof t=="string";case"number":return typeof t=="number"&&!isNaN(t);case"boolean":return typeof t=="boolean";case"object":return this.isObject(t);case"array":return this.isArray(t)}})}isObject(e){return e!==null&&!this.isArray(e)&&typeof e=="object"&&e instanceof Object&&Object.prototype.toString.call(e)==="[object Object]"}isArray(e){return Array.isArray(e)}isCorrectFormat(e,t){switch(e){case"alphanumeric":return new RegExp(/^[a-zA-Z0-9]+$/).test(t);case"numeric":return new RegExp(/^-?\d+(\.\d+)?$/).test(t);case"email":return new RegExp(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/).test(t);case"date":return new RegExp(/^\d{4}-\d{2}-\d{2}$/).test(t);case"url":return new RegExp(/^(https?):\/\/[^\s$.?#].[^\s]*$/).test(t);case"hexColor":return new RegExp(/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i).test(t)}}isMinimumLength(e,t){return Array.isArray(t)?t.length>=e:t?.toString().length>=e}isMaximumLength(e,t){return Array.isArray(t)?t.length<=e:t.toString().length<=e}isMinimumValue(e,t){return t>=e}isMaximumValue(e,t){return t<=e}matchesPattern(e,t){return new RegExp(e).test(t)}schemaFrom(e){let t={properties:{additionalProperties:!1,required:[]}};for(let s in e){let r=e[s];t.properties.required.push(s),Array.isArray(r)?t.properties[s]=this.generateArraySchema(r):typeof r=="object"&&r!==null?t.properties[s]=this.generateNestedObjectSchema(r):t.properties[s]=this.generatePropertySchema(r)}return t}generateArraySchema(e){let t={type:"array"},s=e.filter(r=>r);if(s.length>0){let r=s[0];s.every(n=>typeof n==typeof r)?typeof r=="object"&&!Array.isArray(r)?t.items=this.generateNestedObjectSchema(r):t.items=this.generatePropertySchema(r):console.warn("All elements in array are not of the same type. Unable to generate a schema for these elements.")}return t}generateNestedObjectSchema(e){let t={type:"object",additionalProperties:!1,required:[]};for(let s in e){let r=e[s];t.required.push(s),typeof r=="object"&&!Array.isArray(r)&&r!==null?t[s]=this.generateNestedObjectSchema(r):t[s]=this.generatePropertySchema(r)}return t}generatePropertySchema(e){let t=typeof e,s={type:t};return t==="string"&&(s.minLength=1),s}};async function j(e){return e.body||{}}function h(e,t="An error occurred"){let s=e?.message||e||t,r=e?.cause?.statusCode||e?.statusCode||400;return{message:s,status:r}}function G(e,t,s={}){let r=Array.isArray(t)?t:[t];if(!e||!e.roles||!Array.isArray(e.roles)){let o=new Error("Unauthorized: User or roles missing");throw o.cause={statusCode:403},o}let i=e.roles.flatMap(o=>o?.policies?.flatMap(a=>(a?.permissions||[]).flatMap(d=>typeof d=="string"?d:d&&typeof d=="object"&&d.actions?d.actions:[]))||[]);if(!r.every(o=>i.includes(o)||i.includes("*")?!0:i.some(a=>{if(a.endsWith(".*")){let l=a.slice(0,-2);return o.startsWith(`${l}.`)}return!1}))){let o=new Error("Unauthorized");throw o.cause={statusCode:403},o}return!0}function W(e,t,s,r,i){let n=e.find(l=>l.service===t);if(!n){let l=new Error(`Function bindings do not include access to service: ${t}`);throw l.cause={statusCode:403},l}if(!n.permissions||n.permissions.length===0)return;for(let l of n.permissions)if(!(l.resource&&l.resource!==s)){if(!l.resource||!l.actions||l.actions.length===0)return;if(l.actions.includes(r)){if(l.targets&&l.targets.length>0){if(!i)return;if(!l.targets.includes(i))continue}return}}let o=i?`:${i}`:"",a=new Error(`Function bindings do not allow: ${t}.${s}.${r}${o}`);throw a.cause={statusCode:403},a}async function p(e,t,s,r,i,n,o){if(!t)return null;let a=e.state.user;if(!a){let d=e.headers.authorization;if(!d){let c=new Error("Unauthorized: No authentication provided");throw c.cause={statusCode:401},c}let f=d.replace(/^Bearer\s+/i,"");if(a=await t.getUserFromToken(f),!a){let c=new Error("Unauthorized: Invalid token");throw c.cause={statusCode:401},c}}G(a,s,{});let l=e.headers["x-function-bindings"];if(l)try{let d=Array.isArray(l)?l[0]:l,f=JSON.parse(d);W(f,r,i,n,o)}catch(d){if(d.cause?.statusCode===403)throw d;let f=new Error("Invalid function bindings header");throw f.cause={statusCode:400},f}return a}var J={properties:{tableName:{type:"string",minLength:1},key:{type:"string"}},required:["tableName"],additionalProperties:!1};var Me=new m;async function _(e,t,s){try{let r=await j(e),i=Me.test(J,r);if(!i.success)return e.json({error:"Invalid input",details:i.errors},400);let{tableName:n,key:o}=r;if(!n)return e.json("tableName is required",400);await p(e,s,"databases.table.get","databases","table","read",n);let a=await t.get(n,o);return a===void 0?e.json(null,404):e.json(a,200)}catch(r){let{message:i,status:n}=h(r,"Error getting table data");return e.json({error:i},n)}}var K={properties:{tableName:{type:"string",minLength:1},key:{type:"string"},value:{},expiration:{type:"number"},dictionaryName:{type:"string"}},required:["tableName"],additionalProperties:!1};var Oe=new m;async function X(e,t,s){try{let r=await j(e),i=Oe.test(K,r);if(!i.success)return e.json({error:"Invalid input",details:i.errors},400);let{tableName:n,key:o,value:a,expiration:l,dictionaryName:d}=r;if(!n||a===void 0)return e.json("tableName and value are required",400);await p(e,s,"databases.table.update","databases","table","write",n);let f=await t.write(n,o,a,l,d);return e.json(f,200)}catch(r){let{message:i,status:n}=h(r,"Error writing table data");return e.json({error:i},n)}}var Z={properties:{tableName:{type:"string",minLength:1},key:{type:"string",minLength:1}},required:["tableName","key"],additionalProperties:!1};var $e=new m;async function Y(e,t,s){try{let r=$e.test(Z,e.query);if(!r.success)return e.json({error:"Invalid input",details:r.errors},400);let{tableName:i,key:n}=e.query;if(!i||!n)return e.json("tableName and key are required",400);await p(e,s,"databases.table.delete","databases","table","delete",i);let o=await t.delete(i,n);return e.json(o,200)}catch(r){let{message:i,status:n}=h(r,"Error deleting table item");return e.json({error:i},n)}}async function Q(e,t,s,r,i,n){try{await p(e,s,"databases.table.get","databases","table","read");let o=t.listTables(),a=await Promise.all(o.map(async l=>{let d=await t.getTableSize(l),f=i(r,l);return{name:l,items:d,size:n(f)}}));return e.json({tables:a},200)}catch(o){let{message:a,status:l}=h(o,"Error listing tables");return e.json({error:a},l)}}var v={properties:{tableName:{type:"string",minLength:1}},required:["tableName"],additionalProperties:!1};var Le=new m;async function ee(e,t,s){try{let r=e.params.tableName;if(!r)return e.json({error:"tableName is required"},400);let i=Le.test(v,{tableName:r});return i.success?(await p(e,s,"databases.table.create","databases","table","create",r),t.listTables().includes(r)?e.json({error:"Table already exists"},409):(await t.write(r,"__init__",null),await t.delete(r,"__init__"),e.json({success:!0,name:r,message:"Table created successfully"},201))):e.json({error:"Invalid input",details:i.errors},400)}catch(r){let{message:i,status:n}=h(r,"Error creating table");return e.json({error:i},n)}}var He=new m;async function te(e,t,s){try{let r=e.params.tableName;if(!r)return e.json({error:"tableName is required"},400);let i=He.test(v,{tableName:r});if(!i.success)return e.json({error:"Invalid input",details:i.errors},400);if(await p(e,s,"databases.table.delete","databases","table","delete",r),!t.listTables().includes(r))return e.json({error:"Table not found"},404);let o=await t.deleteTable(r);return e.json({success:o,name:r,message:"Table deleted successfully"},200)}catch(r){let{message:i,status:n}=h(r,"Error deleting table");return e.json({error:i},n)}}var Ve=new m;async function re(e,t,s,r,i,n){try{let o=e.params.tableName;if(!o)return e.json({error:"tableName is required"},400);let a=Ve.test(v,{tableName:o});if(!a.success)return e.json({error:"Invalid input",details:a.errors},400);if(await p(e,s,"databases.table.get","databases","table","read",o),!t.listTables().includes(o))return e.json({error:"Table not found"},404);let d=await t.getTableSize(o),f=i(r,o);return e.json({name:o,items:d,size:n(f)},200)}catch(o){let{message:a,status:l}=h(o,"Error getting table info");return e.json({error:a},l)}}async function se(e,t,s){try{if(!e.query.tableName)return e.json({error:"tableName is required"},400);let{tableName:r}=e.query;await p(e,s,"databases.table.get","databases","table","read",r);let i=await t.get(r),n=i?i.length:0;return e.json(n,200)}catch(r){let{message:i,status:n}=h(r,"Error getting table size");return e.json({error:i},n)}}var Ne=new m;async function ie(e,t,s){try{let r=e.params.tableName;if(!r)return e.json({error:"tableName is required"},400);let i=Ne.test(v,{tableName:r});if(!i.success)return e.json({error:"Invalid input",details:i.errors},400);if(await p(e,s,"databases.table.get","databases","table","read",r),!t.listTables().includes(r))return e.json({error:"Table not found"},404);let o=await t.get(r),a=o?Object.entries(o).map(([l,d])=>Array.isArray(d)&&d.length===2?{key:d[0],value:d[1]}:{key:l,value:d}):[];return e.json({items:a},200)}catch(r){let{message:i,status:n}=h(r,"Error getting table items");return e.json({error:i},n)}}import{readFileSync as De,existsSync as qe}from"node:fs";function x(){let e=process.env.MOLNOS_RUNTIME_CONFIG,t={molnos:{dataPath:"data",rateLimit:{global:{enabled:!1,requestsPerMinute:0}},signedUrlSecret:"molnos-default-signed-url-secret"},server:{host:"127.0.0.1",port:3e3},identity:{apiUrl:""},services:{storage:{host:"127.0.0.1",port:3001,url:"http://127.0.0.1:3001"},functions:{host:"127.0.0.1",port:3002,url:"http://127.0.0.1:3002"},sites:{host:"127.0.0.1",port:3003,url:"http://127.0.0.1:3003"},databases:{host:"127.0.0.1",port:3004,url:"http://127.0.0.1:3004"},observability:{host:"127.0.0.1",port:3005,url:"http://127.0.0.1:3005"}}};if(!e||!qe(e))return t;try{let s=De(e,"utf-8");return JSON.parse(s)}catch(s){return console.error("[loadRuntimeConfig] Failed to load runtime config:",s),t}}function oe(e,t){let s={enabled:!1,requestsPerMinute:0};if(!t)return s;let r=t.services?.[e];return r||(t.global?t.global:s)}function ne(e,t){let s=e?.api?.port;if(!s)throw new Error('Missing "port" input when create API service!');let r=x(),i=e?.dataPath||r.molnos.dataPath,n=e?.api?.host||r.server.host,o=e?.identityApiUrl!==void 0?e.identityApiUrl:r.identity.apiUrl,a=e?.debug||!1,l;return t&&(l=oe(t,r.molnos.rateLimit)),{dataPath:i,api:{port:s,host:n},...o?{identityApiUrl:o}:{},...l?{rateLimit:l}:{},debug:a}}var M=class{baseUrl;authToken;constructor(t,s){this.baseUrl=t.replace(/\/$/,""),this.authToken=s}async createCustomRole(t,s,r,i){let n=await fetch(`${this.baseUrl}/identity/roles`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({roleId:t,name:s,description:r,permissions:i})});if(!n.ok){let o=`Failed to create role: ${n.statusText}`;try{o=(await n.json()).error||o}catch{o=await n.text().catch(()=>n.statusText)||o}throw new Error(o)}}async updateRole(t,s){let r=await fetch(`${this.baseUrl}/identity/roles/${t}`,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(s)});if(!r.ok){let i=await r.json();throw new Error(i.error||`Failed to update role: ${r.statusText}`)}}async deleteRole(t){let s=await fetch(`${this.baseUrl}/identity/roles/${t}`,{method:"DELETE",headers:this.getHeaders()});if(!s.ok){let r=await s.json();throw new Error(r.error||`Failed to delete role: ${s.statusText}`)}}async addServiceAccount(t,s,r){let i=await fetch(`${this.baseUrl}/identity/service-accounts`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({name:t,description:s,roles:r})});if(!i.ok){let o=`Failed to create service account: ${i.statusText}`;try{o=(await i.json()).error||o}catch{o=await i.text().catch(()=>i.statusText)||o}throw new Error(o)}let n=await i.json();return{id:n.id,apiKey:n.apiKey}}async deleteIdentity(t){let s=await fetch(`${this.baseUrl}/identity/service-accounts/${t}`,{method:"DELETE",headers:this.getHeaders()});if(!s.ok){let r=await s.json();throw new Error(r.error||`Failed to delete service account: ${s.statusText}`)}}async getUserFromToken(t){try{let s=await fetch(`${this.baseUrl}/identity/whoami`,{method:"GET",headers:{Authorization:`Bearer ${t}`}});return s.ok?await s.json():null}catch{return null}}getHeaders(){let t={"Content-Type":"application/json"};return this.authToken&&(t.Authorization=`Bearer ${this.authToken}`),t}};function ae(e){return e?new M(e):null}function le(e){if(e===0)return"0 B";let t=["B","KB","MB","GB"],s=Math.floor(Math.log(e)/Math.log(1024));return`${(e/1024**s).toFixed(1)} ${t[s]}`}function ce(e,t){try{let s=de(e,t);return ze(s).size}catch{return 0}}async function Fe(e){let t=e.dataPath||"data",s=de(t,"databases"),r=new V({databaseDirectory:s});await r.start();let i=ae(e.identityApiUrl),n=x(),o=new k({port:e.api.port||n.services.databases.port,host:e.api.host||n.services.databases.host,rateLimit:e.rateLimit||n.molnos.rateLimit.global});return o.get("/table",async l=>se(l,r,i)),o.post("/get",async l=>_(l,r,i)),o.post("/write",async l=>X(l,r,i)),o.delete("/delete",async l=>Y(l,r,i)),o.get("/tables",async l=>Q(l,r,i,s,ce,le)),o.post("/tables/:tableName",async l=>ee(l,r,i)),o.delete("/tables/:tableName",async l=>te(l,r,i)),o.get("/tables/:tableName",async l=>re(l,r,i,s,ce,le)),o.get("/tables/:tableName/items",async l=>ie(l,r,i)),o.start()}if(import.meta.url===`file://${process.argv[1]}`){let e=x(),s=process.argv.slice(2).find(n=>n.startsWith("--port=")),r=s?parseInt(s.split("=")[1],10):e.services.databases.port,i=ne({api:{port:r}},"databases");Fe(i)}export{Fe as startServer};
10
+ `),s=t.indexOf(e);if(s===-1)return null;let r=t.subarray(0,s),i=t.subarray(s+4),o=r.toString("utf8").split(`\r
11
+ `),a="",c="",l,f;for(let u of o){let y=u.toLowerCase();if(y.startsWith("content-disposition:")){a=u.substring(20).trim();let w=a.match(/name="([^"]+)"/);w&&(c=w[1]);let b=a.match(/filename="([^"]+)"/);b&&(l=b[1])}else y.startsWith("content-type:")&&(f=u.substring(13).trim())}if(!c)return null;let d=i;return d.length>=2&&d[d.length-2]===13&&d[d.length-1]===10&&(d=d.subarray(0,d.length-2)),{disposition:a,name:c,filename:l,contentType:f,data:d}}import{readFileSync as x}from"fs";import k from"http";import wt from"http2";import vt from"https";var L=class{config;rateLimiter;router;shutdownHandlers=[];constructor(t){let e=new I(z(t||{})).get();e.debug&&console.log("Using configuration:",e),this.config=e,this.router=new q;let s=e.rateLimit.requestsPerMinute||E().rateLimit.requestsPerMinute;this.rateLimiter=new D(s,60),e.rateLimit.enabled===!0&&this.use(this.rateLimitMiddleware.bind(this))}use(t){return this.router.use(t),this}get(t,...e){return this.router.get(t,...e),this}post(t,...e){return this.router.post(t,...e),this}put(t,...e){return this.router.put(t,...e),this}delete(t,...e){return this.router.delete(t,...e),this}patch(t,...e){return this.router.patch(t,...e),this}any(t,...e){return this.router.any(t,...e),this}options(t,...e){return this.router.options(t,...e),this}start(){let t=this.createServer(),{port:e,host:s}=this.config;return this.setupGracefulShutdown(t),t.listen(e,s,()=>{let r=t.address(),i=this.config.useHttps||this.config.useHttp2?"https":"http";console.log(`MikroServe running at ${i}://${r.address!=="::"?r.address:"localhost"}:${r.port}`)}),t}createServer(){let t=this.requestHandler.bind(this);if(this.config.useHttp2){if(!this.config.sslCert||!this.config.sslKey)throw new Error("SSL certificate and key paths are required when useHttp2 is true");try{let e={key:x(this.config.sslKey),cert:x(this.config.sslCert),...this.config.sslCa?{ca:x(this.config.sslCa)}:{}};return wt.createSecureServer(e,t)}catch(e){throw e.message.includes("key values mismatch")?new Error(`SSL certificate and key do not match: ${e.message}`):e}}else if(this.config.useHttps){if(!this.config.sslCert||!this.config.sslKey)throw new Error("SSL certificate and key paths are required when useHttps is true");try{let e={key:x(this.config.sslKey),cert:x(this.config.sslCert),...this.config.sslCa?{ca:x(this.config.sslCa)}:{}};return vt.createServer(e,t)}catch(e){throw e.message.includes("key values mismatch")?new Error(`SSL certificate and key do not match: ${e.message}`):e}}return k.createServer(t)}async rateLimitMiddleware(t,e){let s=t.req.socket.remoteAddress||"unknown";return t.res.setHeader("X-RateLimit-Limit",this.rateLimiter.getLimit().toString()),t.res.setHeader("X-RateLimit-Remaining",this.rateLimiter.getRemainingRequests(s).toString()),t.res.setHeader("X-RateLimit-Reset",this.rateLimiter.getResetTime(s).toString()),this.rateLimiter.isAllowed(s)?e():{statusCode:429,body:{error:"Too Many Requests",message:"Rate limit exceeded, please try again later"},headers:{"Content-Type":"application/json"}}}async requestHandler(t,e){let s=Date.now(),r=t.method||"UNKNOWN",i=t.url||"/unknown",n=this.config.debug;try{if(this.setCorsHeaders(e,t),this.setSecurityHeaders(e,this.config.useHttps),n&&console.log(`${r} ${i}`),t.method==="OPTIONS"){if(e instanceof k.ServerResponse)e.statusCode=204,e.end();else{let a=e;a.writeHead(204),a.end()}return}try{t.body=await this.parseBody(t)}catch(a){return n&&console.error("Body parsing error:",a.message),this.respond(e,{statusCode:400,body:{error:"Bad Request",message:a.message}})}let o=await this.router.handle(t,e);return o?o._handled?void 0:this.respond(e,o):this.respond(e,{statusCode:404,body:{error:"Not Found",message:"The requested endpoint does not exist"}})}catch(o){return console.error("Server error:",o),this.respond(e,{statusCode:500,body:{error:"Internal Server Error",message:n?o.message:"An unexpected error occurred"}})}finally{n&&this.logDuration(s,r,i)}}logDuration(t,e,s){let r=Date.now()-t;console.log(`${e} ${s} completed in ${r}ms`)}async parseBody(t){return new Promise((e,s)=>{let r=[],i=0,n=this.config.maxBodySize,o=!1,a=null,c=this.config.debug,l=t.headers["content-type"]||"";c&&console.log("Content-Type:",l),this.config.requestTimeout>0&&(a=setTimeout(()=>{o||(o=!0,c&&console.log("Request timeout exceeded"),s(new Error("Request timeout")))},this.config.requestTimeout));let f=()=>{a&&(clearTimeout(a),a=null)};t.on("data",d=>{if(!o){if(i+=d.length,c&&console.log(`Received chunk: ${d.length} bytes, total size: ${i}`),i>n){o=!0,f(),c&&console.log(`Body size exceeded limit: ${i} > ${n}`),s(new Error("Request body too large"));return}r.push(d)}}),t.on("end",()=>{if(!o){o=!0,f(),c&&console.log(`Request body complete: ${i} bytes`);try{if(r.length>0){let d=Buffer.concat(r);if(l.includes("application/json"))try{let u=d.toString("utf8");e(JSON.parse(u))}catch(u){s(new Error(`Invalid JSON in request body: ${u.message}`))}else if(l.includes("application/x-www-form-urlencoded")){let u=d.toString("utf8"),y={};new URLSearchParams(u).forEach((w,b)=>{y[b]=w}),e(y)}else if(l.includes("multipart/form-data"))try{let u=B(d,l);e(u)}catch(u){s(new Error(`Invalid multipart form data: ${u.message}`))}else this.isBinaryContentType(l)?e(d):e(d.toString("utf8"))}else e({})}catch(d){s(new Error(`Invalid request body: ${d}`))}}}),t.on("error",d=>{o||(o=!0,f(),s(new Error(`Error reading request body: ${d.message}`)))}),t.on("close",()=>{f()})})}isBinaryContentType(t){return["application/octet-stream","application/pdf","application/zip","application/gzip","application/x-tar","application/x-rar-compressed","application/x-7z-compressed","image/","video/","audio/","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument","application/msword","application/vnd.ms-powerpoint"].some(s=>t.includes(s))}setCorsHeaders(t,e){let s=e.headers.origin,{allowedDomains:r=["*"]}=this.config;!s||r.length===0||r.includes("*")?t.setHeader("Access-Control-Allow-Origin","*"):r.includes(s)&&(t.setHeader("Access-Control-Allow-Origin",s),t.setHeader("Vary","Origin")),t.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, PATCH, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization"),t.setHeader("Access-Control-Max-Age","86400")}setSecurityHeaders(t,e=!1){let s={"X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","Content-Security-Policy":"default-src 'self'; script-src 'self'; object-src 'none'","X-XSS-Protection":"1; mode=block"};if((e||this.config.useHttp2)&&(s["Strict-Transport-Security"]="max-age=31536000; includeSubDomains"),t instanceof k.ServerResponse)Object.entries(s).forEach(([r,i])=>{t.setHeader(r,i)});else{let r=t;Object.entries(s).forEach(([i,n])=>{r.setHeader(i,n)})}}respond(t,e){let s={...e.headers||{}};(i=>typeof i.writeHead=="function"&&typeof i.end=="function")(t)?(t.writeHead(e.statusCode,s),e.body===null||e.body===void 0?t.end():e.isRaw||typeof e.body=="string"?t.end(e.body):t.end(JSON.stringify(e.body))):(console.warn("Unexpected response object type without writeHead/end methods"),t.writeHead?.(e.statusCode,s),e.body===null||e.body===void 0?t.end?.():e.isRaw||typeof e.body=="string"?t.end?.(e.body):t.end?.(JSON.stringify(e.body)))}setupGracefulShutdown(t){let e=o=>{console.log("Shutting down MikroServe server..."),o&&console.error("Error:",o),this.cleanupShutdownHandlers(),t.close(()=>{console.log("Server closed successfully"),process.env.NODE_ENV!=="test"&&process.env.VITEST!=="true"&&setImmediate(()=>process.exit(o?1:0))})},s=()=>e(),r=()=>e(),i=o=>e(o),n=o=>e(o);this.shutdownHandlers=[s,r,i,n],process.on("SIGINT",s),process.on("SIGTERM",r),process.on("uncaughtException",i),process.on("unhandledRejection",n)}cleanupShutdownHandlers(){if(this.shutdownHandlers.length>0){let[t,e,s,r]=this.shutdownHandlers;process.removeListener("SIGINT",t),process.removeListener("SIGTERM",e),process.removeListener("uncaughtException",s),process.removeListener("unhandledRejection",r),this.shutdownHandlers=[]}}};function P(t){if(!t.deflate&&!t.inflate)throw new Error("Dictionary must provide either deflate or inflate mapping");if(t.deflate&&t.inflate)throw new Error("Dictionary should provide only one of deflate or inflate (not both). The inverse will be auto-generated.");return t.deflate?{deflate:t.deflate,inflate:F(t.deflate)}:{deflate:F(t.inflate),inflate:t.inflate}}function F(t){let e={};for(let[s,r]of Object.entries(t))e[r]=s;return e}function S(t,e){if(t==null||typeof t!="object")return t;if(Array.isArray(t))return t.map(r=>S(r,e));let s={};for(let[r,i]of Object.entries(t)){let n=e[r]||r;s[n]=S(i,e)}return s}function C(t){if(!t||typeof t!="string")throw new Error("Table name must be a non-empty string");if(t.length>255)throw new Error("Table name must not exceed 255 characters");if(t.includes("/")||t.includes("\\"))throw new Error("Table name must not contain path separators");if(t.includes(".."))throw new Error('Table name must not contain ".."');if(t.startsWith("."))throw new Error('Table name must not start with "."');if(t.includes("\0"))throw new Error("Table name must not contain null bytes");if(["CON","PRN","AUX","NUL","COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9","LPT1","LPT2","LPT3","LPT4","LPT5","LPT6","LPT7","LPT8","LPT9"].includes(t.toUpperCase()))throw new Error(`Table name "${t}" is reserved by the filesystem`)}function R(t){if(t==null)throw new Error("Key must be defined");if(typeof t!="string")throw new Error("Key must be a string");if(t.length===0)throw new Error("Key must not be empty");if(t.length>1024)throw new Error("Key must not exceed 1024 characters");if(t.includes("\0"))throw new Error("Key must not contain null bytes")}function U(t){if(t===void 0)throw new Error("Value must not be undefined (use null instead)");let e=typeof t;if(e==="function")throw new Error("Value must be JSON-serializable: functions are not supported");if(e==="symbol")throw new Error("Value must be JSON-serializable: symbols are not supported");try{if(JSON.stringify(t)===void 0)throw new Error("Value must be JSON-serializable: value cannot be serialized")}catch(s){throw new Error(`Value must be JSON-serializable: ${s instanceof Error?s.message:String(s)}`)}}import{existsSync as H,mkdirSync as Ct,readdirSync as xt,openSync as St,closeSync as Tt}from"fs";import{readFile as Et,writeFile as Pt,rename as Rt,unlink as G,open as jt}from"fs/promises";import{join as V,dirname as At}from"path";var N=class{data=new Map;databaseDirectory;dictionaries=new Map;useFsync;constructor(t){this.databaseDirectory=t.databaseDirectory,this.useFsync=t.durableWrites??!1,t.dictionaries&&Object.entries(t.dictionaries).forEach(([e,s])=>{let r=P(s);this.dictionaries.set(e,r)}),H(this.databaseDirectory)||Ct(this.databaseDirectory,{recursive:!0})}async start(){try{let t=xt(this.databaseDirectory);for(let e of t)!e.endsWith(".tmp")&&!e.startsWith(".")&&await this.loadTable(e)}catch(t){throw console.error("Failed to start database:",t),t}}async write(t,e,s,r,i){if(C(t),R(e),U(s),i&&!this.dictionaries.has(i))throw new Error(`Dictionary "${i}" not found. Available dictionaries: ${Array.from(this.dictionaries.keys()).join(", ")||"none"}`);try{this.data.has(t)||this.data.set(t,new Map);let n=this.data.get(t),a=(n.get(e)?.version||0)+1,c={value:s,version:a,timestamp:Date.now(),expiration:r||null,dictionaryName:i||void 0};return n.set(e,c),await this.persistTable(t),!0}catch(n){return console.error(`Write failed for ${t}:${e}:`,n),!1}}async get(t,e){C(t),e!==void 0&&R(e);try{this.data.has(t)||await this.loadTable(t);let s=this.data.get(t);if(!s)return e?void 0:[];if(e!==void 0){let n=s.get(e);if(!n)return;if(this.isExpired(n)){s.delete(e),await this.persistTable(t);return}return n.value}let r=[],i=[];for(let[n,o]of s.entries())this.isExpired(o)?i.push(n):r.push([n,o.value]);if(i.length>0){for(let n of i)s.delete(n);await this.persistTable(t)}return r}catch(s){return console.error(`Read failed for ${t}:${e}:`,s),e?void 0:[]}}async delete(t,e){C(t),R(e);try{this.data.has(t)||await this.loadTable(t);let s=this.data.get(t);if(!s||!s.has(e))return!1;let r=s.get(e);return r?this.isExpired(r)?(s.delete(e),await this.persistTable(t),!1):(s.delete(e),await this.persistTable(t),!0):!1}catch(s){return console.error(`Delete failed for ${t}:${e}:`,s),!1}}async getTableSize(t){C(t);try{this.data.has(t)||await this.loadTable(t);let e=this.data.get(t);if(!e)return 0;let s=0,r=[];for(let[i,n]of e.entries())this.isExpired(n)?r.push(i):s++;if(r.length>0){for(let i of r)e.delete(i);await this.persistTable(t)}return s}catch(e){return console.error(`Get table size failed for ${t}:`,e),0}}isExpired(t){return t.expiration===null?!1:Date.now()>t.expiration}async cleanupExpired(t){C(t);try{this.data.has(t)||await this.loadTable(t);let e=this.data.get(t);if(!e)return 0;let s=[];for(let[r,i]of e.entries())this.isExpired(i)&&s.push(r);for(let r of s)e.delete(r);return s.length>0&&await this.persistTable(t),s.length}catch(e){return console.error(`Cleanup failed for ${t}:`,e),0}}async cleanupAllExpired(){let t=0;for(let e of this.data.keys())t+=await this.cleanupExpired(e);return t}async deleteTable(t){C(t);try{this.data.delete(t);let e=V(this.databaseDirectory,t);return H(e)&&await G(e),!0}catch(e){return console.error(`Delete table failed for ${t}:`,e),!1}}listTables(){return Array.from(this.data.keys())}async flush(){try{let t=Array.from(this.data.keys()).map(e=>this.persistTable(e));await Promise.all(t)}catch(t){throw console.error("Flush failed:",t),t}}async close(){await this.flush()}addDictionary(t,e){let s=P(e);this.dictionaries.set(t,s)}removeDictionary(t){return this.dictionaries.delete(t)}listDictionaries(){return Array.from(this.dictionaries.keys())}async loadTable(t){let e=V(this.databaseDirectory,t);if(!H(e)){this.data.set(t,new Map);return}try{let s=await Et(e);if(s.length===0){this.data.set(t,new Map);return}let r=this.deserializeTable(s);this.data.set(t,r)}catch(s){console.error(`Failed to load table ${t}:`,s),this.data.set(t,new Map)}}async persistTable(t){let e=this.data.get(t);if(!e)return;let s=this.serializeTable(e),r=V(this.databaseDirectory,t),i=`${r}.tmp.${Date.now()}.${Math.random().toString(36).substring(7)}`;try{if(await Pt(i,s),this.useFsync){let n=await jt(i,"r+");try{await n.sync()}finally{await n.close()}}if(await Rt(i,r),this.useFsync){let n=At(r),o=St(n,"r");try{Tt(o)}catch{}}}catch(n){try{await G(i)}catch{}throw n}}serializeTable(t){let e=Array.from(t.entries()).map(([s,r])=>{let i=r.dictionaryName?this.dictionaries.get(r.dictionaryName):void 0,n={d:i?S(r.value,i.deflate):r.value,v:r.version,t:r.timestamp,x:r.expiration};return r.dictionaryName&&(n.n=r.dictionaryName),[s,n]});return Buffer.from(JSON.stringify(e),"utf8")}deserializeTable(t){let s=JSON.parse(t.toString("utf8")).map(([r,i])=>{let n=i.n,o=n?this.dictionaries.get(n):void 0;return[r,{value:o?S(i.d,o.inflate):i.d,version:i.v,timestamp:i.t,expiration:i.x,dictionaryName:n||void 0}]});return new Map(s)}};import{join as ft}from"node:path";import{statSync as Ft}from"node:fs";var m=class{isSilent;propertyPath="";constructor(t=!1){this.isSilent=t}test(t,e){if(!e)throw new Error("Missing input!");this.updatePropertyPath();let{results:s,errors:r}=this.validate(t.properties,e),i=this.compileErrors(s,r),n=this.isSuccessful(s,i);return{errors:i,success:n}}compileErrors(t,e){let s=t.filter(r=>r.success===!1);return[...e,...s].flatMap(r=>r)}isSuccessful(t,e){return t.every(s=>s.success===!0)&&e.length===0}validate(t,e,s=[],r=[]){let i=t?.additionalProperties??!0,n=t?.required||[];r=this.checkForRequiredKeysErrors(n,e,r),r=this.checkForDisallowedProperties(Object.keys(e),Object.keys(t),r,i);for(let o in t){let a=n.includes(o)&&o!=="required",c=t[o],l=e[o],f=c.additionalProperties??!0;a&&(r=this.checkForRequiredKeysErrors(c.required||[],l,r)),this.isDefined(l)&&(this.handleValidation(o,l,c,s),r=this.checkForDisallowedProperties(Object.keys(l),Object.keys(c),r,f),this.handleNestedObject(l,c,s,r))}return{results:s,errors:r}}updatePropertyPath(t,e=""){if(!t){this.propertyPath="";return}e&&(this.propertyPath=e),this.propertyPath=`${this.propertyPath}.${t}`,this.propertyPath.startsWith(".")&&(this.propertyPath=this.propertyPath.substring(1,this.propertyPath.length))}isDefined(t){return!!(typeof t=="number"&&t===0||t||t===""||typeof t=="boolean")}checkForRequiredKeysErrors(t,e,s){if(!this.areRequiredKeysPresent(t,e)){let r=e?Object.keys(e):[],i=this.findNonOverlappingElements(t,r),n=i.length>0?`Missing the required key: '${i.join(", ")}'!`:`Missing values for required keys: '${r.filter(o=>!e[o]).join(", ")}'!`;s.push({key:"",value:e,success:!1,error:n})}return s}checkForDisallowedProperties(t,e,s,r){if(!r){let i=this.findNonOverlappingElements(t,e);i.length>0&&s.push({key:`${e}`,value:t,success:!1,error:`Has additional (disallowed) properties: '${i.join(", ")}'!`})}return s}handleValidation(t,e,s,r){this.updatePropertyPath(t);let i=this.validateProperty(this.propertyPath,s,e);r.push(...i);let n=(a,c)=>{a.forEach(l=>{let f=this.validateProperty(this.propertyPath,c.items,l);r.push(...f)}),this.updatePropertyPath()},o=a=>{let c=Object.keys(a),l=this.propertyPath;c.forEach(f=>{if(this.updatePropertyPath(f,l),this.isArray(a[f])&&s[f]?.items!=null)n(a[f],s[f]);else{let d=this.validateProperty(this.propertyPath,s[f],a[f]);r.push(...d)}})};this.isArray(e)&&s.items!=null?n(e,s):this.isObject(e)?o(e):this.updatePropertyPath()}handleNestedObject(t,e,s,r){if(this.isObject(t)){let i=this.getNestedObjects(t);for(let n of i){let o=e[n],a=t[n];o&&typeof a=="object"&&this.validate(o,a,s,r)}}}getNestedObjects(t){return Object.keys(t).filter(e=>{if(this.isObject(t))return e})}findNonOverlappingElements(t,e){return t.filter(s=>!e.includes(s))}areRequiredKeysPresent(t,e=[]){return t.every(s=>Object.keys(e).includes(s)?this.isDefined(e[s]):!1)}validateProperty(t,e,s){return this.validateInput(e,s).map(i=>{let{success:n,error:o}=i;return{key:t,value:s,success:n,error:o??""}})}validateInput(t,e){if(t){let s=[{condition:()=>t.type,validator:()=>this.isCorrectType(t.type,e),error:"Invalid type"},{condition:()=>t.format,validator:()=>this.isCorrectFormat(t.format,e),error:"Invalid format"},{condition:()=>t.minLength,validator:()=>this.isMinimumLength(t.minLength,e),error:"Length too short"},{condition:()=>t.maxLength,validator:()=>this.isMaximumLength(t.maxLength,e),error:"Length too long"},{condition:()=>t.minValue,validator:()=>this.isMinimumValue(t.minValue,e),error:"Value too small"},{condition:()=>t.maxValue,validator:()=>this.isMaximumValue(t.maxValue,e),error:"Value too large"},{condition:()=>t.matchesPattern,validator:()=>this.matchesPattern(t.matchesPattern,e),error:"Pattern does not match"}],r=[];for(let i of s)i.condition()&&!i.validator()&&r.push({success:!1,error:i.error});return r}else this.isSilent||console.warn(`Missing property '${t}' for match '${e}'. Skipping...`);return[{success:!0}]}isCorrectType(t,e){return Array.isArray(t)||(t=[t]),t.some(s=>{switch(s){case"string":return typeof e=="string";case"number":return typeof e=="number"&&!isNaN(e);case"boolean":return typeof e=="boolean";case"object":return this.isObject(e);case"array":return this.isArray(e)}})}isObject(t){return t!==null&&!this.isArray(t)&&typeof t=="object"&&t instanceof Object&&Object.prototype.toString.call(t)==="[object Object]"}isArray(t){return Array.isArray(t)}isCorrectFormat(t,e){switch(t){case"alphanumeric":return new RegExp(/^[a-zA-Z0-9]+$/).test(e);case"numeric":return new RegExp(/^-?\d+(\.\d+)?$/).test(e);case"email":return new RegExp(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/).test(e);case"date":return new RegExp(/^\d{4}-\d{2}-\d{2}$/).test(e);case"url":return new RegExp(/^(https?):\/\/[^\s$.?#].[^\s]*$/).test(e);case"hexColor":return new RegExp(/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i).test(e)}}isMinimumLength(t,e){return Array.isArray(e)?e.length>=t:e?.toString().length>=t}isMaximumLength(t,e){return Array.isArray(e)?e.length<=t:e.toString().length<=t}isMinimumValue(t,e){return e>=t}isMaximumValue(t,e){return e<=t}matchesPattern(t,e){return new RegExp(t).test(e)}schemaFrom(t){let e={properties:{additionalProperties:!1,required:[]}};for(let s in t){let r=t[s];e.properties.required.push(s),Array.isArray(r)?e.properties[s]=this.generateArraySchema(r):typeof r=="object"&&r!==null?e.properties[s]=this.generateNestedObjectSchema(r):e.properties[s]=this.generatePropertySchema(r)}return e}generateArraySchema(t){let e={type:"array"},s=t.filter(r=>r);if(s.length>0){let r=s[0];s.every(n=>typeof n==typeof r)?typeof r=="object"&&!Array.isArray(r)?e.items=this.generateNestedObjectSchema(r):e.items=this.generatePropertySchema(r):console.warn("All elements in array are not of the same type. Unable to generate a schema for these elements.")}return e}generateNestedObjectSchema(t){let e={type:"object",additionalProperties:!1,required:[]};for(let s in t){let r=t[s];e.required.push(s),typeof r=="object"&&!Array.isArray(r)&&r!==null?e[s]=this.generateNestedObjectSchema(r):e[s]=this.generatePropertySchema(r)}return e}generatePropertySchema(t){let e=typeof t,s={type:e};return e==="string"&&(s.minLength=1),s}};async function j(t){return t.body||{}}function h(t,e="An error occurred"){let s=t?.message||t||e,r=t?.cause?.statusCode||t?.statusCode||400;return{message:s,status:r}}function W(t,e,s={}){let r=Array.isArray(e)?e:[e];if(!t||!t.roles||!Array.isArray(t.roles)){let o=new Error("Unauthorized: User or roles missing");throw o.cause={statusCode:403},o}let i=t.roles.flatMap(o=>o?.policies?.flatMap(a=>(a?.permissions||[]).flatMap(l=>typeof l=="string"?l:l&&typeof l=="object"&&l.actions?l.actions:[]))||[]);if(!r.every(o=>i.includes(o)||i.includes("*")?!0:i.some(a=>{if(a.endsWith(".*")){let c=a.slice(0,-2);return o.startsWith(`${c}.`)}return!1}))){let o=new Error("Unauthorized");throw o.cause={statusCode:403},o}return!0}function J(t,e,s,r,i){let n=t.find(c=>c.service===e);if(!n){let c=new Error(`Function bindings do not include access to service: ${e}`);throw c.cause={statusCode:403},c}if(!n.permissions||n.permissions.length===0)return;for(let c of n.permissions)if(!(c.resource&&c.resource!==s)){if(!c.resource||!c.actions||c.actions.length===0)return;if(c.actions.includes(r)){if(c.targets&&c.targets.length>0){if(!i)return;if(!c.targets.includes(i))continue}return}}let o=i?`:${i}`:"",a=new Error(`Function bindings do not allow: ${e}.${s}.${r}${o}`);throw a.cause={statusCode:403},a}async function p(t,e,s,r,i,n,o){if(!e)return null;let a=t.state.user;if(!a){let l=t.headers.authorization;if(!l){let d=new Error("Unauthorized: No authentication provided");throw d.cause={statusCode:401},d}let f=l.replace(/^Bearer\s+/i,"");if(a=await e.getUserFromToken(f),!a){let d=new Error("Unauthorized: Invalid token");throw d.cause={statusCode:401},d}}W(a,s,{});let c=t.headers["x-function-bindings"];if(c)try{let l=Array.isArray(c)?c[0]:c,f=JSON.parse(l);J(f,r,i,n,o)}catch(l){if(l.cause?.statusCode===403)throw l;let f=new Error("Invalid function bindings header");throw f.cause={statusCode:400},f}return a}var _={properties:{tableName:{type:"string",minLength:1},key:{type:"string"}},required:["tableName"],additionalProperties:!1};var $t=new m(!0);async function K(t,e,s){try{let r=await j(t),i=$t.test(_,r);if(!i.success)return t.json({error:"Invalid input",details:i.errors},400);let{tableName:n,key:o}=r;if(!n)return t.json("tableName is required",400);await p(t,s,"databases.table.get","databases","table","read",n);let a=await e.get(n,o);return a===void 0?t.json(null,404):t.json(a,200)}catch(r){let{message:i,status:n}=h(r,"Error getting table data");return t.json({error:i},n)}}var X={properties:{tableName:{type:"string",minLength:1},key:{type:"string"},value:{},expiration:{type:"number"},dictionaryName:{type:"string"}},required:["tableName"],additionalProperties:!1};var Ot=new m(!0);async function Z(t,e,s){try{let r=await j(t),i=Ot.test(X,r);if(!i.success)return t.json({error:"Invalid input",details:i.errors},400);let{tableName:n,key:o,value:a,expiration:c,dictionaryName:l}=r;if(!n||a===void 0)return t.json("tableName and value are required",400);await p(t,s,"databases.table.update","databases","table","write",n);let f=await e.write(n,o,a,c,l);return t.json(f,200)}catch(r){let{message:i,status:n}=h(r,"Error writing table data");return t.json({error:i},n)}}var Y={properties:{tableName:{type:"string",minLength:1},key:{type:"string",minLength:1}},required:["tableName","key"],additionalProperties:!1};var Lt=new m(!0);async function Q(t,e,s){try{let r=Lt.test(Y,t.query);if(!r.success)return t.json({error:"Invalid input",details:r.errors},400);let{tableName:i,key:n}=t.query;if(!i||!n)return t.json("tableName and key are required",400);await p(t,s,"databases.table.delete","databases","table","delete",i);let o=await e.delete(i,n);return t.json(o,200)}catch(r){let{message:i,status:n}=h(r,"Error deleting table item");return t.json({error:i},n)}}async function tt(t,e,s,r,i,n,o){try{await p(t,s,"databases.table.get","databases","table","read");let a=e.listTables(),c=t.query.context;if(c&&r){let f=t.headers.authorization?.replace(/^Bearer\s+/i,""),d=await r.listResourcesByType(c,"database",f);a=a.filter(u=>d.includes(u))}let l=await Promise.all(a.map(async f=>{let d=await e.getTableSize(f),u=n(i,f);return{name:f,items:d,size:o(u)}}));return t.json({tables:l},200)}catch(a){let{message:c,status:l}=h(a,"Error listing tables");return t.json({error:c},l)}}var v={properties:{tableName:{type:"string",minLength:1},context:{type:"string",minLength:1}},required:["tableName"],additionalProperties:!1};var Vt=new m(!0);async function et(t,e,s){try{let r=t.params.tableName;if(!r)return t.json({error:"tableName is required"},400);let i=Vt.test(v,{tableName:r});return i.success?(await p(t,s,"databases.table.create","databases","table","create",r),e.listTables().includes(r)?t.json({error:"Table already exists"},409):(await e.write(r,"__init__",null),await e.delete(r,"__init__"),t.json({success:!0,name:r,message:"Table created successfully"},201))):t.json({error:"Invalid input",details:i.errors},400)}catch(r){let{message:i,status:n}=h(r,"Error creating table");return t.json({error:i},n)}}var Nt=new m(!0);async function rt(t,e,s){try{let r=t.params.tableName;if(!r)return t.json({error:"tableName is required"},400);let i=Nt.test(v,{tableName:r});if(!i.success)return t.json({error:"Invalid input",details:i.errors},400);if(await p(t,s,"databases.table.delete","databases","table","delete",r),!e.listTables().includes(r))return t.json({error:"Table not found"},404);let o=await e.deleteTable(r);return t.json({success:o,name:r,message:"Table deleted successfully"},200)}catch(r){let{message:i,status:n}=h(r,"Error deleting table");return t.json({error:i},n)}}var Dt=new m(!0);async function st(t,e,s,r,i,n){try{let o=t.params.tableName;if(!o)return t.json({error:"tableName is required"},400);let a=Dt.test(v,{tableName:o});if(!a.success)return t.json({error:"Invalid input",details:a.errors},400);if(await p(t,s,"databases.table.get","databases","table","read",o),!e.listTables().includes(o))return t.json({error:"Table not found"},404);let l=await e.getTableSize(o),f=i(r,o);return t.json({name:o,items:l,size:n(f)},200)}catch(o){let{message:a,status:c}=h(o,"Error getting table info");return t.json({error:a},c)}}async function it(t,e,s){try{if(!t.query.tableName)return t.json({error:"tableName is required"},400);let{tableName:r}=t.query;await p(t,s,"databases.table.get","databases","table","read",r);let i=await e.get(r),n=i?i.length:0;return t.json(n,200)}catch(r){let{message:i,status:n}=h(r,"Error getting table size");return t.json({error:i},n)}}var qt=new m(!0);async function ot(t,e,s){try{let r=t.params.tableName;if(!r)return t.json({error:"tableName is required"},400);let i=qt.test(v,{tableName:r});if(!i.success)return t.json({error:"Invalid input",details:i.errors},400);if(await p(t,s,"databases.table.get","databases","table","read",r),!e.listTables().includes(r))return t.json({error:"Table not found"},404);let o=await e.get(r),a=o?Object.entries(o).map(([c,l])=>Array.isArray(l)&&l.length===2?{key:l[0],value:l[1]}:{key:c,value:l}):[];return t.json({items:a},200)}catch(r){let{message:i,status:n}=h(r,"Error getting table items");return t.json({error:i},n)}}import{readFileSync as zt,existsSync as Bt}from"node:fs";function T(){let t=process.env.MOLNOS_RUNTIME_CONFIG,e={molnos:{dataPath:"data",rateLimit:{global:{enabled:!1,requestsPerMinute:0}},signedUrlSecret:"molnos-default-signed-url-secret"},server:{host:"127.0.0.1",port:3e3},identity:{apiUrl:"http://127.0.0.1:3000"},context:{apiUrl:"http://127.0.0.1:3000"},services:{storage:{host:"127.0.0.1",port:3001,url:"http://127.0.0.1:3001"},functions:{host:"127.0.0.1",port:3002,url:"http://127.0.0.1:3002"},sites:{host:"127.0.0.1",port:3003,url:"http://127.0.0.1:3003"},databases:{host:"127.0.0.1",port:3004,url:"http://127.0.0.1:3004"},observability:{host:"127.0.0.1",port:3005,url:"http://127.0.0.1:3005"}}};if(!t||!Bt(t))return e;try{let s=zt(t,"utf-8");return JSON.parse(s)}catch(s){return console.error("[loadRuntimeConfig] Failed to load runtime config:",s),e}}function nt(t,e){let s={enabled:!1,requestsPerMinute:0};if(!e)return s;let r=e.services?.[t];return r||(e.global?e.global:s)}function at(t,e){let s=t?.api?.port;if(!s)throw new Error('Missing "port" input when create API service!');let r=T(),i=t?.dataPath||r.molnos.dataPath,n=t?.api?.host||r.server.host,o=t?.identityApiUrl!==void 0?t.identityApiUrl:r.identity.apiUrl,a=t?.contextApiUrl!==void 0?t.contextApiUrl:r.context.apiUrl,c=t?.debug||!1,l;return e&&(l=nt(e,r.molnos.rateLimit)),{dataPath:i,api:{port:s,host:n},...o?{identityApiUrl:o}:{},...a?{contextApiUrl:a}:{},...l?{rateLimit:l}:{},debug:c}}var A=class{baseUrl;authToken;constructor(e,s){this.baseUrl=e.replace(/\/$/,""),this.authToken=s}async createCustomRole(e,s,r,i){let n=await fetch(`${this.baseUrl}/identity/roles`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({roleId:e,name:s,description:r,permissions:i})});if(!n.ok){let o=`Failed to create role: ${n.statusText}`;try{o=(await n.json()).error||o}catch{o=await n.text().catch(()=>n.statusText)||o}throw new Error(o)}}async updateRole(e,s){let r=await fetch(`${this.baseUrl}/identity/roles/${e}`,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(s)});if(!r.ok){let i=await r.json();throw new Error(i.error||`Failed to update role: ${r.statusText}`)}}async deleteRole(e){let s=await fetch(`${this.baseUrl}/identity/roles/${e}`,{method:"DELETE",headers:this.getHeaders()});if(!s.ok){let r=await s.json();throw new Error(r.error||`Failed to delete role: ${s.statusText}`)}}async addServiceAccount(e,s,r){let i=await fetch(`${this.baseUrl}/identity/service-accounts`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({name:e,description:s,roles:r})});if(!i.ok){let o=`Failed to create service account: ${i.statusText}`;try{o=(await i.json()).error||o}catch{o=await i.text().catch(()=>i.statusText)||o}throw new Error(o)}let n=await i.json();return{id:n.id,apiKey:n.apiKey}}async deleteIdentity(e){let s=await fetch(`${this.baseUrl}/identity/service-accounts/${e}`,{method:"DELETE",headers:this.getHeaders()});if(!s.ok){let r=await s.json();throw new Error(r.error||`Failed to delete service account: ${s.statusText}`)}}async getUserFromToken(e){try{let s=await fetch(`${this.baseUrl}/identity/whoami`,{method:"GET",headers:{Authorization:`Bearer ${e}`}});return s.ok?await s.json():null}catch{return null}}getHeaders(){let e={"Content-Type":"application/json"};return this.authToken&&(e.Authorization=`Bearer ${this.authToken}`),e}};function lt(t){return t?new A(t):null}var M=class{baseUrl;constructor(e){this.baseUrl=e.replace(/\/$/,"")}async listResourcesByType(e,s,r){let i=`${this.baseUrl}/contexts/${encodeURIComponent(e)}`;try{let n={"Content-Type":"application/json"};r&&(n.Authorization=`Bearer ${r}`);let o=await fetch(i,{method:"GET",headers:n});if(!o.ok)return[];let c=(await o.json()).context?.resources||{};switch(s){case"function":return c.functions||[];case"database":return c.databases||[];case"storage":return c.storage||[];case"site":return c.sites||[];default:return[]}}catch{return[]}}};function ct(t){return t?new M(t):null}function dt(t){if(t===0)return"0 B";let e=["B","KB","MB","GB"],s=Math.floor(Math.log(t)/Math.log(1024));return`${(t/1024**s).toFixed(1)} ${e[s]}`}function ut(t,e){try{let s=ft(t,e);return Ft(s).size}catch{return 0}}async function Ut(t){let e=t.dataPath||"data",s=ft(e,"databases"),r=new N({databaseDirectory:s});await r.start();let i=lt(t.identityApiUrl),n=ct(t.contextApiUrl),o=T(),a=new L({port:t.api.port||o.services.databases.port,host:t.api.host||o.services.databases.host,rateLimit:t.rateLimit||o.molnos.rateLimit.global});return a.get("/table",async l=>it(l,r,i)),a.post("/get",async l=>K(l,r,i)),a.post("/write",async l=>Z(l,r,i)),a.delete("/delete",async l=>Q(l,r,i)),a.get("/tables",async l=>tt(l,r,i,n,s,ut,dt)),a.post("/tables/:tableName",async l=>et(l,r,i)),a.delete("/tables/:tableName",async l=>rt(l,r,i)),a.get("/tables/:tableName",async l=>st(l,r,i,s,ut,dt)),a.get("/tables/:tableName/items",async l=>ot(l,r,i)),a.start()}if(import.meta.url===`file://${process.argv[1]}`){let t=T(),s=process.argv.slice(2).find(n=>n.startsWith("--port=")),r=s?parseInt(s.split("=")[1],10):t.services.databases.port,i=at({api:{port:r}},"databases");Ut(i)}export{Ut as startServer};
@@ -1,20 +1,20 @@
1
1
  // MolnOS Core - See LICENSE file for copyright and license details.
2
- var Z=class{requests=new Map;limit;windowMs;constructor(e=100,t=60){this.limit=e,this.windowMs=t*1e3,setInterval(()=>this.cleanup(),this.windowMs)}getLimit(){return this.limit}isAllowed(e){let t=Date.now(),r=e||"unknown",n=this.requests.get(r);return(!n||n.resetTime<t)&&(n={count:0,resetTime:t+this.windowMs},this.requests.set(r,n)),n.count++,n.count<=this.limit}getRemainingRequests(e){let t=Date.now(),r=e||"unknown",n=this.requests.get(r);return!n||n.resetTime<t?this.limit:Math.max(0,this.limit-n.count)}getResetTime(e){let t=Date.now(),r=e||"unknown",n=this.requests.get(r);return!n||n.resetTime<t?Math.floor((t+this.windowMs)/1e3):Math.floor(n.resetTime/1e3)}cleanup(){let e=Date.now();for(let[t,r]of this.requests.entries())r.resetTime<e&&this.requests.delete(t)}};import{URL as gt}from"url";var K=class{routes=[];globalMiddlewares=[];pathPatterns=new Map;use(e){return this.globalMiddlewares.push(e),this}get(e,...t){let r=t.pop();return this.register("GET",e,r,t)}post(e,...t){let r=t.pop();return this.register("POST",e,r,t)}put(e,...t){let r=t.pop();return this.register("PUT",e,r,t)}delete(e,...t){let r=t.pop();return this.register("DELETE",e,r,t)}patch(e,...t){let r=t.pop();return this.register("PATCH",e,r,t)}any(e,...t){let r=t.pop(),n=t;return this.register("GET",e,r,n),this.register("POST",e,r,n),this.register("PUT",e,r,n),this.register("DELETE",e,r,n),this.register("PATCH",e,r,n),this.register("OPTIONS",e,r,n),this}options(e,...t){let r=t.pop();return this.register("OPTIONS",e,r,t)}match(e,t){for(let r of this.routes){if(r.method!==e)continue;let n=this.pathPatterns.get(r.path);if(!n)continue;let s=n.pattern.exec(t);if(!s)continue;let i={};return n.paramNames.forEach((o,a)=>{i[o]=s[a+1]||""}),{route:r,params:i}}return null}async handle(e,t){let r=e.method||"GET",n=new gt(e.url||"/",`http://${e.headers.host}`),s=n.pathname,i=this.match(r,s);if(!i)return null;let{route:o,params:a}=i,c={};n.searchParams.forEach((l,u)=>{c[u]=l});let d={req:e,res:t,params:a,query:c,body:e.body||{},headers:e.headers,path:s,state:{},raw:()=>t,binary:(l,u="application/octet-stream",h=200)=>({statusCode:h,body:l,headers:{"Content-Type":u,"Content-Length":l.length.toString()},isRaw:!0}),text:(l,u=200)=>({statusCode:u,body:l,headers:{"Content-Type":"text/plain"}}),form:(l,u=200)=>({statusCode:u,body:l,headers:{"Content-Type":"application/x-www-form-urlencoded"}}),json:(l,u=200)=>({statusCode:u,body:l,headers:{"Content-Type":"application/json"}}),html:(l,u=200)=>({statusCode:u,body:l,headers:{"Content-Type":"text/html"}}),redirect:(l,u=302)=>({statusCode:u,body:null,headers:{Location:l}}),status:function(l){return{raw:()=>t,binary:(u,h="application/octet-stream")=>({statusCode:l,body:u,headers:{"Content-Type":h,"Content-Length":u.length.toString()},isRaw:!0}),text:u=>({statusCode:l,body:u,headers:{"Content-Type":"text/plain"}}),json:u=>({statusCode:l,body:u,headers:{"Content-Type":"application/json"}}),html:u=>({statusCode:l,body:u,headers:{"Content-Type":"text/html"}}),form:u=>({statusCode:l,body:u,headers:{"Content-Type":"application/x-www-form-urlencoded"}}),redirect:(u,h=302)=>({statusCode:h,body:null,headers:{Location:u}}),status:u=>this.status(u)}}},f=[...this.globalMiddlewares,...o.middlewares];return this.executeMiddlewareChain(d,f,o.handler)}register(e,t,r,n=[]){return this.routes.push({method:e,path:t,handler:r,middlewares:n}),this.pathPatterns.set(t,this.createPathPattern(t)),this}createPathPattern(e){let t=[],r=e.replace(/\/:[^/]+/g,n=>{let s=n.slice(2);return t.push(s),"/([^/]+)"});return r.endsWith("/*")?(r=`${r.slice(0,-2)}(?:/(.*))?`,t.push("wildcard")):r=r.replace(/\/$/,"/?"),{pattern:new RegExp(`^${r}$`),paramNames:t}}async executeMiddlewareChain(e,t,r){let n=0,s=async()=>{if(n<t.length){let i=t[n++];return i(e,s)}return r(e)};return s()}};var R=()=>({port:Number(process.env.PORT)||3e3,host:process.env.HOST||"0.0.0.0",useHttps:!1,useHttp2:!1,sslCert:"",sslKey:"",sslCa:"",debug:yt(process.env.DEBUG)||!1,maxBodySize:1048576,requestTimeout:3e4,rateLimit:{enabled:!0,requestsPerMinute:100},allowedDomains:["*"]});function yt(e){return e==="true"||e===!0}var N=class extends Error{constructor(e){super(e),this.name="ValidationError",this.message=e||"Validation did not pass",this.cause={statusCode:400}}};import{existsSync as bt,readFileSync as wt}from"node:fs";var U=class{config={};options=[];validators=[];autoValidate=!0;constructor(e){let t=e?.configFilePath,r=e?.args||[],n=e?.config||{};this.options=e?.options||[],this.validators=e?.validators||[],e?.autoValidate!==void 0&&(this.autoValidate=e.autoValidate),this.config=this.createConfig(t,r,n)}deepMerge(e,t){let r={...e};for(let n in t)t[n]!==void 0&&(t[n]!==null&&typeof t[n]=="object"&&!Array.isArray(t[n])&&n in e&&e[n]!==null&&typeof e[n]=="object"&&!Array.isArray(e[n])?r[n]=this.deepMerge(e[n],t[n]):t[n]!==void 0&&(r[n]=t[n]));return r}setValueAtPath(e,t,r){let n=t.split("."),s=e;for(let o=0;o<n.length-1;o++){let a=n[o];!(a in s)||s[a]===null?s[a]={}:typeof s[a]!="object"&&(s[a]={}),s=s[a]}let i=n[n.length-1];s[i]=r}getValueAtPath(e,t){let r=t.split("."),n=e;for(let s of r){if(n==null)return;n=n[s]}return n}createConfig(e,t=[],r={}){let n={};for(let a of this.options)a.defaultValue!==void 0&&this.setValueAtPath(n,a.path,a.defaultValue);let s={};if(e&&bt(e))try{let a=wt(e,"utf8");s=JSON.parse(a),console.log(`Loaded configuration from ${e}`)}catch(a){console.error(`Error reading config file: ${a instanceof Error?a.message:String(a)}`)}let i=this.parseCliArgs(t),o=this.deepMerge({},n);return o=this.deepMerge(o,s),o=this.deepMerge(o,r),o=this.deepMerge(o,i),o}parseCliArgs(e){let t={},r=e[0]?.endsWith("node")||e[0]?.endsWith("node.exe")?2:0;for(;r<e.length;){let n=e[r++],s=this.options.find(i=>i.flag===n);if(s)if(s.isFlag)this.setValueAtPath(t,s.path,!0);else if(r<e.length&&!e[r].startsWith("-")){let i=e[r++];if(s.parser)try{i=s.parser(i)}catch(o){console.error(`Error parsing value for ${s.flag}: ${o instanceof Error?o.message:String(o)}`);continue}if(s.validator){let o=s.validator(i);if(o!==!0&&typeof o=="string"){console.error(`Invalid value for ${s.flag}: ${o}`);continue}if(o===!1){console.error(`Invalid value for ${s.flag}`);continue}}this.setValueAtPath(t,s.path,i)}else console.error(`Missing value for option ${n}`)}return t}validate(){for(let e of this.validators){let t=this.getValueAtPath(this.config,e.path),r=e.validator(t,this.config);if(r===!1)throw new N(e.message);if(typeof r=="string")throw new N(r)}}get(){return this.autoValidate&&this.validate(),this.config}getValue(e,t){let r=this.getValueAtPath(this.config,e);return r!==void 0?r:t}setValue(e,t){if(typeof t=="object"&&t!==null&&!Array.isArray(t)){let r=this.getValueAtPath(this.config,e)||{};if(typeof r=="object"&&!Array.isArray(r)){let n=this.deepMerge(r,t);this.setValueAtPath(this.config,e,n);return}}this.setValueAtPath(this.config,e,t)}getHelpText(){let e=`Available configuration options:
2
+ import{existsSync as U}from"node:fs";import{join as F}from"node:path";import{mkdir as Bt,writeFile as Y,readFile as wt,unlink as Vt}from"node:fs/promises";import{pathToFileURL as zt}from"node:url";import{getRandomValues as vt}from"node:crypto";var q=class{options;defaultLength=16;defaultOnlyLowerCase=!1;defaultStyle="extended";defaultUrlSafe=!0;constructor(e){if(this.options={},e)for(let[t,r]of Object.entries(e))this.options[t]=this.generateConfig(r)}add(e){if(!e?.name)throw new Error("Missing name for the ID configuration");let t=this.generateConfig(e);this.options[e.name]=t}remove(e){if(!e?.name)throw new Error("Missing name for the ID configuration");delete this.options[e.name]}create(e,t,r,n){let s=this.generateConfig({length:e,style:t,onlyLowerCase:r,urlSafe:n});return this.generateId(s)}custom(e){if(this.options[e])return this.generateId(this.options[e]);throw new Error(`No configuration found with name: ${e}`)}generateConfig(e){return{name:e?.name||"",length:e?.length||this.defaultLength,onlyLowerCase:e?.onlyLowerCase??this.defaultOnlyLowerCase,style:e?.style||this.defaultStyle,urlSafe:e?.urlSafe??this.defaultUrlSafe}}getCharacterSet(e,t,r){if(e==="hex")return t?"0123456789abcdef":"0123456789ABCDEFabcdef";if(e==="alphanumeric")return t?"abcdefghijklmnopqrstuvwxyz0123456789":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";if(e==="extended")return r?t?"abcdefghijklmnopqrstuvwxyz0123456789-._~":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~":t?"abcdefghijklmnopqrstuvwxyz0123456789-._~!$()*+,;=:":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$()*+,;=:";throw new Error(`Unknown ID style "${e} provided. Must be one of "extended" (default), "alphanumeric", or "hex".`)}generateId(e){let{length:t,onlyLowerCase:r,style:n,urlSafe:s}=e;if(t<0||t===0)throw new Error("ID length cannot be negative");let o=this.getCharacterSet(n,r,s),i=(2<<Math.log(o.length-1)/Math.LN2)-1,a=Math.ceil(1.6*i*t/o.length),c="";for(;c.length<t;){let d=new Uint8Array(a);vt(d);for(let l=0;l<a;l++){let u=d[l]&i;if(u<o.length&&(c+=o[u],c.length===t))break}}return c}};var xt=8,Ct=40,St=/^[a-zA-Z0-9_-]{1,40}$/;function Et(){return new q().create(xt,"alphanumeric",!1,!0)}function Pt(e){return St.test(e)}function It(e){if(!Pt(e))throw new Error(`Invalid ID format: "${e}". IDs must be 1-${Ct} characters using only alphanumeric characters, underscores, and hyphens.`)}function Q(e){return e?(It(e),e):Et()}var tt=class{requests=new Map;limit;windowMs;constructor(e=100,t=60){this.limit=e,this.windowMs=t*1e3,setInterval(()=>this.cleanup(),this.windowMs)}getLimit(){return this.limit}isAllowed(e){let t=Date.now(),r=e||"unknown",n=this.requests.get(r);return(!n||n.resetTime<t)&&(n={count:0,resetTime:t+this.windowMs},this.requests.set(r,n)),n.count++,n.count<=this.limit}getRemainingRequests(e){let t=Date.now(),r=e||"unknown",n=this.requests.get(r);return!n||n.resetTime<t?this.limit:Math.max(0,this.limit-n.count)}getResetTime(e){let t=Date.now(),r=e||"unknown",n=this.requests.get(r);return!n||n.resetTime<t?Math.floor((t+this.windowMs)/1e3):Math.floor(n.resetTime/1e3)}cleanup(){let e=Date.now();for(let[t,r]of this.requests.entries())r.resetTime<e&&this.requests.delete(t)}};import{URL as Tt}from"url";var et=class{routes=[];globalMiddlewares=[];pathPatterns=new Map;use(e){return this.globalMiddlewares.push(e),this}get(e,...t){let r=t.pop();return this.register("GET",e,r,t)}post(e,...t){let r=t.pop();return this.register("POST",e,r,t)}put(e,...t){let r=t.pop();return this.register("PUT",e,r,t)}delete(e,...t){let r=t.pop();return this.register("DELETE",e,r,t)}patch(e,...t){let r=t.pop();return this.register("PATCH",e,r,t)}any(e,...t){let r=t.pop(),n=t;return this.register("GET",e,r,n),this.register("POST",e,r,n),this.register("PUT",e,r,n),this.register("DELETE",e,r,n),this.register("PATCH",e,r,n),this.register("OPTIONS",e,r,n),this}options(e,...t){let r=t.pop();return this.register("OPTIONS",e,r,t)}match(e,t){for(let r of this.routes){if(r.method!==e)continue;let n=this.pathPatterns.get(r.path);if(!n)continue;let s=n.pattern.exec(t);if(!s)continue;let o={};return n.paramNames.forEach((i,a)=>{o[i]=s[a+1]||""}),{route:r,params:o}}return null}async handle(e,t){let r=e.method||"GET",n=new Tt(e.url||"/",`http://${e.headers.host}`),s=n.pathname,o=this.match(r,s);if(!o)return null;let{route:i,params:a}=o,c={};n.searchParams.forEach((u,h)=>{c[h]=u});let d={req:e,res:t,params:a,query:c,body:e.body||{},headers:e.headers,path:s,state:{},raw:()=>t,binary:(u,h="application/octet-stream",f=200)=>({statusCode:f,body:u,headers:{"Content-Type":h,"Content-Length":u.length.toString()},isRaw:!0}),text:(u,h=200)=>({statusCode:h,body:u,headers:{"Content-Type":"text/plain"}}),form:(u,h=200)=>({statusCode:h,body:u,headers:{"Content-Type":"application/x-www-form-urlencoded"}}),json:(u,h=200)=>({statusCode:h,body:u,headers:{"Content-Type":"application/json"}}),html:(u,h=200)=>({statusCode:h,body:u,headers:{"Content-Type":"text/html"}}),redirect:(u,h=302)=>({statusCode:h,body:null,headers:{Location:u}}),status:function(u){return{raw:()=>t,binary:(h,f="application/octet-stream")=>({statusCode:u,body:h,headers:{"Content-Type":f,"Content-Length":h.length.toString()},isRaw:!0}),text:h=>({statusCode:u,body:h,headers:{"Content-Type":"text/plain"}}),json:h=>({statusCode:u,body:h,headers:{"Content-Type":"application/json"}}),html:h=>({statusCode:u,body:h,headers:{"Content-Type":"text/html"}}),form:h=>({statusCode:u,body:h,headers:{"Content-Type":"application/x-www-form-urlencoded"}}),redirect:(h,f=302)=>({statusCode:f,body:null,headers:{Location:h}}),status:h=>this.status(h)}}},l=[...this.globalMiddlewares,...i.middlewares];return this.executeMiddlewareChain(d,l,i.handler)}register(e,t,r,n=[]){return this.routes.push({method:e,path:t,handler:r,middlewares:n}),this.pathPatterns.set(t,this.createPathPattern(t)),this}createPathPattern(e){let t=[],r=e.replace(/\/:[^/]+/g,n=>{let s=n.slice(2);return t.push(s),"/([^/]+)"});return r.endsWith("/*")?(r=`${r.slice(0,-2)}(?:/(.*))?`,t.push("wildcard")):r=r.replace(/\/$/,"/?"),{pattern:new RegExp(`^${r}$`),paramNames:t}}async executeMiddlewareChain(e,t,r){let n=0,s=async()=>{if(n<t.length){let o=t[n++];return o(e,s)}return r(e)};return s()}};var $=()=>({port:Number(process.env.PORT)||3e3,host:process.env.HOST||"0.0.0.0",useHttps:!1,useHttp2:!1,sslCert:"",sslKey:"",sslCa:"",debug:At(process.env.DEBUG)||!1,maxBodySize:1048576,requestTimeout:3e4,rateLimit:{enabled:!0,requestsPerMinute:100},allowedDomains:["*"]});function At(e){return e==="true"||e===!0}var B=class extends Error{constructor(e){super(e),this.name="ValidationError",this.message=e||"Validation did not pass",this.cause={statusCode:400}}};import{existsSync as jt,readFileSync as Ft}from"node:fs";var V=class{config={};options=[];validators=[];autoValidate=!0;constructor(e){let t=e?.configFilePath,r=e?.args||[],n=e?.config||{};this.options=e?.options||[],this.validators=e?.validators||[],e?.autoValidate!==void 0&&(this.autoValidate=e.autoValidate),this.config=this.createConfig(t,r,n)}deepMerge(e,t){let r={...e};for(let n in t)t[n]!==void 0&&(t[n]!==null&&typeof t[n]=="object"&&!Array.isArray(t[n])&&n in e&&e[n]!==null&&typeof e[n]=="object"&&!Array.isArray(e[n])?r[n]=this.deepMerge(e[n],t[n]):t[n]!==void 0&&(r[n]=t[n]));return r}setValueAtPath(e,t,r){let n=t.split("."),s=e;for(let i=0;i<n.length-1;i++){let a=n[i];!(a in s)||s[a]===null?s[a]={}:typeof s[a]!="object"&&(s[a]={}),s=s[a]}let o=n[n.length-1];s[o]=r}getValueAtPath(e,t){let r=t.split("."),n=e;for(let s of r){if(n==null)return;n=n[s]}return n}createConfig(e,t=[],r={}){let n={};for(let a of this.options)a.defaultValue!==void 0&&this.setValueAtPath(n,a.path,a.defaultValue);let s={};if(e&&jt(e))try{let a=Ft(e,"utf8");s=JSON.parse(a),console.log(`Loaded configuration from ${e}`)}catch(a){console.error(`Error reading config file: ${a instanceof Error?a.message:String(a)}`)}let o=this.parseCliArgs(t),i=this.deepMerge({},n);return i=this.deepMerge(i,s),i=this.deepMerge(i,r),i=this.deepMerge(i,o),i}parseCliArgs(e){let t={},r=e[0]?.endsWith("node")||e[0]?.endsWith("node.exe")?2:0;for(;r<e.length;){let n=e[r++],s=this.options.find(o=>o.flag===n);if(s)if(s.isFlag)this.setValueAtPath(t,s.path,!0);else if(r<e.length&&!e[r].startsWith("-")){let o=e[r++];if(s.parser)try{o=s.parser(o)}catch(i){console.error(`Error parsing value for ${s.flag}: ${i instanceof Error?i.message:String(i)}`);continue}if(s.validator){let i=s.validator(o);if(i!==!0&&typeof i=="string"){console.error(`Invalid value for ${s.flag}: ${i}`);continue}if(i===!1){console.error(`Invalid value for ${s.flag}`);continue}}this.setValueAtPath(t,s.path,o)}else console.error(`Missing value for option ${n}`)}return t}validate(){for(let e of this.validators){let t=this.getValueAtPath(this.config,e.path),r=e.validator(t,this.config);if(r===!1)throw new B(e.message);if(typeof r=="string")throw new B(r)}}get(){return this.autoValidate&&this.validate(),this.config}getValue(e,t){let r=this.getValueAtPath(this.config,e);return r!==void 0?r:t}setValue(e,t){if(typeof t=="object"&&t!==null&&!Array.isArray(t)){let r=this.getValueAtPath(this.config,e)||{};if(typeof r=="object"&&!Array.isArray(r)){let n=this.deepMerge(r,t);this.setValueAtPath(this.config,e,n);return}}this.setValueAtPath(this.config,e,t)}getHelpText(){let e=`Available configuration options:
3
3
 
4
4
  `;for(let t of this.options)e+=`${t.flag}${t.isFlag?"":" <value>"}
5
5
  `,t.description&&(e+=` ${t.description}
6
6
  `),t.defaultValue!==void 0&&(e+=` Default: ${JSON.stringify(t.defaultValue)}
7
7
  `),e+=`
8
- `;return e}};var V={int:e=>{let t=e.trim();if(!/^[+-]?\d+$/.test(t))throw new Error(`Cannot parse "${e}" as an integer`);let r=Number.parseInt(t,10);if(Number.isNaN(r))throw new Error(`Cannot parse "${e}" as an integer`);return r},float:e=>{let t=e.trim();if(!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(t)){if(t==="Infinity"||t==="-Infinity")return t==="Infinity"?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY;throw new Error(`Cannot parse "${e}" as a number`)}let r=Number.parseFloat(t);if(Number.isNaN(r))throw new Error(`Cannot parse "${e}" as a number`);return r},boolean:e=>{let t=e.trim().toLowerCase();if(["true","yes","1","y"].includes(t))return!0;if(["false","no","0","n"].includes(t))return!1;throw new Error(`Cannot parse "${e}" as a boolean`)},array:e=>e.split(",").map(t=>t.trim()),json:e=>{try{return JSON.parse(e)}catch{throw new Error(`Cannot parse "${e}" as JSON`)}}};var b=R(),Q=e=>({configFilePath:"mikroserve.config.json",args:process.argv,options:[{flag:"--port",path:"port",defaultValue:b.port},{flag:"--host",path:"host",defaultValue:b.host},{flag:"--https",path:"useHttps",defaultValue:b.useHttps,isFlag:!0},{flag:"--http2",path:"useHttp2",defaultValue:b.useHttp2,isFlag:!0},{flag:"--cert",path:"sslCert",defaultValue:b.sslCert},{flag:"--key",path:"sslKey",defaultValue:b.sslKey},{flag:"--ca",path:"sslCa",defaultValue:b.sslCa},{flag:"--ratelimit",path:"rateLimit.enabled",defaultValue:b.rateLimit.enabled,isFlag:!0},{flag:"--rps",path:"rateLimit.requestsPerMinute",defaultValue:b.rateLimit.requestsPerMinute},{flag:"--allowed",path:"allowedDomains",defaultValue:b.allowedDomains,parser:V.array},{flag:"--debug",path:"debug",defaultValue:b.debug,isFlag:!0},{flag:"--max-body-size",path:"maxBodySize",defaultValue:b.maxBodySize},{flag:"--request-timeout",path:"requestTimeout",defaultValue:b.requestTimeout}],config:e});function tt(e,t){let r=t.match(/boundary=(?:"([^"]+)"|([^;]+))/i);if(!r)throw new Error("Invalid multipart/form-data: missing boundary");let n=r[1]||r[2],s=Buffer.from(`--${n}`),i=Buffer.from(`--${n}--`),o={},a={},c=vt(e,s);for(let d of c){if(d.length===0||d.equals(i.subarray(s.length)))continue;let f=St(d);if(!f)continue;let{name:l,filename:u,contentType:h,data:p}=f;if(u){let m={filename:u,contentType:h||"application/octet-stream",data:p,size:p.length};a[l]?Array.isArray(a[l])?a[l].push(m):a[l]=[a[l],m]:a[l]=m}else{let m=p.toString("utf8");o[l]?Array.isArray(o[l])?o[l].push(m):o[l]=[o[l],m]:o[l]=m}}return{fields:o,files:a}}function vt(e,t){let r=[],n=0;for(;n<e.length;){let s=e.indexOf(t,n);if(s===-1)break;n!==s&&r.push(e.subarray(n,s)),n=s+t.length,n<e.length&&e[n]===13&&e[n+1]===10&&(n+=2)}return r}function St(e){let t=Buffer.from(`\r
8
+ `;return e}};var z={int:e=>{let t=e.trim();if(!/^[+-]?\d+$/.test(t))throw new Error(`Cannot parse "${e}" as an integer`);let r=Number.parseInt(t,10);if(Number.isNaN(r))throw new Error(`Cannot parse "${e}" as an integer`);return r},float:e=>{let t=e.trim();if(!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(t)){if(t==="Infinity"||t==="-Infinity")return t==="Infinity"?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY;throw new Error(`Cannot parse "${e}" as a number`)}let r=Number.parseFloat(t);if(Number.isNaN(r))throw new Error(`Cannot parse "${e}" as a number`);return r},boolean:e=>{let t=e.trim().toLowerCase();if(["true","yes","1","y"].includes(t))return!0;if(["false","no","0","n"].includes(t))return!1;throw new Error(`Cannot parse "${e}" as a boolean`)},array:e=>e.split(",").map(t=>t.trim()),json:e=>{try{return JSON.parse(e)}catch{throw new Error(`Cannot parse "${e}" as JSON`)}}};var b=$(),rt=e=>({configFilePath:"mikroserve.config.json",args:process.argv,options:[{flag:"--port",path:"port",defaultValue:b.port},{flag:"--host",path:"host",defaultValue:b.host},{flag:"--https",path:"useHttps",defaultValue:b.useHttps,isFlag:!0},{flag:"--http2",path:"useHttp2",defaultValue:b.useHttp2,isFlag:!0},{flag:"--cert",path:"sslCert",defaultValue:b.sslCert},{flag:"--key",path:"sslKey",defaultValue:b.sslKey},{flag:"--ca",path:"sslCa",defaultValue:b.sslCa},{flag:"--ratelimit",path:"rateLimit.enabled",defaultValue:b.rateLimit.enabled,isFlag:!0},{flag:"--rps",path:"rateLimit.requestsPerMinute",defaultValue:b.rateLimit.requestsPerMinute},{flag:"--allowed",path:"allowedDomains",defaultValue:b.allowedDomains,parser:z.array},{flag:"--debug",path:"debug",defaultValue:b.debug,isFlag:!0},{flag:"--max-body-size",path:"maxBodySize",defaultValue:b.maxBodySize},{flag:"--request-timeout",path:"requestTimeout",defaultValue:b.requestTimeout}],config:e});function nt(e,t){let r=t.match(/boundary=(?:"([^"]+)"|([^;]+))/i);if(!r)throw new Error("Invalid multipart/form-data: missing boundary");let n=r[1]||r[2],s=Buffer.from(`--${n}`),o=Buffer.from(`--${n}--`),i={},a={},c=Rt(e,s);for(let d of c){if(d.length===0||d.equals(o.subarray(s.length)))continue;let l=$t(d);if(!l)continue;let{name:u,filename:h,contentType:f,data:m}=l;if(h){let p={filename:h,contentType:f||"application/octet-stream",data:m,size:m.length};a[u]?Array.isArray(a[u])?a[u].push(p):a[u]=[a[u],p]:a[u]=p}else{let p=m.toString("utf8");i[u]?Array.isArray(i[u])?i[u].push(p):i[u]=[i[u],p]:i[u]=p}}return{fields:i,files:a}}function Rt(e,t){let r=[],n=0;for(;n<e.length;){let s=e.indexOf(t,n);if(s===-1)break;n!==s&&r.push(e.subarray(n,s)),n=s+t.length,n<e.length&&e[n]===13&&e[n+1]===10&&(n+=2)}return r}function $t(e){let t=Buffer.from(`\r
9
9
  \r
10
- `),r=e.indexOf(t);if(r===-1)return null;let n=e.subarray(0,r),s=e.subarray(r+4),o=n.toString("utf8").split(`\r
11
- `),a="",c="",d,f;for(let u of o){let h=u.toLowerCase();if(h.startsWith("content-disposition:")){a=u.substring(20).trim();let p=a.match(/name="([^"]+)"/);p&&(c=p[1]);let m=a.match(/filename="([^"]+)"/);m&&(d=m[1])}else h.startsWith("content-type:")&&(f=u.substring(13).trim())}if(!c)return null;let l=s;return l.length>=2&&l[l.length-2]===13&&l[l.length-1]===10&&(l=l.subarray(0,l.length-2)),{disposition:a,name:c,filename:d,contentType:f,data:l}}import{readFileSync as x}from"fs";import B from"http";import Ct from"http2";import xt from"https";var z=class{config;rateLimiter;router;shutdownHandlers=[];constructor(e){let t=new U(Q(e||{})).get();t.debug&&console.log("Using configuration:",t),this.config=t,this.router=new K;let r=t.rateLimit.requestsPerMinute||R().rateLimit.requestsPerMinute;this.rateLimiter=new Z(r,60),t.rateLimit.enabled===!0&&this.use(this.rateLimitMiddleware.bind(this))}use(e){return this.router.use(e),this}get(e,...t){return this.router.get(e,...t),this}post(e,...t){return this.router.post(e,...t),this}put(e,...t){return this.router.put(e,...t),this}delete(e,...t){return this.router.delete(e,...t),this}patch(e,...t){return this.router.patch(e,...t),this}any(e,...t){return this.router.any(e,...t),this}options(e,...t){return this.router.options(e,...t),this}start(){let e=this.createServer(),{port:t,host:r}=this.config;return this.setupGracefulShutdown(e),e.listen(t,r,()=>{let n=e.address(),s=this.config.useHttps||this.config.useHttp2?"https":"http";console.log(`MikroServe running at ${s}://${n.address!=="::"?n.address:"localhost"}:${n.port}`)}),e}createServer(){let e=this.requestHandler.bind(this);if(this.config.useHttp2){if(!this.config.sslCert||!this.config.sslKey)throw new Error("SSL certificate and key paths are required when useHttp2 is true");try{let t={key:x(this.config.sslKey),cert:x(this.config.sslCert),...this.config.sslCa?{ca:x(this.config.sslCa)}:{}};return Ct.createSecureServer(t,e)}catch(t){throw t.message.includes("key values mismatch")?new Error(`SSL certificate and key do not match: ${t.message}`):t}}else if(this.config.useHttps){if(!this.config.sslCert||!this.config.sslKey)throw new Error("SSL certificate and key paths are required when useHttps is true");try{let t={key:x(this.config.sslKey),cert:x(this.config.sslCert),...this.config.sslCa?{ca:x(this.config.sslCa)}:{}};return xt.createServer(t,e)}catch(t){throw t.message.includes("key values mismatch")?new Error(`SSL certificate and key do not match: ${t.message}`):t}}return B.createServer(e)}async rateLimitMiddleware(e,t){let r=e.req.socket.remoteAddress||"unknown";return e.res.setHeader("X-RateLimit-Limit",this.rateLimiter.getLimit().toString()),e.res.setHeader("X-RateLimit-Remaining",this.rateLimiter.getRemainingRequests(r).toString()),e.res.setHeader("X-RateLimit-Reset",this.rateLimiter.getResetTime(r).toString()),this.rateLimiter.isAllowed(r)?t():{statusCode:429,body:{error:"Too Many Requests",message:"Rate limit exceeded, please try again later"},headers:{"Content-Type":"application/json"}}}async requestHandler(e,t){let r=Date.now(),n=e.method||"UNKNOWN",s=e.url||"/unknown",i=this.config.debug;try{if(this.setCorsHeaders(t,e),this.setSecurityHeaders(t,this.config.useHttps),i&&console.log(`${n} ${s}`),e.method==="OPTIONS"){if(t instanceof B.ServerResponse)t.statusCode=204,t.end();else{let a=t;a.writeHead(204),a.end()}return}try{e.body=await this.parseBody(e)}catch(a){return i&&console.error("Body parsing error:",a.message),this.respond(t,{statusCode:400,body:{error:"Bad Request",message:a.message}})}let o=await this.router.handle(e,t);return o?o._handled?void 0:this.respond(t,o):this.respond(t,{statusCode:404,body:{error:"Not Found",message:"The requested endpoint does not exist"}})}catch(o){return console.error("Server error:",o),this.respond(t,{statusCode:500,body:{error:"Internal Server Error",message:i?o.message:"An unexpected error occurred"}})}finally{i&&this.logDuration(r,n,s)}}logDuration(e,t,r){let n=Date.now()-e;console.log(`${t} ${r} completed in ${n}ms`)}async parseBody(e){return new Promise((t,r)=>{let n=[],s=0,i=this.config.maxBodySize,o=!1,a=null,c=this.config.debug,d=e.headers["content-type"]||"";c&&console.log("Content-Type:",d),this.config.requestTimeout>0&&(a=setTimeout(()=>{o||(o=!0,c&&console.log("Request timeout exceeded"),r(new Error("Request timeout")))},this.config.requestTimeout));let f=()=>{a&&(clearTimeout(a),a=null)};e.on("data",l=>{if(!o){if(s+=l.length,c&&console.log(`Received chunk: ${l.length} bytes, total size: ${s}`),s>i){o=!0,f(),c&&console.log(`Body size exceeded limit: ${s} > ${i}`),r(new Error("Request body too large"));return}n.push(l)}}),e.on("end",()=>{if(!o){o=!0,f(),c&&console.log(`Request body complete: ${s} bytes`);try{if(n.length>0){let l=Buffer.concat(n);if(d.includes("application/json"))try{let u=l.toString("utf8");t(JSON.parse(u))}catch(u){r(new Error(`Invalid JSON in request body: ${u.message}`))}else if(d.includes("application/x-www-form-urlencoded")){let u=l.toString("utf8"),h={};new URLSearchParams(u).forEach((p,m)=>{h[m]=p}),t(h)}else if(d.includes("multipart/form-data"))try{let u=tt(l,d);t(u)}catch(u){r(new Error(`Invalid multipart form data: ${u.message}`))}else this.isBinaryContentType(d)?t(l):t(l.toString("utf8"))}else t({})}catch(l){r(new Error(`Invalid request body: ${l}`))}}}),e.on("error",l=>{o||(o=!0,f(),r(new Error(`Error reading request body: ${l.message}`)))}),e.on("close",()=>{f()})})}isBinaryContentType(e){return["application/octet-stream","application/pdf","application/zip","application/gzip","application/x-tar","application/x-rar-compressed","application/x-7z-compressed","image/","video/","audio/","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument","application/msword","application/vnd.ms-powerpoint"].some(r=>e.includes(r))}setCorsHeaders(e,t){let r=t.headers.origin,{allowedDomains:n=["*"]}=this.config;!r||n.length===0||n.includes("*")?e.setHeader("Access-Control-Allow-Origin","*"):n.includes(r)&&(e.setHeader("Access-Control-Allow-Origin",r),e.setHeader("Vary","Origin")),e.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, PATCH, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization"),e.setHeader("Access-Control-Max-Age","86400")}setSecurityHeaders(e,t=!1){let r={"X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","Content-Security-Policy":"default-src 'self'; script-src 'self'; object-src 'none'","X-XSS-Protection":"1; mode=block"};if((t||this.config.useHttp2)&&(r["Strict-Transport-Security"]="max-age=31536000; includeSubDomains"),e instanceof B.ServerResponse)Object.entries(r).forEach(([n,s])=>{e.setHeader(n,s)});else{let n=e;Object.entries(r).forEach(([s,i])=>{n.setHeader(s,i)})}}respond(e,t){let r={...t.headers||{}};(s=>typeof s.writeHead=="function"&&typeof s.end=="function")(e)?(e.writeHead(t.statusCode,r),t.body===null||t.body===void 0?e.end():t.isRaw||typeof t.body=="string"?e.end(t.body):e.end(JSON.stringify(t.body))):(console.warn("Unexpected response object type without writeHead/end methods"),e.writeHead?.(t.statusCode,r),t.body===null||t.body===void 0?e.end?.():t.isRaw||typeof t.body=="string"?e.end?.(t.body):e.end?.(JSON.stringify(t.body)))}setupGracefulShutdown(e){let t=o=>{console.log("Shutting down MikroServe server..."),o&&console.error("Error:",o),this.cleanupShutdownHandlers(),e.close(()=>{console.log("Server closed successfully"),process.env.NODE_ENV!=="test"&&process.env.VITEST!=="true"&&setImmediate(()=>process.exit(o?1:0))})},r=()=>t(),n=()=>t(),s=o=>t(o),i=o=>t(o);this.shutdownHandlers=[r,n,s,i],process.on("SIGINT",r),process.on("SIGTERM",n),process.on("uncaughtException",s),process.on("unhandledRejection",i)}cleanupShutdownHandlers(){if(this.shutdownHandlers.length>0){let[e,t,r,n]=this.shutdownHandlers;process.removeListener("SIGINT",e),process.removeListener("SIGTERM",t),process.removeListener("uncaughtException",r),process.removeListener("unhandledRejection",n),this.shutdownHandlers=[]}}};import{createHash as Rt}from"node:crypto";import{existsSync as L}from"node:fs";import{join as j}from"node:path";import{mkdir as $t,writeFile as X,readFile as mt,unlink as Ot}from"node:fs/promises";import{pathToFileURL as Ht}from"node:url";var y=class extends Error{constructor(t){super(),this.name="ValidationError",this.message=t||"Invalid input",this.cause={statusCode:400}}};var $=class extends Error{constructor(t){super(),this.name="NotFoundError",this.message=t||"Resource not found",this.cause={statusCode:404}}};var A=class extends Error{constructor(t){super(),this.name="InvalidMethodError",this.message=t||"Invalid HTTP method",this.cause={statusCode:400}}};var O=class extends Error{constructor(t){super(),this.name="ServiceRequestError",this.message=t||"Service request failed",this.cause={statusCode:502}}};var H=class{generatePermissionsFromBindings(t){let r=[];for(let n of t){let s=n.service;for(let i of n.permissions){if(!i.resource){r.push(`${s}.*`);continue}let o=i.resource,a=i.actions||["*"];if(i.targets&&i.targets.length>0)for(let c of a)for(let d of i.targets)r.push(`${s}.${o}.${c}:${d}`);else for(let c of a)r.push(`${s}.${o}.${c}`)}}return[...new Set(r)]}validateBindings(t){let r=["databases","storage","observability","sites","functions"];for(let n of t){if(!r.includes(n.service))throw new y(`Invalid service: ${n.service}. Must be one of: ${r.join(", ")}`);if(!n.permissions||n.permissions.length===0)throw new y("Bindings must have at least one permission");for(let s of n.permissions)if(s.targets&&s.targets.length>0){if(!s.resource)throw new y("Action-level bindings (with targets) must specify resource");if(!s.actions||s.actions.length===0)throw new y("Action-level bindings (with targets) must specify actions")}}}};var G=class{constructor(t,r,n){this.baseUrl=t;this.authToken=r;this.bindings=n}async request(t,r,n,s){let i=`${this.baseUrl}${r}`;if(s){let l=new URLSearchParams(s);i+=`?${l.toString()}`}let o={"Content-Type":"application/json"};this.authToken&&(o.Authorization=`Bearer ${this.authToken}`),this.bindings&&this.bindings.length>0&&(o["X-Function-Bindings"]=JSON.stringify(this.bindings));let a={method:t,headers:o};n&&(a.body=JSON.stringify(n));let c=await fetch(i,a),d=c.headers.get("content-type"),f;if(d?.includes("application/json")?f=await c.json():f=await c.text(),!c.ok)throw new O(`Service request failed (${c.status}): ${typeof f=="string"?f:JSON.stringify(f)}`);return f}},J=class extends G{async get(t,r){return this.request("POST","/get",{tableName:t,key:r})}async write(t,r,n,s,i){return this.request("POST","/write",{tableName:t,key:r,value:n,expiration:s,dictionaryName:i})}async delete(t,r){return this.request("DELETE","/delete",void 0,{tableName:t,key:r})}async listTables(){return this.request("GET","/tables")}async getTableSize(t){return this.request("GET","/table",void 0,{tableName:t})}async getTableInfo(t){return this.request("GET",`/tables/${t}`)}async createTable(t){return this.request("POST",`/tables/${t}`)}async deleteTable(t){return this.request("DELETE",`/tables/${t}`)}},M=class{constructor(t,r){this.serviceBaseUrls=t;this.authToken=r}createBindings(t){let r={};for(let n of t){let s=this.serviceBaseUrls[n.service];s&&n.service==="databases"&&(r.databases=new J(s,this.authToken,t))}return r}};import{EventEmitter as Et}from"node:events";var W=class e{static instance;constructor(){}static getInstance(){return e.instance||(e.instance=new Et,e.instance.setMaxListeners(100)),e.instance}};function _(){return W.getInstance()}function et(e){let t=_();try{t.emit("function.log",e)}catch(r){console.error("Failed to emit function log event:",r)}}async function E(e){return e.body||{}}var F=class{isSilent;propertyPath="";constructor(e=!1){this.isSilent=e}test(e,t){if(!t)throw new Error("Missing input!");this.updatePropertyPath();let{results:r,errors:n}=this.validate(e.properties,t),s=this.compileErrors(r,n),i=this.isSuccessful(r,s);return{errors:s,success:i}}compileErrors(e,t){let r=e.filter(n=>n.success===!1);return[...t,...r].flatMap(n=>n)}isSuccessful(e,t){return e.every(r=>r.success===!0)&&t.length===0}validate(e,t,r=[],n=[]){let s=e?.additionalProperties??!0,i=e?.required||[];n=this.checkForRequiredKeysErrors(i,t,n),n=this.checkForDisallowedProperties(Object.keys(t),Object.keys(e),n,s);for(let o in e){let a=i.includes(o)&&o!=="required",c=e[o],d=t[o],f=c.additionalProperties??!0;a&&(n=this.checkForRequiredKeysErrors(c.required||[],d,n)),this.isDefined(d)&&(this.handleValidation(o,d,c,r),n=this.checkForDisallowedProperties(Object.keys(d),Object.keys(c),n,f),this.handleNestedObject(d,c,r,n))}return{results:r,errors:n}}updatePropertyPath(e,t=""){if(!e){this.propertyPath="";return}t&&(this.propertyPath=t),this.propertyPath=`${this.propertyPath}.${e}`,this.propertyPath.startsWith(".")&&(this.propertyPath=this.propertyPath.substring(1,this.propertyPath.length))}isDefined(e){return!!(typeof e=="number"&&e===0||e||e===""||typeof e=="boolean")}checkForRequiredKeysErrors(e,t,r){if(!this.areRequiredKeysPresent(e,t)){let n=t?Object.keys(t):[],s=this.findNonOverlappingElements(e,n),i=s.length>0?`Missing the required key: '${s.join(", ")}'!`:`Missing values for required keys: '${n.filter(o=>!t[o]).join(", ")}'!`;r.push({key:"",value:t,success:!1,error:i})}return r}checkForDisallowedProperties(e,t,r,n){if(!n){let s=this.findNonOverlappingElements(e,t);s.length>0&&r.push({key:`${t}`,value:e,success:!1,error:`Has additional (disallowed) properties: '${s.join(", ")}'!`})}return r}handleValidation(e,t,r,n){this.updatePropertyPath(e);let s=this.validateProperty(this.propertyPath,r,t);n.push(...s);let i=(a,c)=>{a.forEach(d=>{let f=this.validateProperty(this.propertyPath,c.items,d);n.push(...f)}),this.updatePropertyPath()},o=a=>{let c=Object.keys(a),d=this.propertyPath;c.forEach(f=>{if(this.updatePropertyPath(f,d),this.isArray(a[f])&&r[f]?.items!=null)i(a[f],r[f]);else{let l=this.validateProperty(this.propertyPath,r[f],a[f]);n.push(...l)}})};this.isArray(t)&&r.items!=null?i(t,r):this.isObject(t)?o(t):this.updatePropertyPath()}handleNestedObject(e,t,r,n){if(this.isObject(e)){let s=this.getNestedObjects(e);for(let i of s){let o=t[i],a=e[i];o&&typeof a=="object"&&this.validate(o,a,r,n)}}}getNestedObjects(e){return Object.keys(e).filter(t=>{if(this.isObject(e))return t})}findNonOverlappingElements(e,t){return e.filter(r=>!t.includes(r))}areRequiredKeysPresent(e,t=[]){return e.every(r=>Object.keys(t).includes(r)?this.isDefined(t[r]):!1)}validateProperty(e,t,r){return this.validateInput(t,r).map(s=>{let{success:i,error:o}=s;return{key:e,value:r,success:i,error:o??""}})}validateInput(e,t){if(e){let r=[{condition:()=>e.type,validator:()=>this.isCorrectType(e.type,t),error:"Invalid type"},{condition:()=>e.format,validator:()=>this.isCorrectFormat(e.format,t),error:"Invalid format"},{condition:()=>e.minLength,validator:()=>this.isMinimumLength(e.minLength,t),error:"Length too short"},{condition:()=>e.maxLength,validator:()=>this.isMaximumLength(e.maxLength,t),error:"Length too long"},{condition:()=>e.minValue,validator:()=>this.isMinimumValue(e.minValue,t),error:"Value too small"},{condition:()=>e.maxValue,validator:()=>this.isMaximumValue(e.maxValue,t),error:"Value too large"},{condition:()=>e.matchesPattern,validator:()=>this.matchesPattern(e.matchesPattern,t),error:"Pattern does not match"}],n=[];for(let s of r)s.condition()&&!s.validator()&&n.push({success:!1,error:s.error});return n}else this.isSilent||console.warn(`Missing property '${e}' for match '${t}'. Skipping...`);return[{success:!0}]}isCorrectType(e,t){return Array.isArray(e)||(e=[e]),e.some(r=>{switch(r){case"string":return typeof t=="string";case"number":return typeof t=="number"&&!isNaN(t);case"boolean":return typeof t=="boolean";case"object":return this.isObject(t);case"array":return this.isArray(t)}})}isObject(e){return e!==null&&!this.isArray(e)&&typeof e=="object"&&e instanceof Object&&Object.prototype.toString.call(e)==="[object Object]"}isArray(e){return Array.isArray(e)}isCorrectFormat(e,t){switch(e){case"alphanumeric":return new RegExp(/^[a-zA-Z0-9]+$/).test(t);case"numeric":return new RegExp(/^-?\d+(\.\d+)?$/).test(t);case"email":return new RegExp(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/).test(t);case"date":return new RegExp(/^\d{4}-\d{2}-\d{2}$/).test(t);case"url":return new RegExp(/^(https?):\/\/[^\s$.?#].[^\s]*$/).test(t);case"hexColor":return new RegExp(/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i).test(t)}}isMinimumLength(e,t){return Array.isArray(t)?t.length>=e:t?.toString().length>=e}isMaximumLength(e,t){return Array.isArray(t)?t.length<=e:t.toString().length<=e}isMinimumValue(e,t){return t>=e}isMaximumValue(e,t){return t<=e}matchesPattern(e,t){return new RegExp(e).test(t)}schemaFrom(e){let t={properties:{additionalProperties:!1,required:[]}};for(let r in e){let n=e[r];t.properties.required.push(r),Array.isArray(n)?t.properties[r]=this.generateArraySchema(n):typeof n=="object"&&n!==null?t.properties[r]=this.generateNestedObjectSchema(n):t.properties[r]=this.generatePropertySchema(n)}return t}generateArraySchema(e){let t={type:"array"},r=e.filter(n=>n);if(r.length>0){let n=r[0];r.every(i=>typeof i==typeof n)?typeof n=="object"&&!Array.isArray(n)?t.items=this.generateNestedObjectSchema(n):t.items=this.generatePropertySchema(n):console.warn("All elements in array are not of the same type. Unable to generate a schema for these elements.")}return t}generateNestedObjectSchema(e){let t={type:"object",additionalProperties:!1,required:[]};for(let r in e){let n=e[r];t.required.push(r),typeof n=="object"&&!Array.isArray(n)&&n!==null?t[r]=this.generateNestedObjectSchema(n):t[r]=this.generatePropertySchema(n)}return t}generatePropertySchema(e){let t=typeof e,r={type:t};return t==="string"&&(r.minLength=1),r}};function w(e,t="An error occurred"){let r=e?.message||e||t,n=e?.cause?.statusCode||e?.statusCode||400;return{message:r,status:n}}function rt(e,t,r={}){let n=Array.isArray(t)?t:[t];if(!e||!e.roles||!Array.isArray(e.roles)){let o=new Error("Unauthorized: User or roles missing");throw o.cause={statusCode:403},o}let s=e.roles.flatMap(o=>o?.policies?.flatMap(a=>(a?.permissions||[]).flatMap(d=>typeof d=="string"?d:d&&typeof d=="object"&&d.actions?d.actions:[]))||[]);if(!n.every(o=>s.includes(o)||s.includes("*")?!0:s.some(a=>{if(a.endsWith(".*")){let c=a.slice(0,-2);return o.startsWith(`${c}.`)}return!1}))){let o=new Error("Unauthorized");throw o.cause={statusCode:403},o}return!0}function nt(e,t,r,n,s){let i=e.find(c=>c.service===t);if(!i){let c=new Error(`Function bindings do not include access to service: ${t}`);throw c.cause={statusCode:403},c}if(!i.permissions||i.permissions.length===0)return;for(let c of i.permissions)if(!(c.resource&&c.resource!==r)){if(!c.resource||!c.actions||c.actions.length===0)return;if(c.actions.includes(n)){if(c.targets&&c.targets.length>0){if(!s)return;if(!c.targets.includes(s))continue}return}}let o=s?`:${s}`:"",a=new Error(`Function bindings do not allow: ${t}.${r}.${n}${o}`);throw a.cause={statusCode:403},a}async function v(e,t,r,n,s,i,o){if(!t)return null;let a=e.state.user;if(!a){let d=e.headers.authorization;if(!d){let l=new Error("Unauthorized: No authentication provided");throw l.cause={statusCode:401},l}let f=d.replace(/^Bearer\s+/i,"");if(a=await t.getUserFromToken(f),!a){let l=new Error("Unauthorized: Invalid token");throw l.cause={statusCode:401},l}}rt(a,r,{});let c=e.headers["x-function-bindings"];if(c)try{let d=Array.isArray(c)?c[0]:c,f=JSON.parse(d);nt(f,n,s,i,o)}catch(d){if(d.cause?.statusCode===403)throw d;let f=new Error("Invalid function bindings header");throw f.cause={statusCode:400},f}return a}var st={properties:{name:{type:"string",minLength:1},code:{type:"string",minLength:1},methods:{type:"array",items:{type:"string"}},bindings:{type:"array"},passAllHeaders:{type:"boolean"},allowUnauthenticated:{type:"boolean"}},required:["name","code"],additionalProperties:!1};var Tt=new F;async function it(e,t,r){try{let n=await E(e),s=Tt.test(st,n);if(!s.success)return e.json({error:"Invalid input",details:s.errors},400);await v(e,r,"functions.function.create","functions","function","create");let{name:i,code:o,methods:a,bindings:c,passAllHeaders:d,allowUnauthenticated:f}=n,l=await t.deployFunction(i,o,a,c,d,f);return e.json({success:!0,function:l},201)}catch(n){let{message:s,status:i}=w(n,"Error deploying function");return e.json({error:s},i)}}async function ot(e,t,r){try{let n=e.params.functionId;if(!n)return e.json({error:"functionId is required"},400);let s=t.getFunction(n);return s?(s.allowUnauthenticated!==!0&&await v(e,r,"functions.function.execute","functions","function","execute",n),await t.executeFunction(n,e)):e.json({error:"Not Found",message:"Function not found"},404)}catch(n){let{message:s,status:i}=w(n,"Error executing function");return e.json({error:s},i)}}var at={properties:{code:{type:"string",minLength:1},methods:{type:"array",items:{type:"string"}},bindings:{type:"array"},passAllHeaders:{type:"boolean"},allowUnauthenticated:{type:"boolean"}},additionalProperties:!1};var At=new F;async function ct(e,t,r){try{let n=e.params.functionId,s=await E(e);if(!n)return e.json({error:"functionId is required"},400);let i=At.test(at,s);if(!i.success)return e.json({error:"Invalid input",details:i.errors},400);await v(e,r,"functions.function.update","functions","function","update",n);let{code:o,methods:a,bindings:c,passAllHeaders:d,allowUnauthenticated:f}=s,l=await t.updateFunction(n,{code:o,methods:a,bindings:c,passAllHeaders:d,allowUnauthenticated:f});return l?e.json({success:!0,function:l},200):e.json({error:"Function not found"},404)}catch(n){let{message:s,status:i}=w(n,"Error updating function");return e.json({error:s},i)}}async function ut(e,t,r){try{let n=e.params.functionId;return n?(await v(e,r,"functions.function.delete","functions","function","delete",n),await t.deleteFunction(n)?e.json({success:!0,message:"Function deleted"},200):e.json({error:"Function not found"},404)):e.json({error:"functionId is required"},400)}catch(n){let{message:s,status:i}=w(n,"Error deleting function");return e.json({error:s},i)}}async function dt(e,t,r){try{let n=e.params.functionId;if(!n)return e.json({error:"functionId is required"},400);await v(e,r,"functions.function.get","functions","function","read",n);let s=t.getFunction(n);return s?e.json({success:!0,function:s},200):e.json({error:"Function not found"},404)}catch(n){let{message:s,status:i}=w(n,"Error getting function");return e.json({error:s},i)}}async function lt(e,t,r){try{await v(e,r,"functions.function.get","functions","function","read");let n=t.getFunctions();return e.json({success:!0,count:n.length,functions:n},200)}catch(n){let{message:s,status:i}=w(n,"Error listing functions");return e.json({error:s},i)}}import{readFileSync as Ft,existsSync as jt}from"node:fs";function P(){let e=process.env.MOLNOS_RUNTIME_CONFIG,t={molnos:{dataPath:"data",rateLimit:{global:{enabled:!1,requestsPerMinute:0}},signedUrlSecret:"molnos-default-signed-url-secret"},server:{host:"127.0.0.1",port:3e3},identity:{apiUrl:""},services:{storage:{host:"127.0.0.1",port:3001,url:"http://127.0.0.1:3001"},functions:{host:"127.0.0.1",port:3002,url:"http://127.0.0.1:3002"},sites:{host:"127.0.0.1",port:3003,url:"http://127.0.0.1:3003"},databases:{host:"127.0.0.1",port:3004,url:"http://127.0.0.1:3004"},observability:{host:"127.0.0.1",port:3005,url:"http://127.0.0.1:3005"}}};if(!e||!jt(e))return t;try{let r=Ft(e,"utf-8");return JSON.parse(r)}catch(r){return console.error("[loadRuntimeConfig] Failed to load runtime config:",r),t}}function ft(e,t){let r={enabled:!1,requestsPerMinute:0};if(!t)return r;let n=t.services?.[e];return n||(t.global?t.global:r)}function ht(e,t){let r=e?.api?.port;if(!r)throw new Error('Missing "port" input when create API service!');let n=P(),s=e?.dataPath||n.molnos.dataPath,i=e?.api?.host||n.server.host,o=e?.identityApiUrl!==void 0?e.identityApiUrl:n.identity.apiUrl,a=e?.debug||!1,c;return t&&(c=ft(t,n.molnos.rateLimit)),{dataPath:s,api:{port:r,host:i},...o?{identityApiUrl:o}:{},...c?{rateLimit:c}:{},debug:a}}var k=class{baseUrl;authToken;constructor(t,r){this.baseUrl=t.replace(/\/$/,""),this.authToken=r}async createCustomRole(t,r,n,s){let i=await fetch(`${this.baseUrl}/identity/roles`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({roleId:t,name:r,description:n,permissions:s})});if(!i.ok){let o=`Failed to create role: ${i.statusText}`;try{o=(await i.json()).error||o}catch{o=await i.text().catch(()=>i.statusText)||o}throw new Error(o)}}async updateRole(t,r){let n=await fetch(`${this.baseUrl}/identity/roles/${t}`,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let s=await n.json();throw new Error(s.error||`Failed to update role: ${n.statusText}`)}}async deleteRole(t){let r=await fetch(`${this.baseUrl}/identity/roles/${t}`,{method:"DELETE",headers:this.getHeaders()});if(!r.ok){let n=await r.json();throw new Error(n.error||`Failed to delete role: ${r.statusText}`)}}async addServiceAccount(t,r,n){let s=await fetch(`${this.baseUrl}/identity/service-accounts`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({name:t,description:r,roles:n})});if(!s.ok){let o=`Failed to create service account: ${s.statusText}`;try{o=(await s.json()).error||o}catch{o=await s.text().catch(()=>s.statusText)||o}throw new Error(o)}let i=await s.json();return{id:i.id,apiKey:i.apiKey}}async deleteIdentity(t){let r=await fetch(`${this.baseUrl}/identity/service-accounts/${t}`,{method:"DELETE",headers:this.getHeaders()});if(!r.ok){let n=await r.json();throw new Error(n.error||`Failed to delete service account: ${r.statusText}`)}}async getUserFromToken(t){try{let r=await fetch(`${this.baseUrl}/identity/whoami`,{method:"GET",headers:{Authorization:`Bearer ${t}`}});return r.ok?await r.json():null}catch{return null}}getHeaders(){let t={"Content-Type":"application/json"};return this.authToken&&(t.Authorization=`Bearer ${this.authToken}`),t}};function pt(e){return e?new k(e):null}var Y=class{functionsDir;functions=new Map;debug;bindingService;constructor(t){this.functionsDir=t.functionsDir||j(process.cwd(),"functions-data"),this.debug=t.debug||!1,this.bindingService=new H}async start(){await this.ensureFunctionsDirExists(),await this.loadExistingFunctions()}getFunction(t){return this.functions.get(t)}getFunctions(){return Array.from(this.functions.values()).map(t=>({name:t.name,endpoint:t.endpoint,id:t.id,filePath:t.filePath,methods:t.methods,...t.bindings?{bindings:t.bindings}:{},...t.passAllHeaders!==void 0?{passAllHeaders:t.passAllHeaders}:{},...t.allowUnauthenticated!==void 0?{allowUnauthenticated:t.allowUnauthenticated}:{},createdAt:t.createdAt,updatedAt:t.updatedAt}))}async ensureFunctionsDirExists(){L(this.functionsDir)||await $t(this.functionsDir,{recursive:!0})}async loadExistingFunctions(){try{let t=j(this.functionsDir,"functions.json");if(L(t)){let r=await mt(t,"utf8"),n=JSON.parse(r);for(let s of n)L(s.filePath)&&this.functions.set(s.id,s)}}catch{}}async saveFunctionsMetadata(){try{let t=j(this.functionsDir,"functions.json"),r=Array.from(this.functions.values());await X(t,JSON.stringify(r,null,2),"utf8")}catch{}}async deployFunction(t,r,n,s,i,o){if(!t||typeof t!="string")throw new y("Function name is required and must be a string");if(!r||typeof r!="string")throw new y("Function code is required and must be a string");if(n!==void 0){if(!Array.isArray(n))throw new y("Methods must be an array");let u=["GET","POST","PUT","PATCH","DELETE","HEAD","OPTIONS"];for(let h of n)if(!u.includes(h.toUpperCase()))throw new A(`Invalid HTTP method: ${h}. Must be one of: ${u.join(", ")}`)}s&&s.length>0&&this.bindingService.validateBindings(s);let a=Rt("sha256").update(`${t}-${Date.now()}`).digest("hex").substring(0,12),c=j(this.functionsDir,`${a}.mjs`),d=this.wrapFunctionCode(r);await X(c,d,"utf8");let f=Date.now(),l={id:a,name:t,filePath:c,endpoint:`/functions/run/${a}`,...n&&n.length>0?{methods:n.map(u=>u.toUpperCase())}:{},...s?{bindings:s}:{},...i!==void 0?{passAllHeaders:i}:{},...o!==void 0?{allowUnauthenticated:o}:{},createdAt:f,updatedAt:f};return this.functions.set(a,l),await this.saveFunctionsMetadata(),l}async updateFunction(t,r){let n=this.functions.get(t);if(!n)throw new $(`Function with ID ${t} not found`);let{code:s,methods:i,bindings:o,passAllHeaders:a,allowUnauthenticated:c}=r;if(s===void 0&&i===void 0&&o===void 0&&a===void 0&&c===void 0)throw new y("At least one parameter (code, methods, bindings, passAllHeaders, or allowUnauthenticated) must be provided");if(s!==void 0&&(typeof s!="string"||!s))throw new y("Function code must be a non-empty string");if(i!==void 0){if(!Array.isArray(i))throw new y("Methods must be an array");let d=["GET","POST","PUT","PATCH","DELETE","HEAD","OPTIONS"];for(let f of i)if(!d.includes(f.toUpperCase()))throw new A(`Invalid HTTP method: ${f}. Must be one of: ${d.join(", ")}`)}if(s!==void 0){let d=this.wrapFunctionCode(s);await X(n.filePath,d,"utf8")}return i!==void 0&&(i.length>0?n.methods=i.map(d=>d.toUpperCase()):delete n.methods),o!==void 0&&(o.length>0&&this.bindingService.validateBindings(o),n.bindings=o.length>0?o:void 0),a!==void 0&&(a?n.passAllHeaders=!0:delete n.passAllHeaders),c!==void 0&&(n.allowUnauthenticated=c),n.updatedAt=Date.now(),this.functions.set(t,n),await this.saveFunctionsMetadata(),n}async deleteFunction(t){let r=this.functions.get(t);if(!r)return!1;try{return L(r.filePath)&&await Ot(r.filePath),this.functions.delete(t),await this.saveFunctionsMetadata(),!0}catch(n){throw console.error(`Error deleting function ${t}:`,n.message),n}}wrapFunctionCode(t){let r=t;if(/export\s+default\s+\w+/.test(t))return`// FunctionsService generated module
10
+ `),r=e.indexOf(t);if(r===-1)return null;let n=e.subarray(0,r),s=e.subarray(r+4),i=n.toString("utf8").split(`\r
11
+ `),a="",c="",d,l;for(let h of i){let f=h.toLowerCase();if(f.startsWith("content-disposition:")){a=h.substring(20).trim();let m=a.match(/name="([^"]+)"/);m&&(c=m[1]);let p=a.match(/filename="([^"]+)"/);p&&(d=p[1])}else f.startsWith("content-type:")&&(l=h.substring(13).trim())}if(!c)return null;let u=s;return u.length>=2&&u[u.length-2]===13&&u[u.length-1]===10&&(u=u.subarray(0,u.length-2)),{disposition:a,name:c,filename:d,contentType:l,data:u}}import{readFileSync as P}from"fs";import G from"http";import Ot from"http2";import Ht from"https";var J=class{config;rateLimiter;router;shutdownHandlers=[];constructor(e){let t=new V(rt(e||{})).get();t.debug&&console.log("Using configuration:",t),this.config=t,this.router=new et;let r=t.rateLimit.requestsPerMinute||$().rateLimit.requestsPerMinute;this.rateLimiter=new tt(r,60),t.rateLimit.enabled===!0&&this.use(this.rateLimitMiddleware.bind(this))}use(e){return this.router.use(e),this}get(e,...t){return this.router.get(e,...t),this}post(e,...t){return this.router.post(e,...t),this}put(e,...t){return this.router.put(e,...t),this}delete(e,...t){return this.router.delete(e,...t),this}patch(e,...t){return this.router.patch(e,...t),this}any(e,...t){return this.router.any(e,...t),this}options(e,...t){return this.router.options(e,...t),this}start(){let e=this.createServer(),{port:t,host:r}=this.config;return this.setupGracefulShutdown(e),e.listen(t,r,()=>{let n=e.address(),s=this.config.useHttps||this.config.useHttp2?"https":"http";console.log(`MikroServe running at ${s}://${n.address!=="::"?n.address:"localhost"}:${n.port}`)}),e}createServer(){let e=this.requestHandler.bind(this);if(this.config.useHttp2){if(!this.config.sslCert||!this.config.sslKey)throw new Error("SSL certificate and key paths are required when useHttp2 is true");try{let t={key:P(this.config.sslKey),cert:P(this.config.sslCert),...this.config.sslCa?{ca:P(this.config.sslCa)}:{}};return Ot.createSecureServer(t,e)}catch(t){throw t.message.includes("key values mismatch")?new Error(`SSL certificate and key do not match: ${t.message}`):t}}else if(this.config.useHttps){if(!this.config.sslCert||!this.config.sslKey)throw new Error("SSL certificate and key paths are required when useHttps is true");try{let t={key:P(this.config.sslKey),cert:P(this.config.sslCert),...this.config.sslCa?{ca:P(this.config.sslCa)}:{}};return Ht.createServer(t,e)}catch(t){throw t.message.includes("key values mismatch")?new Error(`SSL certificate and key do not match: ${t.message}`):t}}return G.createServer(e)}async rateLimitMiddleware(e,t){let r=e.req.socket.remoteAddress||"unknown";return e.res.setHeader("X-RateLimit-Limit",this.rateLimiter.getLimit().toString()),e.res.setHeader("X-RateLimit-Remaining",this.rateLimiter.getRemainingRequests(r).toString()),e.res.setHeader("X-RateLimit-Reset",this.rateLimiter.getResetTime(r).toString()),this.rateLimiter.isAllowed(r)?t():{statusCode:429,body:{error:"Too Many Requests",message:"Rate limit exceeded, please try again later"},headers:{"Content-Type":"application/json"}}}async requestHandler(e,t){let r=Date.now(),n=e.method||"UNKNOWN",s=e.url||"/unknown",o=this.config.debug;try{if(this.setCorsHeaders(t,e),this.setSecurityHeaders(t,this.config.useHttps),o&&console.log(`${n} ${s}`),e.method==="OPTIONS"){if(t instanceof G.ServerResponse)t.statusCode=204,t.end();else{let a=t;a.writeHead(204),a.end()}return}try{e.body=await this.parseBody(e)}catch(a){return o&&console.error("Body parsing error:",a.message),this.respond(t,{statusCode:400,body:{error:"Bad Request",message:a.message}})}let i=await this.router.handle(e,t);return i?i._handled?void 0:this.respond(t,i):this.respond(t,{statusCode:404,body:{error:"Not Found",message:"The requested endpoint does not exist"}})}catch(i){return console.error("Server error:",i),this.respond(t,{statusCode:500,body:{error:"Internal Server Error",message:o?i.message:"An unexpected error occurred"}})}finally{o&&this.logDuration(r,n,s)}}logDuration(e,t,r){let n=Date.now()-e;console.log(`${t} ${r} completed in ${n}ms`)}async parseBody(e){return new Promise((t,r)=>{let n=[],s=0,o=this.config.maxBodySize,i=!1,a=null,c=this.config.debug,d=e.headers["content-type"]||"";c&&console.log("Content-Type:",d),this.config.requestTimeout>0&&(a=setTimeout(()=>{i||(i=!0,c&&console.log("Request timeout exceeded"),r(new Error("Request timeout")))},this.config.requestTimeout));let l=()=>{a&&(clearTimeout(a),a=null)};e.on("data",u=>{if(!i){if(s+=u.length,c&&console.log(`Received chunk: ${u.length} bytes, total size: ${s}`),s>o){i=!0,l(),c&&console.log(`Body size exceeded limit: ${s} > ${o}`),r(new Error("Request body too large"));return}n.push(u)}}),e.on("end",()=>{if(!i){i=!0,l(),c&&console.log(`Request body complete: ${s} bytes`);try{if(n.length>0){let u=Buffer.concat(n);if(d.includes("application/json"))try{let h=u.toString("utf8");t(JSON.parse(h))}catch(h){r(new Error(`Invalid JSON in request body: ${h.message}`))}else if(d.includes("application/x-www-form-urlencoded")){let h=u.toString("utf8"),f={};new URLSearchParams(h).forEach((m,p)=>{f[p]=m}),t(f)}else if(d.includes("multipart/form-data"))try{let h=nt(u,d);t(h)}catch(h){r(new Error(`Invalid multipart form data: ${h.message}`))}else this.isBinaryContentType(d)?t(u):t(u.toString("utf8"))}else t({})}catch(u){r(new Error(`Invalid request body: ${u}`))}}}),e.on("error",u=>{i||(i=!0,l(),r(new Error(`Error reading request body: ${u.message}`)))}),e.on("close",()=>{l()})})}isBinaryContentType(e){return["application/octet-stream","application/pdf","application/zip","application/gzip","application/x-tar","application/x-rar-compressed","application/x-7z-compressed","image/","video/","audio/","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument","application/msword","application/vnd.ms-powerpoint"].some(r=>e.includes(r))}setCorsHeaders(e,t){let r=t.headers.origin,{allowedDomains:n=["*"]}=this.config;!r||n.length===0||n.includes("*")?e.setHeader("Access-Control-Allow-Origin","*"):n.includes(r)&&(e.setHeader("Access-Control-Allow-Origin",r),e.setHeader("Vary","Origin")),e.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, PATCH, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization"),e.setHeader("Access-Control-Max-Age","86400")}setSecurityHeaders(e,t=!1){let r={"X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","Content-Security-Policy":"default-src 'self'; script-src 'self'; object-src 'none'","X-XSS-Protection":"1; mode=block"};if((t||this.config.useHttp2)&&(r["Strict-Transport-Security"]="max-age=31536000; includeSubDomains"),e instanceof G.ServerResponse)Object.entries(r).forEach(([n,s])=>{e.setHeader(n,s)});else{let n=e;Object.entries(r).forEach(([s,o])=>{n.setHeader(s,o)})}}respond(e,t){let r={...t.headers||{}};(s=>typeof s.writeHead=="function"&&typeof s.end=="function")(e)?(e.writeHead(t.statusCode,r),t.body===null||t.body===void 0?e.end():t.isRaw||typeof t.body=="string"?e.end(t.body):e.end(JSON.stringify(t.body))):(console.warn("Unexpected response object type without writeHead/end methods"),e.writeHead?.(t.statusCode,r),t.body===null||t.body===void 0?e.end?.():t.isRaw||typeof t.body=="string"?e.end?.(t.body):e.end?.(JSON.stringify(t.body)))}setupGracefulShutdown(e){let t=i=>{console.log("Shutting down MikroServe server..."),i&&console.error("Error:",i),this.cleanupShutdownHandlers(),e.close(()=>{console.log("Server closed successfully"),process.env.NODE_ENV!=="test"&&process.env.VITEST!=="true"&&setImmediate(()=>process.exit(i?1:0))})},r=()=>t(),n=()=>t(),s=i=>t(i),o=i=>t(i);this.shutdownHandlers=[r,n,s,o],process.on("SIGINT",r),process.on("SIGTERM",n),process.on("uncaughtException",s),process.on("unhandledRejection",o)}cleanupShutdownHandlers(){if(this.shutdownHandlers.length>0){let[e,t,r,n]=this.shutdownHandlers;process.removeListener("SIGINT",e),process.removeListener("SIGTERM",t),process.removeListener("uncaughtException",r),process.removeListener("unhandledRejection",n),this.shutdownHandlers=[]}}};var y=class extends Error{constructor(t){super(),this.name="ValidationError",this.message=t||"Invalid input",this.cause={statusCode:400}}};var O=class extends Error{constructor(t){super(),this.name="NotFoundError",this.message=t||"Resource not found",this.cause={statusCode:404}}};var A=class extends Error{constructor(t){super(),this.name="InvalidMethodError",this.message=t||"Invalid HTTP method",this.cause={statusCode:400}}};var H=class extends Error{constructor(t){super(),this.name="ServiceRequestError",this.message=t||"Service request failed",this.cause={statusCode:502}}};var M=class{generatePermissionsFromBindings(t){let r=[];for(let n of t){let s=n.service;for(let o of n.permissions){if(!o.resource){r.push(`${s}.*`);continue}let i=o.resource,a=o.actions||["*"];if(o.targets&&o.targets.length>0)for(let c of a)for(let d of o.targets)r.push(`${s}.${i}.${c}:${d}`);else for(let c of a)r.push(`${s}.${i}.${c}`)}}return[...new Set(r)]}validateBindings(t){let r=["databases","storage","observability","sites","functions"];for(let n of t){if(!r.includes(n.service))throw new y(`Invalid service: ${n.service}. Must be one of: ${r.join(", ")}`);if(!n.permissions||n.permissions.length===0)throw new y("Bindings must have at least one permission");for(let s of n.permissions)if(s.targets&&s.targets.length>0){if(!s.resource)throw new y("Action-level bindings (with targets) must specify resource");if(!s.actions||s.actions.length===0)throw new y("Action-level bindings (with targets) must specify actions")}}}};var _=class{constructor(t,r,n){this.baseUrl=t;this.authToken=r;this.bindings=n}async request(t,r,n,s){let o=`${this.baseUrl}${r}`;if(s){let u=new URLSearchParams(s);o+=`?${u.toString()}`}let i={"Content-Type":"application/json"};this.authToken&&(i.Authorization=`Bearer ${this.authToken}`),this.bindings&&this.bindings.length>0&&(i["X-Function-Bindings"]=JSON.stringify(this.bindings));let a={method:t,headers:i};n&&(a.body=JSON.stringify(n));let c=await fetch(o,a),d=c.headers.get("content-type"),l;if(d?.includes("application/json")){let u=await c.text();u?l=JSON.parse(u):l=null}else l=await c.text();if(!c.ok)throw new H(`Service request failed (${c.status}): ${typeof l=="string"?l:JSON.stringify(l)}`);return l}},W=class extends _{async get(t,r){return this.request("POST","/get",{tableName:t,key:r})}async write(t,r,n,s,o){return this.request("POST","/write",{tableName:t,key:r,value:n,expiration:s,dictionaryName:o})}async delete(t,r){return this.request("DELETE","/delete",void 0,{tableName:t,key:r})}async listTables(){return this.request("GET","/tables")}async getTableSize(t){return this.request("GET","/table",void 0,{tableName:t})}async getTableInfo(t){return this.request("GET",`/tables/${t}`)}async createTable(t){return this.request("POST",`/tables/${t}`)}async deleteTable(t){return this.request("DELETE",`/tables/${t}`)}},k=class{constructor(t,r){this.serviceBaseUrls=t;this.authToken=r}createBindings(t){let r={};for(let n of t){let s=this.serviceBaseUrls[n.service];s&&n.service==="databases"&&(r.databases=new W(s,this.authToken,t))}return r}};import{EventEmitter as Mt}from"node:events";var X=class e{static instance;constructor(){}static getInstance(){return e.instance||(e.instance=new Mt,e.instance.setMaxListeners(100)),e.instance}};function Z(){return X.getInstance()}function st(e){let t=Z();try{t.emit("function.log",e)}catch(r){console.error("Failed to emit function log event:",r)}}async function I(e){return e.body||{}}var j=class{isSilent;propertyPath="";constructor(e=!1){this.isSilent=e}test(e,t){if(!t)throw new Error("Missing input!");this.updatePropertyPath();let{results:r,errors:n}=this.validate(e.properties,t),s=this.compileErrors(r,n),o=this.isSuccessful(r,s);return{errors:s,success:o}}compileErrors(e,t){let r=e.filter(n=>n.success===!1);return[...t,...r].flatMap(n=>n)}isSuccessful(e,t){return e.every(r=>r.success===!0)&&t.length===0}validate(e,t,r=[],n=[]){let s=e?.additionalProperties??!0,o=e?.required||[];n=this.checkForRequiredKeysErrors(o,t,n),n=this.checkForDisallowedProperties(Object.keys(t),Object.keys(e),n,s);for(let i in e){let a=o.includes(i)&&i!=="required",c=e[i],d=t[i],l=c.additionalProperties??!0;a&&(n=this.checkForRequiredKeysErrors(c.required||[],d,n)),this.isDefined(d)&&(this.handleValidation(i,d,c,r),n=this.checkForDisallowedProperties(Object.keys(d),Object.keys(c),n,l),this.handleNestedObject(d,c,r,n))}return{results:r,errors:n}}updatePropertyPath(e,t=""){if(!e){this.propertyPath="";return}t&&(this.propertyPath=t),this.propertyPath=`${this.propertyPath}.${e}`,this.propertyPath.startsWith(".")&&(this.propertyPath=this.propertyPath.substring(1,this.propertyPath.length))}isDefined(e){return!!(typeof e=="number"&&e===0||e||e===""||typeof e=="boolean")}checkForRequiredKeysErrors(e,t,r){if(!this.areRequiredKeysPresent(e,t)){let n=t?Object.keys(t):[],s=this.findNonOverlappingElements(e,n),o=s.length>0?`Missing the required key: '${s.join(", ")}'!`:`Missing values for required keys: '${n.filter(i=>!t[i]).join(", ")}'!`;r.push({key:"",value:t,success:!1,error:o})}return r}checkForDisallowedProperties(e,t,r,n){if(!n){let s=this.findNonOverlappingElements(e,t);s.length>0&&r.push({key:`${t}`,value:e,success:!1,error:`Has additional (disallowed) properties: '${s.join(", ")}'!`})}return r}handleValidation(e,t,r,n){this.updatePropertyPath(e);let s=this.validateProperty(this.propertyPath,r,t);n.push(...s);let o=(a,c)=>{a.forEach(d=>{let l=this.validateProperty(this.propertyPath,c.items,d);n.push(...l)}),this.updatePropertyPath()},i=a=>{let c=Object.keys(a),d=this.propertyPath;c.forEach(l=>{if(this.updatePropertyPath(l,d),this.isArray(a[l])&&r[l]?.items!=null)o(a[l],r[l]);else{let u=this.validateProperty(this.propertyPath,r[l],a[l]);n.push(...u)}})};this.isArray(t)&&r.items!=null?o(t,r):this.isObject(t)?i(t):this.updatePropertyPath()}handleNestedObject(e,t,r,n){if(this.isObject(e)){let s=this.getNestedObjects(e);for(let o of s){let i=t[o],a=e[o];i&&typeof a=="object"&&this.validate(i,a,r,n)}}}getNestedObjects(e){return Object.keys(e).filter(t=>{if(this.isObject(e))return t})}findNonOverlappingElements(e,t){return e.filter(r=>!t.includes(r))}areRequiredKeysPresent(e,t=[]){return e.every(r=>Object.keys(t).includes(r)?this.isDefined(t[r]):!1)}validateProperty(e,t,r){return this.validateInput(t,r).map(s=>{let{success:o,error:i}=s;return{key:e,value:r,success:o,error:i??""}})}validateInput(e,t){if(e){let r=[{condition:()=>e.type,validator:()=>this.isCorrectType(e.type,t),error:"Invalid type"},{condition:()=>e.format,validator:()=>this.isCorrectFormat(e.format,t),error:"Invalid format"},{condition:()=>e.minLength,validator:()=>this.isMinimumLength(e.minLength,t),error:"Length too short"},{condition:()=>e.maxLength,validator:()=>this.isMaximumLength(e.maxLength,t),error:"Length too long"},{condition:()=>e.minValue,validator:()=>this.isMinimumValue(e.minValue,t),error:"Value too small"},{condition:()=>e.maxValue,validator:()=>this.isMaximumValue(e.maxValue,t),error:"Value too large"},{condition:()=>e.matchesPattern,validator:()=>this.matchesPattern(e.matchesPattern,t),error:"Pattern does not match"}],n=[];for(let s of r)s.condition()&&!s.validator()&&n.push({success:!1,error:s.error});return n}else this.isSilent||console.warn(`Missing property '${e}' for match '${t}'. Skipping...`);return[{success:!0}]}isCorrectType(e,t){return Array.isArray(e)||(e=[e]),e.some(r=>{switch(r){case"string":return typeof t=="string";case"number":return typeof t=="number"&&!isNaN(t);case"boolean":return typeof t=="boolean";case"object":return this.isObject(t);case"array":return this.isArray(t)}})}isObject(e){return e!==null&&!this.isArray(e)&&typeof e=="object"&&e instanceof Object&&Object.prototype.toString.call(e)==="[object Object]"}isArray(e){return Array.isArray(e)}isCorrectFormat(e,t){switch(e){case"alphanumeric":return new RegExp(/^[a-zA-Z0-9]+$/).test(t);case"numeric":return new RegExp(/^-?\d+(\.\d+)?$/).test(t);case"email":return new RegExp(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/).test(t);case"date":return new RegExp(/^\d{4}-\d{2}-\d{2}$/).test(t);case"url":return new RegExp(/^(https?):\/\/[^\s$.?#].[^\s]*$/).test(t);case"hexColor":return new RegExp(/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i).test(t)}}isMinimumLength(e,t){return Array.isArray(t)?t.length>=e:t?.toString().length>=e}isMaximumLength(e,t){return Array.isArray(t)?t.length<=e:t.toString().length<=e}isMinimumValue(e,t){return t>=e}isMaximumValue(e,t){return t<=e}matchesPattern(e,t){return new RegExp(e).test(t)}schemaFrom(e){let t={properties:{additionalProperties:!1,required:[]}};for(let r in e){let n=e[r];t.properties.required.push(r),Array.isArray(n)?t.properties[r]=this.generateArraySchema(n):typeof n=="object"&&n!==null?t.properties[r]=this.generateNestedObjectSchema(n):t.properties[r]=this.generatePropertySchema(n)}return t}generateArraySchema(e){let t={type:"array"},r=e.filter(n=>n);if(r.length>0){let n=r[0];r.every(o=>typeof o==typeof n)?typeof n=="object"&&!Array.isArray(n)?t.items=this.generateNestedObjectSchema(n):t.items=this.generatePropertySchema(n):console.warn("All elements in array are not of the same type. Unable to generate a schema for these elements.")}return t}generateNestedObjectSchema(e){let t={type:"object",additionalProperties:!1,required:[]};for(let r in e){let n=e[r];t.required.push(r),typeof n=="object"&&!Array.isArray(n)&&n!==null?t[r]=this.generateNestedObjectSchema(n):t[r]=this.generatePropertySchema(n)}return t}generatePropertySchema(e){let t=typeof e,r={type:t};return t==="string"&&(r.minLength=1),r}};function w(e,t="An error occurred"){let r=e?.message||e||t,n=e?.cause?.statusCode||e?.statusCode||400;return{message:r,status:n}}function ot(e,t,r={}){let n=Array.isArray(t)?t:[t];if(!e||!e.roles||!Array.isArray(e.roles)){let i=new Error("Unauthorized: User or roles missing");throw i.cause={statusCode:403},i}let s=e.roles.flatMap(i=>i?.policies?.flatMap(a=>(a?.permissions||[]).flatMap(d=>typeof d=="string"?d:d&&typeof d=="object"&&d.actions?d.actions:[]))||[]);if(!n.every(i=>s.includes(i)||s.includes("*")?!0:s.some(a=>{if(a.endsWith(".*")){let c=a.slice(0,-2);return i.startsWith(`${c}.`)}return!1}))){let i=new Error("Unauthorized");throw i.cause={statusCode:403},i}return!0}function it(e,t,r,n,s){let o=e.find(c=>c.service===t);if(!o){let c=new Error(`Function bindings do not include access to service: ${t}`);throw c.cause={statusCode:403},c}if(!o.permissions||o.permissions.length===0)return;for(let c of o.permissions)if(!(c.resource&&c.resource!==r)){if(!c.resource||!c.actions||c.actions.length===0)return;if(c.actions.includes(n)){if(c.targets&&c.targets.length>0){if(!s)return;if(!c.targets.includes(s))continue}return}}let i=s?`:${s}`:"",a=new Error(`Function bindings do not allow: ${t}.${r}.${n}${i}`);throw a.cause={statusCode:403},a}async function v(e,t,r,n,s,o,i){if(!t)return null;let a=e.state.user;if(!a){let d=e.headers.authorization;if(!d){let u=new Error("Unauthorized: No authentication provided");throw u.cause={statusCode:401},u}let l=d.replace(/^Bearer\s+/i,"");if(a=await t.getUserFromToken(l),!a){let u=new Error("Unauthorized: Invalid token");throw u.cause={statusCode:401},u}}ot(a,r,{});let c=e.headers["x-function-bindings"];if(c)try{let d=Array.isArray(c)?c[0]:c,l=JSON.parse(d);it(l,n,s,o,i)}catch(d){if(d.cause?.statusCode===403)throw d;let l=new Error("Invalid function bindings header");throw l.cause={statusCode:400},l}return a}var at={properties:{id:{type:"string",minLength:1,maxLength:40,pattern:"^[a-zA-Z0-9_-]{1,40}$"},name:{type:"string",minLength:1},code:{type:"string",minLength:1},methods:{type:"array",items:{type:"string"}},bindings:{type:"array"},passAllHeaders:{type:"boolean"},allowUnauthenticated:{type:"boolean"},context:{type:"string",minLength:1}},required:["name","code"],additionalProperties:!1};var Lt=new j(!0);async function ct(e,t,r){try{let n=await I(e),s=Lt.test(at,n);if(!s.success)return e.json({error:"Invalid input",details:s.errors},400);await v(e,r,"functions.function.create","functions","function","create");let{id:o,name:i,code:a,methods:c,bindings:d,passAllHeaders:l,allowUnauthenticated:u}=n,h=await t.deployFunction(i,a,c,d,l,u,o);return e.json({success:!0,function:h},201)}catch(n){let{message:s,status:o}=w(n,"Error deploying function");return e.json({error:s},o)}}async function ut(e,t,r){try{let n=e.params.functionId;if(!n)return e.json({error:"functionId is required"},400);let s=t.getFunction(n);return s?(s.allowUnauthenticated!==!0&&await v(e,r,"functions.function.execute","functions","function","execute",n),await t.executeFunction(n,e)):e.json({error:"Not Found",message:"Function not found"},404)}catch(n){let{message:s,status:o}=w(n,"Error executing function");return e.json({error:s},o)}}var lt={properties:{code:{type:"string",minLength:1},methods:{type:"array",items:{type:"string"}},bindings:{type:"array"},passAllHeaders:{type:"boolean"},allowUnauthenticated:{type:"boolean"}},additionalProperties:!1};var Ut=new j(!0);async function dt(e,t,r){try{let n=e.params.functionId,s=await I(e);if(!n)return e.json({error:"functionId is required"},400);let o=Ut.test(lt,s);if(!o.success)return e.json({error:"Invalid input",details:o.errors},400);await v(e,r,"functions.function.update","functions","function","update",n);let{code:i,methods:a,bindings:c,passAllHeaders:d,allowUnauthenticated:l}=s,u=await t.updateFunction(n,{code:i,methods:a,bindings:c,passAllHeaders:d,allowUnauthenticated:l});return u?e.json({success:!0,function:u},200):e.json({error:"Function not found"},404)}catch(n){let{message:s,status:o}=w(n,"Error updating function");return e.json({error:s},o)}}async function ft(e,t,r){try{let n=e.params.functionId;return n?(await v(e,r,"functions.function.delete","functions","function","delete",n),await t.deleteFunction(n)?e.json({success:!0,message:"Function deleted"},200):e.json({error:"Function not found"},404)):e.json({error:"functionId is required"},400)}catch(n){let{message:s,status:o}=w(n,"Error deleting function");return e.json({error:s},o)}}async function ht(e,t,r){try{let n=e.params.functionId;if(!n)return e.json({error:"functionId is required"},400);await v(e,r,"functions.function.get","functions","function","read",n);let s=t.getFunction(n);return s?e.json({success:!0,function:s},200):e.json({error:"Function not found"},404)}catch(n){let{message:s,status:o}=w(n,"Error getting function");return e.json({error:s},o)}}async function pt(e,t,r,n){try{await v(e,r,"functions.function.get","functions","function","read");let s=t.getFunctions(),o=e.query.context;if(o&&n){let i=e.headers.authorization?.replace(/^Bearer\s+/i,""),a=await n.listResourcesByType(o,"function",i);s=s.filter(c=>a.includes(c.id))}return e.json({success:!0,count:s.length,functions:s},200)}catch(s){let{message:o,status:i}=w(s,"Error listing functions");return e.json({error:o},i)}}import{readFileSync as Nt,existsSync as qt}from"node:fs";function T(){let e=process.env.MOLNOS_RUNTIME_CONFIG,t={molnos:{dataPath:"data",rateLimit:{global:{enabled:!1,requestsPerMinute:0}},signedUrlSecret:"molnos-default-signed-url-secret"},server:{host:"127.0.0.1",port:3e3},identity:{apiUrl:"http://127.0.0.1:3000"},context:{apiUrl:"http://127.0.0.1:3000"},services:{storage:{host:"127.0.0.1",port:3001,url:"http://127.0.0.1:3001"},functions:{host:"127.0.0.1",port:3002,url:"http://127.0.0.1:3002"},sites:{host:"127.0.0.1",port:3003,url:"http://127.0.0.1:3003"},databases:{host:"127.0.0.1",port:3004,url:"http://127.0.0.1:3004"},observability:{host:"127.0.0.1",port:3005,url:"http://127.0.0.1:3005"}}};if(!e||!qt(e))return t;try{let r=Nt(e,"utf-8");return JSON.parse(r)}catch(r){return console.error("[loadRuntimeConfig] Failed to load runtime config:",r),t}}function mt(e,t){let r={enabled:!1,requestsPerMinute:0};if(!t)return r;let n=t.services?.[e];return n||(t.global?t.global:r)}function gt(e,t){let r=e?.api?.port;if(!r)throw new Error('Missing "port" input when create API service!');let n=T(),s=e?.dataPath||n.molnos.dataPath,o=e?.api?.host||n.server.host,i=e?.identityApiUrl!==void 0?e.identityApiUrl:n.identity.apiUrl,a=e?.contextApiUrl!==void 0?e.contextApiUrl:n.context.apiUrl,c=e?.debug||!1,d;return t&&(d=mt(t,n.molnos.rateLimit)),{dataPath:s,api:{port:r,host:o},...i?{identityApiUrl:i}:{},...a?{contextApiUrl:a}:{},...d?{rateLimit:d}:{},debug:c}}var L=class{baseUrl;authToken;constructor(t,r){this.baseUrl=t.replace(/\/$/,""),this.authToken=r}async createCustomRole(t,r,n,s){let o=await fetch(`${this.baseUrl}/identity/roles`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({roleId:t,name:r,description:n,permissions:s})});if(!o.ok){let i=`Failed to create role: ${o.statusText}`;try{i=(await o.json()).error||i}catch{i=await o.text().catch(()=>o.statusText)||i}throw new Error(i)}}async updateRole(t,r){let n=await fetch(`${this.baseUrl}/identity/roles/${t}`,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let s=await n.json();throw new Error(s.error||`Failed to update role: ${n.statusText}`)}}async deleteRole(t){let r=await fetch(`${this.baseUrl}/identity/roles/${t}`,{method:"DELETE",headers:this.getHeaders()});if(!r.ok){let n=await r.json();throw new Error(n.error||`Failed to delete role: ${r.statusText}`)}}async addServiceAccount(t,r,n){let s=await fetch(`${this.baseUrl}/identity/service-accounts`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({name:t,description:r,roles:n})});if(!s.ok){let i=`Failed to create service account: ${s.statusText}`;try{i=(await s.json()).error||i}catch{i=await s.text().catch(()=>s.statusText)||i}throw new Error(i)}let o=await s.json();return{id:o.id,apiKey:o.apiKey}}async deleteIdentity(t){let r=await fetch(`${this.baseUrl}/identity/service-accounts/${t}`,{method:"DELETE",headers:this.getHeaders()});if(!r.ok){let n=await r.json();throw new Error(n.error||`Failed to delete service account: ${r.statusText}`)}}async getUserFromToken(t){try{let r=await fetch(`${this.baseUrl}/identity/whoami`,{method:"GET",headers:{Authorization:`Bearer ${t}`}});return r.ok?await r.json():null}catch{return null}}getHeaders(){let t={"Content-Type":"application/json"};return this.authToken&&(t.Authorization=`Bearer ${this.authToken}`),t}};function yt(e){return e?new L(e):null}var D=class{baseUrl;constructor(t){this.baseUrl=t.replace(/\/$/,"")}async listResourcesByType(t,r,n){let s=`${this.baseUrl}/contexts/${encodeURIComponent(t)}`;try{let o={"Content-Type":"application/json"};n&&(o.Authorization=`Bearer ${n}`);let i=await fetch(s,{method:"GET",headers:o});if(!i.ok)return[];let c=(await i.json()).context?.resources||{};switch(r){case"function":return c.functions||[];case"database":return c.databases||[];case"storage":return c.storage||[];case"site":return c.sites||[];default:return[]}}catch{return[]}}};function bt(e){return e?new D(e):null}var K=class{functionsDir;functions=new Map;debug;bindingService;constructor(t){this.functionsDir=t.functionsDir||F(process.cwd(),"functions-data"),this.debug=t.debug||!1,this.bindingService=new M}async start(){await this.ensureFunctionsDirExists(),await this.loadExistingFunctions()}getFunction(t){return this.functions.get(t)}getFunctions(){return Array.from(this.functions.values()).map(t=>({name:t.name,endpoint:t.endpoint,id:t.id,filePath:t.filePath,methods:t.methods,...t.bindings?{bindings:t.bindings}:{},...t.passAllHeaders!==void 0?{passAllHeaders:t.passAllHeaders}:{},...t.allowUnauthenticated!==void 0?{allowUnauthenticated:t.allowUnauthenticated}:{},createdAt:t.createdAt,updatedAt:t.updatedAt}))}async ensureFunctionsDirExists(){U(this.functionsDir)||await Bt(this.functionsDir,{recursive:!0})}async loadExistingFunctions(){try{let t=F(this.functionsDir,"functions.json");if(U(t)){let r=await wt(t,"utf8"),n=JSON.parse(r);for(let s of n)U(s.filePath)&&this.functions.set(s.id,s)}}catch{}}async saveFunctionsMetadata(){try{let t=F(this.functionsDir,"functions.json"),r=Array.from(this.functions.values());await Y(t,JSON.stringify(r,null,2),"utf8")}catch{}}async deployFunction(t,r,n,s,o,i,a){if(!t||typeof t!="string")throw new y("Function name is required and must be a string");if(!r||typeof r!="string")throw new y("Function code is required and must be a string");if(n!==void 0){if(!Array.isArray(n))throw new y("Methods must be an array");let f=["GET","POST","PUT","PATCH","DELETE","HEAD","OPTIONS"];for(let m of n)if(!f.includes(m.toUpperCase()))throw new A(`Invalid HTTP method: ${m}. Must be one of: ${f.join(", ")}`)}s&&s.length>0&&this.bindingService.validateBindings(s);let c=Q(a),d=F(this.functionsDir,`${c}.mjs`),l=this.wrapFunctionCode(r);await Y(d,l,"utf8");let u=Date.now(),h={id:c,name:t,filePath:d,endpoint:`/functions/run/${c}`,...n&&n.length>0?{methods:n.map(f=>f.toUpperCase())}:{},...s?{bindings:s}:{},...o!==void 0?{passAllHeaders:o}:{},...i!==void 0?{allowUnauthenticated:i}:{},createdAt:u,updatedAt:u};return this.functions.set(c,h),await this.saveFunctionsMetadata(),h}async updateFunction(t,r){let n=this.functions.get(t);if(!n)throw new O(`Function with ID ${t} not found`);let{code:s,methods:o,bindings:i,passAllHeaders:a,allowUnauthenticated:c}=r;if(s===void 0&&o===void 0&&i===void 0&&a===void 0&&c===void 0)throw new y("At least one parameter (code, methods, bindings, passAllHeaders, or allowUnauthenticated) must be provided");if(s!==void 0&&(typeof s!="string"||!s))throw new y("Function code must be a non-empty string");if(o!==void 0){if(!Array.isArray(o))throw new y("Methods must be an array");let d=["GET","POST","PUT","PATCH","DELETE","HEAD","OPTIONS"];for(let l of o)if(!d.includes(l.toUpperCase()))throw new A(`Invalid HTTP method: ${l}. Must be one of: ${d.join(", ")}`)}if(s!==void 0){let d=this.wrapFunctionCode(s);await Y(n.filePath,d,"utf8")}return o!==void 0&&(o.length>0?n.methods=o.map(d=>d.toUpperCase()):delete n.methods),i!==void 0&&(i.length>0&&this.bindingService.validateBindings(i),n.bindings=i.length>0?i:void 0),a!==void 0&&(a?n.passAllHeaders=!0:delete n.passAllHeaders),c!==void 0&&(n.allowUnauthenticated=c),n.updatedAt=Date.now(),this.functions.set(t,n),await this.saveFunctionsMetadata(),n}async deleteFunction(t){let r=this.functions.get(t);if(!r)return!1;try{return U(r.filePath)&&await Vt(r.filePath),this.functions.delete(t),await this.saveFunctionsMetadata(),!0}catch(n){throw console.error(`Error deleting function ${t}:`,n.message),n}}wrapFunctionCode(t){let r=t;if(/export\s+default\s+\w+/.test(t))return`// FunctionsService generated module
12
12
  // Generated at: ${new Date().toISOString()}
13
13
 
14
14
  // User function code starts here
15
15
  ${r}
16
16
  // User function code ends here
17
- `;let n=t.match(/export\s*\{([^}]+)\}/);if(n){let s=n[1],i=s.match(/(\w+)\s+as\s+handler\b/)||s.match(/\bhandler\b/);if(i){let o=i[1]||"handler";r=t.replace(/export\s*\{[^}]+\}/,`export default ${o}`)}}else r=`${t}
17
+ `;let n=t.match(/export\s*\{([^}]+)\}/);if(n){let s=n[1],o=s.match(/(\w+)\s+as\s+handler\b/)||s.match(/\bhandler\b/);if(o){let i=o[1]||"handler";r=t.replace(/export\s*\{[^}]+\}/,`export default ${i}`)}}else r=`${t}
18
18
 
19
19
  export default handler;`;return`// FunctionsService generated module
20
20
  // Generated at: ${new Date().toISOString()}
@@ -22,4 +22,4 @@ export default handler;`;return`// FunctionsService generated module
22
22
  // User function code starts here
23
23
  ${r}
24
24
  // User function code ends here
25
- `}async executeFunction(t,r){try{let n=this.functions.get(t);if(!n)return r.json({error:"Not Found",message:"Function not found"},404);if(n.allowUnauthenticated!==!0&&!r.headers.authorization)return r.json({error:"Unauthorized",message:"This function requires authentication. Provide a valid Bearer token."},401);if(n.methods&&n.methods.length>0){let h=(r.req.method||"GET").toUpperCase();if(!n.methods.includes(h)){let p=n.methods.join(", "),m=r.json({error:"Method Not Allowed",message:`This function only accepts: ${p}`},405);return m.headers={...m.headers||{},allow:p},m}}let s=null;try{let h=r.req.method||"GET";["POST","PUT","PATCH"].includes(h)&&((r.headers["content-type"]||"").includes("application/json")?s=await E(r):s=r.body)}catch{}let i=["x-molnos-token","x-molnos-service-token","x-molnos-internal"],o={},a=r.req.headers;for(let[h,p]of Object.entries(a))(n.passAllHeaders||!i.includes(h.toLowerCase()))&&(o[h]=p);let c=new URL(r.req.url||"","http://127.0.0.1").pathname,d=`/run/${t}`,f=c.startsWith(d)?c.substring(d.length):"/";f||(f="/");let l={};if(n.bindings&&n.bindings.length>0){let p=r.headers.authorization?.replace(/^Bearer\s+/i,"")||null,m=P(),S={databases:m.services.databases.url,storage:m.services.storage.url,observability:m.services.observability.url,sites:m.services.sites.url,functions:m.services.functions.url};l=new M(S,p).createBindings(n.bindings)}let u={request:{method:r.req.method||"GET",path:c,subpath:f,query:r.query,headers:o,body:s},functionId:t,functionName:n.name,bindings:l};try{let m=(await import(`${Ht(n.filePath).href}?t=${Date.now()}`)).default;if(typeof m!="function")return r.json({error:"Invalid Function",message:"The deployed code does not export a default function"},500);let{interceptedConsole:S,restore:T}=this.createConsoleInterceptor(t,n.name);Object.assign(console,S);let g;try{g=await m(u.request,u)}finally{T()}if(g&&typeof g=="object"){if(g.statusCode!==void 0&&g.body!==void 0){let I=g.statusCode||200,C=g.headers||{};if(typeof g.body=="object"){let q=r.json(g.body,I);return Object.keys(C).length>0&&(q.headers={...q.headers||{},...C}),q}let D=r.text(g.body,I);return Object.keys(C).length>0&&(D.headers={...D.headers||{},...C}),D}return r.json(g)}return typeof g=="string"?r.text(g):typeof g=="number"||typeof g=="boolean"?r.json({result:g}):r.json({result:g===null?null:void 0})}catch(h){return console.error("Function execution error:",h),r.json({error:"Function Execution Error",message:this.debug?h.message:"Error executing function",stack:this.debug?h.stack:void 0},500)}}catch(n){return console.error("Error processing function execution:",n),r.json({error:"Internal Server Error",message:this.debug?n.message:"Failed to process function execution"},500)}}getStats(){return{totalFunctions:this.functions.size,functions:this.getFunctions().map(r=>({id:r.id,name:r.name,endpoint:r.endpoint,createdAt:new Date(r.createdAt).toISOString(),updatedAt:new Date(r.updatedAt).toISOString()}))}}createConsoleInterceptor(t,r){let n={log:console.log.bind(console),error:console.error.bind(console),warn:console.warn.bind(console),info:console.info.bind(console),debug:console.debug.bind(console)},s=(i,o)=>{let a=o.map(c=>typeof c=="object"?JSON.stringify(c):String(c)).join(" ");et({functionId:t,functionName:r,level:i,message:a,timestamp:Date.now()})};return{interceptedConsole:{log:(...i)=>{n.log(...i),s("info",i)},error:(...i)=>{n.error(...i),s("error",i)},warn:(...i)=>{n.warn(...i),s("warn",i)},info:(...i)=>{n.info(...i),s("info",i)},debug:(...i)=>{n.debug(...i),s("debug",i)}},restore:()=>{console.log=n.log,console.error=n.error,console.warn=n.warn,console.info=n.info,console.debug=n.debug}}}};async function Mt(e){let t=e.dataPath||"data",r=j(t,"functions"),n=e.debug||!1,s=new Y({functionsDir:r,debug:n});await s.start();let i=pt(e.identityApiUrl),o=_(),a=P(),c=a.services.observability.url;o.on("function.log",u=>{fetch(`${c}/events`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({service:`functions.${u.functionId}`,level:u.level,message:u.message,metadata:{functionId:u.functionId,functionName:u.functionName,...u.metadata}})}).catch(h=>{n&&console.error("Failed to send log to observability service:",h)})});let d=new z({port:e.api.port||a.services.functions.port,host:e.api.host||a.services.functions.host,rateLimit:e.rateLimit||{enabled:!1,requestsPerMinute:0}});d.post("/deploy",async u=>it(u,s,i)),d.get("/list",async u=>lt(u,s,i)),d.get("/stats",async u=>{try{let h=s.getStats();return u.json({success:!0,stats:h})}catch(h){return u.json({error:h.message},500)}}),d.get("/:functionId/config",async u=>{try{let h=u.params.functionId,p=s.getFunction(h);if(!p)return u.json({error:"Function not found"},404);let m="";try{let S=await mt(p.filePath,"utf8"),T="// User function code starts here",g="// User function code ends here",I=S.indexOf(T),C=S.indexOf(g);I!==-1&&C!==-1?(m=S.substring(I+T.length,C).trim().replace(/^\n+/,"").replace(/\n+$/,""),m=m.replace(/\n*export\s+default\s+handler;\s*$/,"")):m=S}catch(S){return u.json({error:"Failed to read function code",message:S.message},500)}return u.json({success:!0,function:{id:p.id,name:p.name,endpoint:p.endpoint,filePath:p.filePath,code:m,...p.methods?{methods:p.methods}:{},...p.bindings?{bindings:p.bindings}:{},...p.passAllHeaders!==void 0?{passAllHeaders:p.passAllHeaders}:{},...p.allowUnauthenticated!==void 0?{allowUnauthenticated:p.allowUnauthenticated}:{},createdAt:new Date(p.createdAt).toISOString(),updatedAt:new Date(p.updatedAt).toISOString()}})}catch(h){return u.json({error:h.message},500)}}),d.get("/:functionId",async u=>dt(u,s,i)),d.put("/:functionId",async u=>ct(u,s,i)),d.delete("/:functionId",async u=>ut(u,s,i));let f=async u=>ot(u,s,i);return d.get("/run/:functionId/*",f),d.post("/run/:functionId/*",f),d.put("/run/:functionId/*",f),d.patch("/run/:functionId/*",f),d.delete("/run/:functionId/*",f),d.get("/run/:functionId",f),d.post("/run/:functionId",f),d.put("/run/:functionId",f),d.patch("/run/:functionId",f),d.delete("/run/:functionId",f),d.start()}if(import.meta.url===`file://${process.argv[1]}`){let e=P(),r=process.argv.slice(2).find(i=>i.startsWith("--port=")),n=r?parseInt(r.split("=")[1],10):e.services.functions.port,s=ht({api:{port:n}},"functions");Mt(s)}export{Y as FunctionsService,Mt as startServer};
25
+ `}async executeFunction(t,r){try{let n=this.functions.get(t);if(!n)return r.json({error:"Not Found",message:"Function not found"},404);if(n.allowUnauthenticated!==!0&&!r.headers.authorization)return r.json({error:"Unauthorized",message:"This function requires authentication. Provide a valid Bearer token."},401);if(n.methods&&n.methods.length>0){let f=(r.req.method||"GET").toUpperCase();if(!n.methods.includes(f)){let m=n.methods.join(", "),p=r.json({error:"Method Not Allowed",message:`This function only accepts: ${m}`},405);return p.headers={...p.headers||{},allow:m},p}}let s=null;try{let f=r.req.method||"GET";["POST","PUT","PATCH"].includes(f)&&((r.headers["content-type"]||"").includes("application/json")?s=await I(r):s=r.body)}catch{}let o=["x-molnos-token","x-molnos-service-token","x-molnos-internal"],i={},a=r.req.headers;for(let[f,m]of Object.entries(a))(n.passAllHeaders||!o.includes(f.toLowerCase()))&&(i[f]=m);let c=new URL(r.req.url||"","http://127.0.0.1").pathname,d=`/run/${t}`,l=c.startsWith(d)?c.substring(d.length):"/";l||(l="/");let u={};if(n.bindings&&n.bindings.length>0){let m=r.headers.authorization?.replace(/^Bearer\s+/i,"")||null,p=T(),x={databases:p.services.databases.url,storage:p.services.storage.url,observability:p.services.observability.url,sites:p.services.sites.url,functions:p.services.functions.url};u=new k(x,m).createBindings(n.bindings)}let h={request:{method:r.req.method||"GET",path:c,subpath:l,query:r.query,headers:i,body:s},functionId:t,functionName:n.name,bindings:u};try{let p=(await import(`${zt(n.filePath).href}?t=${Date.now()}`)).default;if(typeof p!="function")return r.json({error:"Invalid Function",message:"The deployed code does not export a default function"},500);let{interceptedConsole:x,restore:C}=this.createConsoleInterceptor(t,n.name);Object.assign(console,x);let g;try{g=await p(h.request,h)}finally{C()}if(g&&typeof g=="object"){if(g.statusCode!==void 0&&g.body!==void 0){let R=g.statusCode||200,S=g.headers||{};if(typeof g.body=="object"){let N=r.json(g.body,R);return Object.keys(S).length>0&&(N.headers={...N.headers||{},...S}),N}let E=r.text(g.body,R);return Object.keys(S).length>0&&(E.headers={...E.headers||{},...S}),E}return r.json(g)}return typeof g=="string"?r.text(g):typeof g=="number"||typeof g=="boolean"?r.json({result:g}):r.json({result:g===null?null:void 0})}catch(f){return console.error("Function execution error:",f),r.json({error:"Function Execution Error",message:this.debug?f.message:"Error executing function",stack:this.debug?f.stack:void 0},500)}}catch(n){return console.error("Error processing function execution:",n),r.json({error:"Internal Server Error",message:this.debug?n.message:"Failed to process function execution"},500)}}getStats(){return{totalFunctions:this.functions.size,functions:this.getFunctions().map(r=>({id:r.id,name:r.name,endpoint:r.endpoint,createdAt:new Date(r.createdAt).toISOString(),updatedAt:new Date(r.updatedAt).toISOString()}))}}createConsoleInterceptor(t,r){let n={log:console.log.bind(console),error:console.error.bind(console),warn:console.warn.bind(console),info:console.info.bind(console),debug:console.debug.bind(console)},s=(o,i)=>{let a=i.map(c=>typeof c=="object"?JSON.stringify(c):String(c)).join(" ");st({functionId:t,functionName:r,level:o,message:a,timestamp:Date.now()})};return{interceptedConsole:{log:(...o)=>{n.log(...o),s("info",o)},error:(...o)=>{n.error(...o),s("error",o)},warn:(...o)=>{n.warn(...o),s("warn",o)},info:(...o)=>{n.info(...o),s("info",o)},debug:(...o)=>{n.debug(...o),s("debug",o)}},restore:()=>{console.log=n.log,console.error=n.error,console.warn=n.warn,console.info=n.info,console.debug=n.debug}}}};async function Gt(e){let t=e.dataPath||"data",r=F(t,"functions"),n=e.debug||!1,s=new K({functionsDir:r,debug:n});await s.start();let o=yt(e.identityApiUrl),i=bt(e.contextApiUrl),a=Z(),c=T(),d=c.services.observability.url;a.on("function.log",f=>{fetch(`${d}/events`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({service:`functions.${f.functionId}`,level:f.level,message:f.message,metadata:{functionId:f.functionId,functionName:f.functionName,...f.metadata}})}).catch(m=>{n&&console.error("Failed to send log to observability service:",m)})});let l=new J({port:e.api.port||c.services.functions.port,host:e.api.host||c.services.functions.host,rateLimit:e.rateLimit||{enabled:!1,requestsPerMinute:0}});l.post("/deploy",async f=>ct(f,s,o)),l.get("/list",async f=>pt(f,s,o,i)),l.get("/stats",async f=>{try{let m=s.getStats();return f.json({success:!0,stats:m})}catch(m){return f.json({error:m.message},500)}}),l.get("/:functionId/config",async f=>{try{let m=f.params.functionId,p=s.getFunction(m);if(!p)return f.json({error:"Function not found"},404);let x="";try{let C=await wt(p.filePath,"utf8"),g="// User function code starts here",R="// User function code ends here",S=C.indexOf(g),E=C.indexOf(R);S!==-1&&E!==-1?(x=C.substring(S+g.length,E).trim().replace(/^\n+/,"").replace(/\n+$/,""),x=x.replace(/\n*export\s+default\s+handler;\s*$/,"")):x=C}catch(C){return f.json({error:"Failed to read function code",message:C.message},500)}return f.json({success:!0,function:{id:p.id,name:p.name,endpoint:p.endpoint,filePath:p.filePath,code:x,...p.methods?{methods:p.methods}:{},...p.bindings?{bindings:p.bindings}:{},...p.passAllHeaders!==void 0?{passAllHeaders:p.passAllHeaders}:{},...p.allowUnauthenticated!==void 0?{allowUnauthenticated:p.allowUnauthenticated}:{},createdAt:new Date(p.createdAt).toISOString(),updatedAt:new Date(p.updatedAt).toISOString()}})}catch(m){return f.json({error:m.message},500)}}),l.get("/:functionId",async f=>ht(f,s,o)),l.put("/:functionId",async f=>dt(f,s,o)),l.delete("/:functionId",async f=>ft(f,s,o));let u=async f=>ut(f,s,o);return l.get("/run/:functionId/*",u),l.post("/run/:functionId/*",u),l.put("/run/:functionId/*",u),l.patch("/run/:functionId/*",u),l.delete("/run/:functionId/*",u),l.get("/run/:functionId",u),l.post("/run/:functionId",u),l.put("/run/:functionId",u),l.patch("/run/:functionId",u),l.delete("/run/:functionId",u),l.start()}if(import.meta.url===`file://${process.argv[1]}`){let e=T(),r=process.argv.slice(2).find(o=>o.startsWith("--port=")),n=r?parseInt(r.split("=")[1],10):e.services.functions.port,s=gt({api:{port:n}},"functions");Gt(s)}export{K as FunctionsService,Gt as startServer};