molnos 1.0.3 → 1.1.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/Dockerfile +20 -0
- package/README.md +31 -16
- package/VERSION +1 -0
- package/dist/databases.mjs +10 -1
- package/dist/functions.mjs +14 -5
- package/dist/molnos_core.mjs +37 -38
- package/dist/observability.mjs +12 -3
- package/dist/sites.mjs +10 -1
- package/dist/storage.mjs +10 -1
- package/oss-licenses.txt +97 -0
- package/package.json +14 -9
- package/sbom.json +1 -0
package/dist/observability.mjs
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
// MolnOS Core - See LICENSE file for copyright and license details.
|
|
2
|
-
import{createHash as tr}from"node:crypto";var re=(e,t,s)=>(r,n)=>{let o=-1;return i(0);async function i(a){if(a<=o)throw new Error("next() called multiple times");o=a;let c,l=!1,h;if(e[a]?(h=e[a][0][0],r.req.routeIndex=a):h=a===e.length&&n||void 0,h)try{c=await h(r,()=>i(a+1))}catch(u){if(u instanceof Error&&t)r.error=u,c=await t(u,r),l=!0;else throw u}else r.finalized===!1&&s&&(c=await s(r));return c&&(r.finalized===!1||l)&&(r.res=c),r}};var we=Symbol();var Ee=async(e,t=Object.create(null))=>{let{all:s=!1,dot:r=!1}=t,o=(e instanceof U?e.raw.headers:e.headers).get("Content-Type");return o?.startsWith("multipart/form-data")||o?.startsWith("application/x-www-form-urlencoded")?pt(e,{all:s,dot:r}):{}};async function pt(e,t){let s=await e.formData();return s?mt(s,t):{}}function mt(e,t){let s=Object.create(null);return e.forEach((r,n)=>{t.all||n.endsWith("[]")?yt(s,n,r):s[n]=r}),t.dot&&Object.entries(s).forEach(([r,n])=>{r.includes(".")&&(gt(s,r,n),delete s[r])}),s}var yt=(e,t,s)=>{e[t]!==void 0?Array.isArray(e[t])?e[t].push(s):e[t]=[e[t],s]:t.endsWith("[]")?e[t]=[s]:e[t]=s},gt=(e,t,s)=>{let r=e,n=t.split(".");n.forEach((o,i)=>{i===n.length-1?r[o]=s:((!r[o]||typeof r[o]!="object"||Array.isArray(r[o])||r[o]instanceof File)&&(r[o]=Object.create(null)),r=r[o])})};var ne=e=>{let t=e.split("/");return t[0]===""&&t.shift(),t},Re=e=>{let{groups:t,path:s}=vt(e),r=ne(s);return bt(r,t)},vt=e=>{let t=[];return e=e.replace(/\{[^}]+\}/g,(s,r)=>{let n=`@${r}`;return t.push([n,s]),n}),{groups:t,path:e}},bt=(e,t)=>{for(let s=t.length-1;s>=0;s--){let[r]=t[s];for(let n=e.length-1;n>=0;n--)if(e[n].includes(r)){e[n]=e[n].replace(r,t[s][1]);break}}return e},z={},Pe=(e,t)=>{if(e==="*")return"*";let s=e.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);if(s){let r=`${e}#${t}`;return z[r]||(s[2]?z[r]=t&&t[0]!==":"&&t[0]!=="*"?[r,s[1],new RegExp(`^${s[2]}(?=/${t})`)]:[e,s[1],new RegExp(`^${s[2]}$`)]:z[r]=[e,s[1],!0]),z[r]}return null},W=(e,t)=>{try{return t(e)}catch{return e.replace(/(?:%[0-9A-Fa-f]{2})+/g,s=>{try{return t(s)}catch{return s}})}},wt=e=>W(e,decodeURI),oe=e=>{let t=e.url,s=t.indexOf("/",t.indexOf(":")+4),r=s;for(;r<t.length;r++){let n=t.charCodeAt(r);if(n===37){let o=t.indexOf("?",r),i=t.slice(s,o===-1?void 0:o);return wt(i.includes("%25")?i.replace(/%25/g,"%2525"):i)}else if(n===63)break}return t.slice(s,r)};var xe=e=>{let t=oe(e);return t.length>1&&t.at(-1)==="/"?t.slice(0,-1):t},O=(e,t,...s)=>(s.length&&(t=O(t,...s)),`${e?.[0]==="/"?"":"/"}${e}${t==="/"?"":`${e?.at(-1)==="/"?"":"/"}${t?.[0]==="/"?t.slice(1):t}`}`),V=e=>{if(e.charCodeAt(e.length-1)!==63||!e.includes(":"))return null;let t=e.split("/"),s=[],r="";return t.forEach(n=>{if(n!==""&&!/\:/.test(n))r+="/"+n;else if(/\:/.test(n))if(/\?/.test(n)){s.length===0&&r===""?s.push("/"):s.push(r);let o=n.replace("?","");r+="/"+o,s.push(r)}else r+="/"+n}),s.filter((n,o,i)=>i.indexOf(n)===o)},se=e=>/[%+]/.test(e)?(e.indexOf("+")!==-1&&(e=e.replace(/\+/g," ")),e.indexOf("%")!==-1?W(e,ie):e):e,Se=(e,t,s)=>{let r;if(!s&&t&&!/[%+]/.test(t)){let i=e.indexOf("?",8);if(i===-1)return;for(e.startsWith(t,i+1)||(i=e.indexOf(`&${t}`,i+1));i!==-1;){let a=e.charCodeAt(i+t.length+1);if(a===61){let c=i+t.length+2,l=e.indexOf("&",c);return se(e.slice(c,l===-1?void 0:l))}else if(a==38||isNaN(a))return"";i=e.indexOf(`&${t}`,i+1)}if(r=/[%+]/.test(e),!r)return}let n={};r??=/[%+]/.test(e);let o=e.indexOf("?",8);for(;o!==-1;){let i=e.indexOf("&",o+1),a=e.indexOf("=",o);a>i&&i!==-1&&(a=-1);let c=e.slice(o+1,a===-1?i===-1?void 0:i:a);if(r&&(c=se(c)),o=i,c==="")continue;let l;a===-1?l="":(l=e.slice(a+1,i===-1?void 0:i),r&&(l=se(l))),s?(n[c]&&Array.isArray(n[c])||(n[c]=[]),n[c].push(l)):n[c]??=l}return t?n[t]:n},Oe=Se,je=(e,t)=>Se(e,t,!0),ie=decodeURIComponent;var Ce=e=>W(e,ie),U=class{raw;#t;#e;routeIndex=0;path;bodyCache={};constructor(e,t="/",s=[[]]){this.raw=e,this.path=t,this.#e=s,this.#t={}}param(e){return e?this.#r(e):this.#o()}#r(e){let t=this.#e[0][this.routeIndex][1][e],s=this.#n(t);return s&&/\%/.test(s)?Ce(s):s}#o(){let e={},t=Object.keys(this.#e[0][this.routeIndex][1]);for(let s of t){let r=this.#n(this.#e[0][this.routeIndex][1][s]);r!==void 0&&(e[s]=/\%/.test(r)?Ce(r):r)}return e}#n(e){return this.#e[1]?this.#e[1][e]:e}query(e){return Oe(this.url,e)}queries(e){return je(this.url,e)}header(e){if(e)return this.raw.headers.get(e)??void 0;let t={};return this.raw.headers.forEach((s,r)=>{t[r]=s}),t}async parseBody(e){return this.bodyCache.parsedBody??=await Ee(this,e)}#s=e=>{let{bodyCache:t,raw:s}=this,r=t[e];if(r)return r;let n=Object.keys(t)[0];return n?t[n].then(o=>(n==="json"&&(o=JSON.stringify(o)),new Response(o)[e]())):t[e]=s[e]()};json(){return this.#s("text").then(e=>JSON.parse(e))}text(){return this.#s("text")}arrayBuffer(){return this.#s("arrayBuffer")}blob(){return this.#s("blob")}formData(){return this.#s("formData")}addValidatedData(e,t){this.#t[e]=t}valid(e){return this.#t[e]}get url(){return this.raw.url}get method(){return this.raw.method}get[we](){return this.#e}get matchedRoutes(){return this.#e[0].map(([[,e]])=>e)}get routePath(){return this.#e[0].map(([[,e]])=>e)[this.routeIndex].path}};var Ae={Stringify:1,BeforeStream:2,Stream:3},Et=(e,t)=>{let s=new String(e);return s.isEscaped=!0,s.callbacks=t,s};var ae=async(e,t,s,r,n)=>{typeof e=="object"&&!(e instanceof String)&&(e instanceof Promise||(e=e.toString()),e instanceof Promise&&(e=await e));let o=e.callbacks;if(!o?.length)return Promise.resolve(e);n?n[0]+=e:n=[e];let i=Promise.all(o.map(a=>a({phase:t,buffer:n,context:r}))).then(a=>Promise.all(a.filter(Boolean).map(c=>ae(c,t,!1,r,n))).then(()=>n[0]));return s?Et(await i,o):i};var Rt="text/plain; charset=UTF-8",ce=(e,t)=>({"Content-Type":e,...t}),Le=class{#t;#e;env={};#r;finalized=!1;error;#o;#n;#s;#h;#c;#l;#a;#u;#f;constructor(e,t){this.#t=e,t&&(this.#n=t.executionCtx,this.env=t.env,this.#l=t.notFoundHandler,this.#f=t.path,this.#u=t.matchResult)}get req(){return this.#e??=new U(this.#t,this.#f,this.#u),this.#e}get event(){if(this.#n&&"respondWith"in this.#n)return this.#n;throw Error("This context has no FetchEvent")}get executionCtx(){if(this.#n)return this.#n;throw Error("This context has no ExecutionContext")}get res(){return this.#s||=new Response(null,{headers:this.#a??=new Headers})}set res(e){if(this.#s&&e){e=new Response(e.body,e);for(let[t,s]of this.#s.headers.entries())if(t!=="content-type")if(t==="set-cookie"){let r=this.#s.headers.getSetCookie();e.headers.delete("set-cookie");for(let n of r)e.headers.append("set-cookie",n)}else e.headers.set(t,s)}this.#s=e,this.finalized=!0}render=(...e)=>(this.#c??=t=>this.html(t),this.#c(...e));setLayout=e=>this.#h=e;getLayout=()=>this.#h;setRenderer=e=>{this.#c=e};header=(e,t,s)=>{this.finalized&&(this.#s=new Response(this.#s.body,this.#s));let r=this.#s?this.#s.headers:this.#a??=new Headers;t===void 0?r.delete(e):s?.append?r.append(e,t):r.set(e,t)};status=e=>{this.#o=e};set=(e,t)=>{this.#r??=new Map,this.#r.set(e,t)};get=e=>this.#r?this.#r.get(e):void 0;get var(){return this.#r?Object.fromEntries(this.#r):{}}#i(e,t,s){let r=this.#s?new Headers(this.#s.headers):this.#a??new Headers;if(typeof t=="object"&&"headers"in t){let o=t.headers instanceof Headers?t.headers:new Headers(t.headers);for(let[i,a]of o)i.toLowerCase()==="set-cookie"?r.append(i,a):r.set(i,a)}if(s)for(let[o,i]of Object.entries(s))if(typeof i=="string")r.set(o,i);else{r.delete(o);for(let a of i)r.append(o,a)}let n=typeof t=="number"?t:t?.status??this.#o;return new Response(e,{status:n,headers:r})}newResponse=(...e)=>this.#i(...e);body=(e,t,s)=>this.#i(e,t,s);text=(e,t,s)=>!this.#a&&!this.#o&&!t&&!s&&!this.finalized?new Response(e):this.#i(e,t,ce(Rt,s));json=(e,t,s)=>this.#i(JSON.stringify(e),t,ce("application/json",s));html=(e,t,s)=>{let r=n=>this.#i(n,t,ce("text/html; charset=UTF-8",s));return typeof e=="object"?ae(e,Ae.Stringify,!1,{}).then(r):r(e)};redirect=(e,t)=>{let s=String(e);return this.header("Location",/[^\x00-\xFF]/.test(s)?encodeURI(s):s),this.newResponse(null,t??302)};notFound=()=>(this.#l??=()=>new Response,this.#l(this))};var d="ALL",Te="all",He=["get","post","put","delete","options","patch"],G="Can not add a route since the matcher is already built.",K=class extends Error{};var Ie="__COMPOSED_HANDLER";var Pt=e=>e.text("404 Not Found",404),ke=(e,t)=>{if("getResponse"in e){let s=e.getResponse();return t.newResponse(s.body,s)}return console.error(e),t.text("Internal Server Error",500)},De=class qe{get;post;put;delete;options;patch;all;on;use;router;getPath;_basePath="/";#t="/";routes=[];constructor(t={}){[...He,Te].forEach(o=>{this[o]=(i,...a)=>(typeof i=="string"?this.#t=i:this.#o(o,this.#t,i),a.forEach(c=>{this.#o(o,this.#t,c)}),this)}),this.on=(o,i,...a)=>{for(let c of[i].flat()){this.#t=c;for(let l of[o].flat())a.map(h=>{this.#o(l.toUpperCase(),this.#t,h)})}return this},this.use=(o,...i)=>(typeof o=="string"?this.#t=o:(this.#t="*",i.unshift(o)),i.forEach(a=>{this.#o(d,this.#t,a)}),this);let{strict:r,...n}=t;Object.assign(this,n),this.getPath=r??!0?t.getPath??oe:xe}#e(){let t=new qe({router:this.router,getPath:this.getPath});return t.errorHandler=this.errorHandler,t.#r=this.#r,t.routes=this.routes,t}#r=Pt;errorHandler=ke;route(t,s){let r=this.basePath(t);return s.routes.map(n=>{let o;s.errorHandler===ke?o=n.handler:(o=async(i,a)=>(await re([],s.errorHandler)(i,()=>n.handler(i,a))).res,o[Ie]=n.handler),r.#o(n.method,n.path,o)}),this}basePath(t){let s=this.#e();return s._basePath=O(this._basePath,t),s}onError=t=>(this.errorHandler=t,this);notFound=t=>(this.#r=t,this);mount(t,s,r){let n,o;r&&(typeof r=="function"?o=r:(o=r.optionHandler,r.replaceRequest===!1?n=c=>c:n=r.replaceRequest));let i=o?c=>{let l=o(c);return Array.isArray(l)?l:[l]}:c=>{let l;try{l=c.executionCtx}catch{}return[c.env,l]};n||=(()=>{let c=O(this._basePath,t),l=c==="/"?0:c.length;return h=>{let u=new URL(h.url);return u.pathname=u.pathname.slice(l)||"/",new Request(u,h)}})();let a=async(c,l)=>{let h=await s(n(c.req.raw),...i(c));if(h)return h;await l()};return this.#o(d,O(t,"*"),a),this}#o(t,s,r){t=t.toUpperCase(),s=O(this._basePath,s);let n={basePath:this._basePath,path:s,method:t,handler:r};this.router.add(t,s,[r,n]),this.routes.push(n)}#n(t,s){if(t instanceof Error)return this.errorHandler(t,s);throw t}#s(t,s,r,n){if(n==="HEAD")return(async()=>new Response(null,await this.#s(t,s,r,"GET")))();let o=this.getPath(t,{env:r}),i=this.router.match(n,o),a=new Le(t,{path:o,matchResult:i,env:r,executionCtx:s,notFoundHandler:this.#r});if(i[0].length===1){let l;try{l=i[0][0][0][0](a,async()=>{a.res=await this.#r(a)})}catch(h){return this.#n(h,a)}return l instanceof Promise?l.then(h=>h||(a.finalized?a.res:this.#r(a))).catch(h=>this.#n(h,a)):l??this.#r(a)}let c=re(i[0],this.errorHandler,this.#r);return(async()=>{try{let l=await c(a);if(!l.finalized)throw new Error("Context is not finalized. Did you forget to return a Response object or `await next()`?");return l.res}catch(l){return this.#n(l,a)}})()}fetch=(t,...s)=>this.#s(t,s[1],s[0],t.method);request=(t,s,r,n)=>t instanceof Request?this.fetch(s?new Request(t,s):t,r,n):(t=t.toString(),this.fetch(new Request(/^https?:\/\//.test(t)?t:`http://localhost${O("/",t)}`,s),r,n));fire=()=>{addEventListener("fetch",t=>{t.respondWith(this.#s(t.request,t,void 0,t.request.method))})}};var Q=[];function le(e,t){let s=this.buildAllMatchers(),r=((n,o)=>{let i=s[n]||s[d],a=i[2][o];if(a)return a;let c=o.match(i[0]);if(!c)return[[],Q];let l=c.indexOf("",1);return[i[1][l],c]});return this.match=r,r(e,t)}var J="[^/]+",D=".*",q="(?:|/.*)",j=Symbol(),xt=new Set(".\\+*[^]$()");function St(e,t){return e.length===1?t.length===1?e<t?-1:1:-1:t.length===1||e===D||e===q?1:t===D||t===q?-1:e===J?1:t===J?-1:e.length===t.length?e<t?-1:1:t.length-e.length}var Me=class he{#t;#e;#r=Object.create(null);insert(t,s,r,n,o){if(t.length===0){if(this.#t!==void 0)throw j;if(o)return;this.#t=s;return}let[i,...a]=t,c=i==="*"?a.length===0?["","",D]:["","",J]:i==="/*"?["","",q]:i.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/),l;if(c){let h=c[1],u=c[2]||J;if(h&&c[2]&&(u===".*"||(u=u.replace(/^\((?!\?:)(?=[^)]+\)$)/,"(?:"),/\((?!\?:)/.test(u))))throw j;if(l=this.#r[u],!l){if(Object.keys(this.#r).some(f=>f!==D&&f!==q))throw j;if(o)return;l=this.#r[u]=new he,h!==""&&(l.#e=n.varIndex++)}!o&&h!==""&&r.push([h,l.#e])}else if(l=this.#r[i],!l){if(Object.keys(this.#r).some(h=>h.length>1&&h!==D&&h!==q))throw j;if(o)return;l=this.#r[i]=new he}l.insert(a,s,r,n,o)}buildRegExpStr(){let s=Object.keys(this.#r).sort(St).map(r=>{let n=this.#r[r];return(typeof n.#e=="number"?`(${r})@${n.#e}`:xt.has(r)?`\\${r}`:r)+n.buildRegExpStr()});return typeof this.#t=="number"&&s.unshift(`#${this.#t}`),s.length===0?"":s.length===1?s[0]:"(?:"+s.join("|")+")"}};var Fe=class{#t={varIndex:0};#e=new Me;insert(e,t,s){let r=[],n=[];for(let i=0;;){let a=!1;if(e=e.replace(/\{[^}]+\}/g,c=>{let l=`@\\${i}`;return n[i]=[l,c],i++,a=!0,l}),!a)break}let o=e.match(/(?::[^\/]+)|(?:\/\*$)|./g)||[];for(let i=n.length-1;i>=0;i--){let[a]=n[i];for(let c=o.length-1;c>=0;c--)if(o[c].indexOf(a)!==-1){o[c]=o[c].replace(a,n[i][1]);break}}return this.#e.insert(o,t,r,this.#t,s),r}buildRegExp(){let e=this.#e.buildRegExpStr();if(e==="")return[/^$/,[],[]];let t=0,s=[],r=[];return e=e.replace(/#(\d+)|@(\d+)|\.\*\$/g,(n,o,i)=>o!==void 0?(s[++t]=Number(o),"$()"):(i!==void 0&&(r[Number(i)]=++t),"")),[new RegExp(`^${e}`),s,r]}};var Ot=[/^$/,[],Object.create(null)],$e=Object.create(null);function _e(e){return $e[e]??=new RegExp(e==="*"?"":`^${e.replace(/\/\*$|([.\\+*[^\]$()])/g,(t,s)=>s?`\\${s}`:"(?:|/.*)")}$`)}function jt(){$e=Object.create(null)}function Ct(e){let t=new Fe,s=[];if(e.length===0)return Ot;let r=e.map(l=>[!/\*|\/:/.test(l[0]),...l]).sort(([l,h],[u,f])=>l?1:u?-1:h.length-f.length),n=Object.create(null);for(let l=0,h=-1,u=r.length;l<u;l++){let[f,m,g]=r[l];f?n[m]=[g.map(([y])=>[y,Object.create(null)]),Q]:h++;let p;try{p=t.insert(m,h,f)}catch(y){throw y===j?new K(m):y}f||(s[h]=g.map(([y,b])=>{let v=Object.create(null);for(b-=1;b>=0;b--){let[B,w]=p[b];v[B]=w}return[y,v]}))}let[o,i,a]=t.buildRegExp();for(let l=0,h=s.length;l<h;l++)for(let u=0,f=s[l].length;u<f;u++){let m=s[l][u]?.[1];if(!m)continue;let g=Object.keys(m);for(let p=0,y=g.length;p<y;p++)m[g[p]]=a[m[g[p]]]}let c=[];for(let l in i)c[l]=s[i[l]];return[o,c,n]}function L(e,t){if(e){for(let s of Object.keys(e).sort((r,n)=>n.length-r.length))if(_e(s).test(t))return[...e[s]]}}var X=class{name="RegExpRouter";#t;#e;constructor(){this.#t={[d]:Object.create(null)},this.#e={[d]:Object.create(null)}}add(e,t,s){let r=this.#t,n=this.#e;if(!r||!n)throw new Error(G);r[e]||[r,n].forEach(a=>{a[e]=Object.create(null),Object.keys(a[d]).forEach(c=>{a[e][c]=[...a[d][c]]})}),t==="/*"&&(t="*");let o=(t.match(/\/:/g)||[]).length;if(/\*$/.test(t)){let a=_e(t);e===d?Object.keys(r).forEach(c=>{r[c][t]||=L(r[c],t)||L(r[d],t)||[]}):r[e][t]||=L(r[e],t)||L(r[d],t)||[],Object.keys(r).forEach(c=>{(e===d||e===c)&&Object.keys(r[c]).forEach(l=>{a.test(l)&&r[c][l].push([s,o])})}),Object.keys(n).forEach(c=>{(e===d||e===c)&&Object.keys(n[c]).forEach(l=>a.test(l)&&n[c][l].push([s,o]))});return}let i=V(t)||[t];for(let a=0,c=i.length;a<c;a++){let l=i[a];Object.keys(n).forEach(h=>{(e===d||e===h)&&(n[h][l]||=[...L(r[h],l)||L(r[d],l)||[]],n[h][l].push([s,o-c+a+1]))})}}match=le;buildAllMatchers(){let e=Object.create(null);return Object.keys(this.#e).concat(Object.keys(this.#t)).forEach(t=>{e[t]||=this.#r(t)}),this.#t=this.#e=void 0,jt(),e}#r(e){let t=[],s=e===d;return[this.#t,this.#e].forEach(r=>{let n=r[e]?Object.keys(r[e]).map(o=>[o,r[e][o]]):[];n.length!==0?(s||=!0,t.push(...n)):e!==d&&t.push(...Object.keys(r[d]).map(o=>[o,r[d][o]]))}),s?Ct(t):null}};var ue=class{name="SmartRouter";#t=[];#e=[];constructor(e){this.#t=e.routers}add(e,t,s){if(!this.#e)throw new Error(G);this.#e.push([e,t,s])}match(e,t){if(!this.#e)throw new Error("Fatal error");let s=this.#t,r=this.#e,n=s.length,o=0,i;for(;o<n;o++){let a=s[o];try{for(let c=0,l=r.length;c<l;c++)a.add(...r[c]);i=a.match(e,t)}catch(c){if(c instanceof K)continue;throw c}this.match=a.match.bind(a),this.#t=[a],this.#e=void 0;break}if(o===n)throw new Error("Fatal error");return this.name=`SmartRouter + ${this.activeRouter.name}`,i}get activeRouter(){if(this.#e||this.#t.length!==1)throw new Error("No active router has been determined yet.");return this.#t[0]}};var M=Object.create(null),Ne=class Be{#t;#e;#r;#o=0;#n=M;constructor(t,s,r){if(this.#e=r||Object.create(null),this.#t=[],t&&s){let n=Object.create(null);n[t]={handler:s,possibleKeys:[],score:0},this.#t=[n]}this.#r=[]}insert(t,s,r){this.#o=++this.#o;let n=this,o=Re(s),i=[];for(let a=0,c=o.length;a<c;a++){let l=o[a],h=o[a+1],u=Pe(l,h),f=Array.isArray(u)?u[0]:l;if(f in n.#e){n=n.#e[f],u&&i.push(u[1]);continue}n.#e[f]=new Be,u&&(n.#r.push(u),i.push(u[1])),n=n.#e[f]}return n.#t.push({[t]:{handler:r,possibleKeys:i.filter((a,c,l)=>l.indexOf(a)===c),score:this.#o}}),n}#s(t,s,r,n){let o=[];for(let i=0,a=t.#t.length;i<a;i++){let c=t.#t[i],l=c[s]||c[d],h={};if(l!==void 0&&(l.params=Object.create(null),o.push(l),r!==M||n&&n!==M))for(let u=0,f=l.possibleKeys.length;u<f;u++){let m=l.possibleKeys[u],g=h[l.score];l.params[m]=n?.[m]&&!g?n[m]:r[m]??n?.[m],h[l.score]=!0}}return o}search(t,s){let r=[];this.#n=M;let o=[this],i=ne(s),a=[];for(let c=0,l=i.length;c<l;c++){let h=i[c],u=c===l-1,f=[];for(let m=0,g=o.length;m<g;m++){let p=o[m],y=p.#e[h];y&&(y.#n=p.#n,u?(y.#e["*"]&&r.push(...this.#s(y.#e["*"],t,p.#n)),r.push(...this.#s(y,t,p.#n))):f.push(y));for(let b=0,v=p.#r.length;b<v;b++){let B=p.#r[b],w=p.#n===M?{}:{...p.#n};if(B==="*"){let x=p.#e["*"];x&&(r.push(...this.#s(x,t,p.#n)),x.#n=w,f.push(x));continue}let[ut,be,k]=B;if(!h&&!(k instanceof RegExp))continue;let P=p.#e[ut],ft=i.slice(c).join("/");if(k instanceof RegExp){let x=k.exec(ft);if(x){if(w[be]=x[0],r.push(...this.#s(P,t,p.#n,w)),Object.keys(P.#e).length){P.#n=w;let dt=x[0].match(/\//)?.length??0;(a[dt]||=[]).push(P)}continue}}(k===!0||k.test(h))&&(w[be]=h,u?(r.push(...this.#s(P,t,w,p.#n)),P.#e["*"]&&r.push(...this.#s(P.#e["*"],t,w,p.#n))):(P.#n=w,f.push(P)))}}o=f.concat(a.shift()??[])}return r.length>1&&r.sort((c,l)=>c.score-l.score),[r.map(({handler:c,params:l})=>[c,l])]}};var fe=class{name="TrieRouter";#t;constructor(){this.#t=new Ne}add(e,t,s){let r=V(t);if(r){for(let n=0,o=r.length;n<o;n++)this.#t.insert(e,r[n],s);return}this.#t.insert(e,t,s)}match(e,t){return this.#t.search(e,t)}};var de=class extends De{constructor(e={}){super(e),this.router=e.router??new ue({routers:[new X,new fe]})}};import{join as N}from"node:path";import{promises as S}from"node:fs";import{createServer as At}from"http";import{Http2ServerRequest as Lt}from"http2";import{Http2ServerRequest as pe}from"http2";import{Readable as Ue}from"stream";import Bt from"crypto";var C=class extends Error{constructor(e,t){super(e,t),this.name="RequestError"}},Tt=e=>e instanceof C?e:new C(e.message,{cause:e}),Ht=global.Request,F=class extends Ht{constructor(e,t){typeof e=="object"&&I in e&&(e=e[I]()),typeof t?.body?.getReader<"u"&&(t.duplex??="half"),super(e,t)}},It=e=>{let t=[],s=e.rawHeaders;for(let r=0;r<s.length;r+=2){let{[r]:n,[r+1]:o}=s;n.charCodeAt(0)!==58&&t.push([n,o])}return new Headers(t)},We=Symbol("wrapBodyStream"),kt=(e,t,s,r,n)=>{let o={method:e,headers:s,signal:n.signal};if(e==="TRACE"){o.method="GET";let i=new F(t,o);return Object.defineProperty(i,"method",{get(){return"TRACE"}}),i}if(!(e==="GET"||e==="HEAD"))if("rawBody"in r&&r.rawBody instanceof Buffer)o.body=new ReadableStream({start(i){i.enqueue(r.rawBody),i.close()}});else if(r[We]){let i;o.body=new ReadableStream({async pull(a){try{i||=Ue.toWeb(r).getReader();let{done:c,value:l}=await i.read();c?a.close():a.enqueue(l)}catch(c){a.error(c)}}})}else o.body=Ue.toWeb(r);return new F(t,o)},I=Symbol("getRequestCache"),Dt=Symbol("requestCache"),Y=Symbol("incomingKey"),Z=Symbol("urlKey"),qt=Symbol("headersKey"),H=Symbol("abortControllerKey"),Mt=Symbol("getAbortController"),ee={get method(){return this[Y].method||"GET"},get url(){return this[Z]},get headers(){return this[qt]||=It(this[Y])},[Mt](){return this[I](),this[H]},[I](){return this[H]||=new AbortController,this[Dt]||=kt(this.method,this[Z],this.headers,this[Y],this[H])}};["body","bodyUsed","cache","credentials","destination","integrity","mode","redirect","referrer","referrerPolicy","signal","keepalive"].forEach(e=>{Object.defineProperty(ee,e,{get(){return this[I]()[e]}})});["arrayBuffer","blob","clone","formData","json","text"].forEach(e=>{Object.defineProperty(ee,e,{value:function(){return this[I]()[e]()}})});Object.setPrototypeOf(ee,F.prototype);var Ft=(e,t)=>{let s=Object.create(ee);s[Y]=e;let r=e.url||"";if(r[0]!=="/"&&(r.startsWith("http://")||r.startsWith("https://"))){if(e instanceof pe)throw new C("Absolute URL for :path is not allowed in HTTP/2");try{let a=new URL(r);s[Z]=a.href}catch(a){throw new C("Invalid absolute URL",{cause:a})}return s}let n=(e instanceof pe?e.authority:e.headers.host)||t;if(!n)throw new C("Missing host header");let o;if(e instanceof pe){if(o=e.scheme,!(o==="http"||o==="https"))throw new C("Unsupported scheme")}else o=e.socket&&e.socket.encrypted?"https":"http";let i=new URL(`${o}://${n}${r}`);if(i.hostname.length!==n.length&&i.hostname!==n.replace(/:\d+$/,""))throw new C("Invalid host header");return s[Z]=i.href,s},ze=Symbol("responseCache"),T=Symbol("getResponseCache"),A=Symbol("cache"),ye=global.Response,$=class Ve{#t;#e;[T](){return delete this[A],this[ze]||=new ye(this.#t,this.#e)}constructor(t,s){let r;if(this.#t=t,s instanceof Ve){let n=s[ze];if(n){this.#e=n,this[T]();return}else this.#e=s.#e,r=new Headers(s.#e.headers)}else this.#e=s;(typeof t=="string"||typeof t?.getReader<"u"||t instanceof Blob||t instanceof Uint8Array)&&(r||=s?.headers||{"content-type":"text/plain; charset=UTF-8"},this[A]=[s?.status||200,t,r])}get headers(){let t=this[A];return t?(t[2]instanceof Headers||(t[2]=new Headers(t[2])),t[2]):this[T]().headers}get status(){return this[A]?.[0]??this[T]().status}get ok(){let t=this.status;return t>=200&&t<300}};["body","bodyUsed","redirected","statusText","trailers","type","url"].forEach(e=>{Object.defineProperty($.prototype,e,{get(){return this[T]()[e]}})});["arrayBuffer","blob","clone","formData","json","text"].forEach(e=>{Object.defineProperty($.prototype,e,{value:function(){return this[T]()[e]()}})});Object.setPrototypeOf($,ye);Object.setPrototypeOf($.prototype,ye.prototype);async function $t(e){return Promise.race([e,Promise.resolve().then(()=>Promise.resolve(void 0))])}function Ge(e,t,s){let r=a=>{e.cancel(a).catch(()=>{})};return t.on("close",r),t.on("error",r),(s??e.read()).then(i,n),e.closed.finally(()=>{t.off("close",r),t.off("error",r)});function n(a){a&&t.destroy(a)}function o(){e.read().then(i,n)}function i({done:a,value:c}){try{if(a)t.end();else if(!t.write(c))t.once("drain",o);else return e.read().then(i,n)}catch(l){n(l)}}}function _t(e,t){if(e.locked)throw new TypeError("ReadableStream is locked.");return t.destroyed?void 0:Ge(e.getReader(),t)}var Ke=e=>{let t={};e instanceof Headers||(e=new Headers(e??void 0));let s=[];for(let[r,n]of e)r==="set-cookie"?s.push(n):t[r]=n;return s.length>0&&(t["set-cookie"]=s),t["content-type"]??="text/plain; charset=UTF-8",t},Nt="x-hono-already-sent",Ut=global.fetch;typeof global.crypto>"u"&&(global.crypto=Bt);global.fetch=(e,t)=>(t={compress:!1,...t},Ut(e,t));var ge=Symbol("outgoingEnded"),zt=()=>new Response(null,{status:400}),Qe=e=>new Response(null,{status:e instanceof Error&&(e.name==="TimeoutError"||e.constructor.name==="TimeoutError")?504:500}),me=(e,t)=>{let s=e instanceof Error?e:new Error("unknown error",{cause:e});s.code==="ERR_STREAM_PREMATURE_CLOSE"?console.info("The user aborted a request."):(console.error(e),t.headersSent||t.writeHead(500,{"Content-Type":"text/plain"}),t.end(`Error: ${s.message}`),t.destroy(s))},Je=e=>{"flushHeaders"in e&&e.writable&&e.flushHeaders()},Xe=async(e,t)=>{let[s,r,n]=e[A];n instanceof Headers&&(n=Ke(n)),typeof r=="string"?n["Content-Length"]=Buffer.byteLength(r):r instanceof Uint8Array?n["Content-Length"]=r.byteLength:r instanceof Blob&&(n["Content-Length"]=r.size),t.writeHead(s,n),typeof r=="string"||r instanceof Uint8Array?t.end(r):r instanceof Blob?t.end(new Uint8Array(await r.arrayBuffer())):(Je(t),await _t(r,t)?.catch(o=>me(o,t))),t[ge]?.()},Wt=e=>typeof e.then=="function",Vt=async(e,t,s={})=>{if(Wt(e))if(s.errorHandler)try{e=await e}catch(n){let o=await s.errorHandler(n);if(!o)return;e=o}else e=await e.catch(Qe);if(A in e)return Xe(e,t);let r=Ke(e.headers);if(e.body){let n=e.body.getReader(),o=[],i=!1,a;if(r["transfer-encoding"]!=="chunked"){let c=2;for(let l=0;l<c;l++){a||=n.read();let h=await $t(a).catch(u=>{console.error(u),i=!0});if(!h){if(l===1){await new Promise(u=>setTimeout(u)),c=3;continue}break}if(a=void 0,h.value&&o.push(h.value),h.done){i=!0;break}}i&&!("content-length"in r)&&(r["content-length"]=o.reduce((l,h)=>l+h.length,0))}t.writeHead(e.status,r),o.forEach(c=>{t.write(c)}),i?t.end():(o.length===0&&Je(t),await Ge(n,t,a))}else r[Nt]||(t.writeHead(e.status,r),t.end());t[ge]?.()},Gt=(e,t={})=>{let s=t.autoCleanupIncoming??!0;return t.overrideGlobalObjects!==!1&&global.Request!==F&&(Object.defineProperty(global,"Request",{value:F}),Object.defineProperty(global,"Response",{value:$})),async(r,n)=>{let o,i;try{i=Ft(r,t.hostname);let a=!s||r.method==="GET"||r.method==="HEAD";if(a||(r[We]=!0,r.on("end",()=>{a=!0}),r instanceof Lt&&(n[ge]=()=>{a||setTimeout(()=>{a||setTimeout(()=>{r.destroy(),n.destroy()})})})),n.on("close",()=>{i[H]&&(r.errored?i[H].abort(r.errored.toString()):n.writableFinished||i[H].abort("Client connection prematurely closed.")),a||setTimeout(()=>{a||setTimeout(()=>{r.destroy()})})}),o=e(i,{incoming:r,outgoing:n}),A in o)return Xe(o,n)}catch(a){if(o)return me(a,n);if(t.errorHandler){if(o=await t.errorHandler(i?a:Tt(a)),!o)return}else i?o=Qe(a):o=zt()}try{return await Vt(o,n,t)}catch(a){return me(a,n)}}},Kt=e=>{let t=e.fetch,s=Gt(t,{hostname:e.hostname,overrideGlobalObjects:e.overrideGlobalObjects,autoCleanupIncoming:e.autoCleanupIncoming});return(e.createServer||At)(e.serverOptions||{},s)},Ye=(e,t)=>{let s=Kt(e);return s.listen(e?.port??3e3,e.hostname,()=>{let r=s.address();t&&t(r)}),s};import{readFileSync as Qt,existsSync as Jt}from"node:fs";function Ze(){let e=process.env.MOLNOS_RUNTIME_CONFIG;if(!e||!Jt(e))return{molnos:{dataPath:"data"},server:{host:"localhost",port:3e3}};try{let t=Qt(e,"utf-8");return JSON.parse(t)}catch(t){return console.error("[loadRuntimeConfig] Failed to load runtime config:",t),{molnos:{dataPath:"data"},server:{host:"localhost",port:3e3}}}}var _=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),n=this.compileErrors(s,r),o=this.isSuccessful(s,n);return{errors:n,success:o}}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 n=e?.additionalProperties??!0,o=e?.required||[];r=this.checkForRequiredKeysErrors(o,t,r),r=this.checkForDisallowedProperties(Object.keys(t),Object.keys(e),r,n);for(let i in e){let a=o.includes(i)&&i!=="required",c=e[i],l=t[i],h=c.additionalProperties??!0;a&&(r=this.checkForRequiredKeysErrors(c.required||[],l,r)),this.isDefined(l)&&(this.handleValidation(i,l,c,s),r=this.checkForDisallowedProperties(Object.keys(l),Object.keys(c),r,h),this.handleNestedObject(l,c,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):[],n=this.findNonOverlappingElements(e,r),o=n.length>0?`Missing the required key: '${n.join(", ")}'!`:`Missing values for required keys: '${r.filter(i=>!t[i]).join(", ")}'!`;s.push({key:"",value:t,success:!1,error:o})}return s}checkForDisallowedProperties(e,t,s,r){if(!r){let n=this.findNonOverlappingElements(e,t);n.length>0&&s.push({key:`${t}`,value:e,success:!1,error:`Has additional (disallowed) properties: '${n.join(", ")}'!`})}return s}handleValidation(e,t,s,r){this.updatePropertyPath(e);let n=this.validateProperty(this.propertyPath,s,t);r.push(...n);let o=(a,c)=>{a.forEach(l=>{let h=this.validateProperty(this.propertyPath,c.items,l);r.push(...h)}),this.updatePropertyPath()},i=a=>{let c=Object.keys(a),l=this.propertyPath;c.forEach(h=>{if(this.updatePropertyPath(h,l),this.isArray(a[h])&&s[h]?.items!=null)o(a[h],s[h]);else{let u=this.validateProperty(this.propertyPath,s[h],a[h]);r.push(...u)}})};this.isArray(t)&&s.items!=null?o(t,s):this.isObject(t)?i(t):this.updatePropertyPath()}handleNestedObject(e,t,s,r){if(this.isObject(e)){let n=this.getNestedObjects(e);for(let o of n){let i=t[o],a=e[o];i&&typeof a=="object"&&this.validate(i,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(n=>{let{success:o,error:i}=n;return{key:e,value:s,success:o,error:i??""}})}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 n of s)n.condition()&&!n.validator()&&r.push({success:!1,error:n.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(o=>typeof o==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 te(e){try{return await e.req.json()}catch{return{}}}function E(e,t="An error occurred"){let s=e?.message||e||t,r=e?.cause?.statusCode||e?.statusCode||400;return{message:s,status:r}}function et(e,t,s={}){let r=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 n=e.roles.flatMap(i=>i?.policies?.flatMap(a=>(a?.permissions||[]).flatMap(l=>typeof l=="string"?l:l&&typeof l=="object"&&l.actions?l.actions:[]))||[]);if(!r.every(i=>n.includes(i)||n.includes("*")?!0:n.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 tt(e,t,s,r,n){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!==s)){if(!c.resource||!c.actions||c.actions.length===0)return;if(c.actions.includes(r)){if(c.targets&&c.targets.length>0){if(!n)return;if(!c.targets.includes(n))continue}return}}let i=n?`:${n}`:"",a=new Error(`Function bindings do not allow: ${t}.${s}.${r}${i}`);throw a.cause={statusCode:403},a}async function R(e,t,s,r,n,o,i){if(!t)return null;let a=e.get("user");if(!a){let l=e.req.header("authorization");if(!l){let u=new Error("Unauthorized: No authentication provided");throw u.cause={statusCode:401},u}let h=l.replace(/^Bearer\s+/i,"");if(a=await t.getUserFromToken(h),!a){let u=new Error("Unauthorized: Invalid token");throw u.cause={statusCode:401},u}}et(a,s,{});let c=e.req.header("x-function-bindings");if(c)try{let l=JSON.parse(c);tt(l,r,n,o,i)}catch(l){if(l.cause?.statusCode===403)throw l;let h=new Error("Invalid function bindings header");throw h.cause={statusCode:400},h}return a}var rt={properties:{service:{type:"string",minLength:1},level:{type:"string",enum:["info","warn","error","debug"]},message:{type:"string",minLength:1},metadata:{type:"object"}},required:["service","level","message"],additionalProperties:!1};var Yt=new _;async function st(e,t,s){try{let r=await te(e),n=Yt.test(rt,r);if(!n.success)return e.json({error:"Invalid input",details:n.errors},400);await R(e,s,"observability.event.create","observability","event","create");let{service:o,level:i,message:a,metadata:c}=r;if(!o)return e.json({error:"service is required"},400);if(!i)return e.json({error:"level is required"},400);if(!["info","warn","error","debug"].includes(i))return e.json({error:"level must be one of: info, warn, error, debug"},400);if(!a)return e.json({error:"message is required"},400);let l=await t.log({service:o,level:i,message:a,metadata:c});return e.json({success:!0,event:l},201)}catch(r){let{message:n,status:o}=E(r,"Error logging event");return e.json({error:n},o)}}async function nt(e,t,s){try{await R(e,s,"observability.event.read","observability","event","read");let r=e.req.query("startTime"),n=r?parseInt(r,10):void 0,o=e.req.query("endTime"),i=o?parseInt(o,10):void 0,a=e.req.query("service")||void 0,c=e.req.query("level")||void 0,l=e.req.query("search")||void 0,h=e.req.query("limit"),u=h?parseInt(h,10):1e3,f=e.req.query("offset"),m=f?parseInt(f,10):0,g=await t.query({startTime:n,endTime:i,service:a,level:c,search:l,limit:u,offset:m});return e.json({success:!0,count:g.length,events:g},200)}catch(r){let{message:n,status:o}=E(r,"Error querying events");return e.json({error:n},o)}}async function ot(e,t,s){try{await R(e,s,"observability.stats.read","observability","stats","read");let r=await t.getStats();return e.json({success:!0,stats:r},200)}catch(r){let{message:n,status:o}=E(r,"Error getting statistics");return e.json({error:n},o)}}var it={properties:{olderThanDays:{type:"number",minimum:1}},required:["olderThanDays"],additionalProperties:!1};var er=new _;async function at(e,t,s){try{let r=await te(e),n=er.test(it,r);if(!n.success)return e.json({error:"Invalid input",details:n.errors},400);await R(e,s,"observability.event.delete","observability","event","delete");let{olderThanDays:o}=r;if(!o)return e.json({error:"olderThanDays is required"},400);let i=await t.deleteOldLogs(o);return e.json({success:!0,deletedCount:i},200)}catch(r){let{message:n,status:o}=E(r,"Error cleaning up logs");return e.json({error:n},o)}}async function ct(e,t,s){try{return await R(e,s,"observability.buffer.write","observability","buffer","write"),await t.flush(),e.json({success:!0},200)}catch(r){let{message:n,status:o}=E(r,"Error flushing buffer");return e.json({error:n},o)}}var ve=class{logDir;currentLogFile;writeBuffer=[];bufferSize;flushInterval=null;constructor(t){this.logDir=t.path||"observability-data",this.bufferSize=t.bufferSize||100,this.currentLogFile=this.getLogFileName()}async start(){await S.mkdir(this.logDir,{recursive:!0}),this.flushInterval=setInterval(()=>{this.writeBuffer.length>0&&this.flush().catch(t=>console.error("Failed to flush log buffer:",t))},5e3)}async stop(){this.flushInterval&&(clearInterval(this.flushInterval),this.flushInterval=null),await this.flush()}getLogFileName(){let t=new Date().toISOString().split("T")[0];return N(this.logDir,`logs-${t}.ndjson`)}async log(t){let s={id:this.generateId(),timestamp:Date.now(),service:t.service,level:t.level,message:t.message,metadata:t.metadata};return this.writeBuffer.push(s),this.writeBuffer.length>=this.bufferSize&&await this.flush(),s}async flush(){if(this.writeBuffer.length===0)return;let t=this.getLogFileName(),s=[...this.writeBuffer];this.writeBuffer=[],t!==this.currentLogFile&&(this.currentLogFile=t);let r=`${s.map(n=>JSON.stringify(n)).join(`
|
|
2
|
+
var H=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",s=this.requests.get(r);return(!s||s.resetTime<t)&&(s={count:0,resetTime:t+this.windowMs},this.requests.set(r,s)),s.count++,s.count<=this.limit}getRemainingRequests(e){let t=Date.now(),r=e||"unknown",s=this.requests.get(r);return!s||s.resetTime<t?this.limit:Math.max(0,this.limit-s.count)}getResetTime(e){let t=Date.now(),r=e||"unknown",s=this.requests.get(r);return!s||s.resetTime<t?Math.floor((t+this.windowMs)/1e3):Math.floor(s.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 K}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(),s=t;return this.register("GET",e,r,s),this.register("POST",e,r,s),this.register("PUT",e,r,s),this.register("DELETE",e,r,s),this.register("PATCH",e,r,s),this.register("OPTIONS",e,r,s),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 s=this.pathPatterns.get(r.path);if(!s)continue;let i=s.pattern.exec(t);if(!i)continue;let n={};return s.paramNames.forEach((o,a)=>{n[o]=i[a+1]||""}),{route:r,params:n}}return null}async handle(e,t){let r=e.method||"GET",s=new K(e.url||"/",`http://${e.headers.host}`),i=s.pathname,n=this.match(r,i);if(!n)return null;let{route:o,params:a}=n,l={};s.searchParams.forEach((c,d)=>{l[d]=c});let u={req:e,res:t,params:a,query:l,body:e.body||{},headers:e.headers,path:i,state:{},raw:()=>t,binary:(c,d="application/octet-stream",h=200)=>({statusCode:h,body:c,headers:{"Content-Type":d,"Content-Length":c.length.toString()},isRaw:!0}),text:(c,d=200)=>({statusCode:d,body:c,headers:{"Content-Type":"text/plain"}}),form:(c,d=200)=>({statusCode:d,body:c,headers:{"Content-Type":"application/x-www-form-urlencoded"}}),json:(c,d=200)=>({statusCode:d,body:c,headers:{"Content-Type":"application/json"}}),html:(c,d=200)=>({statusCode:d,body:c,headers:{"Content-Type":"text/html"}}),redirect:(c,d=302)=>({statusCode:d,body:null,headers:{Location:c}}),status:function(c){return{raw:()=>t,binary:(d,h="application/octet-stream")=>({statusCode:c,body:d,headers:{"Content-Type":h,"Content-Length":d.length.toString()},isRaw:!0}),text:d=>({statusCode:c,body:d,headers:{"Content-Type":"text/plain"}}),json:d=>({statusCode:c,body:d,headers:{"Content-Type":"application/json"}}),html:d=>({statusCode:c,body:d,headers:{"Content-Type":"text/html"}}),form:d=>({statusCode:c,body:d,headers:{"Content-Type":"application/x-www-form-urlencoded"}}),redirect:(d,h=302)=>({statusCode:h,body:null,headers:{Location:d}}),status:d=>this.status(d)}}},f=[...this.globalMiddlewares,...o.middlewares];return this.executeMiddlewareChain(u,f,o.handler)}register(e,t,r,s=[]){return this.routes.push({method:e,path:t,handler:r,middlewares:s}),this.pathPatterns.set(t,this.createPathPattern(t)),this}createPathPattern(e){let t=[],r=e.replace(/\/:[^/]+/g,s=>{let i=s.slice(2);return t.push(i),"/([^/]+)"});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 s=0,i=async()=>{if(s<t.length){let n=t[s++];return n(e,i)}return r(e)};return i()}};var x=()=>({port:Number(process.env.PORT)||3e3,host:process.env.HOST||"0.0.0.0",useHttps:!1,useHttp2:!1,sslCert:"",sslKey:"",sslCa:"",debug:Y(process.env.DEBUG)||!1,maxBodySize:1048576,requestTimeout:3e4,rateLimit:{enabled:!0,requestsPerMinute:100},allowedDomains:["*"]});function Y(e){return e==="true"||e===!0}var O=class extends Error{constructor(e){super(e),this.name="ValidationError",this.message=e||"Validation did not pass",this.cause={statusCode:400}}};import{existsSync as ee,readFileSync as te}from"node:fs";var j=class{config={};options=[];validators=[];autoValidate=!0;constructor(e){let t=e?.configFilePath,r=e?.args||[],s=e?.config||{};this.options=e?.options||[],this.validators=e?.validators||[],e?.autoValidate!==void 0&&(this.autoValidate=e.autoValidate),this.config=this.createConfig(t,r,s)}deepMerge(e,t){let r={...e};for(let s in t)t[s]!==void 0&&(t[s]!==null&&typeof t[s]=="object"&&!Array.isArray(t[s])&&s in e&&e[s]!==null&&typeof e[s]=="object"&&!Array.isArray(e[s])?r[s]=this.deepMerge(e[s],t[s]):t[s]!==void 0&&(r[s]=t[s]));return r}setValueAtPath(e,t,r){let s=t.split("."),i=e;for(let o=0;o<s.length-1;o++){let a=s[o];!(a in i)||i[a]===null?i[a]={}:typeof i[a]!="object"&&(i[a]={}),i=i[a]}let n=s[s.length-1];i[n]=r}getValueAtPath(e,t){let r=t.split("."),s=e;for(let i of r){if(s==null)return;s=s[i]}return s}createConfig(e,t=[],r={}){let s={};for(let a of this.options)a.defaultValue!==void 0&&this.setValueAtPath(s,a.path,a.defaultValue);let i={};if(e&&ee(e))try{let a=te(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({},s);return o=this.deepMerge(o,i),o=this.deepMerge(o,r),o=this.deepMerge(o,n),o}parseCliArgs(e){let t={},r=e[0]?.endsWith("node")||e[0]?.endsWith("node.exe")?2:0;for(;r<e.length;){let s=e[r++],i=this.options.find(n=>n.flag===s);if(i)if(i.isFlag)this.setValueAtPath(t,i.path,!0);else if(r<e.length&&!e[r].startsWith("-")){let n=e[r++];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 ${s}`)}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 O(e.message);if(typeof r=="string")throw new O(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 s=this.deepMerge(r,t);this.setValueAtPath(this.config,e,s);return}}this.setValueAtPath(this.config,e,t)}getHelpText(){let e=`Available configuration options:
|
|
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 L={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 m=x(),q=e=>({configFilePath:"mikroserve.config.json",args:process.argv,options:[{flag:"--port",path:"port",defaultValue:m.port},{flag:"--host",path:"host",defaultValue:m.host},{flag:"--https",path:"useHttps",defaultValue:m.useHttps,isFlag:!0},{flag:"--http2",path:"useHttp2",defaultValue:m.useHttp2,isFlag:!0},{flag:"--cert",path:"sslCert",defaultValue:m.sslCert},{flag:"--key",path:"sslKey",defaultValue:m.sslKey},{flag:"--ca",path:"sslCa",defaultValue:m.sslCa},{flag:"--ratelimit",path:"rateLimit.enabled",defaultValue:m.rateLimit.enabled,isFlag:!0},{flag:"--rps",path:"rateLimit.requestsPerMinute",defaultValue:m.rateLimit.requestsPerMinute},{flag:"--allowed",path:"allowedDomains",defaultValue:m.allowedDomains,parser:L.array},{flag:"--debug",path:"debug",defaultValue:m.debug,isFlag:!0},{flag:"--max-body-size",path:"maxBodySize",defaultValue:m.maxBodySize},{flag:"--request-timeout",path:"requestTimeout",defaultValue:m.requestTimeout}],config:e});function F(e,t){let r=t.match(/boundary=(?:"([^"]+)"|([^;]+))/i);if(!r)throw new Error("Invalid multipart/form-data: missing boundary");let s=r[1]||r[2],i=Buffer.from(`--${s}`),n=Buffer.from(`--${s}--`),o={},a={},l=re(e,i);for(let u of l){if(u.length===0||u.equals(n.subarray(i.length)))continue;let f=se(u);if(!f)continue;let{name:c,filename:d,contentType:h,data:g}=f;if(d){let p={filename:d,contentType:h||"application/octet-stream",data:g,size:g.length};a[c]?Array.isArray(a[c])?a[c].push(p):a[c]=[a[c],p]:a[c]=p}else{let p=g.toString("utf8");o[c]?Array.isArray(o[c])?o[c].push(p):o[c]=[o[c],p]:o[c]=p}}return{fields:o,files:a}}function re(e,t){let r=[],s=0;for(;s<e.length;){let i=e.indexOf(t,s);if(i===-1)break;s!==i&&r.push(e.subarray(s,i)),s=i+t.length,s<e.length&&e[s]===13&&e[s+1]===10&&(s+=2)}return r}function se(e){let t=Buffer.from(`\r
|
|
9
|
+
\r
|
|
10
|
+
`),r=e.indexOf(t);if(r===-1)return null;let s=e.subarray(0,r),i=e.subarray(r+4),o=s.toString("utf8").split(`\r
|
|
11
|
+
`),a="",l="",u,f;for(let d of o){let h=d.toLowerCase();if(h.startsWith("content-disposition:")){a=d.substring(20).trim();let g=a.match(/name="([^"]+)"/);g&&(l=g[1]);let p=a.match(/filename="([^"]+)"/);p&&(u=p[1])}else h.startsWith("content-type:")&&(f=d.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:u,contentType:f,data:c}}import{readFileSync as S}from"fs";import A from"http";import ie from"http2";import oe from"https";var I=class{config;rateLimiter;router;shutdownHandlers=[];constructor(e){let t=new j(q(e||{})).get();t.debug&&console.log("Using configuration:",t),this.config=t,this.router=new k;let r=t.rateLimit.requestsPerMinute||x().rateLimit.requestsPerMinute;this.rateLimiter=new H(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 s=e.address(),i=this.config.useHttps||this.config.useHttp2?"https":"http";console.log(`MikroServe running at ${i}://${s.address!=="::"?s.address:"localhost"}:${s.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 ie.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 oe.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 A.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(),s=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(`${s} ${i}`),e.method==="OPTIONS"){if(t instanceof A.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(r,s,i)}}logDuration(e,t,r){let s=Date.now()-e;console.log(`${t} ${r} completed in ${s}ms`)}async parseBody(e){return new Promise((t,r)=>{let s=[],i=0,n=this.config.maxBodySize,o=!1,a=null,l=this.config.debug,u=e.headers["content-type"]||"";l&&console.log("Content-Type:",u),this.config.requestTimeout>0&&(a=setTimeout(()=>{o||(o=!0,l&&console.log("Request timeout exceeded"),r(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}`),r(new Error("Request body too large"));return}s.push(c)}}),e.on("end",()=>{if(!o){o=!0,f(),l&&console.log(`Request body complete: ${i} bytes`);try{if(s.length>0){let c=Buffer.concat(s);if(u.includes("application/json"))try{let d=c.toString("utf8");t(JSON.parse(d))}catch(d){r(new Error(`Invalid JSON in request body: ${d.message}`))}else if(u.includes("application/x-www-form-urlencoded")){let d=c.toString("utf8"),h={};new URLSearchParams(d).forEach((g,p)=>{h[p]=g}),t(h)}else if(u.includes("multipart/form-data"))try{let d=F(c,u);t(d)}catch(d){r(new Error(`Invalid multipart form data: ${d.message}`))}else this.isBinaryContentType(u)?t(c):t(c.toString("utf8"))}else t({})}catch(c){r(new Error(`Invalid request body: ${c}`))}}}),e.on("error",c=>{o||(o=!0,f(),r(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(r=>e.includes(r))}setCorsHeaders(e,t){let r=t.headers.origin,{allowedDomains:s=["*"]}=this.config;!r||s.length===0||s.includes("*")?e.setHeader("Access-Control-Allow-Origin","*"):s.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 A.ServerResponse)Object.entries(r).forEach(([s,i])=>{e.setHeader(s,i)});else{let s=e;Object.entries(r).forEach(([i,n])=>{s.setHeader(i,n)})}}respond(e,t){let r={...t.headers||{}};(i=>typeof i.writeHead=="function"&&typeof i.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(),s=()=>t(),i=o=>t(o),n=o=>t(o);this.shutdownHandlers=[r,s,i,n],process.on("SIGINT",r),process.on("SIGTERM",s),process.on("uncaughtException",i),process.on("unhandledRejection",n)}cleanupShutdownHandlers(){if(this.shutdownHandlers.length>0){let[e,t,r,s]=this.shutdownHandlers;process.removeListener("SIGINT",e),process.removeListener("SIGTERM",t),process.removeListener("uncaughtException",r),process.removeListener("unhandledRejection",s),this.shutdownHandlers=[]}}};import{createHash as fe}from"node:crypto";import{join as P}from"node:path";import{promises as b}from"node:fs";var C=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:s}=this.validate(e.properties,t),i=this.compileErrors(r,s),n=this.isSuccessful(r,i);return{errors:i,success:n}}compileErrors(e,t){let r=e.filter(s=>s.success===!1);return[...t,...r].flatMap(s=>s)}isSuccessful(e,t){return e.every(r=>r.success===!0)&&t.length===0}validate(e,t,r=[],s=[]){let i=e?.additionalProperties??!0,n=e?.required||[];s=this.checkForRequiredKeysErrors(n,t,s),s=this.checkForDisallowedProperties(Object.keys(t),Object.keys(e),s,i);for(let o in e){let a=n.includes(o)&&o!=="required",l=e[o],u=t[o],f=l.additionalProperties??!0;a&&(s=this.checkForRequiredKeysErrors(l.required||[],u,s)),this.isDefined(u)&&(this.handleValidation(o,u,l,r),s=this.checkForDisallowedProperties(Object.keys(u),Object.keys(l),s,f),this.handleNestedObject(u,l,r,s))}return{results:r,errors:s}}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 s=t?Object.keys(t):[],i=this.findNonOverlappingElements(e,s),n=i.length>0?`Missing the required key: '${i.join(", ")}'!`:`Missing values for required keys: '${s.filter(o=>!t[o]).join(", ")}'!`;r.push({key:"",value:t,success:!1,error:n})}return r}checkForDisallowedProperties(e,t,r,s){if(!s){let i=this.findNonOverlappingElements(e,t);i.length>0&&r.push({key:`${t}`,value:e,success:!1,error:`Has additional (disallowed) properties: '${i.join(", ")}'!`})}return r}handleValidation(e,t,r,s){this.updatePropertyPath(e);let i=this.validateProperty(this.propertyPath,r,t);s.push(...i);let n=(a,l)=>{a.forEach(u=>{let f=this.validateProperty(this.propertyPath,l.items,u);s.push(...f)}),this.updatePropertyPath()},o=a=>{let l=Object.keys(a),u=this.propertyPath;l.forEach(f=>{if(this.updatePropertyPath(f,u),this.isArray(a[f])&&r[f]?.items!=null)n(a[f],r[f]);else{let c=this.validateProperty(this.propertyPath,r[f],a[f]);s.push(...c)}})};this.isArray(t)&&r.items!=null?n(t,r):this.isObject(t)?o(t):this.updatePropertyPath()}handleNestedObject(e,t,r,s){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,r,s)}}}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(i=>{let{success:n,error:o}=i;return{key:e,value:r,success:n,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"}],s=[];for(let i of r)i.condition()&&!i.validator()&&s.push({success:!1,error:i.error});return s}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 s=e[r];t.properties.required.push(r),Array.isArray(s)?t.properties[r]=this.generateArraySchema(s):typeof s=="object"&&s!==null?t.properties[r]=this.generateNestedObjectSchema(s):t.properties[r]=this.generatePropertySchema(s)}return t}generateArraySchema(e){let t={type:"array"},r=e.filter(s=>s);if(r.length>0){let s=r[0];r.every(n=>typeof n==typeof s)?typeof s=="object"&&!Array.isArray(s)?t.items=this.generateNestedObjectSchema(s):t.items=this.generatePropertySchema(s):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 s=e[r];t.required.push(r),typeof s=="object"&&!Array.isArray(s)&&s!==null?t[r]=this.generateNestedObjectSchema(s):t[r]=this.generatePropertySchema(s)}return t}generatePropertySchema(e){let t=typeof e,r={type:t};return t==="string"&&(r.minLength=1),r}};async function R(e){return e.body||{}}function y(e,t="An error occurred"){let r=e?.message||e||t,s=e?.cause?.statusCode||e?.statusCode||400;return{message:r,status:s}}function V(e,t,r={}){let s=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(u=>typeof u=="string"?u:u&&typeof u=="object"&&u.actions?u.actions:[]))||[]);if(!s.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 D(e,t,r,s,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!==r)){if(!l.resource||!l.actions||l.actions.length===0)return;if(l.actions.includes(s)){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}.${r}.${s}${o}`);throw a.cause={statusCode:403},a}async function v(e,t,r,s,i,n,o){if(!t)return null;let a=e.state.user;if(!a){let u=e.headers.authorization;if(!u){let c=new Error("Unauthorized: No authentication provided");throw c.cause={statusCode:401},c}let f=u.replace(/^Bearer\s+/i,"");if(a=await t.getUserFromToken(f),!a){let c=new Error("Unauthorized: Invalid token");throw c.cause={statusCode:401},c}}V(a,r,{});let l=e.headers["x-function-bindings"];if(l)try{let u=Array.isArray(l)?l[0]:l,f=JSON.parse(u);D(f,s,i,n,o)}catch(u){if(u.cause?.statusCode===403)throw u;let f=new Error("Invalid function bindings header");throw f.cause={statusCode:400},f}return a}var N={properties:{service:{type:"string",minLength:1},level:{type:"string",enum:["info","warn","error","debug"]},message:{type:"string",minLength:1},metadata:{type:"object"}},required:["service","level","message"],additionalProperties:!1};var ae=new C;async function B(e,t,r){try{let s=await R(e),i=ae.test(N,s);if(!i.success)return e.json({error:"Invalid input",details:i.errors},400);await v(e,r,"observability.event.create","observability","event","create");let{service:n,level:o,message:a,metadata:l}=s;if(!n)return e.json({error:"service is required"},400);if(!o)return e.json({error:"level is required"},400);if(!["info","warn","error","debug"].includes(o))return e.json({error:"level must be one of: info, warn, error, debug"},400);if(!a)return e.json({error:"message is required"},400);let u=await t.log({service:n,level:o,message:a,metadata:l});return e.json({success:!0,event:u},201)}catch(s){let{message:i,status:n}=y(s,"Error logging event");return e.json({error:i},n)}}async function z(e,t,r){try{await v(e,r,"observability.event.read","observability","event","read");let s=e.query.startTime?parseInt(e.query.startTime,10):void 0,i=e.query.endTime?parseInt(e.query.endTime,10):void 0,n=e.query.service||void 0,o=e.query.level||void 0,a=e.query.search||void 0,l=e.query.limit?parseInt(e.query.limit,10):1e3,u=e.query.offset?parseInt(e.query.offset,10):0,f=await t.query({startTime:s,endTime:i,service:n,level:o,search:a,limit:l,offset:u});return e.json({success:!0,count:f.length,events:f},200)}catch(s){let{message:i,status:n}=y(s,"Error querying events");return e.json({error:i},n)}}async function U(e,t,r){try{await v(e,r,"observability.stats.read","observability","stats","read");let s=await t.getStats();return e.json({success:!0,stats:s},200)}catch(s){let{message:i,status:n}=y(s,"Error getting statistics");return e.json({error:i},n)}}var W={properties:{olderThanDays:{type:"number",minimum:1}},required:["olderThanDays"],additionalProperties:!1};var ce=new C;async function G(e,t,r){try{let s=await R(e),i=ce.test(W,s);if(!i.success)return e.json({error:"Invalid input",details:i.errors},400);await v(e,r,"observability.event.delete","observability","event","delete");let{olderThanDays:n}=s;if(!n)return e.json({error:"olderThanDays is required"},400);let o=await t.deleteOldLogs(n);return e.json({success:!0,deletedCount:o},200)}catch(s){let{message:i,status:n}=y(s,"Error cleaning up logs");return e.json({error:i},n)}}async function J(e,t,r){try{return await v(e,r,"observability.buffer.write","observability","buffer","write"),await t.flush(),e.json({success:!0},200)}catch(s){let{message:i,status:n}=y(s,"Error flushing buffer");return e.json({error:i},n)}}import{readFileSync as ue,existsSync as de}from"node:fs";function E(){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||!de(e))return t;try{let r=ue(e,"utf-8");return JSON.parse(r)}catch(r){return console.error("[loadRuntimeConfig] Failed to load runtime config:",r),t}}function _(e,t){let r={enabled:!1,requestsPerMinute:0};if(!t)return r;let s=t.services?.[e];return s||(t.global?t.global:r)}function X(e,t){let r=e?.api?.port;if(!r)throw new Error('Missing "port" input when create API service!');let s=E(),i=e?.dataPath||s.molnos.dataPath,n=e?.api?.host||s.server.host,o=e?.identityApiUrl!==void 0?e.identityApiUrl:s.identity.apiUrl,a=e?.debug||!1,l;return t&&(l=_(t,s.molnos.rateLimit)),{dataPath:i,api:{port:r,host:n},...o?{identityApiUrl:o}:{},...l?{rateLimit:l}:{},debug:a}}var T=class{baseUrl;authToken;constructor(t,r){this.baseUrl=t.replace(/\/$/,""),this.authToken=r}async createCustomRole(t,r,s,i){let n=await fetch(`${this.baseUrl}/identity/roles`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({roleId:t,name:r,description:s,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,r){let s=await fetch(`${this.baseUrl}/identity/roles/${t}`,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(r)});if(!s.ok){let i=await s.json();throw new Error(i.error||`Failed to update role: ${s.statusText}`)}}async deleteRole(t){let r=await fetch(`${this.baseUrl}/identity/roles/${t}`,{method:"DELETE",headers:this.getHeaders()});if(!r.ok){let s=await r.json();throw new Error(s.error||`Failed to delete role: ${r.statusText}`)}}async addServiceAccount(t,r,s){let i=await fetch(`${this.baseUrl}/identity/service-accounts`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({name:t,description:r,roles:s})});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 r=await fetch(`${this.baseUrl}/identity/service-accounts/${t}`,{method:"DELETE",headers:this.getHeaders()});if(!r.ok){let s=await r.json();throw new Error(s.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 Q(e){return e?new T(e):null}var $=class{logDir;currentLogFile;writeBuffer=[];bufferSize;flushInterval=null;constructor(t){this.logDir=t.path||"observability-data",this.bufferSize=t.bufferSize||100,this.currentLogFile=this.getLogFileName()}async start(){await b.mkdir(this.logDir,{recursive:!0}),this.flushInterval=setInterval(()=>{this.writeBuffer.length>0&&this.flush().catch(t=>console.error("Failed to flush log buffer:",t))},5e3)}async stop(){this.flushInterval&&(clearInterval(this.flushInterval),this.flushInterval=null),await this.flush()}getLogFileName(){let t=new Date().toISOString().split("T")[0];return P(this.logDir,`logs-${t}.ndjson`)}async log(t){let r={id:this.generateId(),timestamp:Date.now(),service:t.service,level:t.level,message:t.message,metadata:t.metadata};return this.writeBuffer.push(r),this.writeBuffer.length>=this.bufferSize&&await this.flush(),r}async flush(){if(this.writeBuffer.length===0)return;let t=this.getLogFileName(),r=[...this.writeBuffer];this.writeBuffer=[],t!==this.currentLogFile&&(this.currentLogFile=t);let s=`${r.map(i=>JSON.stringify(i)).join(`
|
|
3
12
|
`)}
|
|
4
|
-
`;await
|
|
5
|
-
`);for(let
|
|
13
|
+
`;await b.appendFile(this.currentLogFile,s,"utf8")}generateId(){return fe("sha256").update(`${Date.now()}-${Math.random()}`).digest("hex").substring(0,16)}async query(t={}){let{startTime:r,endTime:s,service:i,level:n,search:o,limit:a=1e3,offset:l=0}=t,u=await this.getLogFilesInRange(r,s),f=o?.toLowerCase(),c=[],d=0;for(let h of u){let g=P(this.logDir,h);try{let Z=(await b.readFile(g,"utf8")).trim().split(`
|
|
14
|
+
`);for(let M of Z)if(M)try{let w=JSON.parse(M);if(r&&w.timestamp<r||s&&w.timestamp>s||i&&!w.service.startsWith(i)||n&&w.level!==n||f&&!w.message?.toLowerCase().includes(f)&&!w.service?.toLowerCase().includes(f))continue;if(d<l){d++;continue}if(c.push(w),c.length>=a)return c}catch{}}catch{}}return c}async getLogFilesInRange(t,r){try{let i=(await b.readdir(this.logDir)).filter(o=>o.startsWith("logs-")&&o.endsWith(".ndjson"));return!t&&!r?i.sort().reverse():i.filter(o=>{let a=o.replace("logs-","").replace(".ndjson",""),l=new Date(a).getTime();return!(t&&l<t-864e5||r&&l>r+864e5)}).sort().reverse()}catch{return[]}}async getStats(){try{let r=(await b.readdir(this.logDir)).filter(i=>i.startsWith("logs-")&&i.endsWith(".ndjson")),s=await Promise.all(r.map(async i=>{let n=P(this.logDir,i),o=await b.stat(n);return{name:i,size:o.size,date:i.replace("logs-","").replace(".ndjson","")}}));return{totalLogFiles:r.length,logFiles:s.sort((i,n)=>n.date.localeCompare(i.date))}}catch{return{totalLogFiles:0,logFiles:[]}}}async deleteOldLogs(t){let r=Date.now()-t*864e5,i=(await b.readdir(this.logDir)).filter(o=>o.startsWith("logs-")&&o.endsWith(".ndjson")),n=0;for(let o of i){let a=o.replace("logs-","").replace(".ndjson","");if(new Date(a).getTime()<r){let u=P(this.logDir,o);await b.unlink(u),n++}}return n}};async function he(e){let t=e.dataPath||"data",r=P(t,"observability"),s=new $({path:r,bufferSize:100});await s.start();let i=Q(e.identityApiUrl),n=E(),o=new I({port:e.api.port||n.services.observability.port,host:e.api.host||n.services.observability.host,rateLimit:e.rateLimit||{enabled:!1,requestsPerMinute:0}});return o.post("/events",async l=>B(l,s,i)),o.get("/events",async l=>z(l,s,i)),o.get("/stats",async l=>U(l,s,i)),o.delete("/events/cleanup",async l=>G(l,s,i)),o.post("/flush",async l=>J(l,s,i)),{server:o.start(),observability:s}}if(import.meta.url===`file://${process.argv[1]}`){let e=E(),r=process.argv.slice(2).find(n=>n.startsWith("--port=")),s=r?parseInt(r.split("=")[1],10):e.services.observability.port,i=X({api:{port:s}},"observability");he(i)}export{$ as ObservabilityService,he as startServer};
|
package/dist/sites.mjs
CHANGED
|
@@ -1,2 +1,11 @@
|
|
|
1
1
|
// MolnOS Core - See LICENSE file for copyright and license details.
|
|
2
|
-
import{dirname as fr,join as E}from"node:path";import{existsSync as dr,rmSync as ae}from"node:fs";import{isAbsolute as pr,normalize as mr}from"node:path";var ie=(e,t,s)=>(r,o)=>{let n=-1;return a(0);async function a(i){if(i<=n)throw new Error("next() called multiple times");n=i;let c,l=!1,h;if(e[i]?(h=e[i][0][0],r.req.routeIndex=i):h=i===e.length&&o||void 0,h)try{c=await h(r,()=>a(i+1))}catch(u){if(u instanceof Error&&t)r.error=u,c=await t(u,r),l=!0;else throw u}else r.finalized===!1&&s&&(c=await s(r));return c&&(r.finalized===!1||l)&&(r.res=c),r}};var Oe=Symbol();var Ae=async(e,t=Object.create(null))=>{let{all:s=!1,dot:r=!1}=t,n=(e instanceof z?e.raw.headers:e.headers).get("Content-Type");return n?.startsWith("multipart/form-data")||n?.startsWith("application/x-www-form-urlencoded")?St(e,{all:s,dot:r}):{}};async function St(e,t){let s=await e.formData();return s?Ct(s,t):{}}function Ct(e,t){let s=Object.create(null);return e.forEach((r,o)=>{t.all||o.endsWith("[]")?Ot(s,o,r):s[o]=r}),t.dot&&Object.entries(s).forEach(([r,o])=>{r.includes(".")&&(At(s,r,o),delete s[r])}),s}var Ot=(e,t,s)=>{e[t]!==void 0?Array.isArray(e[t])?e[t].push(s):e[t]=[e[t],s]:t.endsWith("[]")?e[t]=[s]:e[t]=s},At=(e,t,s)=>{let r=e,o=t.split(".");o.forEach((n,a)=>{a===o.length-1?r[n]=s:((!r[n]||typeof r[n]!="object"||Array.isArray(r[n])||r[n]instanceof File)&&(r[n]=Object.create(null)),r=r[n])})};var le=e=>{let t=e.split("/");return t[0]===""&&t.shift(),t},Ie=e=>{let{groups:t,path:s}=It(e),r=le(s);return Tt(r,t)},It=e=>{let t=[];return e=e.replace(/\{[^}]+\}/g,(s,r)=>{let o=`@${r}`;return t.push([o,s]),o}),{groups:t,path:e}},Tt=(e,t)=>{for(let s=t.length-1;s>=0;s--){let[r]=t[s];for(let o=e.length-1;o>=0;o--)if(e[o].includes(r)){e[o]=e[o].replace(r,t[s][1]);break}}return e},V={},Te=(e,t)=>{if(e==="*")return"*";let s=e.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);if(s){let r=`${e}#${t}`;return V[r]||(s[2]?V[r]=t&&t[0]!==":"&&t[0]!=="*"?[r,s[1],new RegExp(`^${s[2]}(?=/${t})`)]:[e,s[1],new RegExp(`^${s[2]}$`)]:V[r]=[e,s[1],!0]),V[r]}return null},W=(e,t)=>{try{return t(e)}catch{return e.replace(/(?:%[0-9A-Fa-f]{2})+/g,s=>{try{return t(s)}catch{return s}})}},Ht=e=>W(e,decodeURI),he=e=>{let t=e.url,s=t.indexOf("/",t.indexOf(":")+4),r=s;for(;r<t.length;r++){let o=t.charCodeAt(r);if(o===37){let n=t.indexOf("?",r),a=t.slice(s,n===-1?void 0:n);return Ht(a.includes("%25")?a.replace(/%25/g,"%2525"):a)}else if(o===63)break}return t.slice(s,r)};var He=e=>{let t=he(e);return t.length>1&&t.at(-1)==="/"?t.slice(0,-1):t},j=(e,t,...s)=>(s.length&&(t=j(t,...s)),`${e?.[0]==="/"?"":"/"}${e}${t==="/"?"":`${e?.at(-1)==="/"?"":"/"}${t?.[0]==="/"?t.slice(1):t}`}`),G=e=>{if(e.charCodeAt(e.length-1)!==63||!e.includes(":"))return null;let t=e.split("/"),s=[],r="";return t.forEach(o=>{if(o!==""&&!/\:/.test(o))r+="/"+o;else if(/\:/.test(o))if(/\?/.test(o)){s.length===0&&r===""?s.push("/"):s.push(r);let n=o.replace("?","");r+="/"+n,s.push(r)}else r+="/"+o}),s.filter((o,n,a)=>a.indexOf(o)===n)},ce=e=>/[%+]/.test(e)?(e.indexOf("+")!==-1&&(e=e.replace(/\+/g," ")),e.indexOf("%")!==-1?W(e,ue):e):e,Me=(e,t,s)=>{let r;if(!s&&t&&!/[%+]/.test(t)){let a=e.indexOf("?",8);if(a===-1)return;for(e.startsWith(t,a+1)||(a=e.indexOf(`&${t}`,a+1));a!==-1;){let i=e.charCodeAt(a+t.length+1);if(i===61){let c=a+t.length+2,l=e.indexOf("&",c);return ce(e.slice(c,l===-1?void 0:l))}else if(i==38||isNaN(i))return"";a=e.indexOf(`&${t}`,a+1)}if(r=/[%+]/.test(e),!r)return}let o={};r??=/[%+]/.test(e);let n=e.indexOf("?",8);for(;n!==-1;){let a=e.indexOf("&",n+1),i=e.indexOf("=",n);i>a&&a!==-1&&(i=-1);let c=e.slice(n+1,i===-1?a===-1?void 0:a:i);if(r&&(c=ce(c)),n=a,c==="")continue;let l;i===-1?l="":(l=e.slice(i+1,a===-1?void 0:a),r&&(l=ce(l))),s?(o[c]&&Array.isArray(o[c])||(o[c]=[]),o[c].push(l)):o[c]??=l}return t?o[t]:o},ke=Me,$e=(e,t)=>Me(e,t,!0),ue=decodeURIComponent;var _e=e=>W(e,ue),z=class{raw;#t;#e;routeIndex=0;path;bodyCache={};constructor(e,t="/",s=[[]]){this.raw=e,this.path=t,this.#e=s,this.#t={}}param(e){return e?this.#r(e):this.#n()}#r(e){let t=this.#e[0][this.routeIndex][1][e],s=this.#o(t);return s&&/\%/.test(s)?_e(s):s}#n(){let e={},t=Object.keys(this.#e[0][this.routeIndex][1]);for(let s of t){let r=this.#o(this.#e[0][this.routeIndex][1][s]);r!==void 0&&(e[s]=/\%/.test(r)?_e(r):r)}return e}#o(e){return this.#e[1]?this.#e[1][e]:e}query(e){return ke(this.url,e)}queries(e){return $e(this.url,e)}header(e){if(e)return this.raw.headers.get(e)??void 0;let t={};return this.raw.headers.forEach((s,r)=>{t[r]=s}),t}async parseBody(e){return this.bodyCache.parsedBody??=await Ae(this,e)}#s=e=>{let{bodyCache:t,raw:s}=this,r=t[e];if(r)return r;let o=Object.keys(t)[0];return o?t[o].then(n=>(o==="json"&&(n=JSON.stringify(n)),new Response(n)[e]())):t[e]=s[e]()};json(){return this.#s("text").then(e=>JSON.parse(e))}text(){return this.#s("text")}arrayBuffer(){return this.#s("arrayBuffer")}blob(){return this.#s("blob")}formData(){return this.#s("formData")}addValidatedData(e,t){this.#t[e]=t}valid(e){return this.#t[e]}get url(){return this.raw.url}get method(){return this.raw.method}get[Oe](){return this.#e}get matchedRoutes(){return this.#e[0].map(([[,e]])=>e)}get routePath(){return this.#e[0].map(([[,e]])=>e)[this.routeIndex].path}};var Le={Stringify:1,BeforeStream:2,Stream:3},Mt=(e,t)=>{let s=new String(e);return s.isEscaped=!0,s.callbacks=t,s};var fe=async(e,t,s,r,o)=>{typeof e=="object"&&!(e instanceof String)&&(e instanceof Promise||(e=e.toString()),e instanceof Promise&&(e=await e));let n=e.callbacks;if(!n?.length)return Promise.resolve(e);o?o[0]+=e:o=[e];let a=Promise.all(n.map(i=>i({phase:t,buffer:o,context:r}))).then(i=>Promise.all(i.filter(Boolean).map(c=>fe(c,t,!1,r,o))).then(()=>o[0]));return s?Mt(await a,n):a};var kt="text/plain; charset=UTF-8",de=(e,t)=>({"Content-Type":e,...t}),De=class{#t;#e;env={};#r;finalized=!1;error;#n;#o;#s;#h;#c;#l;#i;#u;#f;constructor(e,t){this.#t=e,t&&(this.#o=t.executionCtx,this.env=t.env,this.#l=t.notFoundHandler,this.#f=t.path,this.#u=t.matchResult)}get req(){return this.#e??=new z(this.#t,this.#f,this.#u),this.#e}get event(){if(this.#o&&"respondWith"in this.#o)return this.#o;throw Error("This context has no FetchEvent")}get executionCtx(){if(this.#o)return this.#o;throw Error("This context has no ExecutionContext")}get res(){return this.#s||=new Response(null,{headers:this.#i??=new Headers})}set res(e){if(this.#s&&e){e=new Response(e.body,e);for(let[t,s]of this.#s.headers.entries())if(t!=="content-type")if(t==="set-cookie"){let r=this.#s.headers.getSetCookie();e.headers.delete("set-cookie");for(let o of r)e.headers.append("set-cookie",o)}else e.headers.set(t,s)}this.#s=e,this.finalized=!0}render=(...e)=>(this.#c??=t=>this.html(t),this.#c(...e));setLayout=e=>this.#h=e;getLayout=()=>this.#h;setRenderer=e=>{this.#c=e};header=(e,t,s)=>{this.finalized&&(this.#s=new Response(this.#s.body,this.#s));let r=this.#s?this.#s.headers:this.#i??=new Headers;t===void 0?r.delete(e):s?.append?r.append(e,t):r.set(e,t)};status=e=>{this.#n=e};set=(e,t)=>{this.#r??=new Map,this.#r.set(e,t)};get=e=>this.#r?this.#r.get(e):void 0;get var(){return this.#r?Object.fromEntries(this.#r):{}}#a(e,t,s){let r=this.#s?new Headers(this.#s.headers):this.#i??new Headers;if(typeof t=="object"&&"headers"in t){let n=t.headers instanceof Headers?t.headers:new Headers(t.headers);for(let[a,i]of n)a.toLowerCase()==="set-cookie"?r.append(a,i):r.set(a,i)}if(s)for(let[n,a]of Object.entries(s))if(typeof a=="string")r.set(n,a);else{r.delete(n);for(let i of a)r.append(n,i)}let o=typeof t=="number"?t:t?.status??this.#n;return new Response(e,{status:o,headers:r})}newResponse=(...e)=>this.#a(...e);body=(e,t,s)=>this.#a(e,t,s);text=(e,t,s)=>!this.#i&&!this.#n&&!t&&!s&&!this.finalized?new Response(e):this.#a(e,t,de(kt,s));json=(e,t,s)=>this.#a(JSON.stringify(e),t,de("application/json",s));html=(e,t,s)=>{let r=o=>this.#a(o,t,de("text/html; charset=UTF-8",s));return typeof e=="object"?fe(e,Le.Stringify,!1,{}).then(r):r(e)};redirect=(e,t)=>{let s=String(e);return this.header("Location",/[^\x00-\xFF]/.test(s)?encodeURI(s):s),this.newResponse(null,t??302)};notFound=()=>(this.#l??=()=>new Response,this.#l(this))};var m="ALL",qe="all",Fe=["get","post","put","delete","options","patch"],K="Can not add a route since the matcher is already built.",X=class extends Error{};var Ne="__COMPOSED_HANDLER";var $t=e=>e.text("404 Not Found",404),Be=(e,t)=>{if("getResponse"in e){let s=e.getResponse();return t.newResponse(s.body,s)}return console.error(e),t.text("Internal Server Error",500)},Ue=class ze{get;post;put;delete;options;patch;all;on;use;router;getPath;_basePath="/";#t="/";routes=[];constructor(t={}){[...Fe,qe].forEach(n=>{this[n]=(a,...i)=>(typeof a=="string"?this.#t=a:this.#n(n,this.#t,a),i.forEach(c=>{this.#n(n,this.#t,c)}),this)}),this.on=(n,a,...i)=>{for(let c of[a].flat()){this.#t=c;for(let l of[n].flat())i.map(h=>{this.#n(l.toUpperCase(),this.#t,h)})}return this},this.use=(n,...a)=>(typeof n=="string"?this.#t=n:(this.#t="*",a.unshift(n)),a.forEach(i=>{this.#n(m,this.#t,i)}),this);let{strict:r,...o}=t;Object.assign(this,o),this.getPath=r??!0?t.getPath??he:He}#e(){let t=new ze({router:this.router,getPath:this.getPath});return t.errorHandler=this.errorHandler,t.#r=this.#r,t.routes=this.routes,t}#r=$t;errorHandler=Be;route(t,s){let r=this.basePath(t);return s.routes.map(o=>{let n;s.errorHandler===Be?n=o.handler:(n=async(a,i)=>(await ie([],s.errorHandler)(a,()=>o.handler(a,i))).res,n[Ne]=o.handler),r.#n(o.method,o.path,n)}),this}basePath(t){let s=this.#e();return s._basePath=j(this._basePath,t),s}onError=t=>(this.errorHandler=t,this);notFound=t=>(this.#r=t,this);mount(t,s,r){let o,n;r&&(typeof r=="function"?n=r:(n=r.optionHandler,r.replaceRequest===!1?o=c=>c:o=r.replaceRequest));let a=n?c=>{let l=n(c);return Array.isArray(l)?l:[l]}:c=>{let l;try{l=c.executionCtx}catch{}return[c.env,l]};o||=(()=>{let c=j(this._basePath,t),l=c==="/"?0:c.length;return h=>{let u=new URL(h.url);return u.pathname=u.pathname.slice(l)||"/",new Request(u,h)}})();let i=async(c,l)=>{let h=await s(o(c.req.raw),...a(c));if(h)return h;await l()};return this.#n(m,j(t,"*"),i),this}#n(t,s,r){t=t.toUpperCase(),s=j(this._basePath,s);let o={basePath:this._basePath,path:s,method:t,handler:r};this.router.add(t,s,[r,o]),this.routes.push(o)}#o(t,s){if(t instanceof Error)return this.errorHandler(t,s);throw t}#s(t,s,r,o){if(o==="HEAD")return(async()=>new Response(null,await this.#s(t,s,r,"GET")))();let n=this.getPath(t,{env:r}),a=this.router.match(o,n),i=new De(t,{path:n,matchResult:a,env:r,executionCtx:s,notFoundHandler:this.#r});if(a[0].length===1){let l;try{l=a[0][0][0][0](i,async()=>{i.res=await this.#r(i)})}catch(h){return this.#o(h,i)}return l instanceof Promise?l.then(h=>h||(i.finalized?i.res:this.#r(i))).catch(h=>this.#o(h,i)):l??this.#r(i)}let c=ie(a[0],this.errorHandler,this.#r);return(async()=>{try{let l=await c(i);if(!l.finalized)throw new Error("Context is not finalized. Did you forget to return a Response object or `await next()`?");return l.res}catch(l){return this.#o(l,i)}})()}fetch=(t,...s)=>this.#s(t,s[1],s[0],t.method);request=(t,s,r,o)=>t instanceof Request?this.fetch(s?new Request(t,s):t,r,o):(t=t.toString(),this.fetch(new Request(/^https?:\/\//.test(t)?t:`http://localhost${j("/",t)}`,s),r,o));fire=()=>{addEventListener("fetch",t=>{t.respondWith(this.#s(t.request,t,void 0,t.request.method))})}};var J=[];function pe(e,t){let s=this.buildAllMatchers(),r=((o,n)=>{let a=s[o]||s[m],i=a[2][n];if(i)return i;let c=n.match(a[0]);if(!c)return[[],J];let l=c.indexOf("",1);return[a[1][l],c]});return this.match=r,r(e,t)}var Z="[^/]+",L=".*",D="(?:|/.*)",S=Symbol(),_t=new Set(".\\+*[^]$()");function Lt(e,t){return e.length===1?t.length===1?e<t?-1:1:-1:t.length===1||e===L||e===D?1:t===L||t===D?-1:e===Z?1:t===Z?-1:e.length===t.length?e<t?-1:1:t.length-e.length}var Ve=class me{#t;#e;#r=Object.create(null);insert(t,s,r,o,n){if(t.length===0){if(this.#t!==void 0)throw S;if(n)return;this.#t=s;return}let[a,...i]=t,c=a==="*"?i.length===0?["","",L]:["","",Z]:a==="/*"?["","",D]:a.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/),l;if(c){let h=c[1],u=c[2]||Z;if(h&&c[2]&&(u===".*"||(u=u.replace(/^\((?!\?:)(?=[^)]+\)$)/,"(?:"),/\((?!\?:)/.test(u))))throw S;if(l=this.#r[u],!l){if(Object.keys(this.#r).some(p=>p!==L&&p!==D))throw S;if(n)return;l=this.#r[u]=new me,h!==""&&(l.#e=o.varIndex++)}!n&&h!==""&&r.push([h,l.#e])}else if(l=this.#r[a],!l){if(Object.keys(this.#r).some(h=>h.length>1&&h!==L&&h!==D))throw S;if(n)return;l=this.#r[a]=new me}l.insert(i,s,r,o,n)}buildRegExpStr(){let s=Object.keys(this.#r).sort(Lt).map(r=>{let o=this.#r[r];return(typeof o.#e=="number"?`(${r})@${o.#e}`:_t.has(r)?`\\${r}`:r)+o.buildRegExpStr()});return typeof this.#t=="number"&&s.unshift(`#${this.#t}`),s.length===0?"":s.length===1?s[0]:"(?:"+s.join("|")+")"}};var We=class{#t={varIndex:0};#e=new Ve;insert(e,t,s){let r=[],o=[];for(let a=0;;){let i=!1;if(e=e.replace(/\{[^}]+\}/g,c=>{let l=`@\\${a}`;return o[a]=[l,c],a++,i=!0,l}),!i)break}let n=e.match(/(?::[^\/]+)|(?:\/\*$)|./g)||[];for(let a=o.length-1;a>=0;a--){let[i]=o[a];for(let c=n.length-1;c>=0;c--)if(n[c].indexOf(i)!==-1){n[c]=n[c].replace(i,o[a][1]);break}}return this.#e.insert(n,t,r,this.#t,s),r}buildRegExp(){let e=this.#e.buildRegExpStr();if(e==="")return[/^$/,[],[]];let t=0,s=[],r=[];return e=e.replace(/#(\d+)|@(\d+)|\.\*\$/g,(o,n,a)=>n!==void 0?(s[++t]=Number(n),"$()"):(a!==void 0&&(r[Number(a)]=++t),"")),[new RegExp(`^${e}`),s,r]}};var Dt=[/^$/,[],Object.create(null)],Ge=Object.create(null);function Ke(e){return Ge[e]??=new RegExp(e==="*"?"":`^${e.replace(/\/\*$|([.\\+*[^\]$()])/g,(t,s)=>s?`\\${s}`:"(?:|/.*)")}$`)}function qt(){Ge=Object.create(null)}function Ft(e){let t=new We,s=[];if(e.length===0)return Dt;let r=e.map(l=>[!/\*|\/:/.test(l[0]),...l]).sort(([l,h],[u,p])=>l?1:u?-1:h.length-p.length),o=Object.create(null);for(let l=0,h=-1,u=r.length;l<u;l++){let[p,d,g]=r[l];p?o[d]=[g.map(([y])=>[y,Object.create(null)]),J]:h++;let f;try{f=t.insert(d,h,p)}catch(y){throw y===S?new X(d):y}p||(s[h]=g.map(([y,v])=>{let B=Object.create(null);for(v-=1;v>=0;v--){let[U,w]=f[v];B[U]=w}return[y,B]}))}let[n,a,i]=t.buildRegExp();for(let l=0,h=s.length;l<h;l++)for(let u=0,p=s[l].length;u<p;u++){let d=s[l][u]?.[1];if(!d)continue;let g=Object.keys(d);for(let f=0,y=g.length;f<y;f++)d[g[f]]=i[d[g[f]]]}let c=[];for(let l in a)c[l]=s[a[l]];return[n,c,o]}function A(e,t){if(e){for(let s of Object.keys(e).sort((r,o)=>o.length-r.length))if(Ke(s).test(t))return[...e[s]]}}var Q=class{name="RegExpRouter";#t;#e;constructor(){this.#t={[m]:Object.create(null)},this.#e={[m]:Object.create(null)}}add(e,t,s){let r=this.#t,o=this.#e;if(!r||!o)throw new Error(K);r[e]||[r,o].forEach(i=>{i[e]=Object.create(null),Object.keys(i[m]).forEach(c=>{i[e][c]=[...i[m][c]]})}),t==="/*"&&(t="*");let n=(t.match(/\/:/g)||[]).length;if(/\*$/.test(t)){let i=Ke(t);e===m?Object.keys(r).forEach(c=>{r[c][t]||=A(r[c],t)||A(r[m],t)||[]}):r[e][t]||=A(r[e],t)||A(r[m],t)||[],Object.keys(r).forEach(c=>{(e===m||e===c)&&Object.keys(r[c]).forEach(l=>{i.test(l)&&r[c][l].push([s,n])})}),Object.keys(o).forEach(c=>{(e===m||e===c)&&Object.keys(o[c]).forEach(l=>i.test(l)&&o[c][l].push([s,n]))});return}let a=G(t)||[t];for(let i=0,c=a.length;i<c;i++){let l=a[i];Object.keys(o).forEach(h=>{(e===m||e===h)&&(o[h][l]||=[...A(r[h],l)||A(r[m],l)||[]],o[h][l].push([s,n-c+i+1]))})}}match=pe;buildAllMatchers(){let e=Object.create(null);return Object.keys(this.#e).concat(Object.keys(this.#t)).forEach(t=>{e[t]||=this.#r(t)}),this.#t=this.#e=void 0,qt(),e}#r(e){let t=[],s=e===m;return[this.#t,this.#e].forEach(r=>{let o=r[e]?Object.keys(r[e]).map(n=>[n,r[e][n]]):[];o.length!==0?(s||=!0,t.push(...o)):e!==m&&t.push(...Object.keys(r[m]).map(n=>[n,r[m][n]]))}),s?Ft(t):null}};var ye=class{name="SmartRouter";#t=[];#e=[];constructor(e){this.#t=e.routers}add(e,t,s){if(!this.#e)throw new Error(K);this.#e.push([e,t,s])}match(e,t){if(!this.#e)throw new Error("Fatal error");let s=this.#t,r=this.#e,o=s.length,n=0,a;for(;n<o;n++){let i=s[n];try{for(let c=0,l=r.length;c<l;c++)i.add(...r[c]);a=i.match(e,t)}catch(c){if(c instanceof X)continue;throw c}this.match=i.match.bind(i),this.#t=[i],this.#e=void 0;break}if(n===o)throw new Error("Fatal error");return this.name=`SmartRouter + ${this.activeRouter.name}`,a}get activeRouter(){if(this.#e||this.#t.length!==1)throw new Error("No active router has been determined yet.");return this.#t[0]}};var q=Object.create(null),Xe=class Je{#t;#e;#r;#n=0;#o=q;constructor(t,s,r){if(this.#e=r||Object.create(null),this.#t=[],t&&s){let o=Object.create(null);o[t]={handler:s,possibleKeys:[],score:0},this.#t=[o]}this.#r=[]}insert(t,s,r){this.#n=++this.#n;let o=this,n=Ie(s),a=[];for(let i=0,c=n.length;i<c;i++){let l=n[i],h=n[i+1],u=Te(l,h),p=Array.isArray(u)?u[0]:l;if(p in o.#e){o=o.#e[p],u&&a.push(u[1]);continue}o.#e[p]=new Je,u&&(o.#r.push(u),a.push(u[1])),o=o.#e[p]}return o.#t.push({[t]:{handler:r,possibleKeys:a.filter((i,c,l)=>l.indexOf(i)===c),score:this.#n}}),o}#s(t,s,r,o){let n=[];for(let a=0,i=t.#t.length;a<i;a++){let c=t.#t[a],l=c[s]||c[m],h={};if(l!==void 0&&(l.params=Object.create(null),n.push(l),r!==q||o&&o!==q))for(let u=0,p=l.possibleKeys.length;u<p;u++){let d=l.possibleKeys[u],g=h[l.score];l.params[d]=o?.[d]&&!g?o[d]:r[d]??o?.[d],h[l.score]=!0}}return n}search(t,s){let r=[];this.#o=q;let n=[this],a=le(s),i=[];for(let c=0,l=a.length;c<l;c++){let h=a[c],u=c===l-1,p=[];for(let d=0,g=n.length;d<g;d++){let f=n[d],y=f.#e[h];y&&(y.#o=f.#o,u?(y.#e["*"]&&r.push(...this.#s(y.#e["*"],t,f.#o)),r.push(...this.#s(y,t,f.#o))):p.push(y));for(let v=0,B=f.#r.length;v<B;v++){let U=f.#r[v],w=f.#o===q?{}:{...f.#o};if(U==="*"){let x=f.#e["*"];x&&(r.push(...this.#s(x,t,f.#o)),x.#o=w,p.push(x));continue}let[Pt,Ce,_]=U;if(!h&&!(_ instanceof RegExp))continue;let b=f.#e[Pt],Rt=a.slice(c).join("/");if(_ instanceof RegExp){let x=_.exec(Rt);if(x){if(w[Ce]=x[0],r.push(...this.#s(b,t,f.#o,w)),Object.keys(b.#e).length){b.#o=w;let jt=x[0].match(/\//)?.length??0;(i[jt]||=[]).push(b)}continue}}(_===!0||_.test(h))&&(w[Ce]=h,u?(r.push(...this.#s(b,t,w,f.#o)),b.#e["*"]&&r.push(...this.#s(b.#e["*"],t,w,f.#o))):(b.#o=w,p.push(b)))}}n=p.concat(i.shift()??[])}return r.length>1&&r.sort((c,l)=>c.score-l.score),[r.map(({handler:c,params:l})=>[c,l])]}};var ge=class{name="TrieRouter";#t;constructor(){this.#t=new Xe}add(e,t,s){let r=G(t);if(r){for(let o=0,n=r.length;o<n;o++)this.#t.insert(e,r[o],s);return}this.#t.insert(e,t,s)}match(e,t){return this.#t.search(e,t)}};var ve=class extends Ue{constructor(e={}){super(e),this.router=e.router??new ye({routers:[new Q,new ge]})}};import{mkdir as Re,writeFile as yr,readFile as gr,stat as gt}from"node:fs/promises";import{randomBytes as vr}from"node:crypto";import{createServer as Nt}from"http";import{Http2ServerRequest as Bt}from"http2";import{Http2ServerRequest as we}from"http2";import{Readable as Ze}from"stream";import er from"crypto";var C=class extends Error{constructor(e,t){super(e,t),this.name="RequestError"}},Ut=e=>e instanceof C?e:new C(e.message,{cause:e}),zt=global.Request,F=class extends zt{constructor(e,t){typeof e=="object"&&H in e&&(e=e[H]()),typeof t?.body?.getReader<"u"&&(t.duplex??="half"),super(e,t)}},Vt=e=>{let t=[],s=e.rawHeaders;for(let r=0;r<s.length;r+=2){let{[r]:o,[r+1]:n}=s;o.charCodeAt(0)!==58&&t.push([o,n])}return new Headers(t)},Ye=Symbol("wrapBodyStream"),Wt=(e,t,s,r,o)=>{let n={method:e,headers:s,signal:o.signal};if(e==="TRACE"){n.method="GET";let a=new F(t,n);return Object.defineProperty(a,"method",{get(){return"TRACE"}}),a}if(!(e==="GET"||e==="HEAD"))if("rawBody"in r&&r.rawBody instanceof Buffer)n.body=new ReadableStream({start(a){a.enqueue(r.rawBody),a.close()}});else if(r[Ye]){let a;n.body=new ReadableStream({async pull(i){try{a||=Ze.toWeb(r).getReader();let{done:c,value:l}=await a.read();c?i.close():i.enqueue(l)}catch(c){i.error(c)}}})}else n.body=Ze.toWeb(r);return new F(t,n)},H=Symbol("getRequestCache"),Gt=Symbol("requestCache"),Y=Symbol("incomingKey"),ee=Symbol("urlKey"),Kt=Symbol("headersKey"),T=Symbol("abortControllerKey"),Xt=Symbol("getAbortController"),te={get method(){return this[Y].method||"GET"},get url(){return this[ee]},get headers(){return this[Kt]||=Vt(this[Y])},[Xt](){return this[H](),this[T]},[H](){return this[T]||=new AbortController,this[Gt]||=Wt(this.method,this[ee],this.headers,this[Y],this[T])}};["body","bodyUsed","cache","credentials","destination","integrity","mode","redirect","referrer","referrerPolicy","signal","keepalive"].forEach(e=>{Object.defineProperty(te,e,{get(){return this[H]()[e]}})});["arrayBuffer","blob","clone","formData","json","text"].forEach(e=>{Object.defineProperty(te,e,{value:function(){return this[H]()[e]()}})});Object.setPrototypeOf(te,F.prototype);var Jt=(e,t)=>{let s=Object.create(te);s[Y]=e;let r=e.url||"";if(r[0]!=="/"&&(r.startsWith("http://")||r.startsWith("https://"))){if(e instanceof we)throw new C("Absolute URL for :path is not allowed in HTTP/2");try{let i=new URL(r);s[ee]=i.href}catch(i){throw new C("Invalid absolute URL",{cause:i})}return s}let o=(e instanceof we?e.authority:e.headers.host)||t;if(!o)throw new C("Missing host header");let n;if(e instanceof we){if(n=e.scheme,!(n==="http"||n==="https"))throw new C("Unsupported scheme")}else n=e.socket&&e.socket.encrypted?"https":"http";let a=new URL(`${n}://${o}${r}`);if(a.hostname.length!==o.length&&a.hostname!==o.replace(/:\d+$/,""))throw new C("Invalid host header");return s[ee]=a.href,s},Qe=Symbol("responseCache"),I=Symbol("getResponseCache"),O=Symbol("cache"),Ee=global.Response,N=class et{#t;#e;[I](){return delete this[O],this[Qe]||=new Ee(this.#t,this.#e)}constructor(t,s){let r;if(this.#t=t,s instanceof et){let o=s[Qe];if(o){this.#e=o,this[I]();return}else this.#e=s.#e,r=new Headers(s.#e.headers)}else this.#e=s;(typeof t=="string"||typeof t?.getReader<"u"||t instanceof Blob||t instanceof Uint8Array)&&(r||=s?.headers||{"content-type":"text/plain; charset=UTF-8"},this[O]=[s?.status||200,t,r])}get headers(){let t=this[O];return t?(t[2]instanceof Headers||(t[2]=new Headers(t[2])),t[2]):this[I]().headers}get status(){return this[O]?.[0]??this[I]().status}get ok(){let t=this.status;return t>=200&&t<300}};["body","bodyUsed","redirected","statusText","trailers","type","url"].forEach(e=>{Object.defineProperty(N.prototype,e,{get(){return this[I]()[e]}})});["arrayBuffer","blob","clone","formData","json","text"].forEach(e=>{Object.defineProperty(N.prototype,e,{value:function(){return this[I]()[e]()}})});Object.setPrototypeOf(N,Ee);Object.setPrototypeOf(N.prototype,Ee.prototype);async function Zt(e){return Promise.race([e,Promise.resolve().then(()=>Promise.resolve(void 0))])}function tt(e,t,s){let r=i=>{e.cancel(i).catch(()=>{})};return t.on("close",r),t.on("error",r),(s??e.read()).then(a,o),e.closed.finally(()=>{t.off("close",r),t.off("error",r)});function o(i){i&&t.destroy(i)}function n(){e.read().then(a,o)}function a({done:i,value:c}){try{if(i)t.end();else if(!t.write(c))t.once("drain",n);else return e.read().then(a,o)}catch(l){o(l)}}}function Qt(e,t){if(e.locked)throw new TypeError("ReadableStream is locked.");return t.destroyed?void 0:tt(e.getReader(),t)}var rt=e=>{let t={};e instanceof Headers||(e=new Headers(e??void 0));let s=[];for(let[r,o]of e)r==="set-cookie"?s.push(o):t[r]=o;return s.length>0&&(t["set-cookie"]=s),t["content-type"]??="text/plain; charset=UTF-8",t},Yt="x-hono-already-sent",tr=global.fetch;typeof global.crypto>"u"&&(global.crypto=er);global.fetch=(e,t)=>(t={compress:!1,...t},tr(e,t));var xe=Symbol("outgoingEnded"),rr=()=>new Response(null,{status:400}),st=e=>new Response(null,{status:e instanceof Error&&(e.name==="TimeoutError"||e.constructor.name==="TimeoutError")?504:500}),be=(e,t)=>{let s=e instanceof Error?e:new Error("unknown error",{cause:e});s.code==="ERR_STREAM_PREMATURE_CLOSE"?console.info("The user aborted a request."):(console.error(e),t.headersSent||t.writeHead(500,{"Content-Type":"text/plain"}),t.end(`Error: ${s.message}`),t.destroy(s))},ot=e=>{"flushHeaders"in e&&e.writable&&e.flushHeaders()},nt=async(e,t)=>{let[s,r,o]=e[O];o instanceof Headers&&(o=rt(o)),typeof r=="string"?o["Content-Length"]=Buffer.byteLength(r):r instanceof Uint8Array?o["Content-Length"]=r.byteLength:r instanceof Blob&&(o["Content-Length"]=r.size),t.writeHead(s,o),typeof r=="string"||r instanceof Uint8Array?t.end(r):r instanceof Blob?t.end(new Uint8Array(await r.arrayBuffer())):(ot(t),await Qt(r,t)?.catch(n=>be(n,t))),t[xe]?.()},sr=e=>typeof e.then=="function",or=async(e,t,s={})=>{if(sr(e))if(s.errorHandler)try{e=await e}catch(o){let n=await s.errorHandler(o);if(!n)return;e=n}else e=await e.catch(st);if(O in e)return nt(e,t);let r=rt(e.headers);if(e.body){let o=e.body.getReader(),n=[],a=!1,i;if(r["transfer-encoding"]!=="chunked"){let c=2;for(let l=0;l<c;l++){i||=o.read();let h=await Zt(i).catch(u=>{console.error(u),a=!0});if(!h){if(l===1){await new Promise(u=>setTimeout(u)),c=3;continue}break}if(i=void 0,h.value&&n.push(h.value),h.done){a=!0;break}}a&&!("content-length"in r)&&(r["content-length"]=n.reduce((l,h)=>l+h.length,0))}t.writeHead(e.status,r),n.forEach(c=>{t.write(c)}),a?t.end():(n.length===0&&ot(t),await tt(o,t,i))}else r[Yt]||(t.writeHead(e.status,r),t.end());t[xe]?.()},nr=(e,t={})=>{let s=t.autoCleanupIncoming??!0;return t.overrideGlobalObjects!==!1&&global.Request!==F&&(Object.defineProperty(global,"Request",{value:F}),Object.defineProperty(global,"Response",{value:N})),async(r,o)=>{let n,a;try{a=Jt(r,t.hostname);let i=!s||r.method==="GET"||r.method==="HEAD";if(i||(r[Ye]=!0,r.on("end",()=>{i=!0}),r instanceof Bt&&(o[xe]=()=>{i||setTimeout(()=>{i||setTimeout(()=>{r.destroy(),o.destroy()})})})),o.on("close",()=>{a[T]&&(r.errored?a[T].abort(r.errored.toString()):o.writableFinished||a[T].abort("Client connection prematurely closed.")),i||setTimeout(()=>{i||setTimeout(()=>{r.destroy()})})}),n=e(a,{incoming:r,outgoing:o}),O in n)return nt(n,o)}catch(i){if(n)return be(i,o);if(t.errorHandler){if(n=await t.errorHandler(a?i:Ut(i)),!n)return}else a?n=st(i):n=rr()}try{return await or(n,o,t)}catch(i){return be(i,o)}}},ar=e=>{let t=e.fetch,s=nr(t,{hostname:e.hostname,overrideGlobalObjects:e.overrideGlobalObjects,autoCleanupIncoming:e.autoCleanupIncoming});return(e.createServer||Nt)(e.serverOptions||{},s)},at=(e,t)=>{let s=ar(e);return s.listen(e?.port??3e3,e.hostname,()=>{let r=s.address();t&&t(r)}),s};import{readFileSync as ir,existsSync as cr}from"node:fs";function it(){let e=process.env.MOLNOS_RUNTIME_CONFIG;if(!e||!cr(e))return{molnos:{dataPath:"data"},server:{host:"localhost",port:3e3}};try{let t=ir(e,"utf-8");return JSON.parse(t)}catch(t){return console.error("[loadRuntimeConfig] Failed to load runtime config:",t),{molnos:{dataPath:"data"},server:{host:"localhost",port:3e3}}}}var M=class extends Error{constructor(t){super(),this.name="ValidationError",this.message=t||"Invalid input",this.cause={statusCode:400}}};var re=class extends Error{constructor(t){super(),this.name="InvalidPathError",this.message=t||"Invalid file path",this.cause={statusCode:400}}},k=class extends Error{constructor(t){super(),this.name="InvalidFormatError",this.message=t||"Invalid format",this.cause={statusCode:400}}},se=class extends Error{constructor(t){super(),this.name="FileTooLargeError",this.message=t||"File exceeds maximum size",this.cause={statusCode:413}}},oe=class extends Error{constructor(t){super(),this.name="ProjectTooLargeError",this.message=t||"Project exceeds maximum size",this.cause={statusCode:413}}},ne=class extends Error{constructor(t){super(),this.name="InvalidContentError",this.message=t||"Invalid content",this.cause={statusCode:400}}};function P(e,t="An error occurred"){let s=e?.message||e||t,r=e?.cause?.statusCode||e?.statusCode||400;return{message:s,status:r}}function ct(e,t,s={}){let r=Array.isArray(t)?t:[t];if(!e||!e.roles||!Array.isArray(e.roles)){let a=new Error("Unauthorized: User or roles missing");throw a.cause={statusCode:403},a}let o=e.roles.flatMap(a=>a?.policies?.flatMap(i=>(i?.permissions||[]).flatMap(l=>typeof l=="string"?l:l&&typeof l=="object"&&l.actions?l.actions:[]))||[]);if(!r.every(a=>o.includes(a)||o.includes("*")?!0:o.some(i=>{if(i.endsWith(".*")){let c=i.slice(0,-2);return a.startsWith(`${c}.`)}return!1}))){let a=new Error("Unauthorized");throw a.cause={statusCode:403},a}return!0}function lt(e,t,s,r,o){let n=e.find(c=>c.service===t);if(!n){let c=new Error(`Function bindings do not include access to service: ${t}`);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(!o)return;if(!c.targets.includes(o))continue}return}}let a=o?`:${o}`:"",i=new Error(`Function bindings do not allow: ${t}.${s}.${r}${a}`);throw i.cause={statusCode:403},i}async function R(e,t,s,r,o,n,a){if(!t)return null;let i=e.get("user");if(!i){let l=e.req.header("authorization");if(!l){let u=new Error("Unauthorized: No authentication provided");throw u.cause={statusCode:401},u}let h=l.replace(/^Bearer\s+/i,"");if(i=await t.getUserFromToken(h),!i){let u=new Error("Unauthorized: Invalid token");throw u.cause={statusCode:401},u}}ct(i,s,{});let c=e.req.header("x-function-bindings");if(c)try{let l=JSON.parse(c);lt(l,r,o,n,a)}catch(l){if(l.cause?.statusCode===403)throw l;let h=new Error("Invalid function bindings header");throw h.cause={statusCode:400},h}return i}async function ht(e,t,s){try{await R(e,s,"sites.project.list","sites","project","list");let r=e.req.header("x-forwarded-proto")||"http",o=e.req.header("host")||"localhost:3003",n=`${r}://${o}`,a=await t.listProjects(n);return e.json({success:!0,count:a.length,projects:a},200)}catch(r){let{message:o,status:n}=P(r,"Error listing projects");return e.json({error:o},n)}}var Pe=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),o=this.compileErrors(s,r),n=this.isSuccessful(s,o);return{errors:o,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 o=e?.additionalProperties??!0,n=e?.required||[];r=this.checkForRequiredKeysErrors(n,t,r),r=this.checkForDisallowedProperties(Object.keys(t),Object.keys(e),r,o);for(let a in e){let i=n.includes(a)&&a!=="required",c=e[a],l=t[a],h=c.additionalProperties??!0;i&&(r=this.checkForRequiredKeysErrors(c.required||[],l,r)),this.isDefined(l)&&(this.handleValidation(a,l,c,s),r=this.checkForDisallowedProperties(Object.keys(l),Object.keys(c),r,h),this.handleNestedObject(l,c,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):[],o=this.findNonOverlappingElements(e,r),n=o.length>0?`Missing the required key: '${o.join(", ")}'!`:`Missing values for required keys: '${r.filter(a=>!t[a]).join(", ")}'!`;s.push({key:"",value:t,success:!1,error:n})}return s}checkForDisallowedProperties(e,t,s,r){if(!r){let o=this.findNonOverlappingElements(e,t);o.length>0&&s.push({key:`${t}`,value:e,success:!1,error:`Has additional (disallowed) properties: '${o.join(", ")}'!`})}return s}handleValidation(e,t,s,r){this.updatePropertyPath(e);let o=this.validateProperty(this.propertyPath,s,t);r.push(...o);let n=(i,c)=>{i.forEach(l=>{let h=this.validateProperty(this.propertyPath,c.items,l);r.push(...h)}),this.updatePropertyPath()},a=i=>{let c=Object.keys(i),l=this.propertyPath;c.forEach(h=>{if(this.updatePropertyPath(h,l),this.isArray(i[h])&&s[h]?.items!=null)n(i[h],s[h]);else{let u=this.validateProperty(this.propertyPath,s[h],i[h]);r.push(...u)}})};this.isArray(t)&&s.items!=null?n(t,s):this.isObject(t)?a(t):this.updatePropertyPath()}handleNestedObject(e,t,s,r){if(this.isObject(e)){let o=this.getNestedObjects(e);for(let n of o){let a=t[n],i=e[n];a&&typeof i=="object"&&this.validate(a,i,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(o=>{let{success:n,error:a}=o;return{key:e,value:s,success:n,error:a??""}})}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 o of s)o.condition()&&!o.validator()&&r.push({success:!1,error:o.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 ut(e){try{return await e.req.json()}catch{return{}}}var ft={properties:{files:{type:"array",minItems:1,items:{type:"object",properties:{path:{type:"string",minLength:1},content:{type:"string",minLength:1}},required:["path","content"]}},projectId:{type:"string",pattern:"^[a-f0-9]+$"}},required:["files"],additionalProperties:!1};var hr=new Pe;async function dt(e,t,s){try{let r=await ut(e),o=hr.test(ft,r);if(!o.success)return e.json({error:"Invalid input",details:o.errors},400);await R(e,s,"sites.project.create","sites","project","create");let{files:n,projectId:a}=r;if(!n)return e.json({error:"files array is required"},400);let i=await t.uploadProject(n,a);return e.json({success:!0,projectId:i},200)}catch(r){let{message:o,status:n}=P(r,"Error uploading project");return e.json({error:o},n)}}async function pt(e,t,s){try{let{projectId:r}=e.req.param();return r?/^[a-f0-9]+$/.test(r)?(await R(e,s,"sites.project.delete","sites","project","delete",r),await t.projectExists(r)?(await t.deleteProject(r),e.json({success:!0,projectId:r},200)):e.json({error:"Project not found"},404)):e.json({error:"Invalid projectId format"},400):e.json({error:"projectId parameter is required"},400)}catch(r){let{message:o,status:n}=P(r,"Error deleting project");return e.json({error:o},n)}}import{extname as ur}from"node:path";function mt(e){let t=ur(e).toLowerCase();return{".html":"text/html",".css":"text/css",".js":"application/javascript",".json":"application/json",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".ico":"image/x-icon",".txt":"text/plain",".pdf":"application/pdf",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".eot":"application/vnd.ms-fontobject",".otf":"font/otf",".xml":"application/xml",".mp4":"video/mp4",".webm":"video/webm",".mp3":"audio/mpeg",".wav":"audio/wav"}[t]||"application/octet-stream"}async function yt(e,t,s){try{let r=e.req.param("projectId");if(!r)return e.json({error:"projectId is required"},400);await R(e,s,"sites.file.read","sites","file","read");let a=new URL(e.req.url).pathname.split(`/projects/${r}/`)[1]||""||"index.html";if(!await t.fileExists(r,a))return e.text("Not Found",404);let c=await t.getFile(r,a),l=mt(a);return e.body(c,200,{"Content-Type":l})}catch(r){let{message:o,status:n}=P(r,"Error serving file");return e.json({error:o},n)}}var wr=10,br=100,vt=xt(wr),wt=xt(br),Er="index.html";function xt(e){return e&&typeof e=="number"&&e>0?e*1024*1024:0}function $(e){return/^[a-z0-9-]{4,40}$/.test(e)}function je(e){if(!e)throw new M("File path is required");let t=mr(e.replace(/^\/+/,""));if(t.includes("..")||pr(t))throw new re("Invalid file path");return t===""||t==="/"?Er:t}var Se=class{rootPath;constructor(t){this.rootPath=t.path||"sites-data"}async start(){await Re(this.rootPath,{recursive:!0})}generateProjectId(t=8){return vr(Math.ceil(t/2)).toString("hex").slice(0,t)}async uploadProject(t,s=null){if(!t||!Array.isArray(t))throw new M("Invalid request format. Expected array of files in the request body.");s||(s=this.generateProjectId());let r=E(this.rootPath,s);if(!$(s))throw new k("Invalid project ID format");dr(r)&&ae(r,{recursive:!0,force:!0}),await Re(r,{recursive:!0});let o=0;for(let n of t){if(!n.path||!n.content)continue;let a=await this.saveFile(r,n.path,n.content);if(o+=a,o>wt)throw ae(r,{recursive:!0,force:!0}),new oe(`Project exceeds maximum size of ${wt/1024/1024}MB`)}if(t.length===0||o===0)throw ae(r,{recursive:!0,force:!0}),new M("No valid files were provided");return s}async saveFile(t,s,r){let o=je(s),n=E(t,o),a=fr(n);await Re(a,{recursive:!0});let i;try{i=Buffer.from(r,"base64")}catch(c){throw new ne(`Invalid content for file "${o}": ${c.message}`)}if(i.length>vt)throw new se(`File "${o}" exceeds maximum size of ${vt/1024/1024}MB`);return await yr(n,i),i.length}async getFile(t,s){if(!$(t))throw new k("Invalid project ID format");let r=je(s),o=E(this.rootPath,t,r);return await gr(o)}async fileExists(t,s){try{if(!$(t))return!1;let r=je(s),o=E(this.rootPath,t,r);return(await gt(o)).isFile()}catch{return!1}}async projectExists(t){try{if(!$(t))return!1;let s=E(this.rootPath,t);return(await gt(s)).isDirectory()}catch{return!1}}async deleteProject(t){if(!$(t))throw new k("Invalid project ID format");let s=E(this.rootPath,t);ae(s,{recursive:!0,force:!0})}async listProjects(t){try{let{readdir:s,stat:r}=await import("node:fs/promises"),o=await s(this.rootPath,{withFileTypes:!0}),n=[];for(let a of o)if(a.isDirectory()&&$(a.name)){let i=E(this.rootPath,a.name),c=await r(i),l=0,h=0,u=async d=>{let g=await s(d,{withFileTypes:!0});for(let f of g){let y=E(d,f.name);if(f.isDirectory())await u(y);else if(f.isFile()){l++;let v=await r(y);h+=v.size}}};await u(i);let p=d=>{if(d===0)return"0 B";let g=1024,f=["B","KB","MB","GB"],y=Math.floor(Math.log(d)/Math.log(g));return`${(d/g**y).toFixed(1)} ${f[y]}`};n.push({projectId:a.name,name:a.name,url:`${t}/projects/${a.name}/`,status:"active",files:l,size:p(h),lastDeployed:c.mtime.toISOString(),createdAt:c.birthtime.toISOString()})}return n}catch{return[]}}};async function xr(e){let t=e.dataPath||"data",s=E(t,"sites"),r=new Se({path:e.sites?.path||s});await r.start();let o=e.identityService||null,n=new ve;return n.get("/projects",async a=>ht(a,r,o)),n.post("/projects",async a=>dt(a,r,o)),n.delete("/projects/:projectId",async a=>pt(a,r,o)),n.get("/projects/:projectId",async a=>{let i=a.req.param("projectId");return a.redirect(`/projects/${i}/`,301)}),n.get("/projects/:projectId/*",async a=>yt(a,r,o)),at({fetch:n.fetch,port:e.server.port||3003,hostname:e.server.host||"localhost"}),console.log(`Sites server started on ${e.server.host||"localhost"}:${e.server.port||3003}`),n}var Pr=process.argv.slice(2),bt=Pr.find(e=>e.startsWith("--port=")),Rr=bt?parseInt(bt.split("=")[1],10):3003,Et=it(),jr={molnos:{dataPath:Et.molnos.dataPath},sites:{},server:{port:Rr,host:Et.server.host}};xr(jr);export{xr as startServer};
|
|
2
|
+
var z=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(),r=t||"unknown",s=this.requests.get(r);return(!s||s.resetTime<e)&&(s={count:0,resetTime:e+this.windowMs},this.requests.set(r,s)),s.count++,s.count<=this.limit}getRemainingRequests(t){let e=Date.now(),r=t||"unknown",s=this.requests.get(r);return!s||s.resetTime<e?this.limit:Math.max(0,this.limit-s.count)}getResetTime(t){let e=Date.now(),r=t||"unknown",s=this.requests.get(r);return!s||s.resetTime<e?Math.floor((e+this.windowMs)/1e3):Math.floor(s.resetTime/1e3)}cleanup(){let t=Date.now();for(let[e,r]of this.requests.entries())r.resetTime<t&&this.requests.delete(e)}};import{URL as lt}from"url";var U=class{routes=[];globalMiddlewares=[];pathPatterns=new Map;use(t){return this.globalMiddlewares.push(t),this}get(t,...e){let r=e.pop();return this.register("GET",t,r,e)}post(t,...e){let r=e.pop();return this.register("POST",t,r,e)}put(t,...e){let r=e.pop();return this.register("PUT",t,r,e)}delete(t,...e){let r=e.pop();return this.register("DELETE",t,r,e)}patch(t,...e){let r=e.pop();return this.register("PATCH",t,r,e)}any(t,...e){let r=e.pop(),s=e;return this.register("GET",t,r,s),this.register("POST",t,r,s),this.register("PUT",t,r,s),this.register("DELETE",t,r,s),this.register("PATCH",t,r,s),this.register("OPTIONS",t,r,s),this}options(t,...e){let r=e.pop();return this.register("OPTIONS",t,r,e)}match(t,e){for(let r of this.routes){if(r.method!==t)continue;let s=this.pathPatterns.get(r.path);if(!s)continue;let o=s.pattern.exec(e);if(!o)continue;let n={};return s.paramNames.forEach((i,a)=>{n[i]=o[a+1]||""}),{route:r,params:n}}return null}async handle(t,e){let r=t.method||"GET",s=new lt(t.url||"/",`http://${t.headers.host}`),o=s.pathname,n=this.match(r,o);if(!n)return null;let{route:i,params:a}=n,c={};s.searchParams.forEach((l,u)=>{c[u]=l});let d={req:t,res:e,params:a,query:c,body:t.body||{},headers:t.headers,path:o,state:{},raw:()=>e,binary:(l,u="application/octet-stream",p=200)=>({statusCode:p,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:()=>e,binary:(u,p="application/octet-stream")=>({statusCode:l,body:u,headers:{"Content-Type":p,"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,p=302)=>({statusCode:p,body:null,headers:{Location:u}}),status:u=>this.status(u)}}},h=[...this.globalMiddlewares,...i.middlewares];return this.executeMiddlewareChain(d,h,i.handler)}register(t,e,r,s=[]){return this.routes.push({method:t,path:e,handler:r,middlewares:s}),this.pathPatterns.set(e,this.createPathPattern(e)),this}createPathPattern(t){let e=[],r=t.replace(/\/:[^/]+/g,s=>{let o=s.slice(2);return e.push(o),"/([^/]+)"});return r.endsWith("/*")?(r=`${r.slice(0,-2)}(?:/(.*))?`,e.push("wildcard")):r=r.replace(/\/$/,"/?"),{pattern:new RegExp(`^${r}$`),paramNames:e}}async executeMiddlewareChain(t,e,r){let s=0,o=async()=>{if(s<e.length){let n=e[s++];return n(t,o)}return r(t)};return o()}};var E=()=>({port:Number(process.env.PORT)||3e3,host:process.env.HOST||"0.0.0.0",useHttps:!1,useHttp2:!1,sslCert:"",sslKey:"",sslCa:"",debug:ut(process.env.DEBUG)||!1,maxBodySize:1048576,requestTimeout:3e4,rateLimit:{enabled:!0,requestsPerMinute:100},allowedDomains:["*"]});function ut(t){return t==="true"||t===!0}var L=class extends Error{constructor(t){super(t),this.name="ValidationError",this.message=t||"Validation did not pass",this.cause={statusCode:400}}};import{existsSync as dt,readFileSync as ht}from"node:fs";var H=class{config={};options=[];validators=[];autoValidate=!0;constructor(t){let e=t?.configFilePath,r=t?.args||[],s=t?.config||{};this.options=t?.options||[],this.validators=t?.validators||[],t?.autoValidate!==void 0&&(this.autoValidate=t.autoValidate),this.config=this.createConfig(e,r,s)}deepMerge(t,e){let r={...t};for(let s in e)e[s]!==void 0&&(e[s]!==null&&typeof e[s]=="object"&&!Array.isArray(e[s])&&s in t&&t[s]!==null&&typeof t[s]=="object"&&!Array.isArray(t[s])?r[s]=this.deepMerge(t[s],e[s]):e[s]!==void 0&&(r[s]=e[s]));return r}setValueAtPath(t,e,r){let s=e.split("."),o=t;for(let i=0;i<s.length-1;i++){let a=s[i];!(a in o)||o[a]===null?o[a]={}:typeof o[a]!="object"&&(o[a]={}),o=o[a]}let n=s[s.length-1];o[n]=r}getValueAtPath(t,e){let r=e.split("."),s=t;for(let o of r){if(s==null)return;s=s[o]}return s}createConfig(t,e=[],r={}){let s={};for(let a of this.options)a.defaultValue!==void 0&&this.setValueAtPath(s,a.path,a.defaultValue);let o={};if(t&&dt(t))try{let a=ht(t,"utf8");o=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),i=this.deepMerge({},s);return i=this.deepMerge(i,o),i=this.deepMerge(i,r),i=this.deepMerge(i,n),i}parseCliArgs(t){let e={},r=t[0]?.endsWith("node")||t[0]?.endsWith("node.exe")?2:0;for(;r<t.length;){let s=t[r++],o=this.options.find(n=>n.flag===s);if(o)if(o.isFlag)this.setValueAtPath(e,o.path,!0);else if(r<t.length&&!t[r].startsWith("-")){let n=t[r++];if(o.parser)try{n=o.parser(n)}catch(i){console.error(`Error parsing value for ${o.flag}: ${i instanceof Error?i.message:String(i)}`);continue}if(o.validator){let i=o.validator(n);if(i!==!0&&typeof i=="string"){console.error(`Invalid value for ${o.flag}: ${i}`);continue}if(i===!1){console.error(`Invalid value for ${o.flag}`);continue}}this.setValueAtPath(e,o.path,n)}else console.error(`Missing value for option ${s}`)}return e}validate(){for(let t of this.validators){let e=this.getValueAtPath(this.config,t.path),r=t.validator(e,this.config);if(r===!1)throw new L(t.message);if(typeof r=="string")throw new L(r)}}get(){return this.autoValidate&&this.validate(),this.config}getValue(t,e){let r=this.getValueAtPath(this.config,t);return r!==void 0?r:e}setValue(t,e){if(typeof e=="object"&&e!==null&&!Array.isArray(e)){let r=this.getValueAtPath(this.config,t)||{};if(typeof r=="object"&&!Array.isArray(r)){let s=this.deepMerge(r,e);this.setValueAtPath(this.config,t,s);return}}this.setValueAtPath(this.config,t,e)}getHelpText(){let t=`Available configuration options:
|
|
3
|
+
|
|
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 k={int:t=>{let e=t.trim();if(!/^[+-]?\d+$/.test(e))throw new Error(`Cannot parse "${t}" as an integer`);let r=Number.parseInt(e,10);if(Number.isNaN(r))throw new Error(`Cannot parse "${t}" as an integer`);return r},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 r=Number.parseFloat(e);if(Number.isNaN(r))throw new Error(`Cannot parse "${t}" as a number`);return r},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(),_=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:k.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 G(t,e){let r=e.match(/boundary=(?:"([^"]+)"|([^;]+))/i);if(!r)throw new Error("Invalid multipart/form-data: missing boundary");let s=r[1]||r[2],o=Buffer.from(`--${s}`),n=Buffer.from(`--${s}--`),i={},a={},c=pt(t,o);for(let d of c){if(d.length===0||d.equals(n.subarray(o.length)))continue;let h=ft(d);if(!h)continue;let{name:l,filename:u,contentType:p,data:m}=h;if(u){let f={filename:u,contentType:p||"application/octet-stream",data:m,size:m.length};a[l]?Array.isArray(a[l])?a[l].push(f):a[l]=[a[l],f]:a[l]=f}else{let f=m.toString("utf8");i[l]?Array.isArray(i[l])?i[l].push(f):i[l]=[i[l],f]:i[l]=f}}return{fields:i,files:a}}function pt(t,e){let r=[],s=0;for(;s<t.length;){let o=t.indexOf(e,s);if(o===-1)break;s!==o&&r.push(t.subarray(s,o)),s=o+e.length,s<t.length&&t[s]===13&&t[s+1]===10&&(s+=2)}return r}function ft(t){let e=Buffer.from(`\r
|
|
9
|
+
\r
|
|
10
|
+
`),r=t.indexOf(e);if(r===-1)return null;let s=t.subarray(0,r),o=t.subarray(r+4),i=s.toString("utf8").split(`\r
|
|
11
|
+
`),a="",c="",d,h;for(let u of i){let p=u.toLowerCase();if(p.startsWith("content-disposition:")){a=u.substring(20).trim();let m=a.match(/name="([^"]+)"/);m&&(c=m[1]);let f=a.match(/filename="([^"]+)"/);f&&(d=f[1])}else p.startsWith("content-type:")&&(h=u.substring(13).trim())}if(!c)return null;let l=o;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:h,data:l}}import{readFileSync as v}from"fs";import V from"http";import mt from"http2";import gt from"https";var N=class{config;rateLimiter;router;shutdownHandlers=[];constructor(t){let e=new H(_(t||{})).get();e.debug&&console.log("Using configuration:",e),this.config=e,this.router=new U;let r=e.rateLimit.requestsPerMinute||E().rateLimit.requestsPerMinute;this.rateLimiter=new z(r,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:r}=this.config;return this.setupGracefulShutdown(t),t.listen(e,r,()=>{let s=t.address(),o=this.config.useHttps||this.config.useHttp2?"https":"http";console.log(`MikroServe running at ${o}://${s.address!=="::"?s.address:"localhost"}:${s.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:v(this.config.sslKey),cert:v(this.config.sslCert),...this.config.sslCa?{ca:v(this.config.sslCa)}:{}};return mt.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:v(this.config.sslKey),cert:v(this.config.sslCert),...this.config.sslCa?{ca:v(this.config.sslCa)}:{}};return gt.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 V.createServer(t)}async rateLimitMiddleware(t,e){let r=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(r).toString()),t.res.setHeader("X-RateLimit-Reset",this.rateLimiter.getResetTime(r).toString()),this.rateLimiter.isAllowed(r)?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 r=Date.now(),s=t.method||"UNKNOWN",o=t.url||"/unknown",n=this.config.debug;try{if(this.setCorsHeaders(e,t),this.setSecurityHeaders(e,this.config.useHttps),n&&console.log(`${s} ${o}`),t.method==="OPTIONS"){if(e instanceof V.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 i=await this.router.handle(t,e);return i?i._handled?void 0:this.respond(e,i):this.respond(e,{statusCode:404,body:{error:"Not Found",message:"The requested endpoint does not exist"}})}catch(i){return console.error("Server error:",i),this.respond(e,{statusCode:500,body:{error:"Internal Server Error",message:n?i.message:"An unexpected error occurred"}})}finally{n&&this.logDuration(r,s,o)}}logDuration(t,e,r){let s=Date.now()-t;console.log(`${e} ${r} completed in ${s}ms`)}async parseBody(t){return new Promise((e,r)=>{let s=[],o=0,n=this.config.maxBodySize,i=!1,a=null,c=this.config.debug,d=t.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 h=()=>{a&&(clearTimeout(a),a=null)};t.on("data",l=>{if(!i){if(o+=l.length,c&&console.log(`Received chunk: ${l.length} bytes, total size: ${o}`),o>n){i=!0,h(),c&&console.log(`Body size exceeded limit: ${o} > ${n}`),r(new Error("Request body too large"));return}s.push(l)}}),t.on("end",()=>{if(!i){i=!0,h(),c&&console.log(`Request body complete: ${o} bytes`);try{if(s.length>0){let l=Buffer.concat(s);if(d.includes("application/json"))try{let u=l.toString("utf8");e(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"),p={};new URLSearchParams(u).forEach((m,f)=>{p[f]=m}),e(p)}else if(d.includes("multipart/form-data"))try{let u=G(l,d);e(u)}catch(u){r(new Error(`Invalid multipart form data: ${u.message}`))}else this.isBinaryContentType(d)?e(l):e(l.toString("utf8"))}else e({})}catch(l){r(new Error(`Invalid request body: ${l}`))}}}),t.on("error",l=>{i||(i=!0,h(),r(new Error(`Error reading request body: ${l.message}`)))}),t.on("close",()=>{h()})})}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(r=>t.includes(r))}setCorsHeaders(t,e){let r=e.headers.origin,{allowedDomains:s=["*"]}=this.config;!r||s.length===0||s.includes("*")?t.setHeader("Access-Control-Allow-Origin","*"):s.includes(r)&&(t.setHeader("Access-Control-Allow-Origin",r),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 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((e||this.config.useHttp2)&&(r["Strict-Transport-Security"]="max-age=31536000; includeSubDomains"),t instanceof V.ServerResponse)Object.entries(r).forEach(([s,o])=>{t.setHeader(s,o)});else{let s=t;Object.entries(r).forEach(([o,n])=>{s.setHeader(o,n)})}}respond(t,e){let r={...e.headers||{}};(o=>typeof o.writeHead=="function"&&typeof o.end=="function")(t)?(t.writeHead(e.statusCode,r),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,r),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=i=>{console.log("Shutting down MikroServe server..."),i&&console.error("Error:",i),this.cleanupShutdownHandlers(),t.close(()=>{console.log("Server closed successfully"),process.env.NODE_ENV!=="test"&&process.env.VITEST!=="true"&&setImmediate(()=>process.exit(i?1:0))})},r=()=>e(),s=()=>e(),o=i=>e(i),n=i=>e(i);this.shutdownHandlers=[r,s,o,n],process.on("SIGINT",r),process.on("SIGTERM",s),process.on("uncaughtException",o),process.on("unhandledRejection",n)}cleanupShutdownHandlers(){if(this.shutdownHandlers.length>0){let[t,e,r,s]=this.shutdownHandlers;process.removeListener("SIGINT",t),process.removeListener("SIGTERM",e),process.removeListener("uncaughtException",r),process.removeListener("unhandledRejection",s),this.shutdownHandlers=[]}}};import{dirname as Ct,join as y}from"node:path";import{existsSync as St,rmSync as O}from"node:fs";import{isAbsolute as Pt,normalize as jt}from"node:path";import{mkdir as q,writeFile as Et,readFile as It,stat as it}from"node:fs/promises";import{randomBytes as Rt}from"node:crypto";function w(t,e="An error occurred"){let r=t?.message||t||e,s=t?.cause?.statusCode||t?.statusCode||400;return{message:r,status:s}}function J(t,e,r={}){let s=Array.isArray(e)?e:[e];if(!t||!t.roles||!Array.isArray(t.roles)){let i=new Error("Unauthorized: User or roles missing");throw i.cause={statusCode:403},i}let o=t.roles.flatMap(i=>i?.policies?.flatMap(a=>(a?.permissions||[]).flatMap(d=>typeof d=="string"?d:d&&typeof d=="object"&&d.actions?d.actions:[]))||[]);if(!s.every(i=>o.includes(i)||o.includes("*")?!0:o.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 W(t,e,r,s,o){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!==r)){if(!c.resource||!c.actions||c.actions.length===0)return;if(c.actions.includes(s)){if(c.targets&&c.targets.length>0){if(!o)return;if(!c.targets.includes(o))continue}return}}let i=o?`:${o}`:"",a=new Error(`Function bindings do not allow: ${e}.${r}.${s}${i}`);throw a.cause={statusCode:403},a}async function b(t,e,r,s,o,n,i){if(!e)return null;let a=t.state.user;if(!a){let d=t.headers.authorization;if(!d){let l=new Error("Unauthorized: No authentication provided");throw l.cause={statusCode:401},l}let h=d.replace(/^Bearer\s+/i,"");if(a=await e.getUserFromToken(h),!a){let l=new Error("Unauthorized: Invalid token");throw l.cause={statusCode:401},l}}J(a,r,{});let c=t.headers["x-function-bindings"];if(c)try{let d=Array.isArray(c)?c[0]:c,h=JSON.parse(d);W(h,s,o,n,i)}catch(d){if(d.cause?.statusCode===403)throw d;let h=new Error("Invalid function bindings header");throw h.cause={statusCode:400},h}return a}async function X(t,e,r){try{await b(t,r,"sites.project.list","sites","project","list");let s=t.headers["x-forwarded-proto"]||"http",o=t.headers.host||"localhost:3003",n=`${s}://${o}`,i=await e.listProjects(n);return t.json({success:!0,count:i.length,projects:i},200)}catch(s){let{message:o,status:n}=w(s,"Error listing projects");return t.json({error:o},n)}}var F=class{isSilent;propertyPath="";constructor(t=!1){this.isSilent=t}test(t,e){if(!e)throw new Error("Missing input!");this.updatePropertyPath();let{results:r,errors:s}=this.validate(t.properties,e),o=this.compileErrors(r,s),n=this.isSuccessful(r,o);return{errors:o,success:n}}compileErrors(t,e){let r=t.filter(s=>s.success===!1);return[...e,...r].flatMap(s=>s)}isSuccessful(t,e){return t.every(r=>r.success===!0)&&e.length===0}validate(t,e,r=[],s=[]){let o=t?.additionalProperties??!0,n=t?.required||[];s=this.checkForRequiredKeysErrors(n,e,s),s=this.checkForDisallowedProperties(Object.keys(e),Object.keys(t),s,o);for(let i in t){let a=n.includes(i)&&i!=="required",c=t[i],d=e[i],h=c.additionalProperties??!0;a&&(s=this.checkForRequiredKeysErrors(c.required||[],d,s)),this.isDefined(d)&&(this.handleValidation(i,d,c,r),s=this.checkForDisallowedProperties(Object.keys(d),Object.keys(c),s,h),this.handleNestedObject(d,c,r,s))}return{results:r,errors:s}}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,r){if(!this.areRequiredKeysPresent(t,e)){let s=e?Object.keys(e):[],o=this.findNonOverlappingElements(t,s),n=o.length>0?`Missing the required key: '${o.join(", ")}'!`:`Missing values for required keys: '${s.filter(i=>!e[i]).join(", ")}'!`;r.push({key:"",value:e,success:!1,error:n})}return r}checkForDisallowedProperties(t,e,r,s){if(!s){let o=this.findNonOverlappingElements(t,e);o.length>0&&r.push({key:`${e}`,value:t,success:!1,error:`Has additional (disallowed) properties: '${o.join(", ")}'!`})}return r}handleValidation(t,e,r,s){this.updatePropertyPath(t);let o=this.validateProperty(this.propertyPath,r,e);s.push(...o);let n=(a,c)=>{a.forEach(d=>{let h=this.validateProperty(this.propertyPath,c.items,d);s.push(...h)}),this.updatePropertyPath()},i=a=>{let c=Object.keys(a),d=this.propertyPath;c.forEach(h=>{if(this.updatePropertyPath(h,d),this.isArray(a[h])&&r[h]?.items!=null)n(a[h],r[h]);else{let l=this.validateProperty(this.propertyPath,r[h],a[h]);s.push(...l)}})};this.isArray(e)&&r.items!=null?n(e,r):this.isObject(e)?i(e):this.updatePropertyPath()}handleNestedObject(t,e,r,s){if(this.isObject(t)){let o=this.getNestedObjects(t);for(let n of o){let i=e[n],a=t[n];i&&typeof a=="object"&&this.validate(i,a,r,s)}}}getNestedObjects(t){return Object.keys(t).filter(e=>{if(this.isObject(t))return e})}findNonOverlappingElements(t,e){return t.filter(r=>!e.includes(r))}areRequiredKeysPresent(t,e=[]){return t.every(r=>Object.keys(e).includes(r)?this.isDefined(e[r]):!1)}validateProperty(t,e,r){return this.validateInput(e,r).map(o=>{let{success:n,error:i}=o;return{key:t,value:r,success:n,error:i??""}})}validateInput(t,e){if(t){let r=[{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"}],s=[];for(let o of r)o.condition()&&!o.validator()&&s.push({success:!1,error:o.error});return s}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(r=>{switch(r){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 r in t){let s=t[r];e.properties.required.push(r),Array.isArray(s)?e.properties[r]=this.generateArraySchema(s):typeof s=="object"&&s!==null?e.properties[r]=this.generateNestedObjectSchema(s):e.properties[r]=this.generatePropertySchema(s)}return e}generateArraySchema(t){let e={type:"array"},r=t.filter(s=>s);if(r.length>0){let s=r[0];r.every(n=>typeof n==typeof s)?typeof s=="object"&&!Array.isArray(s)?e.items=this.generateNestedObjectSchema(s):e.items=this.generatePropertySchema(s):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 r in t){let s=t[r];e.required.push(r),typeof s=="object"&&!Array.isArray(s)&&s!==null?e[r]=this.generateNestedObjectSchema(s):e[r]=this.generatePropertySchema(s)}return e}generatePropertySchema(t){let e=typeof t,r={type:e};return e==="string"&&(r.minLength=1),r}};async function Z(t){return t.body||{}}var K={properties:{files:{type:"array",minItems:1,items:{type:"object",properties:{path:{type:"string",minLength:1},content:{type:"string",minLength:1}},required:["path","content"]}},projectId:{type:"string",pattern:"^[a-f0-9]+$"}},required:["files"],additionalProperties:!1};var wt=new F;async function Y(t,e,r){try{await b(t,r,"sites.project.create","sites","project","create");let s=await Z(t),o=wt.test(K,s);if(!o.success)return t.json({error:"Invalid input",details:o.errors},400);let{files:n,projectId:i}=s;if(!n)return t.json({error:"files array is required"},400);let a=await e.uploadProject(n,i);return t.json({success:!0,projectId:a},200)}catch(s){let{message:o,status:n}=w(s,"Error uploading project");return t.json({error:o},n)}}async function Q(t,e,r){try{let s=t.params.projectId;return s?/^[a-f0-9]+$/.test(s)?(await b(t,r,"sites.project.delete","sites","project","delete",s),await e.projectExists(s)?(await e.deleteProject(s),t.json({success:!0,projectId:s},200)):t.json({error:"Project not found"},404)):t.json({error:"Invalid projectId format"},400):t.json({error:"projectId parameter is required"},400)}catch(s){let{message:o,status:n}=w(s,"Error deleting project");return t.json({error:o},n)}}import{extname as vt}from"node:path";function tt(t){let e=vt(t).toLowerCase();return{".html":"text/html",".css":"text/css",".js":"application/javascript",".json":"application/json",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".ico":"image/x-icon",".txt":"text/plain",".pdf":"application/pdf",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".eot":"application/vnd.ms-fontobject",".otf":"font/otf",".xml":"application/xml",".mp4":"video/mp4",".webm":"video/webm",".mp3":"audio/mpeg",".wav":"audio/wav"}[e]||"application/octet-stream"}async function et(t,e){try{let r=t.params.projectId;if(!r)return t.json({error:"projectId is required"},400);let n=new URL(t.req.url||"","http://localhost").pathname.split(`/projects/${r}/`)[1]||""||"index.html";if(!await e.fileExists(r,n))return t.text("Not Found",404);let a=await e.getFile(r,n),c=tt(n);return t.binary(a,c)}catch(r){let{message:s,status:o}=w(r,"Error serving file");return t.json({error:s},o)}}var x=class extends Error{constructor(e){super(),this.name="ValidationError",this.message=e||"Invalid input",this.cause={statusCode:400}}};var I=class extends Error{constructor(e){super(),this.name="InvalidPathError",this.message=e||"Invalid file path",this.cause={statusCode:400}}},C=class extends Error{constructor(e){super(),this.name="InvalidFormatError",this.message=e||"Invalid format",this.cause={statusCode:400}}},R=class extends Error{constructor(e){super(),this.name="FileTooLargeError",this.message=e||"File exceeds maximum size",this.cause={statusCode:413}}},T=class extends Error{constructor(e){super(),this.name="ProjectTooLargeError",this.message=e||"Project exceeds maximum size",this.cause={statusCode:413}}},A=class extends Error{constructor(e){super(),this.name="InvalidContentError",this.message=e||"Invalid content",this.cause={statusCode:400}}};function $(t){return t&&typeof t=="number"&&t>0?t*1024*1024:0}import{readFileSync as bt,existsSync as xt}from"node:fs";function j(){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:""},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||!xt(t))return e;try{let r=bt(t,"utf-8");return JSON.parse(r)}catch(r){return console.error("[loadRuntimeConfig] Failed to load runtime config:",r),e}}function rt(t,e){let r={enabled:!1,requestsPerMinute:0};if(!e)return r;let s=e.services?.[t];return s||(e.global?e.global:r)}function st(t,e){let r=t?.api?.port;if(!r)throw new Error('Missing "port" input when create API service!');let s=j(),o=t?.dataPath||s.molnos.dataPath,n=t?.api?.host||s.server.host,i=t?.identityApiUrl!==void 0?t.identityApiUrl:s.identity.apiUrl,a=t?.debug||!1,c;return e&&(c=rt(e,s.molnos.rateLimit)),{dataPath:o,api:{port:r,host:n},...i?{identityApiUrl:i}:{},...c?{rateLimit:c}:{},debug:a}}var M=class{baseUrl;authToken;constructor(e,r){this.baseUrl=e.replace(/\/$/,""),this.authToken=r}async createCustomRole(e,r,s,o){let n=await fetch(`${this.baseUrl}/identity/roles`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({roleId:e,name:r,description:s,permissions:o})});if(!n.ok){let i=`Failed to create role: ${n.statusText}`;try{i=(await n.json()).error||i}catch{i=await n.text().catch(()=>n.statusText)||i}throw new Error(i)}}async updateRole(e,r){let s=await fetch(`${this.baseUrl}/identity/roles/${e}`,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(r)});if(!s.ok){let o=await s.json();throw new Error(o.error||`Failed to update role: ${s.statusText}`)}}async deleteRole(e){let r=await fetch(`${this.baseUrl}/identity/roles/${e}`,{method:"DELETE",headers:this.getHeaders()});if(!r.ok){let s=await r.json();throw new Error(s.error||`Failed to delete role: ${r.statusText}`)}}async addServiceAccount(e,r,s){let o=await fetch(`${this.baseUrl}/identity/service-accounts`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({name:e,description:r,roles:s})});if(!o.ok){let i=`Failed to create service account: ${o.statusText}`;try{i=(await o.json()).error||i}catch{i=await o.text().catch(()=>o.statusText)||i}throw new Error(i)}let n=await o.json();return{id:n.id,apiKey:n.apiKey}}async deleteIdentity(e){let r=await fetch(`${this.baseUrl}/identity/service-accounts/${e}`,{method:"DELETE",headers:this.getHeaders()});if(!r.ok){let s=await r.json();throw new Error(s.error||`Failed to delete service account: ${r.statusText}`)}}async getUserFromToken(e){try{let r=await fetch(`${this.baseUrl}/identity/whoami`,{method:"GET",headers:{Authorization:`Bearer ${e}`}});return r.ok?await r.json():null}catch{return null}}getHeaders(){let e={"Content-Type":"application/json"};return this.authToken&&(e.Authorization=`Bearer ${this.authToken}`),e}};function ot(t){return t?new M(t):null}var Tt=10,At=100,nt=$(Tt),at=$(At),$t="index.html";function S(t){return/^[a-z0-9-]{4,40}$/.test(t)}function D(t){if(!t)throw new x("File path is required");let e=jt(t.replace(/^\/+/,""));if(e.includes("..")||Pt(e))throw new I("Invalid file path");return e===""||e==="/"?$t:e}var B=class{rootPath;constructor(e){this.rootPath=e.path||"sites-data"}async start(){await q(this.rootPath,{recursive:!0})}generateProjectId(e=8){return Rt(Math.ceil(e/2)).toString("hex").slice(0,e)}async uploadProject(e,r=null){if(!e||!Array.isArray(e))throw new x("Invalid request format. Expected array of files in the request body.");r||(r=this.generateProjectId());let s=y(this.rootPath,r);if(!S(r))throw new C("Invalid project ID format");St(s)&&O(s,{recursive:!0,force:!0}),await q(s,{recursive:!0});let o=0;for(let n of e){if(!n.path||!n.content)continue;let i=await this.saveFile(s,n.path,n.content);if(o+=i,o>at)throw O(s,{recursive:!0,force:!0}),new T(`Project exceeds maximum size of ${at/1024/1024}MB`)}if(e.length===0||o===0)throw O(s,{recursive:!0,force:!0}),new x("No valid files were provided");return r}async saveFile(e,r,s){let o=D(r),n=y(e,o),i=Ct(n);await q(i,{recursive:!0});let a;try{a=Buffer.from(s,"base64")}catch(c){throw new A(`Invalid content for file "${o}": ${c.message}`)}if(a.length>nt)throw new R(`File "${o}" exceeds maximum size of ${nt/1024/1024}MB`);return await Et(n,a),a.length}async getFile(e,r){if(!S(e))throw new C("Invalid project ID format");let s=D(r),o=y(this.rootPath,e,s);return await It(o)}async fileExists(e,r){try{if(!S(e))return!1;let s=D(r),o=y(this.rootPath,e,s);return(await it(o)).isFile()}catch{return!1}}async projectExists(e){try{if(!S(e))return!1;let r=y(this.rootPath,e);return(await it(r)).isDirectory()}catch{return!1}}async deleteProject(e){if(!S(e))throw new C("Invalid project ID format");let r=y(this.rootPath,e);O(r,{recursive:!0,force:!0})}async listProjects(e){try{let{readdir:r,stat:s}=await import("node:fs/promises"),o=await r(this.rootPath,{withFileTypes:!0}),n=[];for(let i of o)if(i.isDirectory()&&S(i.name)){let a=y(this.rootPath,i.name),c=await s(a),d=0,h=0,l=async p=>{let m=await r(p,{withFileTypes:!0});for(let f of m){let P=y(p,f.name);if(f.isDirectory())await l(P);else if(f.isFile()){d++;let ct=await s(P);h+=ct.size}}};await l(a);let u=p=>{if(p===0)return"0 B";let m=1024,f=["B","KB","MB","GB"],P=Math.floor(Math.log(p)/Math.log(m));return`${(p/m**P).toFixed(1)} ${f[P]}`};n.push({projectId:i.name,name:i.name,url:`${e}/projects/${i.name}/`,status:"active",files:d,size:u(h),lastDeployed:c.mtime.toISOString(),createdAt:c.birthtime.toISOString()})}return n}catch{return[]}}};async function Mt(t){let e=t.dataPath||"data",r=y(e,"sites"),s=new B({path:r});await s.start();let o=ot(t.identityApiUrl),n=j(),i=new N({port:t.api.port||n.services.sites.port,host:t.api.host||n.services.sites.host,maxBodySize:$(1e3),rateLimit:t.rateLimit||{enabled:!1,requestsPerMinute:0}});return i.get("/projects",async c=>X(c,s,o)),i.post("/projects",async c=>Y(c,s,o)),i.delete("/projects/:projectId",async c=>Q(c,s,o)),i.get("/projects/:projectId",async c=>{let d=c.params.projectId;return c.redirect(`/projects/${d}/`,301)}),i.get("/projects/:projectId/*",async c=>et(c,s)),i.start()}if(import.meta.url===`file://${process.argv[1]}`){let t=j(),r=process.argv.slice(2).find(n=>n.startsWith("--port=")),s=r?parseInt(r.split("=")[1],10):t.services.sites.port,o=st({api:{port:s}},"sites");Mt(o)}export{B as SitesService,Mt as startServer};
|