molnos 1.4.2 → 1.5.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/dist/storage.mjs CHANGED
@@ -1,11 +1,11 @@
1
1
  // MolnOS Core - See LICENSE file for copyright and license details.
2
- var H=class{requests=new Map;limit;windowMs;constructor(t=100,e=60){this.limit=t,this.windowMs=e*1e3,setInterval(()=>this.cleanup(),this.windowMs)}getLimit(){return this.limit}isAllowed(t){let e=Date.now(),s=t||"unknown",r=this.requests.get(s);return(!r||r.resetTime<e)&&(r={count:0,resetTime:e+this.windowMs},this.requests.set(s,r)),r.count++,r.count<=this.limit}getRemainingRequests(t){let e=Date.now(),s=t||"unknown",r=this.requests.get(s);return!r||r.resetTime<e?this.limit:Math.max(0,this.limit-r.count)}getResetTime(t){let e=Date.now(),s=t||"unknown",r=this.requests.get(s);return!r||r.resetTime<e?Math.floor((e+this.windowMs)/1e3):Math.floor(r.resetTime/1e3)}cleanup(){let t=Date.now();for(let[e,s]of this.requests.entries())s.resetTime<t&&this.requests.delete(e)}};import{URL as ft}from"url";var L=class{routes=[];globalMiddlewares=[];pathPatterns=new Map;use(t){return this.globalMiddlewares.push(t),this}get(t,...e){let s=e.pop();return this.register("GET",t,s,e)}post(t,...e){let s=e.pop();return this.register("POST",t,s,e)}put(t,...e){let s=e.pop();return this.register("PUT",t,s,e)}delete(t,...e){let s=e.pop();return this.register("DELETE",t,s,e)}patch(t,...e){let s=e.pop();return this.register("PATCH",t,s,e)}any(t,...e){let s=e.pop(),r=e;return this.register("GET",t,s,r),this.register("POST",t,s,r),this.register("PUT",t,s,r),this.register("DELETE",t,s,r),this.register("PATCH",t,s,r),this.register("OPTIONS",t,s,r),this}options(t,...e){let s=e.pop();return this.register("OPTIONS",t,s,e)}match(t,e){for(let s of this.routes){if(s.method!==t)continue;let r=this.pathPatterns.get(s.path);if(!r)continue;let o=r.pattern.exec(e);if(!o)continue;let n={};return r.paramNames.forEach((i,a)=>{n[i]=o[a+1]||""}),{route:s,params:n}}return null}async handle(t,e){let s=t.method||"GET",r=new ft(t.url||"/",`http://${t.headers.host}`),o=r.pathname,n=this.match(s,o);if(!n)return null;let{route:i,params:a}=n,l={};r.searchParams.forEach((u,d)=>{l[d]=u});let c={req:t,res:e,params:a,query:l,body:t.body||{},headers:t.headers,path:o,state:{},raw:()=>e,binary:(u,d="application/octet-stream",h=200)=>({statusCode:h,body:u,headers:{"Content-Type":d,"Content-Length":u.length.toString()},isRaw:!0}),text:(u,d=200)=>({statusCode:d,body:u,headers:{"Content-Type":"text/plain"}}),form:(u,d=200)=>({statusCode:d,body:u,headers:{"Content-Type":"application/x-www-form-urlencoded"}}),json:(u,d=200)=>({statusCode:d,body:u,headers:{"Content-Type":"application/json"}}),html:(u,d=200)=>({statusCode:d,body:u,headers:{"Content-Type":"text/html"}}),redirect:(u,d=302)=>({statusCode:d,body:null,headers:{Location:u}}),status:function(u){return{raw:()=>e,binary:(d,h="application/octet-stream")=>({statusCode:u,body:d,headers:{"Content-Type":h,"Content-Length":d.length.toString()},isRaw:!0}),text:d=>({statusCode:u,body:d,headers:{"Content-Type":"text/plain"}}),json:d=>({statusCode:u,body:d,headers:{"Content-Type":"application/json"}}),html:d=>({statusCode:u,body:d,headers:{"Content-Type":"text/html"}}),form:d=>({statusCode:u,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)}}},p=[...this.globalMiddlewares,...i.middlewares];return this.executeMiddlewareChain(c,p,i.handler)}register(t,e,s,r=[]){return this.routes.push({method:t,path:e,handler:s,middlewares:r}),this.pathPatterns.set(e,this.createPathPattern(e)),this}createPathPattern(t){let e=[],s=t.replace(/\/:[^/]+/g,r=>{let o=r.slice(2);return e.push(o),"/([^/]+)"});return s.endsWith("/*")?(s=`${s.slice(0,-2)}(?:/(.*))?`,e.push("wildcard")):s=s.replace(/\/$/,"/?"),{pattern:new RegExp(`^${s}$`),paramNames:e}}async executeMiddlewareChain(t,e,s){let r=0,o=async()=>{if(r<e.length){let n=e[r++];return n(t,o)}return s(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:mt(process.env.DEBUG)||!1,maxBodySize:1048576,requestTimeout:3e4,rateLimit:{enabled:!0,requestsPerMinute:100},allowedDomains:["*"]});function mt(t){return t==="true"||t===!0}var I=class extends Error{constructor(t){super(t),this.name="ValidationError",this.message=t||"Validation did not pass",this.cause={statusCode:400}}};import{existsSync as ht,readFileSync as gt}from"node:fs";var B=class{config={};options=[];validators=[];autoValidate=!0;constructor(t){let e=t?.configFilePath,s=t?.args||[],r=t?.config||{};this.options=t?.options||[],this.validators=t?.validators||[],t?.autoValidate!==void 0&&(this.autoValidate=t.autoValidate),this.config=this.createConfig(e,s,r)}deepMerge(t,e){let s={...t};for(let r in e)e[r]!==void 0&&(e[r]!==null&&typeof e[r]=="object"&&!Array.isArray(e[r])&&r in t&&t[r]!==null&&typeof t[r]=="object"&&!Array.isArray(t[r])?s[r]=this.deepMerge(t[r],e[r]):e[r]!==void 0&&(s[r]=e[r]));return s}setValueAtPath(t,e,s){let r=e.split("."),o=t;for(let i=0;i<r.length-1;i++){let a=r[i];!(a in o)||o[a]===null?o[a]={}:typeof o[a]!="object"&&(o[a]={}),o=o[a]}let n=r[r.length-1];o[n]=s}getValueAtPath(t,e){let s=e.split("."),r=t;for(let o of s){if(r==null)return;r=r[o]}return r}createConfig(t,e=[],s={}){let r={};for(let a of this.options)a.defaultValue!==void 0&&this.setValueAtPath(r,a.path,a.defaultValue);let o={};if(t&&ht(t))try{let a=gt(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({},r);return i=this.deepMerge(i,o),i=this.deepMerge(i,s),i=this.deepMerge(i,n),i}parseCliArgs(t){let e={},s=t[0]?.endsWith("node")||t[0]?.endsWith("node.exe")?2:0;for(;s<t.length;){let r=t[s++],o=this.options.find(n=>n.flag===r);if(o)if(o.isFlag)this.setValueAtPath(e,o.path,!0);else if(s<t.length&&!t[s].startsWith("-")){let n=t[s++];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 ${r}`)}return e}validate(){for(let t of this.validators){let e=this.getValueAtPath(this.config,t.path),s=t.validator(e,this.config);if(s===!1)throw new I(t.message);if(typeof s=="string")throw new I(s)}}get(){return this.autoValidate&&this.validate(),this.config}getValue(t,e){let s=this.getValueAtPath(this.config,t);return s!==void 0?s:e}setValue(t,e){if(typeof e=="object"&&e!==null&&!Array.isArray(e)){let s=this.getValueAtPath(this.config,t)||{};if(typeof s=="object"&&!Array.isArray(s)){let r=this.deepMerge(s,e);this.setValueAtPath(this.config,t,r);return}}this.setValueAtPath(this.config,t,e)}getHelpText(){let t=`Available configuration options:
2
+ var V=class{requests=new Map;limit;windowMs;constructor(t=100,e=60){this.limit=t,this.windowMs=e*1e3,setInterval(()=>this.cleanup(),this.windowMs)}getLimit(){return this.limit}isAllowed(t){let e=Date.now(),s=t||"unknown",r=this.requests.get(s);return(!r||r.resetTime<e)&&(r={count:0,resetTime:e+this.windowMs},this.requests.set(s,r)),r.count++,r.count<=this.limit}getRemainingRequests(t){let e=Date.now(),s=t||"unknown",r=this.requests.get(s);return!r||r.resetTime<e?this.limit:Math.max(0,this.limit-r.count)}getResetTime(t){let e=Date.now(),s=t||"unknown",r=this.requests.get(s);return!r||r.resetTime<e?Math.floor((e+this.windowMs)/1e3):Math.floor(r.resetTime/1e3)}cleanup(){let t=Date.now();for(let[e,s]of this.requests.entries())s.resetTime<t&&this.requests.delete(e)}};import{URL as vt}from"url";var D=class{routes=[];globalMiddlewares=[];pathPatterns=new Map;use(t){return this.globalMiddlewares.push(t),this}get(t,...e){let s=e.pop();return this.register("GET",t,s,e)}post(t,...e){let s=e.pop();return this.register("POST",t,s,e)}put(t,...e){let s=e.pop();return this.register("PUT",t,s,e)}delete(t,...e){let s=e.pop();return this.register("DELETE",t,s,e)}patch(t,...e){let s=e.pop();return this.register("PATCH",t,s,e)}any(t,...e){let s=e.pop(),r=e;return this.register("GET",t,s,r),this.register("POST",t,s,r),this.register("PUT",t,s,r),this.register("DELETE",t,s,r),this.register("PATCH",t,s,r),this.register("OPTIONS",t,s,r),this}options(t,...e){let s=e.pop();return this.register("OPTIONS",t,s,e)}match(t,e){for(let s of this.routes){if(s.method!==t)continue;let r=this.pathPatterns.get(s.path);if(!r)continue;let i=r.pattern.exec(e);if(!i)continue;let n={};return r.paramNames.forEach((o,a)=>{n[o]=i[a+1]||""}),{route:s,params:n}}return null}async handle(t,e){let s=t.method||"GET",r=new vt(t.url||"/",`http://${t.headers.host}`),i=r.pathname,n=this.match(s,i);if(!n)return null;let{route:o,params:a}=n,l={};r.searchParams.forEach((u,d)=>{l[d]=u});let c={req:t,res:e,params:a,query:l,body:t.body||{},headers:t.headers,path:i,state:{},raw:()=>e,binary:(u,d="application/octet-stream",g=200)=>({statusCode:g,body:u,headers:{"Content-Type":d,"Content-Length":u.length.toString()},isRaw:!0}),text:(u,d=200)=>({statusCode:d,body:u,headers:{"Content-Type":"text/plain"}}),form:(u,d=200)=>({statusCode:d,body:u,headers:{"Content-Type":"application/x-www-form-urlencoded"}}),json:(u,d=200)=>({statusCode:d,body:u,headers:{"Content-Type":"application/json"}}),html:(u,d=200)=>({statusCode:d,body:u,headers:{"Content-Type":"text/html"}}),redirect:(u,d=302)=>({statusCode:d,body:null,headers:{Location:u}}),status:function(u){return{raw:()=>e,binary:(d,g="application/octet-stream")=>({statusCode:u,body:d,headers:{"Content-Type":g,"Content-Length":d.length.toString()},isRaw:!0}),text:d=>({statusCode:u,body:d,headers:{"Content-Type":"text/plain"}}),json:d=>({statusCode:u,body:d,headers:{"Content-Type":"application/json"}}),html:d=>({statusCode:u,body:d,headers:{"Content-Type":"text/html"}}),form:d=>({statusCode:u,body:d,headers:{"Content-Type":"application/x-www-form-urlencoded"}}),redirect:(d,g=302)=>({statusCode:g,body:null,headers:{Location:d}}),status:d=>this.status(d)}}},p=[...this.globalMiddlewares,...o.middlewares];return this.executeMiddlewareChain(c,p,o.handler)}register(t,e,s,r=[]){return this.routes.push({method:t,path:e,handler:s,middlewares:r}),this.pathPatterns.set(e,this.createPathPattern(e)),this}createPathPattern(t){let e=[],s=t.replace(/\/:[^/]+/g,r=>{let i=r.slice(2);return e.push(i),"/([^/]+)"});return s.endsWith("/*")?(s=`${s.slice(0,-2)}(?:/(.*))?`,e.push("wildcard")):s=s.replace(/\/$/,"/?"),{pattern:new RegExp(`^${s}$`),paramNames:e}}async executeMiddlewareChain(t,e,s){let r=0,i=async()=>{if(r<e.length){let n=e[r++];return n(t,i)}return s(t)};return i()}};var R=()=>({port:Number(process.env.PORT)||3e3,host:process.env.HOST||"0.0.0.0",useHttps:!1,useHttp2:!1,sslCert:"",sslKey:"",sslCa:"",debug:wt(process.env.DEBUG)||!1,maxBodySize:1048576,requestTimeout:3e4,rateLimit:{enabled:!0,requestsPerMinute:100},allowedDomains:["*"]});function wt(t){return t==="true"||t===!0}var T=class extends Error{constructor(t){super(t),this.name="ValidationError",this.message=t||"Validation did not pass",this.cause={statusCode:400}}};import{existsSync as St,readFileSync as xt}from"node:fs";var A=class{config={};options=[];validators=[];autoValidate=!0;constructor(t){let e=t?.configFilePath,s=t?.args||[],r=t?.config||{};this.options=t?.options||[],this.validators=t?.validators||[],t?.autoValidate!==void 0&&(this.autoValidate=t.autoValidate),this.config=this.createConfig(e,s,r)}deepMerge(t,e){let s={...t};for(let r in e)e[r]!==void 0&&(e[r]!==null&&typeof e[r]=="object"&&!Array.isArray(e[r])&&r in t&&t[r]!==null&&typeof t[r]=="object"&&!Array.isArray(t[r])?s[r]=this.deepMerge(t[r],e[r]):e[r]!==void 0&&(s[r]=e[r]));return s}setValueAtPath(t,e,s){let r=e.split("."),i=t;for(let o=0;o<r.length-1;o++){let a=r[o];!(a in i)||i[a]===null?i[a]={}:typeof i[a]!="object"&&(i[a]={}),i=i[a]}let n=r[r.length-1];i[n]=s}getValueAtPath(t,e){let s=e.split("."),r=t;for(let i of s){if(r==null)return;r=r[i]}return r}createConfig(t,e=[],s={}){let r={};for(let a of this.options)a.defaultValue!==void 0&&this.setValueAtPath(r,a.path,a.defaultValue);let i={};if(t&&St(t))try{let a=xt(t,"utf8");i=JSON.parse(a),console.log(`Loaded configuration from ${t}`)}catch(a){console.error(`Error reading config file: ${a instanceof Error?a.message:String(a)}`)}let n=this.parseCliArgs(e),o=this.deepMerge({},r);return o=this.deepMerge(o,i),o=this.deepMerge(o,s),o=this.deepMerge(o,n),o}parseCliArgs(t){let e={},s=t[0]?.endsWith("node")||t[0]?.endsWith("node.exe")?2:0;for(;s<t.length;){let r=t[s++],i=this.options.find(n=>n.flag===r);if(i)if(i.isFlag)this.setValueAtPath(e,i.path,!0);else if(s<t.length&&!t[s].startsWith("-")){let n=t[s++];if(i.parser)try{n=i.parser(n)}catch(o){console.error(`Error parsing value for ${i.flag}: ${o instanceof Error?o.message:String(o)}`);continue}if(i.validator){let o=i.validator(n);if(o!==!0&&typeof o=="string"){console.error(`Invalid value for ${i.flag}: ${o}`);continue}if(o===!1){console.error(`Invalid value for ${i.flag}`);continue}}this.setValueAtPath(e,i.path,n)}else console.error(`Missing value for option ${r}`)}return e}validate(){for(let t of this.validators){let e=this.getValueAtPath(this.config,t.path),s=t.validator(e,this.config);if(s===!1)throw new T(t.message);if(typeof s=="string")throw new T(s)}}get(){return this.autoValidate&&this.validate(),this.config}getValue(t,e){let s=this.getValueAtPath(this.config,t);return s!==void 0?s:e}setValue(t,e){if(typeof e=="object"&&e!==null&&!Array.isArray(e)){let s=this.getValueAtPath(this.config,t)||{};if(typeof s=="object"&&!Array.isArray(s)){let r=this.deepMerge(s,e);this.setValueAtPath(this.config,t,r);return}}this.setValueAtPath(this.config,t,e)}getHelpText(){let t=`Available configuration options:
3
3
 
4
4
  `;for(let e of this.options)t+=`${e.flag}${e.isFlag?"":" <value>"}
5
5
  `,e.description&&(t+=` ${e.description}
6
6
  `),e.defaultValue!==void 0&&(t+=` Default: ${JSON.stringify(e.defaultValue)}
7
7
  `),t+=`
8
- `;return t}};var T={int:t=>{let e=t.trim();if(!/^[+-]?\d+$/.test(e))throw new Error(`Cannot parse "${t}" as an integer`);let s=Number.parseInt(e,10);if(Number.isNaN(s))throw new Error(`Cannot parse "${t}" as an integer`);return s},float:t=>{let e=t.trim();if(!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(e)){if(e==="Infinity"||e==="-Infinity")return e==="Infinity"?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY;throw new Error(`Cannot parse "${t}" as a number`)}let s=Number.parseFloat(e);if(Number.isNaN(s))throw new Error(`Cannot parse "${t}" as a number`);return s},boolean:t=>{let e=t.trim().toLowerCase();if(["true","yes","1","y"].includes(e))return!0;if(["false","no","0","n"].includes(e))return!1;throw new Error(`Cannot parse "${t}" as a boolean`)},array:t=>t.split(",").map(e=>e.trim()),json:t=>{try{return JSON.parse(t)}catch{throw new Error(`Cannot parse "${t}" as JSON`)}}};var v=E(),q=t=>({configFilePath:"mikroserve.config.json",args:process.argv,options:[{flag:"--port",path:"port",defaultValue:v.port},{flag:"--host",path:"host",defaultValue:v.host},{flag:"--https",path:"useHttps",defaultValue:v.useHttps,isFlag:!0},{flag:"--http2",path:"useHttp2",defaultValue:v.useHttp2,isFlag:!0},{flag:"--cert",path:"sslCert",defaultValue:v.sslCert},{flag:"--key",path:"sslKey",defaultValue:v.sslKey},{flag:"--ca",path:"sslCa",defaultValue:v.sslCa},{flag:"--ratelimit",path:"rateLimit.enabled",defaultValue:v.rateLimit.enabled,isFlag:!0},{flag:"--rps",path:"rateLimit.requestsPerMinute",defaultValue:v.rateLimit.requestsPerMinute},{flag:"--allowed",path:"allowedDomains",defaultValue:v.allowedDomains,parser:T.array},{flag:"--debug",path:"debug",defaultValue:v.debug,isFlag:!0},{flag:"--max-body-size",path:"maxBodySize",defaultValue:v.maxBodySize},{flag:"--request-timeout",path:"requestTimeout",defaultValue:v.requestTimeout}],config:t});function N(t,e){let s=e.match(/boundary=(?:"([^"]+)"|([^;]+))/i);if(!s)throw new Error("Invalid multipart/form-data: missing boundary");let r=s[1]||s[2],o=Buffer.from(`--${r}`),n=Buffer.from(`--${r}--`),i={},a={},l=yt(t,o);for(let c of l){if(c.length===0||c.equals(n.subarray(o.length)))continue;let p=bt(c);if(!p)continue;let{name:u,filename:d,contentType:h,data:m}=p;if(d){let f={filename:d,contentType:h||"application/octet-stream",data:m,size:m.length};a[u]?Array.isArray(a[u])?a[u].push(f):a[u]=[a[u],f]:a[u]=f}else{let f=m.toString("utf8");i[u]?Array.isArray(i[u])?i[u].push(f):i[u]=[i[u],f]:i[u]=f}}return{fields:i,files:a}}function yt(t,e){let s=[],r=0;for(;r<t.length;){let o=t.indexOf(e,r);if(o===-1)break;r!==o&&s.push(t.subarray(r,o)),r=o+e.length,r<t.length&&t[r]===13&&t[r+1]===10&&(r+=2)}return s}function bt(t){let e=Buffer.from(`\r
8
+ `;return t}};var $={int:t=>{let e=t.trim();if(!/^[+-]?\d+$/.test(e))throw new Error(`Cannot parse "${t}" as an integer`);let s=Number.parseInt(e,10);if(Number.isNaN(s))throw new Error(`Cannot parse "${t}" as an integer`);return s},float:t=>{let e=t.trim();if(!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(e)){if(e==="Infinity"||e==="-Infinity")return e==="Infinity"?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY;throw new Error(`Cannot parse "${t}" as a number`)}let s=Number.parseFloat(e);if(Number.isNaN(s))throw new Error(`Cannot parse "${t}" as a number`);return s},boolean:t=>{let e=t.trim().toLowerCase();if(["true","yes","1","y"].includes(e))return!0;if(["false","no","0","n"].includes(e))return!1;throw new Error(`Cannot parse "${t}" as a boolean`)},array:t=>t.split(",").map(e=>e.trim()),json:t=>{try{return JSON.parse(t)}catch{throw new Error(`Cannot parse "${t}" as JSON`)}}};var w=R(),U=t=>({configFilePath:"mikroserve.config.json",args:process.argv,options:[{flag:"--port",path:"port",defaultValue:w.port},{flag:"--host",path:"host",defaultValue:w.host},{flag:"--https",path:"useHttps",defaultValue:w.useHttps,isFlag:!0},{flag:"--http2",path:"useHttp2",defaultValue:w.useHttp2,isFlag:!0},{flag:"--cert",path:"sslCert",defaultValue:w.sslCert},{flag:"--key",path:"sslKey",defaultValue:w.sslKey},{flag:"--ca",path:"sslCa",defaultValue:w.sslCa},{flag:"--ratelimit",path:"rateLimit.enabled",defaultValue:w.rateLimit.enabled,isFlag:!0},{flag:"--rps",path:"rateLimit.requestsPerMinute",defaultValue:w.rateLimit.requestsPerMinute},{flag:"--allowed",path:"allowedDomains",defaultValue:w.allowedDomains,parser:$.array},{flag:"--debug",path:"debug",defaultValue:w.debug,isFlag:!0},{flag:"--max-body-size",path:"maxBodySize",defaultValue:w.maxBodySize},{flag:"--request-timeout",path:"requestTimeout",defaultValue:w.requestTimeout}],config:t});function F(t,e){let s=e.match(/boundary=(?:"([^"]+)"|([^;]+))/i);if(!s)throw new Error("Invalid multipart/form-data: missing boundary");let r=s[1]||s[2],i=Buffer.from(`--${r}`),n=Buffer.from(`--${r}--`),o={},a={},l=kt(t,i);for(let c of l){if(c.length===0||c.equals(n.subarray(i.length)))continue;let p=jt(c);if(!p)continue;let{name:u,filename:d,contentType:g,data:m}=p;if(d){let f={filename:d,contentType:g||"application/octet-stream",data:m,size:m.length};a[u]?Array.isArray(a[u])?a[u].push(f):a[u]=[a[u],f]:a[u]=f}else{let f=m.toString("utf8");o[u]?Array.isArray(o[u])?o[u].push(f):o[u]=[o[u],f]:o[u]=f}}return{fields:o,files:a}}function kt(t,e){let s=[],r=0;for(;r<t.length;){let i=t.indexOf(e,r);if(i===-1)break;r!==i&&s.push(t.subarray(r,i)),r=i+e.length,r<t.length&&t[r]===13&&t[r+1]===10&&(r+=2)}return s}function jt(t){let e=Buffer.from(`\r
9
9
  \r
10
- `),s=t.indexOf(e);if(s===-1)return null;let r=t.subarray(0,s),o=t.subarray(s+4),i=r.toString("utf8").split(`\r
11
- `),a="",l="",c,p;for(let d of i){let h=d.toLowerCase();if(h.startsWith("content-disposition:")){a=d.substring(20).trim();let m=a.match(/name="([^"]+)"/);m&&(l=m[1]);let f=a.match(/filename="([^"]+)"/);f&&(c=f[1])}else h.startsWith("content-type:")&&(p=d.substring(13).trim())}if(!l)return null;let u=o;return u.length>=2&&u[u.length-2]===13&&u[u.length-1]===10&&(u=u.subarray(0,u.length-2)),{disposition:a,name:l,filename:c,contentType:p,data:u}}import{readFileSync as P}from"fs";import M from"http";import wt from"http2";import vt from"https";var A=class{config;rateLimiter;router;shutdownHandlers=[];constructor(t){let e=new B(q(t||{})).get();e.debug&&console.log("Using configuration:",e),this.config=e,this.router=new L;let s=e.rateLimit.requestsPerMinute||E().rateLimit.requestsPerMinute;this.rateLimiter=new H(s,60),e.rateLimit.enabled===!0&&this.use(this.rateLimitMiddleware.bind(this))}use(t){return this.router.use(t),this}get(t,...e){return this.router.get(t,...e),this}post(t,...e){return this.router.post(t,...e),this}put(t,...e){return this.router.put(t,...e),this}delete(t,...e){return this.router.delete(t,...e),this}patch(t,...e){return this.router.patch(t,...e),this}any(t,...e){return this.router.any(t,...e),this}options(t,...e){return this.router.options(t,...e),this}start(){let t=this.createServer(),{port:e,host:s}=this.config;return this.setupGracefulShutdown(t),t.listen(e,s,()=>{let r=t.address(),o=this.config.useHttps||this.config.useHttp2?"https":"http";console.log(`MikroServe running at ${o}://${r.address!=="::"?r.address:"localhost"}:${r.port}`)}),t}createServer(){let t=this.requestHandler.bind(this);if(this.config.useHttp2){if(!this.config.sslCert||!this.config.sslKey)throw new Error("SSL certificate and key paths are required when useHttp2 is true");try{let e={key:P(this.config.sslKey),cert:P(this.config.sslCert),...this.config.sslCa?{ca:P(this.config.sslCa)}:{}};return wt.createSecureServer(e,t)}catch(e){throw e.message.includes("key values mismatch")?new Error(`SSL certificate and key do not match: ${e.message}`):e}}else if(this.config.useHttps){if(!this.config.sslCert||!this.config.sslKey)throw new Error("SSL certificate and key paths are required when useHttps is true");try{let e={key:P(this.config.sslKey),cert:P(this.config.sslCert),...this.config.sslCa?{ca:P(this.config.sslCa)}:{}};return vt.createServer(e,t)}catch(e){throw e.message.includes("key values mismatch")?new Error(`SSL certificate and key do not match: ${e.message}`):e}}return M.createServer(t)}async rateLimitMiddleware(t,e){let s=t.req.socket.remoteAddress||"unknown";return t.res.setHeader("X-RateLimit-Limit",this.rateLimiter.getLimit().toString()),t.res.setHeader("X-RateLimit-Remaining",this.rateLimiter.getRemainingRequests(s).toString()),t.res.setHeader("X-RateLimit-Reset",this.rateLimiter.getResetTime(s).toString()),this.rateLimiter.isAllowed(s)?e():{statusCode:429,body:{error:"Too Many Requests",message:"Rate limit exceeded, please try again later"},headers:{"Content-Type":"application/json"}}}async requestHandler(t,e){let s=Date.now(),r=t.method||"UNKNOWN",o=t.url||"/unknown",n=this.config.debug;try{if(this.setCorsHeaders(e,t),this.setSecurityHeaders(e,this.config.useHttps),n&&console.log(`${r} ${o}`),t.method==="OPTIONS"){if(e instanceof M.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(s,r,o)}}logDuration(t,e,s){let r=Date.now()-t;console.log(`${e} ${s} completed in ${r}ms`)}async parseBody(t){return new Promise((e,s)=>{let r=[],o=0,n=this.config.maxBodySize,i=!1,a=null,l=this.config.debug,c=t.headers["content-type"]||"";l&&console.log("Content-Type:",c),this.config.requestTimeout>0&&(a=setTimeout(()=>{i||(i=!0,l&&console.log("Request timeout exceeded"),s(new Error("Request timeout")))},this.config.requestTimeout));let p=()=>{a&&(clearTimeout(a),a=null)};t.on("data",u=>{if(!i){if(o+=u.length,l&&console.log(`Received chunk: ${u.length} bytes, total size: ${o}`),o>n){i=!0,p(),l&&console.log(`Body size exceeded limit: ${o} > ${n}`),s(new Error("Request body too large"));return}r.push(u)}}),t.on("end",()=>{if(!i){i=!0,p(),l&&console.log(`Request body complete: ${o} bytes`);try{if(r.length>0){let u=Buffer.concat(r);if(c.includes("application/json"))try{let d=u.toString("utf8");e(JSON.parse(d))}catch(d){s(new Error(`Invalid JSON in request body: ${d.message}`))}else if(c.includes("application/x-www-form-urlencoded")){let d=u.toString("utf8"),h={};new URLSearchParams(d).forEach((m,f)=>{h[f]=m}),e(h)}else if(c.includes("multipart/form-data"))try{let d=N(u,c);e(d)}catch(d){s(new Error(`Invalid multipart form data: ${d.message}`))}else this.isBinaryContentType(c)?e(u):e(u.toString("utf8"))}else e({})}catch(u){s(new Error(`Invalid request body: ${u}`))}}}),t.on("error",u=>{i||(i=!0,p(),s(new Error(`Error reading request body: ${u.message}`)))}),t.on("close",()=>{p()})})}isBinaryContentType(t){return["application/octet-stream","application/pdf","application/zip","application/gzip","application/x-tar","application/x-rar-compressed","application/x-7z-compressed","image/","video/","audio/","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument","application/msword","application/vnd.ms-powerpoint"].some(s=>t.includes(s))}setCorsHeaders(t,e){let s=e.headers.origin,{allowedDomains:r=["*"]}=this.config;!s||r.length===0||r.includes("*")?t.setHeader("Access-Control-Allow-Origin","*"):r.includes(s)&&(t.setHeader("Access-Control-Allow-Origin",s),t.setHeader("Vary","Origin")),t.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, PATCH, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization"),t.setHeader("Access-Control-Max-Age","86400")}setSecurityHeaders(t,e=!1){let s={"X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","Content-Security-Policy":"default-src 'self'; script-src 'self'; object-src 'none'","X-XSS-Protection":"1; mode=block"};if((e||this.config.useHttp2)&&(s["Strict-Transport-Security"]="max-age=31536000; includeSubDomains"),t instanceof M.ServerResponse)Object.entries(s).forEach(([r,o])=>{t.setHeader(r,o)});else{let r=t;Object.entries(s).forEach(([o,n])=>{r.setHeader(o,n)})}}respond(t,e){let s={...e.headers||{}};(o=>typeof o.writeHead=="function"&&typeof o.end=="function")(t)?(t.writeHead(e.statusCode,s),e.body===null||e.body===void 0?t.end():e.isRaw||typeof e.body=="string"?t.end(e.body):t.end(JSON.stringify(e.body))):(console.warn("Unexpected response object type without writeHead/end methods"),t.writeHead?.(e.statusCode,s),e.body===null||e.body===void 0?t.end?.():e.isRaw||typeof e.body=="string"?t.end?.(e.body):t.end?.(JSON.stringify(e.body)))}setupGracefulShutdown(t){let e=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))})},s=()=>e(),r=()=>e(),o=i=>e(i),n=i=>e(i);this.shutdownHandlers=[s,r,o,n],process.on("SIGINT",s),process.on("SIGTERM",r),process.on("uncaughtException",o),process.on("unhandledRejection",n)}cleanupShutdownHandlers(){if(this.shutdownHandlers.length>0){let[t,e,s,r]=this.shutdownHandlers;process.removeListener("SIGINT",t),process.removeListener("SIGTERM",e),process.removeListener("uncaughtException",s),process.removeListener("unhandledRejection",r),this.shutdownHandlers=[]}}};import{join as w,dirname as Lt}from"node:path";import{promises as b}from"node:fs";function g(t,e="An error occurred"){let s=t?.message||t||e,r=t?.cause?.statusCode||t?.statusCode||400;return{message:s,status:r}}function V(t,e,s={}){let r=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(c=>typeof c=="string"?c:c&&typeof c=="object"&&c.actions?c.actions:[]))||[]);if(!r.every(i=>o.includes(i)||o.includes("*")?!0:o.some(a=>{if(a.endsWith(".*")){let l=a.slice(0,-2);return i.startsWith(`${l}.`)}return!1}))){let i=new Error("Unauthorized");throw i.cause={statusCode:403},i}return!0}function D(t,e,s,r,o){let n=t.find(l=>l.service===e);if(!n){let l=new Error(`Function bindings do not include access to service: ${e}`);throw l.cause={statusCode:403},l}if(!n.permissions||n.permissions.length===0)return;for(let l of n.permissions)if(!(l.resource&&l.resource!==s)){if(!l.resource||!l.actions||l.actions.length===0)return;if(l.actions.includes(r)){if(l.targets&&l.targets.length>0){if(!o)return;if(!l.targets.includes(o))continue}return}}let i=o?`:${o}`:"",a=new Error(`Function bindings do not allow: ${e}.${s}.${r}${i}`);throw a.cause={statusCode:403},a}import{readFileSync as xt,existsSync as Ct}from"node:fs";function x(){let t=process.env.MOLNOS_RUNTIME_CONFIG,e={molnos:{dataPath:"data",rateLimit:{global:{enabled:!1,requestsPerMinute:0}},signedUrlSecret:"molnos-default-signed-url-secret"},server:{host:"127.0.0.1",port:3e3},identity:{apiUrl:"http://127.0.0.1:3000"},context:{apiUrl:"http://127.0.0.1:3000"},services:{storage:{host:"127.0.0.1",port:3001,url:"http://127.0.0.1:3001"},functions:{host:"127.0.0.1",port:3002,url:"http://127.0.0.1:3002"},sites:{host:"127.0.0.1",port:3003,url:"http://127.0.0.1:3003"},databases:{host:"127.0.0.1",port:3004,url:"http://127.0.0.1:3004"},observability:{host:"127.0.0.1",port:3005,url:"http://127.0.0.1:3005"}}};if(!t||!Ct(t))return e;try{let s=xt(t,"utf-8");return JSON.parse(s)}catch(s){return console.error("[loadRuntimeConfig] Failed to load runtime config:",s),e}}async function y(t,e,s,r,o,n,i){if(!e)return null;let a=t.headers["x-molnos-service-token"];if(a){let p=x();if(p.internalServiceSecret&&a===p.internalServiceSecret)return null}let l=t.state.user;if(!l){let p=t.headers.authorization;if(!p){let d=new Error("Unauthorized: No authentication provided");throw d.cause={statusCode:401},d}let u=p.replace(/^Bearer\s+/i,"");if(l=await e.getUserFromToken(u),!l){let d=new Error("Unauthorized: Invalid token");throw d.cause={statusCode:401},d}}V(l,s,{});let c=t.headers["x-function-bindings"];if(c)try{let p=Array.isArray(c)?c[0]:c,u=JSON.parse(p);D(u,r,o,n,i)}catch(p){if(p.cause?.statusCode===403)throw p;let u=new Error("Invalid function bindings header");throw u.cause={statusCode:400},u}return l}async function U(t,e,s,r){try{await y(t,s,"storage.bucket.list","storage","bucket","list");let o=await e.listBuckets(),n=t.query.context;if(n&&r){let i=t.headers.authorization?.replace(/^Bearer\s+/i,""),a=await r.listResourcesByType(n,"storage",i);o=o.filter(l=>a.includes(l))}return t.json({buckets:o},200)}catch(o){let{message:n,status:i}=g(o,"Error listing buckets");return t.json({error:n},i)}}var C=class{isSilent;propertyPath="";constructor(t=!1){this.isSilent=t}test(t,e){if(!e)throw new Error("Missing input!");this.updatePropertyPath();let{results:s,errors:r}=this.validate(t.properties,e),o=this.compileErrors(s,r),n=this.isSuccessful(s,o);return{errors:o,success:n}}compileErrors(t,e){let s=t.filter(r=>r.success===!1);return[...e,...s].flatMap(r=>r)}isSuccessful(t,e){return t.every(s=>s.success===!0)&&e.length===0}validate(t,e,s=[],r=[]){let o=t?.additionalProperties??!0,n=t?.required||[];r=this.checkForRequiredKeysErrors(n,e,r),r=this.checkForDisallowedProperties(Object.keys(e),Object.keys(t),r,o);for(let i in t){let a=n.includes(i)&&i!=="required",l=t[i],c=e[i],p=l.additionalProperties??!0;a&&(r=this.checkForRequiredKeysErrors(l.required||[],c,r)),this.isDefined(c)&&(this.handleValidation(i,c,l,s),r=this.checkForDisallowedProperties(Object.keys(c),Object.keys(l),r,p),this.handleNestedObject(c,l,s,r))}return{results:s,errors:r}}updatePropertyPath(t,e=""){if(!t){this.propertyPath="";return}e&&(this.propertyPath=e),this.propertyPath=`${this.propertyPath}.${t}`,this.propertyPath.startsWith(".")&&(this.propertyPath=this.propertyPath.substring(1,this.propertyPath.length))}isDefined(t){return!!(typeof t=="number"&&t===0||t||t===""||typeof t=="boolean")}checkForRequiredKeysErrors(t,e,s){if(!this.areRequiredKeysPresent(t,e)){let r=e?Object.keys(e):[],o=this.findNonOverlappingElements(t,r),n=o.length>0?`Missing the required key: '${o.join(", ")}'!`:`Missing values for required keys: '${r.filter(i=>!e[i]).join(", ")}'!`;s.push({key:"",value:e,success:!1,error:n})}return s}checkForDisallowedProperties(t,e,s,r){if(!r){let o=this.findNonOverlappingElements(t,e);o.length>0&&s.push({key:`${e}`,value:t,success:!1,error:`Has additional (disallowed) properties: '${o.join(", ")}'!`})}return s}handleValidation(t,e,s,r){this.updatePropertyPath(t);let o=this.validateProperty(this.propertyPath,s,e);r.push(...o);let n=(a,l)=>{a.forEach(c=>{let p=this.validateProperty(this.propertyPath,l.items,c);r.push(...p)}),this.updatePropertyPath()},i=a=>{let l=Object.keys(a),c=this.propertyPath;l.forEach(p=>{if(this.updatePropertyPath(p,c),this.isArray(a[p])&&s[p]?.items!=null)n(a[p],s[p]);else{let u=this.validateProperty(this.propertyPath,s[p],a[p]);r.push(...u)}})};this.isArray(e)&&s.items!=null?n(e,s):this.isObject(e)?i(e):this.updatePropertyPath()}handleNestedObject(t,e,s,r){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,s,r)}}}getNestedObjects(t){return Object.keys(t).filter(e=>{if(this.isObject(t))return e})}findNonOverlappingElements(t,e){return t.filter(s=>!e.includes(s))}areRequiredKeysPresent(t,e=[]){return t.every(s=>Object.keys(e).includes(s)?this.isDefined(e[s]):!1)}validateProperty(t,e,s){return this.validateInput(e,s).map(o=>{let{success:n,error:i}=o;return{key:t,value:s,success:n,error:i??""}})}validateInput(t,e){if(t){let s=[{condition:()=>t.type,validator:()=>this.isCorrectType(t.type,e),error:"Invalid type"},{condition:()=>t.format,validator:()=>this.isCorrectFormat(t.format,e),error:"Invalid format"},{condition:()=>t.minLength,validator:()=>this.isMinimumLength(t.minLength,e),error:"Length too short"},{condition:()=>t.maxLength,validator:()=>this.isMaximumLength(t.maxLength,e),error:"Length too long"},{condition:()=>t.minValue,validator:()=>this.isMinimumValue(t.minValue,e),error:"Value too small"},{condition:()=>t.maxValue,validator:()=>this.isMaximumValue(t.maxValue,e),error:"Value too large"},{condition:()=>t.matchesPattern,validator:()=>this.matchesPattern(t.matchesPattern,e),error:"Pattern does not match"}],r=[];for(let o of s)o.condition()&&!o.validator()&&r.push({success:!1,error:o.error});return r}else this.isSilent||console.warn(`Missing property '${t}' for match '${e}'. Skipping...`);return[{success:!0}]}isCorrectType(t,e){return Array.isArray(t)||(t=[t]),t.some(s=>{switch(s){case"string":return typeof e=="string";case"number":return typeof e=="number"&&!isNaN(e);case"boolean":return typeof e=="boolean";case"object":return this.isObject(e);case"array":return this.isArray(e)}})}isObject(t){return t!==null&&!this.isArray(t)&&typeof t=="object"&&t instanceof Object&&Object.prototype.toString.call(t)==="[object Object]"}isArray(t){return Array.isArray(t)}isCorrectFormat(t,e){switch(t){case"alphanumeric":return new RegExp(/^[a-zA-Z0-9]+$/).test(e);case"numeric":return new RegExp(/^-?\d+(\.\d+)?$/).test(e);case"email":return new RegExp(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/).test(e);case"date":return new RegExp(/^\d{4}-\d{2}-\d{2}$/).test(e);case"url":return new RegExp(/^(https?):\/\/[^\s$.?#].[^\s]*$/).test(e);case"hexColor":return new RegExp(/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i).test(e)}}isMinimumLength(t,e){return Array.isArray(e)?e.length>=t:e?.toString().length>=t}isMaximumLength(t,e){return Array.isArray(e)?e.length<=t:e.toString().length<=t}isMinimumValue(t,e){return e>=t}isMaximumValue(t,e){return e<=t}matchesPattern(t,e){return new RegExp(t).test(e)}schemaFrom(t){let e={properties:{additionalProperties:!1,required:[]}};for(let s in t){let r=t[s];e.properties.required.push(s),Array.isArray(r)?e.properties[s]=this.generateArraySchema(r):typeof r=="object"&&r!==null?e.properties[s]=this.generateNestedObjectSchema(r):e.properties[s]=this.generatePropertySchema(r)}return e}generateArraySchema(t){let e={type:"array"},s=t.filter(r=>r);if(s.length>0){let r=s[0];s.every(n=>typeof n==typeof r)?typeof r=="object"&&!Array.isArray(r)?e.items=this.generateNestedObjectSchema(r):e.items=this.generatePropertySchema(r):console.warn("All elements in array are not of the same type. Unable to generate a schema for these elements.")}return e}generateNestedObjectSchema(t){let e={type:"object",additionalProperties:!1,required:[]};for(let s in t){let r=t[s];e.required.push(s),typeof r=="object"&&!Array.isArray(r)&&r!==null?e[s]=this.generateNestedObjectSchema(r):e[s]=this.generatePropertySchema(r)}return e}generatePropertySchema(t){let e=typeof t,s={type:e};return e==="string"&&(s.minLength=1),s}};async function k(t){return t.body||{}}var F={properties:{public:{type:"boolean"},context:{type:"string",minLength:1}},additionalProperties:!1};var St=new C(!0);async function z(t,e,s){try{let r=t.params.bucket;if(!r)return t.json({error:"bucket parameter is required"},400);let o=await k(t),n=St.test(F,o||{});if(!n.success)return t.json({error:"Invalid input",details:n.errors},400);await y(t,s,"storage.bucket.create","storage","bucket","create");let{public:i}=o||{};return await e.createBucket(r,i),t.json({success:!0,bucket:r,public:i||!1},200)}catch(r){let{message:o,status:n}=g(r,"Error creating bucket");return t.json({error:o},n)}}async function G(t,e,s){try{let r=t.params.bucket;if(!r)return t.json({error:"bucket parameter is required"},400);await y(t,s,"storage.bucket.read","storage","bucket","read",r);let o=await e.getBucketStats(r),n=await e.isBucketPublic(r);return t.json({bucket:r,...o,public:n},200)}catch(r){let{message:o,status:n}=g(r,"Error getting bucket stats");return t.json({error:o},n)}}var J={properties:{public:{type:"boolean"}},required:["public"],additionalProperties:!1};var Pt=new C(!0);async function W(t,e,s){try{let r=t.params.bucket;if(!r)return t.json({error:"bucket parameter is required"},400);let o;try{o=await k(t)}catch{return t.json({error:"Invalid JSON body"},400)}let{public:n}=o;if(n===void 0)return t.json({error:"No valid configuration provided"},400);let i=Pt.test(J,o);if(!i.success)return t.json({error:"Invalid input",details:i.errors},400);if(await y(t,s,"storage.bucket.update","storage","bucket","update",r),!await e.bucketExists(r))return t.json({error:"Bucket not found"},404);await e.updateBucket(r,{public:n});let l=await e.isBucketPublic(r);return t.json({success:!0,bucket:r,public:l},200)}catch(r){let{message:o,status:n}=g(r,"Error updating bucket");return t.json({error:o},n)}}async function _(t,e,s){try{let r=t.params.bucket;return r?(await y(t,s,"storage.bucket.delete","storage","bucket","delete",r),await e.bucketExists(r)?(await e.deleteBucket(r),t.json({success:!0,bucket:r},200)):t.json({error:"Bucket not found"},404)):t.json({error:"bucket parameter is required"},400)}catch(r){let{message:o,status:n}=g(r,"Error deleting bucket");return t.json({error:o},n)}}async function X(t,e,s){try{let r=t.params.bucket;if(!r)return t.json({error:"bucket parameter is required"},400);let o=t.query.prefix||"";await y(t,s,"storage.object.list","storage","object","list");let n=await e.listObjects(r,o);return t.json({objects:n,prefix:o},200)}catch(r){let{message:o,status:n}=g(r,"Error listing objects");return t.json({error:o},n)}}var Z={properties:{key:{type:"string",minLength:1},content:{type:"string"}},required:["key"],additionalProperties:!1};var Rt=new C(!0);async function K(t,e,s){try{let r=t.params.bucket,o=t.headers["content-type"]||"";if(!r)return t.json({error:"bucket parameter is required"},400);if(await y(t,s,"storage.object.write","storage","object","write"),o.includes("multipart/form-data")){let{fields:u,files:d}=t.body,h=u?.key,m=d?.file;if(!h)return t.json({error:"key is required"},400);if(!m)return t.json({error:"file is required"},400);let f;return Buffer.isBuffer(m)?f=m:m.data&&Buffer.isBuffer(m.data)?f=m.data:m.data?f=Buffer.from(m.data):f=Buffer.from(m),await e.putObject(r,h,f),t.json({success:!0,bucket:r,key:h},200)}if(o.includes("application/json")){let u=t.body;if(typeof t.body=="string")try{u=JSON.parse(t.body)}catch{u=t.body}if(u&&typeof u=="object"&&("fields"in u||"files"in u)){let{fields:d,files:h}=u,m=d?.key,f=h?.file;if(!m)return t.json({error:"key is required"},400);if(!f)return t.json({error:"file is required"},400);let S;return Buffer.isBuffer(f)?S=f:f.data&&Buffer.isBuffer(f.data)?S=f.data:f.data?f.data.type==="Buffer"&&Array.isArray(f.data.data)?S=Buffer.from(f.data.data):S=Buffer.from(f.data):typeof f=="object"&&f.type==="Buffer"&&Array.isArray(f.data)?S=Buffer.from(f.data):S=Buffer.from(f),await e.putObject(r,m,S),t.json({success:!0,bucket:r,key:m},200)}}if(o.includes("application/octet-stream")||o.includes("video/")||o.includes("image/")){let u=t.query.key;if(!u)return t.json({error:"key query parameter is required for binary uploads"},400);let d=Buffer.isBuffer(t.body)?t.body:Buffer.from(t.body);return await e.putObject(r,u,d),t.json({success:!0,bucket:r,key:u},200)}let n=await k(t),i=Rt.test(Z,n);if(!i.success)return t.json({error:"Invalid input",details:i.errors},400);let{key:a,content:l}=n;if(!a)return t.json({error:"key is required"},400);if(!l)return t.json({error:"content is required"},400);let p=l.length>=20&&l.length%4===0&&/^[A-Za-z0-9+/]*={0,2}$/.test(l)?Buffer.from(l,"base64"):l;return await e.putObject(r,a,p),t.json({success:!0,bucket:r,key:a},200)}catch(r){let{message:o,status:n}=g(r,"Error storing object");return t.json({error:o},n)}}var Y={properties:{key:{type:"string",minLength:1}},required:["key"],additionalProperties:!1};var It=new C(!0);async function Q(t,e,s){try{let r=t.params.bucket;if(!r)return t.json({error:"bucket parameter is required"},400);let o=await k(t),n=It.test(Y,o);if(!n.success)return t.json({error:"Invalid input",details:n.errors},400);await y(t,s,"storage.object.read","storage","object","read");let{key:i}=o;if(!await e.objectExists(r,i))return t.json({error:"Object not found"},404);let l=await e.getObject(r,i);return t.json({bucket:r,key:i,content:l.toString()},200)}catch(r){let{message:o,status:n}=g(r,"Error getting object");return t.json({error:o},n)}}var tt={properties:{key:{type:"string",minLength:1}},required:["key"],additionalProperties:!1};var Tt=new C(!0);async function et(t,e,s){try{let r=t.params.bucket;if(!r)return t.json({error:"bucket parameter is required"},400);let o=await k(t),n=Tt.test(tt,o);if(!n.success)return t.json({error:"Invalid input",details:n.errors},400);await y(t,s,"storage.object.delete","storage","object","delete");let{key:i}=o;return await e.objectExists(r,i)?(await e.deleteObject(r,i),t.json({success:!0,bucket:r,key:i},200)):t.json({error:"Object not found"},404)}catch(r){let{message:o,status:n}=g(r,"Error deleting object");return t.json({error:o},n)}}import Mt from"node:crypto";function rt(t,e,s,r){try{let[o,n]=t.split(".");if(!o||!n)return!1;let i=Buffer.from(o,"base64url").toString("utf-8"),a=JSON.parse(i);if(Date.now()>=a.expiresAt||a.bucket!==e||a.key!==s)return!1;let l=x().molnos.signedUrlSecret,c=Mt.createHmac("sha256",r||l).update(i).digest("base64url");return n===c}catch{return!1}}import{extname as At}from"node:path";function st(t){let e=At(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 ot(t,e,s){try{let r=t.params.bucket,n=new URL(t.req.url||"","http://localhost").pathname.match(/^\/buckets\/[^/]+\/objects\/(.+)$/);if(!n)return t.json({error:"Invalid object path"},400);let i=decodeURIComponent(n[1]);if(!r)return t.json({error:"bucket parameter is required"},400);if(!await e.isBucketPublic(r)){let u=t.query.token;if(u){if(!rt(u,r,i))return t.json({error:"Invalid or expired token"},401)}else await y(t,s,"storage.object.read","storage","object","read")}if(!await e.objectExists(r,i))return t.json({error:"Object not found"},404);let c=await e.getObject(r,i),p=st(i);return t.binary(c,p)}catch(r){let{message:o,status:n}=g(r,"Error retrieving object");return t.json({error:o},n)}}import $t from"node:crypto";function it(t,e,s,r){let o=JSON.stringify({bucket:t,key:e,expiresAt:s}),n=x().molnos.signedUrlSecret,i=$t.createHmac("sha256",r||n).update(o).digest("base64url");return`${Buffer.from(o).toString("base64url")}.${i}`}var Ht=3600;function nt(t,e,s){let r=parseInt(t.query.expiresIn,10),o=Number.isNaN(r)?Ht:r,n=Date.now()+o*1e3,i=it(e,s,n),a=t.req.headers["x-forwarded-proto"]||"http",l=t.req.headers.host||"localhost:3000";return{signedUrl:`${a}://${l}/buckets/${e}/objects/${encodeURIComponent(s)}?token=${i}`,expiresAt:n,expirySeconds:o}}async function at(t,e,s){try{let r=t.params.bucket,n=new URL(t.req.url||"","http://localhost").pathname.match(/^\/buckets\/[^/]+\/objects\/(.+)\/sign$/);if(!n)return t.json({error:"Invalid object path"},400);let i=decodeURIComponent(n[1]);if(!r)return t.json({error:"bucket parameter is required"},400);if(await y(t,s,"storage.object.read","storage","object","read"),!await e.objectExists(r,i))return t.json({error:"Object not found"},404);let{signedUrl:l,expiresAt:c,expirySeconds:p}=nt(t,r,i);return t.json({url:l,expiresAt:new Date(c).toISOString(),expiresIn:p})}catch(r){let{message:o,status:n}=g(r,"Error signing object URL");return t.json({error:o},n)}}function ct(t){return t&&typeof t=="number"&&t>0?t*1024*1024:0}function ut(t,e){let s={enabled:!1,requestsPerMinute:0};if(!e)return s;let r=e.services?.[t];return r||(e.global?e.global:s)}function lt(t,e){let s=t?.api?.port;if(!s)throw new Error('Missing "port" input when create API service!');let r=x(),o=t?.dataPath||r.molnos.dataPath,n=t?.api?.host||r.server.host,i=t?.identityApiUrl!==void 0?t.identityApiUrl:r.identity.apiUrl,a=t?.contextApiUrl!==void 0?t.contextApiUrl:r.context.apiUrl,l=t?.debug||!1,c;return e&&(c=ut(e,r.molnos.rateLimit)),{dataPath:o,api:{port:s,host:n},...i?{identityApiUrl:i}:{},...a?{contextApiUrl:a}:{},...c?{rateLimit:c}:{},debug:l}}var R=class{baseUrl;authToken;constructor(e,s){this.baseUrl=e.replace(/\/$/,""),this.authToken=s}async createCustomRole(e,s,r,o){let n=await fetch(`${this.baseUrl}/identity/roles`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({roleId:e,name:s,description:r,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,s){let r=await fetch(`${this.baseUrl}/identity/roles/${e}`,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(s)});if(!r.ok){let o=await r.json();throw new Error(o.error||`Failed to update role: ${r.statusText}`)}}async deleteRole(e){let s=await fetch(`${this.baseUrl}/identity/roles/${e}`,{method:"DELETE",headers:this.getHeaders()});if(!s.ok){let r=await s.json();throw new Error(r.error||`Failed to delete role: ${s.statusText}`)}}async addServiceAccount(e,s,r){let o=await fetch(`${this.baseUrl}/identity/service-accounts`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({name:e,description:s,roles:r})});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 s=await fetch(`${this.baseUrl}/identity/service-accounts/${e}`,{method:"DELETE",headers:this.getHeaders()});if(!s.ok){let r=await s.json();throw new Error(r.error||`Failed to delete service account: ${s.statusText}`)}}async getUserFromToken(e){try{let s=await fetch(`${this.baseUrl}/identity/whoami`,{method:"GET",headers:{Authorization:`Bearer ${e}`}});return s.ok?await s.json():null}catch{return null}}getHeaders(){let e={"Content-Type":"application/json"};return this.authToken&&(e.Authorization=`Bearer ${this.authToken}`),e}};function dt(t){return t?new R(t):null}var O=class{baseUrl;constructor(e){this.baseUrl=e.replace(/\/$/,"")}async listResourcesByType(e,s,r){let o=`${this.baseUrl}/contexts/${encodeURIComponent(e)}`;try{let n={"Content-Type":"application/json"};r&&(n.Authorization=`Bearer ${r}`);let i=await fetch(o,{method:"GET",headers:n});if(!i.ok)return[];let l=(await i.json()).context?.resources||{};switch(s){case"function":return l.functions||[];case"database":return l.databases||[];case"storage":return l.storage||[];case"site":return l.sites||[];default:return[]}}catch{return[]}}};function pt(t){return t?new O(t):null}var j=class extends Error{constructor(e){super(),this.name="NotFoundError",this.message=e||"Resource not found",this.cause={statusCode:404}}};var $=class{rootPath;metadataPath;constructor(e){this.rootPath=e.path||"storage-data",this.metadataPath=w(this.rootPath,".metadata")}async start(){await b.mkdir(this.rootPath,{recursive:!0}),await b.mkdir(this.metadataPath,{recursive:!0})}getBucketMetadataPath(e){return w(this.metadataPath,`${e}.json`)}async readBucketMetadata(e){let s=this.getBucketMetadataPath(e);try{let r=await b.readFile(s,"utf-8");return JSON.parse(r)}catch{return{public:!1}}}async writeBucketMetadata(e,s){let r=this.getBucketMetadataPath(e);await b.writeFile(r,JSON.stringify(s,null,2))}async deleteBucketMetadata(e){let s=this.getBucketMetadataPath(e);try{await b.unlink(s)}catch{}}async putObject(e,s,r){let o=w(this.rootPath,e,s);await b.mkdir(Lt(o),{recursive:!0}),await b.writeFile(o,r)}async getObject(e,s){let r=w(this.rootPath,e,s);return await b.readFile(r)}async deleteObject(e,s){let r=w(this.rootPath,e,s);await b.unlink(r)}async objectExists(e,s){let r=w(this.rootPath,e,s);try{return await b.access(r),!0}catch{return!1}}async createBucket(e,s=!1){let r=w(this.rootPath,e);await b.mkdir(r,{recursive:!0}),await this.writeBucketMetadata(e,{public:s})}async deleteBucket(e){let s=w(this.rootPath,e);await b.rm(s,{recursive:!0,force:!0}),await this.deleteBucketMetadata(e)}async bucketExists(e){let s=w(this.rootPath,e);try{return(await b.stat(s)).isDirectory()}catch{return!1}}async isBucketPublic(e){return(await this.readBucketMetadata(e)).public}async updateBucket(e,s){if(!await this.bucketExists(e))throw new Error("Bucket not found");let n={...await this.readBucketMetadata(e),...s.public!==void 0&&{public:s.public}};await this.writeBucketMetadata(e,n)}async listBuckets(){try{return(await b.readdir(this.rootPath,{withFileTypes:!0})).filter(s=>s.isDirectory()).map(s=>s.name)}catch{return[]}}async getBucketStats(e){let s=w(this.rootPath,e);try{if(!(await b.stat(s)).isDirectory())throw new j("Bucket not found")}catch(i){throw i.code==="ENOENT"?new j("Bucket not found"):i}let r=0,o=0,n=async i=>{let a=await b.readdir(i,{withFileTypes:!0});for(let l of a){let c=w(i,l.name);if(l.isDirectory())await n(c);else if(l.isFile()){r++;let p=await b.stat(c);o+=p.size}}};try{await n(s)}catch{return{objectCount:0,totalSize:0}}return{objectCount:r,totalSize:o}}async listObjects(e,s=""){let r=w(this.rootPath,e);try{if(!(await b.stat(r)).isDirectory())throw new j("Bucket not found")}catch(c){throw c.code==="ENOENT"?new j("Bucket not found"):c}let o=[],n=async(c,p="")=>{let u=await b.readdir(c,{withFileTypes:!0});for(let d of u){let h=w(c,d.name),m=p?`${p}/${d.name}`:d.name;if(d.isDirectory())await n(h,m);else if(d.isFile()){let f=await b.stat(h);o.push({key:m,size:f.size,lastModified:f.mtime,type:"file"})}}};try{await n(r)}catch{return[]}let i=s?o.filter(c=>c.key.startsWith(s)):o,a=[],l=new Set;for(let c of i){let p=s?c.key.substring(s.length):c.key,u=p.indexOf("/");if(u===-1)a.push({key:p,size:c.size,lastModified:c.lastModified,type:"file"});else{let d=p.substring(0,u);l.has(d)||(l.add(d),a.push({key:`${d}/`,size:0,lastModified:c.lastModified,type:"folder"}))}}return a.sort((c,p)=>c.type!==p.type?c.type==="folder"?-1:1:c.key.localeCompare(p.key))}};async function qt(t){let e=t.dataPath||"data",s=w(e,"storage"),r=new $({path:s});await r.start();let o=dt(t.identityApiUrl),n=pt(t.contextApiUrl),i=x(),a=new A({port:t.api.port||i.services.storage.port,host:t.api.host||i.services.storage.host,maxBodySize:ct(1e3),rateLimit:t.rateLimit||{enabled:!1,requestsPerMinute:0}});return a.get("/buckets",async c=>U(c,r,o,n)),a.post("/buckets/:bucket",async c=>z(c,r,o)),a.get("/buckets/:bucket",async c=>G(c,r,o)),a.patch("/buckets/:bucket",async c=>W(c,r,o)),a.delete("/buckets/:bucket",async c=>_(c,r,o)),a.get("/buckets/:bucket/objects",async c=>X(c,r,o)),a.put("/buckets/:bucket/objects",async c=>K(c,r,o)),a.post("/buckets/:bucket/objects",async c=>Q(c,r,o)),a.delete("/buckets/:bucket/objects",async c=>et(c,r,o)),a.post("/buckets/:bucket/objects/*",async c=>new URL(c.req.url||"","http://localhost").pathname.endsWith("/sign")?at(c,r,o):c.json({error:"Not Found"},404)),a.get("/buckets/:bucket/objects/*",async c=>ot(c,r,o)),a.start()}if(import.meta.url===`file://${process.argv[1]}`){let t=x(),s=process.argv.slice(2).find(n=>n.startsWith("--port=")),r=s?parseInt(s.split("=")[1],10):t.services.storage.port,o=lt({api:{port:r}},"storage");qt(o)}export{$ as StorageService,qt as startServer};
10
+ `),s=t.indexOf(e);if(s===-1)return null;let r=t.subarray(0,s),i=t.subarray(s+4),o=r.toString("utf8").split(`\r
11
+ `),a="",l="",c,p;for(let d of o){let g=d.toLowerCase();if(g.startsWith("content-disposition:")){a=d.substring(20).trim();let m=a.match(/name="([^"]+)"/);m&&(l=m[1]);let f=a.match(/filename="([^"]+)"/);f&&(c=f[1])}else g.startsWith("content-type:")&&(p=d.substring(13).trim())}if(!l)return null;let u=i;return u.length>=2&&u[u.length-2]===13&&u[u.length-1]===10&&(u=u.subarray(0,u.length-2)),{disposition:a,name:l,filename:c,contentType:p,data:u}}import{readFileSync as E}from"fs";import N from"http";import Ct from"http2";import Pt from"https";var H=class{config;rateLimiter;router;shutdownHandlers=[];constructor(t){let e=new A(U(t||{})).get();e.debug&&console.log("Using configuration:",e),this.config=e,this.router=new D;let s=e.rateLimit.requestsPerMinute||R().rateLimit.requestsPerMinute;this.rateLimiter=new V(s,60),e.rateLimit.enabled===!0&&this.use(this.rateLimitMiddleware.bind(this))}use(t){return this.router.use(t),this}get(t,...e){return this.router.get(t,...e),this}post(t,...e){return this.router.post(t,...e),this}put(t,...e){return this.router.put(t,...e),this}delete(t,...e){return this.router.delete(t,...e),this}patch(t,...e){return this.router.patch(t,...e),this}any(t,...e){return this.router.any(t,...e),this}options(t,...e){return this.router.options(t,...e),this}start(){let t=this.createServer(),{port:e,host:s}=this.config;return this.setupGracefulShutdown(t),t.listen(e,s,()=>{let r=t.address(),i=this.config.useHttps||this.config.useHttp2?"https":"http";console.log(`MikroServe running at ${i}://${r.address!=="::"?r.address:"localhost"}:${r.port}`)}),t}createServer(){let t=this.requestHandler.bind(this);if(this.config.useHttp2){if(!this.config.sslCert||!this.config.sslKey)throw new Error("SSL certificate and key paths are required when useHttp2 is true");try{let e={key:E(this.config.sslKey),cert:E(this.config.sslCert),...this.config.sslCa?{ca:E(this.config.sslCa)}:{}};return Ct.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:E(this.config.sslKey),cert:E(this.config.sslCert),...this.config.sslCa?{ca:E(this.config.sslCa)}:{}};return Pt.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 N.createServer(t)}async rateLimitMiddleware(t,e){let s=t.req.socket.remoteAddress||"unknown";return t.res.setHeader("X-RateLimit-Limit",this.rateLimiter.getLimit().toString()),t.res.setHeader("X-RateLimit-Remaining",this.rateLimiter.getRemainingRequests(s).toString()),t.res.setHeader("X-RateLimit-Reset",this.rateLimiter.getResetTime(s).toString()),this.rateLimiter.isAllowed(s)?e():{statusCode:429,body:{error:"Too Many Requests",message:"Rate limit exceeded, please try again later"},headers:{"Content-Type":"application/json"}}}async requestHandler(t,e){let s=Date.now(),r=t.method||"UNKNOWN",i=t.url||"/unknown",n=this.config.debug;try{if(this.setCorsHeaders(e,t),this.setSecurityHeaders(e,this.config.useHttps),n&&console.log(`${r} ${i}`),t.method==="OPTIONS"){if(e instanceof N.ServerResponse)e.statusCode=204,e.end();else{let a=e;a.writeHead(204),a.end()}return}try{t.body=await this.parseBody(t)}catch(a){return n&&console.error("Body parsing error:",a.message),this.respond(e,{statusCode:400,body:{error:"Bad Request",message:a.message}})}let o=await this.router.handle(t,e);return o?o._handled?void 0:this.respond(e,o):this.respond(e,{statusCode:404,body:{error:"Not Found",message:"The requested endpoint does not exist"}})}catch(o){return console.error("Server error:",o),this.respond(e,{statusCode:500,body:{error:"Internal Server Error",message:n?o.message:"An unexpected error occurred"}})}finally{n&&this.logDuration(s,r,i)}}logDuration(t,e,s){let r=Date.now()-t;console.log(`${e} ${s} completed in ${r}ms`)}async parseBody(t){return new Promise((e,s)=>{let r=[],i=0,n=this.config.maxBodySize,o=!1,a=null,l=this.config.debug,c=t.headers["content-type"]||"";l&&console.log("Content-Type:",c),this.config.requestTimeout>0&&(a=setTimeout(()=>{o||(o=!0,l&&console.log("Request timeout exceeded"),s(new Error("Request timeout")))},this.config.requestTimeout));let p=()=>{a&&(clearTimeout(a),a=null)};t.on("data",u=>{if(!o){if(i+=u.length,l&&console.log(`Received chunk: ${u.length} bytes, total size: ${i}`),i>n){o=!0,p(),l&&console.log(`Body size exceeded limit: ${i} > ${n}`),s(new Error("Request body too large"));return}r.push(u)}}),t.on("end",()=>{if(!o){o=!0,p(),l&&console.log(`Request body complete: ${i} bytes`);try{if(r.length>0){let u=Buffer.concat(r);if(c.includes("application/json"))try{let d=u.toString("utf8");e(JSON.parse(d))}catch(d){s(new Error(`Invalid JSON in request body: ${d.message}`))}else if(c.includes("application/x-www-form-urlencoded")){let d=u.toString("utf8"),g={};new URLSearchParams(d).forEach((m,f)=>{g[f]=m}),e(g)}else if(c.includes("multipart/form-data"))try{let d=F(u,c);e(d)}catch(d){s(new Error(`Invalid multipart form data: ${d.message}`))}else this.isBinaryContentType(c)?e(u):e(u.toString("utf8"))}else e({})}catch(u){s(new Error(`Invalid request body: ${u}`))}}}),t.on("error",u=>{o||(o=!0,p(),s(new Error(`Error reading request body: ${u.message}`)))}),t.on("close",()=>{p()})})}isBinaryContentType(t){return["application/octet-stream","application/pdf","application/zip","application/gzip","application/x-tar","application/x-rar-compressed","application/x-7z-compressed","image/","video/","audio/","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument","application/msword","application/vnd.ms-powerpoint"].some(s=>t.includes(s))}setCorsHeaders(t,e){let s=e.headers.origin,{allowedDomains:r=["*"]}=this.config;!s||r.length===0||r.includes("*")?t.setHeader("Access-Control-Allow-Origin","*"):r.includes(s)&&(t.setHeader("Access-Control-Allow-Origin",s),t.setHeader("Vary","Origin")),t.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, PATCH, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization"),t.setHeader("Access-Control-Max-Age","86400")}setSecurityHeaders(t,e=!1){let s={"X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","Content-Security-Policy":"default-src 'self'; script-src 'self'; object-src 'none'","X-XSS-Protection":"1; mode=block"};if((e||this.config.useHttp2)&&(s["Strict-Transport-Security"]="max-age=31536000; includeSubDomains"),t instanceof N.ServerResponse)Object.entries(s).forEach(([r,i])=>{t.setHeader(r,i)});else{let r=t;Object.entries(s).forEach(([i,n])=>{r.setHeader(i,n)})}}respond(t,e){let s={...e.headers||{}};(i=>typeof i.writeHead=="function"&&typeof i.end=="function")(t)?(t.writeHead(e.statusCode,s),e.body===null||e.body===void 0?t.end():e.isRaw||typeof e.body=="string"?t.end(e.body):t.end(JSON.stringify(e.body))):(console.warn("Unexpected response object type without writeHead/end methods"),t.writeHead?.(e.statusCode,s),e.body===null||e.body===void 0?t.end?.():e.isRaw||typeof e.body=="string"?t.end?.(e.body):t.end?.(JSON.stringify(e.body)))}setupGracefulShutdown(t){let e=o=>{console.log("Shutting down MikroServe server..."),o&&console.error("Error:",o),this.cleanupShutdownHandlers(),t.close(()=>{console.log("Server closed successfully"),process.env.NODE_ENV!=="test"&&process.env.VITEST!=="true"&&setImmediate(()=>process.exit(o?1:0))})},s=()=>e(),r=()=>e(),i=o=>e(o),n=o=>e(o);this.shutdownHandlers=[s,r,i,n],process.on("SIGINT",s),process.on("SIGTERM",r),process.on("uncaughtException",i),process.on("unhandledRejection",n)}cleanupShutdownHandlers(){if(this.shutdownHandlers.length>0){let[t,e,s,r]=this.shutdownHandlers;process.removeListener("SIGINT",t),process.removeListener("SIGTERM",e),process.removeListener("uncaughtException",s),process.removeListener("unhandledRejection",r),this.shutdownHandlers=[]}}};import{join as M,dirname as Gt,resolve as B,relative as Wt,isAbsolute as Jt}from"node:path";import{promises as v}from"node:fs";function y(t,e="An error occurred"){let s=t?.message||t||e,r=t?.cause?.statusCode||t?.statusCode||400;return{message:s,status:r}}function z(t,e,s={}){let r=Array.isArray(e)?e:[e];if(!t||!t.roles||!Array.isArray(t.roles)){let o=new Error("Unauthorized: User or roles missing");throw o.cause={statusCode:403},o}let i=t.roles.flatMap(o=>o?.policies?.flatMap(a=>(a?.permissions||[]).flatMap(c=>typeof c=="string"?c:c&&typeof c=="object"&&c.actions?c.actions:[]))||[]);if(!r.every(o=>i.some(a=>Et(a,o)))){let o=new Error("Unauthorized");throw o.cause={statusCode:403},o}return!0}function Et(t,e){if(t==="*"||t===e)return!0;if(!t.includes("*"))return!1;let s=t.split("*").map(i=>i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join(".*");return new RegExp(`^${s}$`).test(e)}function G(t,e,s,r,i){let n=t.find(l=>l.service===e);if(!n){let l=new Error(`Function bindings do not include access to service: ${e}`);throw l.cause={statusCode:403},l}if(!n.permissions||n.permissions.length===0)return;for(let l of n.permissions)if(!(l.resource&&l.resource!==s)){if(!l.resource||!l.actions||l.actions.length===0)return;if(l.actions.includes(r)&&!(l.targets&&l.targets.length>0&&(!i||!l.targets.includes(i)&&!l.targets.includes("*"))))return}let o=i?`:${i}`:"",a=new Error(`Function bindings do not allow: ${e}.${s}.${r}${o}`);throw a.cause={statusCode:403},a}import{readFileSync as Rt,existsSync as It}from"node:fs";function S(){let t=process.env.MOLNOS_RUNTIME_CONFIG,e={molnos:{dataPath:"data",rateLimit:{global:{enabled:!1,requestsPerMinute:0}},signedUrlSecret:"molnos-default-signed-url-secret"},server:{host:"127.0.0.1",port:3e3},identity:{apiUrl:"http://127.0.0.1:3000"},context:{apiUrl:"http://127.0.0.1:3000"},services:{storage:{host:"127.0.0.1",port:3001,url:"http://127.0.0.1:3001"},functions:{host:"127.0.0.1",port:3002,url:"http://127.0.0.1:3002"},sites:{host:"127.0.0.1",port:3003,url:"http://127.0.0.1:3003"},databases:{host:"127.0.0.1",port:3004,url:"http://127.0.0.1:3004"},observability:{host:"127.0.0.1",port:3005,url:"http://127.0.0.1:3005"}}};if(!t||!It(t))return e;try{let s=Rt(t,"utf-8");return JSON.parse(s)}catch(s){return console.error("[loadRuntimeConfig] Failed to load runtime config:",s),e}}async function b(t,e,s,r,i,n,o){if(!e)return null;let a=t.headers["x-molnos-service-token"];if(a){let p=S();if(p.internalServiceSecret&&a===p.internalServiceSecret)return null}let l=t.state.user;if(!l){let p=t.headers.authorization;if(!p){let d=new Error("Unauthorized: No authentication provided");throw d.cause={statusCode:401},d}let u=p.replace(/^Bearer\s+/i,"");if(l=await e.getUserFromToken(u),!l){let d=new Error("Unauthorized: Invalid token");throw d.cause={statusCode:401},d}}z(l,s,{});let c=t.headers["x-function-bindings"];if(c)try{let p=Array.isArray(c)?c[0]:c,u=JSON.parse(p);G(u,r,i,n,o)}catch(p){if(p.cause?.statusCode===403)throw p;let u=new Error("Invalid function bindings header");throw u.cause={statusCode:400},u}return l}var h={applications:{application:{create:"applications.application.create",read:"applications.application.read",list:"applications.application.list",update:"applications.application.update",delete:"applications.application.delete"}},builder:{artifact:{read:"builder.artifact.read",list:"builder.artifact.list",update:"builder.artifact.update"},revision:{create:"builder.revision.create",read:"builder.revision.read",list:"builder.revision.list",activate:"builder.revision.activate"},run:{plan:"builder.run.plan",import:"builder.run.import",generate:"builder.run.generate",evolve:"builder.run.evolve",apply:"builder.run.apply",evaluate:"builder.run.evaluate",read:"builder.run.read",list:"builder.run.list"}},contexts:{context:{create:"contexts.context.create",get:"contexts.context.get",update:"contexts.context.update",delete:"contexts.context.delete",deleteResources:"contexts.context.delete-resources"}},databases:{table:{create:"databases.table.create",get:"databases.table.get",update:"databases.table.update",delete:"databases.table.delete"}},functions:{function:{create:"functions.function.create",get:"functions.function.get",update:"functions.function.update",delete:"functions.function.delete",execute:"functions.function.execute"}},iac:{config:{create:"iac.config.create",get:"iac.config.get"}},identity:{identities:{get:"identity.identities.get"},user:{create:"identity.user.create",get:"identity.user.get",update:"identity.user.update",delete:"identity.user.delete"},role:{create:"identity.role.create",get:"identity.role.get",update:"identity.role.update",delete:"identity.role.delete"},serviceAccount:{create:"identity.service-account.create",get:"identity.service-account.get",update:"identity.service-account.update",delete:"identity.service-account.delete"}},management:{service:{create:"management.service.create",get:"management.service.get",update:"management.service.update",delete:"management.service.delete",start:"management.service.start",stop:"management.service.stop"},services:{get:"management.services.get"}},observability:{event:{create:"observability.event.create",read:"observability.event.read",delete:"observability.event.delete"},stats:{read:"observability.stats.read"},buffer:{write:"observability.buffer.write"},metrics:{read:"observability.metrics.read"}},schemas:{schema:{create:"schemas.schema.create",read:"schemas.schema.read",list:"schemas.schema.list",update:"schemas.schema.update",delete:"schemas.schema.delete"}},sites:{project:{create:"sites.project.create",list:"sites.project.list",delete:"sites.project.delete",download:"sites.project.download"}},storage:{bucket:{create:"storage.bucket.create",read:"storage.bucket.read",update:"storage.bucket.update",delete:"storage.bucket.delete",list:"storage.bucket.list"},object:{write:"storage.object.write",read:"storage.object.read",delete:"storage.object.delete",list:"storage.object.list"}}};function W(t,e){if(typeof t=="string"){e.push(t);return}if(!(!t||typeof t!="object"))for(let s of Object.values(t))W(s,e)}var J=[];W(h,J);var Ot=[...new Set(J)],Je=Object.freeze(Ot);async function _(t,e,s,r){try{await b(t,s,h.storage.bucket.list,"storage","bucket","list");let i=await e.listBuckets(),n=t.query.context;if(n&&r){let o=t.headers.authorization?.replace(/^Bearer\s+/i,""),a=await r.listResourcesByType(n,"storage",o);i=i.filter(l=>a.includes(l))}return t.json({buckets:i},200)}catch(i){let{message:n,status:o}=y(i,"Error listing buckets");return t.json({error:n},o)}}var x=class{isSilent;propertyPath="";constructor(t=!1){this.isSilent=t}test(t,e){if(!e)throw new Error("Missing input!");this.updatePropertyPath();let{results:s,errors:r}=this.validate(t.properties,e),i=this.compileErrors(s,r),n=this.isSuccessful(s,i);return{errors:i,success:n}}compileErrors(t,e){let s=t.filter(r=>r.success===!1);return[...e,...s].flatMap(r=>r)}isSuccessful(t,e){return t.every(s=>s.success===!0)&&e.length===0}validate(t,e,s=[],r=[]){let i=t?.additionalProperties??!0,n=t?.required||[];r=this.checkForRequiredKeysErrors(n,e,r),r=this.checkForDisallowedProperties(Object.keys(e),Object.keys(t),r,i);for(let o in t){let a=n.includes(o)&&o!=="required",l=t[o],c=e[o],p=l.additionalProperties??!0;a&&(r=this.checkForRequiredKeysErrors(l.required||[],c,r)),this.isDefined(c)&&(this.handleValidation(o,c,l,s),r=this.checkForDisallowedProperties(Object.keys(c),Object.keys(l),r,p),this.handleNestedObject(c,l,s,r))}return{results:s,errors:r}}updatePropertyPath(t,e=""){if(!t){this.propertyPath="";return}e&&(this.propertyPath=e),this.propertyPath=`${this.propertyPath}.${t}`,this.propertyPath.startsWith(".")&&(this.propertyPath=this.propertyPath.substring(1,this.propertyPath.length))}isDefined(t){return!!(typeof t=="number"&&t===0||t||t===""||typeof t=="boolean")}checkForRequiredKeysErrors(t,e,s){if(!this.areRequiredKeysPresent(t,e)){let r=e?Object.keys(e):[],i=this.findNonOverlappingElements(t,r),n=i.length>0?`Missing the required key: '${i.join(", ")}'!`:`Missing values for required keys: '${r.filter(o=>!e[o]).join(", ")}'!`;s.push({key:"",value:e,success:!1,error:n})}return s}checkForDisallowedProperties(t,e,s,r){if(!r){let i=this.findNonOverlappingElements(t,e);i.length>0&&s.push({key:`${e}`,value:t,success:!1,error:`Has additional (disallowed) properties: '${i.join(", ")}'!`})}return s}handleValidation(t,e,s,r){this.updatePropertyPath(t);let i=this.validateProperty(this.propertyPath,s,e);r.push(...i);let n=(a,l)=>{a.forEach(c=>{let p=this.validateProperty(this.propertyPath,l.items,c);r.push(...p)}),this.updatePropertyPath()},o=a=>{let l=Object.keys(a),c=this.propertyPath;l.forEach(p=>{if(this.updatePropertyPath(p,c),this.isArray(a[p])&&s[p]?.items!=null)n(a[p],s[p]);else{let u=this.validateProperty(this.propertyPath,s[p],a[p]);r.push(...u)}})};this.isArray(e)&&s.items!=null?n(e,s):this.isObject(e)?o(e):this.updatePropertyPath()}handleNestedObject(t,e,s,r){if(this.isObject(t)){let i=this.getNestedObjects(t);for(let n of i){let o=e[n],a=t[n];o&&typeof a=="object"&&this.validate(o,a,s,r)}}}getNestedObjects(t){return Object.keys(t).filter(e=>{if(this.isObject(t))return e})}findNonOverlappingElements(t,e){return t.filter(s=>!e.includes(s))}areRequiredKeysPresent(t,e=[]){return t.every(s=>Object.keys(e).includes(s)?this.isDefined(e[s]):!1)}validateProperty(t,e,s){return this.validateInput(e,s).map(i=>{let{success:n,error:o}=i;return{key:t,value:s,success:n,error:o??""}})}validateInput(t,e){if(t){let s=[{condition:()=>t.type,validator:()=>this.isCorrectType(t.type,e),error:"Invalid type"},{condition:()=>t.format,validator:()=>this.isCorrectFormat(t.format,e),error:"Invalid format"},{condition:()=>t.minLength,validator:()=>this.isMinimumLength(t.minLength,e),error:"Length too short"},{condition:()=>t.maxLength,validator:()=>this.isMaximumLength(t.maxLength,e),error:"Length too long"},{condition:()=>t.minValue,validator:()=>this.isMinimumValue(t.minValue,e),error:"Value too small"},{condition:()=>t.maxValue,validator:()=>this.isMaximumValue(t.maxValue,e),error:"Value too large"},{condition:()=>t.matchesPattern,validator:()=>this.matchesPattern(t.matchesPattern,e),error:"Pattern does not match"}],r=[];for(let i of s)i.condition()&&!i.validator()&&r.push({success:!1,error:i.error});return r}else this.isSilent||console.warn(`Missing property '${t}' for match '${e}'. Skipping...`);return[{success:!0}]}isCorrectType(t,e){return Array.isArray(t)||(t=[t]),t.some(s=>{switch(s){case"string":return typeof e=="string";case"number":return typeof e=="number"&&!isNaN(e);case"boolean":return typeof e=="boolean";case"object":return this.isObject(e);case"array":return this.isArray(e)}})}isObject(t){return t!==null&&!this.isArray(t)&&typeof t=="object"&&t instanceof Object&&Object.prototype.toString.call(t)==="[object Object]"}isArray(t){return Array.isArray(t)}isCorrectFormat(t,e){switch(t){case"alphanumeric":return new RegExp(/^[a-zA-Z0-9]+$/).test(e);case"numeric":return new RegExp(/^-?\d+(\.\d+)?$/).test(e);case"email":return new RegExp(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/).test(e);case"date":return new RegExp(/^\d{4}-\d{2}-\d{2}$/).test(e);case"url":return new RegExp(/^(https?):\/\/[^\s$.?#].[^\s]*$/).test(e);case"hexColor":return new RegExp(/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i).test(e)}}isMinimumLength(t,e){return Array.isArray(e)?e.length>=t:e?.toString().length>=t}isMaximumLength(t,e){return Array.isArray(e)?e.length<=t:e.toString().length<=t}isMinimumValue(t,e){return e>=t}isMaximumValue(t,e){return e<=t}matchesPattern(t,e){return new RegExp(t).test(e)}schemaFrom(t){let e={properties:{additionalProperties:!1,required:[]}};for(let s in t){let r=t[s];e.properties.required.push(s),Array.isArray(r)?e.properties[s]=this.generateArraySchema(r):typeof r=="object"&&r!==null?e.properties[s]=this.generateNestedObjectSchema(r):e.properties[s]=this.generatePropertySchema(r)}return e}generateArraySchema(t){let e={type:"array"},s=t.filter(r=>r);if(s.length>0){let r=s[0];s.every(n=>typeof n==typeof r)?typeof r=="object"&&!Array.isArray(r)?e.items=this.generateNestedObjectSchema(r):e.items=this.generatePropertySchema(r):console.warn("All elements in array are not of the same type. Unable to generate a schema for these elements.")}return e}generateNestedObjectSchema(t){let e={type:"object",additionalProperties:!1,required:[]};for(let s in t){let r=t[s];e.required.push(s),typeof r=="object"&&!Array.isArray(r)&&r!==null?e[s]=this.generateNestedObjectSchema(r):e[s]=this.generatePropertySchema(r)}return e}generatePropertySchema(t){let e=typeof t,s={type:e};return e==="string"&&(s.minLength=1),s}};async function k(t){return t.body||{}}var K={properties:{public:{type:"boolean"},context:{type:"string",minLength:1}},additionalProperties:!1};var Mt=new x(!0);async function X(t,e,s){try{let r=t.params.bucket;if(!r)return t.json({error:"bucket parameter is required"},400);let i=await k(t),n=Mt.test(K,i||{});if(!n.success)return t.json({error:"Invalid input",details:n.errors},400);await b(t,s,h.storage.bucket.create,"storage","bucket","create");let{public:o}=i||{};return await e.createBucket(r,o),t.json({success:!0,bucket:r,public:o||!1},200)}catch(r){let{message:i,status:n}=y(r,"Error creating bucket");return t.json({error:i},n)}}async function Y(t,e,s){try{let r=t.params.bucket;if(!r)return t.json({error:"bucket parameter is required"},400);await b(t,s,h.storage.bucket.read,"storage","bucket","read",r);let i=await e.getBucketStats(r),n=await e.isBucketPublic(r);return t.json({bucket:r,...i,public:n},200)}catch(r){let{message:i,status:n}=y(r,"Error getting bucket stats");return t.json({error:i},n)}}var Z={properties:{public:{type:"boolean"}},required:["public"],additionalProperties:!1};var At=new x(!0);async function Q(t,e,s){try{let r=t.params.bucket;if(!r)return t.json({error:"bucket parameter is required"},400);let i;try{i=await k(t)}catch{return t.json({error:"Invalid JSON body"},400)}let{public:n}=i;if(n===void 0)return t.json({error:"No valid configuration provided"},400);let o=At.test(Z,i);if(!o.success)return t.json({error:"Invalid input",details:o.errors},400);if(await b(t,s,h.storage.bucket.update,"storage","bucket","update",r),!await e.bucketExists(r))return t.json({error:"Bucket not found"},404);await e.updateBucket(r,{public:n});let l=await e.isBucketPublic(r);return t.json({success:!0,bucket:r,public:l},200)}catch(r){let{message:i,status:n}=y(r,"Error updating bucket");return t.json({error:i},n)}}async function tt(t,e,s){try{let r=t.params.bucket;return r?(await b(t,s,h.storage.bucket.delete,"storage","bucket","delete",r),await e.bucketExists(r)?(await e.deleteBucket(r),t.json({success:!0,bucket:r},200)):t.json({error:"Bucket not found"},404)):t.json({error:"bucket parameter is required"},400)}catch(r){let{message:i,status:n}=y(r,"Error deleting bucket");return t.json({error:i},n)}}async function et(t,e,s){try{let r=t.params.bucket;if(!r)return t.json({error:"bucket parameter is required"},400);let i=t.query.prefix||"";await b(t,s,h.storage.object.list,"storage","object","list");let n=await e.listObjects(r,i);return t.json({objects:n,prefix:i},200)}catch(r){let{message:i,status:n}=y(r,"Error listing objects");return t.json({error:i},n)}}var rt={properties:{key:{type:"string",minLength:1},content:{type:"string"}},required:["key"],additionalProperties:!1};var Nt=new x(!0);async function st(t,e,s){try{let r=t.params.bucket,i=t.headers["content-type"]||"";if(!r)return t.json({error:"bucket parameter is required"},400);if(await b(t,s,h.storage.object.write,"storage","object","write"),i.includes("multipart/form-data")){let{fields:u,files:d}=t.body,g=u?.key,m=d?.file;if(!g)return t.json({error:"key is required"},400);if(!m)return t.json({error:"file is required"},400);let f;return Buffer.isBuffer(m)?f=m:m.data&&Buffer.isBuffer(m.data)?f=m.data:m.data?f=Buffer.from(m.data):f=Buffer.from(m),await e.putObject(r,g,f),t.json({success:!0,bucket:r,key:g},200)}if(i.includes("application/json")){let u=t.body;if(typeof t.body=="string")try{u=JSON.parse(t.body)}catch{u=t.body}if(u&&typeof u=="object"&&("fields"in u||"files"in u)){let{fields:d,files:g}=u,m=d?.key,f=g?.file;if(!m)return t.json({error:"key is required"},400);if(!f)return t.json({error:"file is required"},400);let C;return Buffer.isBuffer(f)?C=f:f.data&&Buffer.isBuffer(f.data)?C=f.data:f.data?f.data.type==="Buffer"&&Array.isArray(f.data.data)?C=Buffer.from(f.data.data):C=Buffer.from(f.data):typeof f=="object"&&f.type==="Buffer"&&Array.isArray(f.data)?C=Buffer.from(f.data):C=Buffer.from(f),await e.putObject(r,m,C),t.json({success:!0,bucket:r,key:m},200)}}if(i.includes("application/octet-stream")||i.includes("video/")||i.includes("image/")){let u=t.query.key;if(!u)return t.json({error:"key query parameter is required for binary uploads"},400);let d=Buffer.isBuffer(t.body)?t.body:Buffer.from(t.body);return await e.putObject(r,u,d),t.json({success:!0,bucket:r,key:u},200)}let n=await k(t),o=Nt.test(rt,n);if(!o.success)return t.json({error:"Invalid input",details:o.errors},400);let{key:a,content:l}=n;if(!a)return t.json({error:"key is required"},400);if(!l)return t.json({error:"content is required"},400);let p=l.length>=20&&l.length%4===0&&/^[A-Za-z0-9+/]*={0,2}$/.test(l)?Buffer.from(l,"base64"):l;return await e.putObject(r,a,p),t.json({success:!0,bucket:r,key:a},200)}catch(r){let{message:i,status:n}=y(r,"Error storing object");return t.json({error:i},n)}}var it={properties:{key:{type:"string",minLength:1}},required:["key"],additionalProperties:!1};var Lt=new x(!0);async function ot(t,e,s){try{let r=t.params.bucket;if(!r)return t.json({error:"bucket parameter is required"},400);let i=await k(t),n=Lt.test(it,i);if(!n.success)return t.json({error:"Invalid input",details:n.errors},400);await b(t,s,h.storage.object.read,"storage","object","read");let{key:o}=i;if(!await e.objectExists(r,o))return t.json({error:"Object not found"},404);let l=await e.getObject(r,o);return t.json({bucket:r,key:o,content:l.toString()},200)}catch(r){let{message:i,status:n}=y(r,"Error getting object");return t.json({error:i},n)}}var nt={properties:{key:{type:"string",minLength:1}},required:["key"],additionalProperties:!1};var Vt=new x(!0);async function at(t,e,s){try{let r=t.params.bucket;if(!r)return t.json({error:"bucket parameter is required"},400);let i=await k(t),n=Vt.test(nt,i);if(!n.success)return t.json({error:"Invalid input",details:n.errors},400);await b(t,s,h.storage.object.delete,"storage","object","delete");let{key:o}=i;return await e.objectExists(r,o)?(await e.deleteObject(r,o),t.json({success:!0,bucket:r,key:o},200)):t.json({error:"Object not found"},404)}catch(r){let{message:i,status:n}=y(r,"Error deleting object");return t.json({error:i},n)}}import Dt from"node:crypto";function ct(t,e,s,r){try{let[i,n]=t.split(".");if(!i||!n)return!1;let o=Buffer.from(i,"base64url").toString("utf-8"),a=JSON.parse(o);if(Date.now()>=a.expiresAt||a.bucket!==e||a.key!==s)return!1;let l=S().molnos.signedUrlSecret,c=Dt.createHmac("sha256",r||l).update(o).digest("base64url");return n===c}catch{return!1}}import{extname as Ut}from"node:path";function ut(t){let e=Ut(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 lt(t,e,s){try{let r=t.params.bucket,n=new URL(t.req.url||"","http://localhost").pathname.match(/^\/buckets\/[^/]+\/objects\/(.+)$/);if(!n)return t.json({error:"Invalid object path"},400);let o=decodeURIComponent(n[1]);if(!r)return t.json({error:"bucket parameter is required"},400);if(!await e.isBucketPublic(r)){let u=t.query.token;if(u){if(!ct(u,r,o))return t.json({error:"Invalid or expired token"},401)}else await b(t,s,h.storage.object.read,"storage","object","read")}if(!await e.objectExists(r,o))return t.json({error:"Object not found"},404);let c=await e.getObject(r,o),p=ut(o);return t.binary(c,p)}catch(r){let{message:i,status:n}=y(r,"Error retrieving object");return t.json({error:i},n)}}import Ft from"node:crypto";function dt(t,e,s,r){let i=JSON.stringify({bucket:t,key:e,expiresAt:s}),n=S().molnos.signedUrlSecret,o=Ft.createHmac("sha256",r||n).update(i).digest("base64url");return`${Buffer.from(i).toString("base64url")}.${o}`}var zt=3600;function pt(t,e,s){let r=parseInt(t.query.expiresIn,10),i=Number.isNaN(r)?zt:r,n=Date.now()+i*1e3,o=dt(e,s,n),a=t.req.headers["x-forwarded-proto"]||"http",l=t.req.headers.host||"localhost:3000";return{signedUrl:`${a}://${l}/buckets/${e}/objects/${encodeURIComponent(s)}?token=${o}`,expiresAt:n,expirySeconds:i}}async function ft(t,e,s){try{let r=t.params.bucket,n=new URL(t.req.url||"","http://localhost").pathname.match(/^\/buckets\/[^/]+\/objects\/(.+)\/sign$/);if(!n)return t.json({error:"Invalid object path"},400);let o=decodeURIComponent(n[1]);if(!r)return t.json({error:"bucket parameter is required"},400);if(await b(t,s,h.storage.object.read,"storage","object","read"),!await e.objectExists(r,o))return t.json({error:"Object not found"},404);let{signedUrl:l,expiresAt:c,expirySeconds:p}=pt(t,r,o);return t.json({url:l,expiresAt:new Date(c).toISOString(),expiresIn:p})}catch(r){let{message:i,status:n}=y(r,"Error signing object URL");return t.json({error:i},n)}}function mt(t){return t&&typeof t=="number"&&t>0?t*1024*1024:0}function ht(t,e){let s={enabled:!1,requestsPerMinute:0};if(!e)return s;let r=e.services?.[t];return r||(e.global?e.global:s)}function gt(t,e){let s=t?.api?.port;if(!s)throw new Error('Missing "port" input when create API service!');let r=S(),i=t?.dataPath||r.molnos.dataPath,n=t?.api?.host||r.server.host,o=t?.identityApiUrl!==void 0?t.identityApiUrl:r.identity.apiUrl,a=t?.contextApiUrl!==void 0?t.contextApiUrl:r.context.apiUrl,l=t?.debug||!1,c;return e&&(c=ht(e,r.molnos.rateLimit)),{dataPath:i,api:{port:s,host:n},...o?{identityApiUrl:o}:{},...a?{contextApiUrl:a}:{},...c?{rateLimit:c}:{},debug:l}}var I=class{baseUrl;authToken;constructor(e,s){this.baseUrl=e.replace(/\/$/,""),this.authToken=s}async createCustomRole(e,s,r,i){let n=await fetch(`${this.baseUrl}/identity/roles`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({roleId:e,name:s,description:r,permissions:i})});if(!n.ok){let o=`Failed to create role: ${n.statusText}`;try{o=(await n.json()).error||o}catch{o=await n.text().catch(()=>n.statusText)||o}throw new Error(o)}}async updateRole(e,s){let r=await fetch(`${this.baseUrl}/identity/roles/${e}`,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(s)});if(!r.ok){let i=await r.json();throw new Error(i.error||`Failed to update role: ${r.statusText}`)}}async deleteRole(e){let s=await fetch(`${this.baseUrl}/identity/roles/${e}`,{method:"DELETE",headers:this.getHeaders()});if(!s.ok){let r=await s.json();throw new Error(r.error||`Failed to delete role: ${s.statusText}`)}}async addServiceAccount(e,s,r){let i=await fetch(`${this.baseUrl}/identity/service-accounts`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({name:e,description:s,roles:r})});if(!i.ok){let o=`Failed to create service account: ${i.statusText}`;try{o=(await i.json()).error||o}catch{o=await i.text().catch(()=>i.statusText)||o}throw new Error(o)}let n=await i.json();return{id:n.id,apiKey:n.apiKey}}async deleteIdentity(e){let s=await fetch(`${this.baseUrl}/identity/service-accounts/${e}`,{method:"DELETE",headers:this.getHeaders()});if(!s.ok){let r=await s.json();throw new Error(r.error||`Failed to delete service account: ${s.statusText}`)}}async getUserFromToken(e){try{let s=await fetch(`${this.baseUrl}/identity/whoami`,{method:"GET",headers:{Authorization:`Bearer ${e}`}});return s.ok?await s.json():null}catch{return null}}getHeaders(){let e={"Content-Type":"application/json"};return this.authToken&&(e.Authorization=`Bearer ${this.authToken}`),e}};function yt(t){return t?new I(t):null}var O=class{baseUrl;constructor(e){this.baseUrl=e.replace(/\/$/,"")}async listResourcesByType(e,s,r){let i=`${this.baseUrl}/contexts/${encodeURIComponent(e)}`;try{let n={"Content-Type":"application/json"};r&&(n.Authorization=`Bearer ${r}`);let o=await fetch(i,{method:"GET",headers:n});if(!o.ok)return[];let l=(await o.json()).context?.resources||{};switch(s){case"function":return l.functions||[];case"database":return l.databases||[];case"storage":return l.storage||[];case"site":return l.sites||[];default:return[]}}catch{return[]}}};function bt(t){return t?new O(t):null}var P=class extends Error{constructor(e){super(),this.name="NotFoundError",this.message=e||"Resource not found",this.cause={statusCode:404}}};var j=class extends Error{constructor(e){super(),this.name="InvalidPathError",this.message=e||"Invalid file path",this.cause={statusCode:400}}};var L=".metadata",q=class{rootPath;metadataPath;constructor(e){this.rootPath=B(e.path||"storage-data"),this.metadataPath=M(this.rootPath,L)}async start(){await v.mkdir(this.rootPath,{recursive:!0}),await v.mkdir(this.metadataPath,{recursive:!0})}getBucketMetadataPath(e){let s=this.validateBucketName(e),r=B(this.metadataPath,`${s}.json`);return this.assertWithinRoot(this.metadataPath,r),r}validateBucketName(e){if(!e||typeof e!="string")throw new j("Bucket name is required");if(e===L||e==="."||e==="..")throw new j("Invalid bucket name");if(e.includes("/")||e.includes("\\")||e.includes("\0"))throw new j("Invalid bucket name");return e}validateObjectKey(e){if(!e||typeof e!="string")throw new j("Object key is required");if(e==="."||e===".."||e.includes("\0"))throw new j("Invalid object key");return e}assertWithinRoot(e,s){let r=Wt(e,s);if(r.startsWith("..")||Jt(r))throw new j("Invalid path")}getBucketPath(e){let s=this.validateBucketName(e),r=B(this.rootPath,s);return this.assertWithinRoot(this.rootPath,r),r}getObjectPath(e,s){let r=this.getBucketPath(e),i=this.validateObjectKey(s),n=B(r,i);return this.assertWithinRoot(r,n),n}async readBucketMetadata(e){let s=this.getBucketMetadataPath(e);try{let r=await v.readFile(s,"utf-8");return JSON.parse(r)}catch{return{public:!1}}}async writeBucketMetadata(e,s){let r=this.getBucketMetadataPath(e);await v.writeFile(r,JSON.stringify(s,null,2))}async deleteBucketMetadata(e){let s=this.getBucketMetadataPath(e);try{await v.unlink(s)}catch{}}async putObject(e,s,r){let i=this.getObjectPath(e,s);await v.mkdir(Gt(i),{recursive:!0}),await v.writeFile(i,r)}async getObject(e,s){let r=this.getObjectPath(e,s);return await v.readFile(r)}async deleteObject(e,s){let r=this.getObjectPath(e,s);await v.unlink(r)}async objectExists(e,s){let r=this.getObjectPath(e,s);try{return await v.access(r),!0}catch{return!1}}async createBucket(e,s=!1){let r=this.getBucketPath(e);await v.mkdir(r,{recursive:!0}),await this.writeBucketMetadata(e,{public:s})}async deleteBucket(e){let s=this.getBucketPath(e);await v.rm(s,{recursive:!0,force:!0}),await this.deleteBucketMetadata(e)}async bucketExists(e){let s=this.getBucketPath(e);try{return(await v.stat(s)).isDirectory()}catch{return!1}}async isBucketPublic(e){return(await this.readBucketMetadata(e)).public}async updateBucket(e,s){if(!await this.bucketExists(e))throw new Error("Bucket not found");let n={...await this.readBucketMetadata(e),...s.public!==void 0&&{public:s.public}};await this.writeBucketMetadata(e,n)}async listBuckets(){try{return(await v.readdir(this.rootPath,{withFileTypes:!0})).filter(s=>s.isDirectory()&&s.name!==L).map(s=>s.name)}catch{return[]}}async getBucketStats(e){let s=this.getBucketPath(e);try{if(!(await v.stat(s)).isDirectory())throw new P("Bucket not found")}catch(o){throw o.code==="ENOENT"?new P("Bucket not found"):o}let r=0,i=0,n=async o=>{let a=await v.readdir(o,{withFileTypes:!0});for(let l of a){let c=M(o,l.name);if(l.isDirectory())await n(c);else if(l.isFile()){r++;let p=await v.stat(c);i+=p.size}}};try{await n(s)}catch{return{objectCount:0,totalSize:0}}return{objectCount:r,totalSize:i}}async listObjects(e,s=""){let r=this.getBucketPath(e);try{if(!(await v.stat(r)).isDirectory())throw new P("Bucket not found")}catch(c){throw c.code==="ENOENT"?new P("Bucket not found"):c}let i=[],n=async(c,p="")=>{let u=await v.readdir(c,{withFileTypes:!0});for(let d of u){let g=M(c,d.name),m=p?`${p}/${d.name}`:d.name;if(d.isDirectory())await n(g,m);else if(d.isFile()){let f=await v.stat(g);i.push({key:m,size:f.size,lastModified:f.mtime,type:"file"})}}};try{await n(r)}catch{return[]}let o=s?i.filter(c=>c.key.startsWith(s)):i,a=[],l=new Set;for(let c of o){let p=s?c.key.substring(s.length):c.key,u=p.indexOf("/");if(u===-1)a.push({key:p,size:c.size,lastModified:c.lastModified,type:"file"});else{let d=p.substring(0,u);l.has(d)||(l.add(d),a.push({key:`${d}/`,size:0,lastModified:c.lastModified,type:"folder"}))}}return a.sort((c,p)=>c.type!==p.type?c.type==="folder"?-1:1:c.key.localeCompare(p.key))}};async function _t(t){let e=t.dataPath||"data",s=M(e,"storage"),r=new q({path:s});await r.start();let i=yt(t.identityApiUrl),n=bt(t.contextApiUrl),o=S(),a=new H({port:t.api.port||o.services.storage.port,host:t.api.host||o.services.storage.host,maxBodySize:mt(1e3),rateLimit:t.rateLimit||{enabled:!1,requestsPerMinute:0}});return a.get("/buckets",async c=>_(c,r,i,n)),a.post("/buckets/:bucket",async c=>X(c,r,i)),a.get("/buckets/:bucket",async c=>Y(c,r,i)),a.patch("/buckets/:bucket",async c=>Q(c,r,i)),a.delete("/buckets/:bucket",async c=>tt(c,r,i)),a.get("/buckets/:bucket/objects",async c=>et(c,r,i)),a.put("/buckets/:bucket/objects",async c=>st(c,r,i)),a.post("/buckets/:bucket/objects",async c=>ot(c,r,i)),a.delete("/buckets/:bucket/objects",async c=>at(c,r,i)),a.post("/buckets/:bucket/objects/*",async c=>new URL(c.req.url||"","http://localhost").pathname.endsWith("/sign")?ft(c,r,i):c.json({error:"Not Found"},404)),a.get("/buckets/:bucket/objects/*",async c=>lt(c,r,i)),a.start()}if(import.meta.url===`file://${process.argv[1]}`){let t=S(),s=process.argv.slice(2).find(n=>n.startsWith("--port=")),r=s?parseInt(s.split("=")[1],10):t.services.storage.port,i=gt({api:{port:r}},"storage");_t(i)}export{q as StorageService,_t as startServer};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "molnos",
3
3
  "description": "The core API for MolnOS.",
4
- "version": "1.4.2",
4
+ "version": "1.5.0",
5
5
  "author": "MolnOS",
6
6
  "license": "MolnOS Software License",
7
7
  "keywords": [],
package/sbom.json CHANGED
@@ -1 +1 @@
1
- {"spdxVersion":"SPDX-2.3","dataLicense":"CC0-1.0","SPDXID":"SPDXRef-DOCUMENT","name":"package-lock.json","documentNamespace":"https://anchore.com/syft/file/package-lock.json-a69694b4-da34-450c-acf4-a19e22dd4a74","creationInfo":{"licenseListVersion":"3.27","creators":["Organization: Anchore, Inc","Tool: syft-1.41.2"],"created":"2026-02-07T14:47:41Z"},"packages":[{"name":"mikroauth","SPDXID":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","versionInfo":"1.1.0","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikroauth/-/mikroauth-1.1.0.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikroauth:mikroauth:1.1.0:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikroauth@1.1.0"}]},{"name":"mikroconf","SPDXID":"SPDXRef-Package-npm-mikroconf-b297d975cb09169c","versionInfo":"1.0.0","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikroconf/-/mikroconf-1.0.0.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikroconf:mikroconf:1.0.0:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikroconf@1.0.0"}]},{"name":"mikroevent","SPDXID":"SPDXRef-Package-npm-mikroevent-5bd10e41dccc0f47","versionInfo":"1.0.1","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikroevent/-/mikroevent-1.0.1.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikroevent:mikroevent:1.0.1:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikroevent@1.0.1"}]},{"name":"mikroid","SPDXID":"SPDXRef-Package-npm-mikroid-505e62805cb5678f","versionInfo":"1.0.0","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikroid/-/mikroid-1.0.0.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikroid:mikroid:1.0.0:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikroid@1.0.0"}]},{"name":"mikromail","SPDXID":"SPDXRef-Package-npm-mikromail-2f017138ed7f39a9","versionInfo":"1.0.0","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikromail/-/mikromail-1.0.0.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikromail:mikromail:1.0.0:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikromail@1.0.0"}]},{"name":"mikropermit","SPDXID":"SPDXRef-Package-npm-mikropermit-0f36ec54f335a15e","versionInfo":"1.0.0","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikropermit/-/mikropermit-1.0.0.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikropermit:mikropermit:1.0.0:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikropermit@1.0.0"}]},{"name":"mikroserve","SPDXID":"SPDXRef-Package-npm-mikroserve-1c5cbf0685852d2c","versionInfo":"1.1.1","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikroserve/-/mikroserve-1.1.1.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikroserve:mikroserve:1.1.1:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikroserve@1.1.1"}]},{"name":"mikrovalid","SPDXID":"SPDXRef-Package-npm-mikrovalid-2873df526a8a0901","versionInfo":"1.0.23","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikrovalid/-/mikrovalid-1.0.23.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikrovalid:mikrovalid:1.0.23:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikrovalid@1.0.23"}]},{"name":"molnos","SPDXID":"SPDXRef-Package-npm-molnos-7fc07dcf3cd69416","versionInfo":"1.4.2","supplier":"NOASSERTION","downloadLocation":"NOASSERTION","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"LicenseRef-MolnOS-Software-License","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:molnos:molnos:1.4.2:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/molnos@1.4.2"}]},{"name":"pikodb","SPDXID":"SPDXRef-Package-npm-pikodb-2e1e5824d502124f","versionInfo":"1.0.1","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/pikodb/-/pikodb-1.0.1.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:pikodb:pikodb:1.0.1:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/pikodb@1.0.1"}]},{"name":"package-lock.json","SPDXID":"SPDXRef-DocumentRoot-File-package-lock.json","versionInfo":"sha256:6f2742a819331fdfb63c34c081203d81e6752ba085692dd9efbd570c7760febb","supplier":"NOASSERTION","downloadLocation":"NOASSERTION","filesAnalyzed":false,"checksums":[{"algorithm":"SHA256","checksumValue":"6f2742a819331fdfb63c34c081203d81e6752ba085692dd9efbd570c7760febb"}],"licenseConcluded":"NOASSERTION","licenseDeclared":"NOASSERTION","copyrightText":"NOASSERTION","primaryPackagePurpose":"FILE"}],"files":[{"fileName":"package-lock.json","SPDXID":"SPDXRef-File-package-lock.json-fd71c2238fc07657","fileTypes":["APPLICATION"],"checksums":[{"algorithm":"SHA1","checksumValue":"e0f3f22d257f9060843b688a4d977d9bdb4c4da6"},{"algorithm":"SHA256","checksumValue":"6f2742a819331fdfb63c34c081203d81e6752ba085692dd9efbd570c7760febb"}],"licenseConcluded":"NOASSERTION","licenseInfoInFiles":["NOASSERTION"],"copyrightText":"NOASSERTION"}],"hasExtractedLicensingInfos":[{"licenseId":"LicenseRef-MolnOS-Software-License","extractedText":"NOASSERTION","name":"MolnOS Software License"}],"relationships":[{"spdxElementId":"SPDXRef-Package-npm-mikropermit-0f36ec54f335a15e","relatedSpdxElement":"SPDXRef-Package-npm-molnos-7fc07dcf3cd69416","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroserve-1c5cbf0685852d2c","relatedSpdxElement":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroserve-1c5cbf0685852d2c","relatedSpdxElement":"SPDXRef-Package-npm-molnos-7fc07dcf3cd69416","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikrovalid-2873df526a8a0901","relatedSpdxElement":"SPDXRef-Package-npm-molnos-7fc07dcf3cd69416","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-pikodb-2e1e5824d502124f","relatedSpdxElement":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-pikodb-2e1e5824d502124f","relatedSpdxElement":"SPDXRef-Package-npm-molnos-7fc07dcf3cd69416","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikromail-2f017138ed7f39a9","relatedSpdxElement":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroid-505e62805cb5678f","relatedSpdxElement":"SPDXRef-Package-npm-molnos-7fc07dcf3cd69416","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroevent-5bd10e41dccc0f47","relatedSpdxElement":"SPDXRef-Package-npm-molnos-7fc07dcf3cd69416","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","relatedSpdxElement":"SPDXRef-Package-npm-molnos-7fc07dcf3cd69416","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroconf-b297d975cb09169c","relatedSpdxElement":"SPDXRef-Package-npm-mikroserve-1c5cbf0685852d2c","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroconf-b297d975cb09169c","relatedSpdxElement":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroconf-b297d975cb09169c","relatedSpdxElement":"SPDXRef-Package-npm-molnos-7fc07dcf3cd69416","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikropermit-0f36ec54f335a15e","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-mikroserve-1c5cbf0685852d2c","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-mikrovalid-2873df526a8a0901","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-pikodb-2e1e5824d502124f","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-mikromail-2f017138ed7f39a9","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-mikroid-505e62805cb5678f","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-mikroevent-5bd10e41dccc0f47","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-molnos-7fc07dcf3cd69416","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-mikroconf-b297d975cb09169c","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikroconf-b297d975cb09169c","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikroevent-5bd10e41dccc0f47","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikroid-505e62805cb5678f","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikromail-2f017138ed7f39a9","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikropermit-0f36ec54f335a15e","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikroserve-1c5cbf0685852d2c","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikrovalid-2873df526a8a0901","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-molnos-7fc07dcf3cd69416","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-pikodb-2e1e5824d502124f","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DOCUMENT","relatedSpdxElement":"SPDXRef-DocumentRoot-File-package-lock.json","relationshipType":"DESCRIBES"}]}
1
+ {"spdxVersion":"SPDX-2.3","dataLicense":"CC0-1.0","SPDXID":"SPDXRef-DOCUMENT","name":"package-lock.json","documentNamespace":"https://anchore.com/syft/file/package-lock.json-fc3cffb2-c889-4c4f-93a8-85ad23a5c541","creationInfo":{"licenseListVersion":"3.27","creators":["Organization: Anchore, Inc","Tool: syft-1.42.1"],"created":"2026-02-27T20:27:26Z"},"packages":[{"name":"mikroauth","SPDXID":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","versionInfo":"1.1.0","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikroauth/-/mikroauth-1.1.0.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikroauth:mikroauth:1.1.0:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikroauth@1.1.0"}]},{"name":"mikroconf","SPDXID":"SPDXRef-Package-npm-mikroconf-b297d975cb09169c","versionInfo":"1.0.0","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikroconf/-/mikroconf-1.0.0.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikroconf:mikroconf:1.0.0:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikroconf@1.0.0"}]},{"name":"mikroevent","SPDXID":"SPDXRef-Package-npm-mikroevent-5bd10e41dccc0f47","versionInfo":"1.0.1","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikroevent/-/mikroevent-1.0.1.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikroevent:mikroevent:1.0.1:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikroevent@1.0.1"}]},{"name":"mikroid","SPDXID":"SPDXRef-Package-npm-mikroid-505e62805cb5678f","versionInfo":"1.0.0","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikroid/-/mikroid-1.0.0.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikroid:mikroid:1.0.0:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikroid@1.0.0"}]},{"name":"mikromail","SPDXID":"SPDXRef-Package-npm-mikromail-2f017138ed7f39a9","versionInfo":"1.0.0","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikromail/-/mikromail-1.0.0.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikromail:mikromail:1.0.0:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikromail@1.0.0"}]},{"name":"mikropermit","SPDXID":"SPDXRef-Package-npm-mikropermit-0f36ec54f335a15e","versionInfo":"1.0.0","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikropermit/-/mikropermit-1.0.0.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikropermit:mikropermit:1.0.0:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikropermit@1.0.0"}]},{"name":"mikroserve","SPDXID":"SPDXRef-Package-npm-mikroserve-1c5cbf0685852d2c","versionInfo":"1.1.1","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikroserve/-/mikroserve-1.1.1.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikroserve:mikroserve:1.1.1:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikroserve@1.1.1"}]},{"name":"mikrovalid","SPDXID":"SPDXRef-Package-npm-mikrovalid-2873df526a8a0901","versionInfo":"1.0.23","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/mikrovalid/-/mikrovalid-1.0.23.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:mikrovalid:mikrovalid:1.0.23:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/mikrovalid@1.0.23"}]},{"name":"molnos","SPDXID":"SPDXRef-Package-npm-molnos-aff8a34e1f85e860","versionInfo":"1.5.0","supplier":"NOASSERTION","downloadLocation":"NOASSERTION","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"LicenseRef-MolnOS-Software-License","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:molnos:molnos:1.5.0:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/molnos@1.5.0"}]},{"name":"pikodb","SPDXID":"SPDXRef-Package-npm-pikodb-2e1e5824d502124f","versionInfo":"1.0.1","supplier":"NOASSERTION","downloadLocation":"https://registry.npmjs.org/pikodb/-/pikodb-1.0.1.tgz","filesAnalyzed":false,"sourceInfo":"acquired package info from installed node module manifest file: /package-lock.json","licenseConcluded":"NOASSERTION","licenseDeclared":"MIT","copyrightText":"NOASSERTION","externalRefs":[{"referenceCategory":"SECURITY","referenceType":"cpe23Type","referenceLocator":"cpe:2.3:a:pikodb:pikodb:1.0.1:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/pikodb@1.0.1"}]},{"name":"package-lock.json","SPDXID":"SPDXRef-DocumentRoot-File-package-lock.json","versionInfo":"sha256:9ff7f65abe6ff3b92cc0906cf3206ea729c9e1789b254ee1f175187f4ac16b35","supplier":"NOASSERTION","downloadLocation":"NOASSERTION","filesAnalyzed":false,"checksums":[{"algorithm":"SHA256","checksumValue":"9ff7f65abe6ff3b92cc0906cf3206ea729c9e1789b254ee1f175187f4ac16b35"}],"licenseConcluded":"NOASSERTION","licenseDeclared":"NOASSERTION","copyrightText":"NOASSERTION","primaryPackagePurpose":"FILE"}],"files":[{"fileName":"package-lock.json","SPDXID":"SPDXRef-File-package-lock.json-fd71c2238fc07657","fileTypes":["APPLICATION"],"checksums":[{"algorithm":"SHA1","checksumValue":"18e6569ca9176102ce13a0263e252bc35e5d8678"},{"algorithm":"SHA256","checksumValue":"9ff7f65abe6ff3b92cc0906cf3206ea729c9e1789b254ee1f175187f4ac16b35"}],"licenseConcluded":"NOASSERTION","licenseInfoInFiles":["NOASSERTION"],"copyrightText":"NOASSERTION"}],"hasExtractedLicensingInfos":[{"licenseId":"LicenseRef-MolnOS-Software-License","extractedText":"NOASSERTION","name":"MolnOS Software License"}],"relationships":[{"spdxElementId":"SPDXRef-Package-npm-mikropermit-0f36ec54f335a15e","relatedSpdxElement":"SPDXRef-Package-npm-molnos-aff8a34e1f85e860","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroserve-1c5cbf0685852d2c","relatedSpdxElement":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroserve-1c5cbf0685852d2c","relatedSpdxElement":"SPDXRef-Package-npm-molnos-aff8a34e1f85e860","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikrovalid-2873df526a8a0901","relatedSpdxElement":"SPDXRef-Package-npm-molnos-aff8a34e1f85e860","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-pikodb-2e1e5824d502124f","relatedSpdxElement":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-pikodb-2e1e5824d502124f","relatedSpdxElement":"SPDXRef-Package-npm-molnos-aff8a34e1f85e860","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikromail-2f017138ed7f39a9","relatedSpdxElement":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroid-505e62805cb5678f","relatedSpdxElement":"SPDXRef-Package-npm-molnos-aff8a34e1f85e860","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroevent-5bd10e41dccc0f47","relatedSpdxElement":"SPDXRef-Package-npm-molnos-aff8a34e1f85e860","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","relatedSpdxElement":"SPDXRef-Package-npm-molnos-aff8a34e1f85e860","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroconf-b297d975cb09169c","relatedSpdxElement":"SPDXRef-Package-npm-mikroserve-1c5cbf0685852d2c","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroconf-b297d975cb09169c","relatedSpdxElement":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroconf-b297d975cb09169c","relatedSpdxElement":"SPDXRef-Package-npm-molnos-aff8a34e1f85e860","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikropermit-0f36ec54f335a15e","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-mikroserve-1c5cbf0685852d2c","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-mikrovalid-2873df526a8a0901","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-pikodb-2e1e5824d502124f","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-mikromail-2f017138ed7f39a9","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-mikroid-505e62805cb5678f","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-mikroevent-5bd10e41dccc0f47","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-molnos-aff8a34e1f85e860","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-Package-npm-mikroconf-b297d975cb09169c","relatedSpdxElement":"SPDXRef-File-package-lock.json-fd71c2238fc07657","relationshipType":"OTHER","comment":"evident-by: indicates the package's existence is evident by the given file"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikroconf-b297d975cb09169c","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikroevent-5bd10e41dccc0f47","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikroid-505e62805cb5678f","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikromail-2f017138ed7f39a9","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikropermit-0f36ec54f335a15e","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikroserve-1c5cbf0685852d2c","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-mikrovalid-2873df526a8a0901","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-molnos-aff8a34e1f85e860","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DocumentRoot-File-package-lock.json","relatedSpdxElement":"SPDXRef-Package-npm-pikodb-2e1e5824d502124f","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef-DOCUMENT","relatedSpdxElement":"SPDXRef-DocumentRoot-File-package-lock.json","relationshipType":"DESCRIBES"}]}