molnos 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/VERSION CHANGED
@@ -1 +1 @@
1
- 1.4.0
1
+ 1.4.2
@@ -111,7 +111,7 @@ If you didn't request this link, please ignore this email.
111
111
  `},di=class{constructor(t){this.options=t}sentEmails=[];async sendMail(t){this.sentEmails.push(t),this.options?.logToConsole&&(console.log("Email sent:"),console.log(`From: ${t.from}`),console.log(`To: ${t.to}`),console.log(`Subject: ${t.subject}`),console.log(`Text: ${t.text}`)),this.options?.onSend&&this.options.onSend(t)}getSentEmails(){return[...this.sentEmails]}clearSentEmails(){this.sentEmails=[]}},pi=class{data=new Map;collections=new Map;expiryEmitter=new oi;expiryCheckInterval;constructor(t=1e3){this.expiryCheckInterval=setInterval(()=>this.checkExpiredItems(),t)}destroy(){clearInterval(this.expiryCheckInterval),this.data.clear(),this.collections.clear(),this.expiryEmitter.removeAllListeners()}checkExpiredItems(){let t=Date.now();for(let[e,r]of this.data.entries())r.expiry&&r.expiry<t&&(this.data.delete(e),this.expiryEmitter.emit("expired",e));for(let[e,r]of this.collections.entries())r.expiry&&r.expiry<t&&(this.collections.delete(e),this.expiryEmitter.emit("expired",e))}async set(t,e,r){let s=r?Date.now()+r*1e3:null;this.data.set(t,{value:e,expiry:s})}async get(t){let e=this.data.get(t);return e?e.expiry&&e.expiry<Date.now()?(this.data.delete(t),null):e.value:null}async delete(t){this.data.delete(t),this.collections.delete(t)}async addToCollection(t,e,r){this.collections.has(t)||this.collections.set(t,{items:[],expiry:r?Date.now()+r*1e3:null});let s=this.collections.get(t);s&&(r&&(s.expiry=Date.now()+r*1e3),s.items.push(e))}async removeFromCollection(t,e){let r=this.collections.get(t);r&&(r.items=r.items.filter(s=>s!==e))}async getCollection(t){let e=this.collections.get(t);return e?[...e.items]:[]}async getCollectionSize(t){let e=this.collections.get(t);return e?e.items.length:0}async removeOldestFromCollection(t){let e=this.collections.get(t);return!e||e.items.length===0?null:e.items.shift()||null}async findKeys(t){let e=t.replace(/\*/g,".*").replace(/\?/g,"."),r=new RegExp(`^${e}$`),s=Array.from(this.data.keys()).filter(n=>r.test(n)),i=Array.from(this.collections.keys()).filter(n=>r.test(n));return[...new Set([...s,...i])]}};function Wt(t){if(!t||t.trim()===""||(t.match(/@/g)||[]).length!==1)return!1;let[e,r]=t.split("@");return!(!e||!r||t.includes("..")||!mi(e)||!hi(r))}function mi(t){return t.startsWith('"')&&t.endsWith('"')?!t.slice(1,-1).includes('"'):t.length>64||t.startsWith(".")||t.endsWith(".")?!1:/^[a-zA-Z0-9!#$%&'*+/=?^_`{|}~.-]+$/.test(t)}function hi(t){if(t.startsWith("[")&&t.endsWith("]")){let r=t.slice(1,-1);return r.startsWith("IPv6:")?gi(r.slice(5)):fi(r)}let e=t.split(".");if(e.length===0)return!1;for(let r of e)if(!r||r.length>63||!/^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/.test(r))return!1;if(e.length>1){let r=e[e.length-1];if(!/^[a-zA-Z]{2,}$/.test(r))return!1}return!0}function fi(t){return/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/.test(t)}function gi(t){if(!/^[a-fA-F0-9:]+$/.test(t))return!1;let e=t.split(":");return!(e.length<2||e.length>8)}var k=yt(),yi=t=>{let e={configFilePath:"mikroauth.config.json",args:process.argv,options:[{flag:"--jwtSecret",path:"auth.jwtSecret",defaultValue:k.auth.jwtSecret},{flag:"--magicLinkExpirySeconds",path:"auth.magicLinkExpirySeconds",defaultValue:k.auth.magicLinkExpirySeconds},{flag:"--jwtExpirySeconds",path:"auth.jwtExpirySeconds",defaultValue:k.auth.jwtExpirySeconds},{flag:"--refreshTokenExpirySeconds",path:"auth.refreshTokenExpirySeconds",defaultValue:k.auth.refreshTokenExpirySeconds},{flag:"--maxActiveSessions",path:"auth.maxActiveSessions",defaultValue:k.auth.maxActiveSessions},{flag:"--appUrl",path:"auth.appUrl",defaultValue:k.auth.appUrl},{flag:"--debug",path:"auth.debug",isFlag:!0,defaultValue:k.auth.debug},{flag:"--emailSubject",path:"email.emailSubject",defaultValue:"Your Secure Login Link"},{flag:"--emailHost",path:"email.host",defaultValue:k.email.host},{flag:"--emailUser",path:"email.user",defaultValue:k.email.user},{flag:"--emailPassword",path:"email.password",defaultValue:k.email.password},{flag:"--emailPort",path:"email.port",defaultValue:k.email.port},{flag:"--emailSecure",path:"email.secure",isFlag:!0,defaultValue:k.email.secure},{flag:"--emailMaxRetries",path:"email.maxRetries",defaultValue:k.email.maxRetries},{flag:"--debug",path:"email.debug",isFlag:!0,defaultValue:k.email.debug},{flag:"--dir",path:"storage.databaseDirectory",defaultValue:k.storage.databaseDirectory},{flag:"--encryptionKey",path:"storage.encryptionKey",defaultValue:k.storage.encryptionKey},{flag:"--debug",path:"storage.debug",defaultValue:k.storage.debug},{flag:"--port",path:"server.port",defaultValue:k.server.port},{flag:"--host",path:"server.host",defaultValue:k.server.host},{flag:"--https",path:"server.useHttps",isFlag:!0,defaultValue:k.server.useHttps},{flag:"--https",path:"server.useHttp2",isFlag:!0,defaultValue:k.server.useHttp2},{flag:"--cert",path:"server.sslCert",defaultValue:k.server.sslCert},{flag:"--key",path:"server.sslKey",defaultValue:k.server.sslKey},{flag:"--ca",path:"server.sslCa",defaultValue:k.server.sslCa},{flag:"--ratelimit",path:"server.rateLimit.enabled",defaultValue:k.server.rateLimit.enabled,isFlag:!0},{flag:"--rps",path:"server.rateLimit.requestsPerMinute",defaultValue:k.server.rateLimit.requestsPerMinute},{flag:"--allowed",path:"server.allowedDomains",defaultValue:k.server.allowedDomains,parser:oe.array},{flag:"--debug",path:"server.debug",isFlag:!0,defaultValue:k.server.debug}]};return t&&(e.config=t),e},Ue={linkSent:"If a matching account was found, a magic link has been sent.",revokedSuccess:"All other sessions revoked successfully.",logoutSuccess:"Logged out successfully."},Jt=class{config;email;storage;jwtService;templates;constructor(t,e,r){let s=new ne(yi({auth:t.auth,email:t.email})).get();s.auth.debug&&console.log("Using configuration:",s),this.config=s,this.email=e||new di,this.storage=r||new pi,this.jwtService=new ci(s.auth.jwtSecret),this.templates=new li(s?.auth.templates),this.checkIfUsingDefaultCredentialsInProduction()}checkIfUsingDefaultCredentialsInProduction(){process.env.NODE_ENV==="production"&&this.config.auth.jwtSecret===yt().auth.jwtSecret&&(console.error("WARNING: Using default secrets in production environment!"),process.exit(1))}generateToken(t){let e=Date.now().toString(),r=ae.randomBytes(32).toString("hex");return ae.createHash("sha256").update(`${t}:${e}:${r}`).digest("hex")}generateJsonWebToken(t){return this.jwtService.sign({sub:t.id,email:t.email,username:t.username,role:t.role,exp:Math.floor(Date.now()/1e3)+3600*24})}generateRefreshToken(){return ae.randomBytes(40).toString("hex")}async trackSession(t,e,r){let s=`sessions:${t}`;if(await this.storage.getCollectionSize(s)>=this.config.auth.maxActiveSessions){let i=await this.storage.removeOldestFromCollection(s);i&&await this.storage.delete(`refresh:${i}`)}await this.storage.addToCollection(s,e,this.config.auth.refreshTokenExpirySeconds),await this.storage.set(`refresh:${e}`,JSON.stringify(r),this.config.auth.refreshTokenExpirySeconds)}generateMagicLinkUrl(t){let{token:e,email:r,appUrl:s}=t,i=s||this.config.auth.appUrl;try{return new ni(i),`${i}?token=${encodeURIComponent(e)}&email=${encodeURIComponent(r)}`}catch{throw new Error("Invalid base URL configuration")}}async createMagicLink(t){let{email:e,ip:r,metadata:s,appUrl:i,subject:n}=t;if(!Wt(e))throw new Error("Valid email required");try{let o=this.generateToken(e),a=`magic_link:${o}`,c={email:e,ipAddress:r||"unknown",createdAt:Date.now()};await this.storage.set(a,JSON.stringify(c),this.config.auth.magicLinkExpirySeconds);let l=await this.storage.findKeys("magic_link:*");for(let m of l){if(m===a)continue;let w=await this.storage.get(m);if(w)try{JSON.parse(w).email===e&&await this.storage.delete(m)}catch{}}let u=this.generateMagicLinkUrl({token:o,email:e,appUrl:i}),p=Math.ceil(this.config.auth.magicLinkExpirySeconds/60);return await this.email.sendMail({from:this.config.email.user,to:e,subject:n||this.config.email.emailSubject,text:this.templates.getText(u,p,s),html:this.templates.getHtml(u,p,s)}),{message:Ue.linkSent}}catch(o){throw console.error(`Failed to process magic link request: ${o}`),new Error("Failed to process magic link request")}}async createToken(t){let{email:e,username:r,role:s,ip:i}=t;if(!Wt(e))throw new Error("Valid email required");try{let n=ae.randomBytes(16).toString("hex"),o=this.generateRefreshToken(),a=Date.now(),c={sub:e,username:r,role:s,jti:n,lastLogin:a,metadata:{ip:i||"unknown"},exp:Math.floor(Date.now()/1e3)+3600*24},l=this.jwtService.sign(c,{exp:this.config.auth.jwtExpirySeconds}),u={email:e,username:r,role:s,ipAddress:i||"unknown",tokenId:n,createdAt:a,lastLogin:a};return await this.trackSession(e,o,u),{accessToken:l,refreshToken:o,exp:this.config.auth.jwtExpirySeconds,tokenType:"Bearer"}}catch(n){throw console.error("Token creation error:",n),new Error("Token creation failed")}}async verifyToken(t){let{token:e,email:r}=t;try{let s=`magic_link:${e}`,i=await this.storage.get(s);if(!i)throw new Error("Invalid or expired token");let n=JSON.parse(i);if(n.email!==r)throw new Error("Email mismatch");let o=n.username,a=n.role;await this.storage.delete(s);let c=ae.randomBytes(16).toString("hex"),l=this.generateRefreshToken(),u={sub:r,username:o,role:a,jti:c,lastLogin:n.createdAt,metadata:{ip:n.ipAddress},exp:Math.floor(Date.now()/1e3)+3600*24},p=this.jwtService.sign(u,{exp:this.config.auth.jwtExpirySeconds});return await this.trackSession(r,l,{...n,tokenId:c,createdAt:Date.now()}),{accessToken:p,refreshToken:l,exp:this.config.auth.jwtExpirySeconds,tokenType:"Bearer"}}catch(s){throw console.error("Token verification error:",s),new Error("Verification failed")}}async refreshAccessToken(t){try{let e=await this.storage.get(`refresh:${t}`);if(!e)throw new Error("Invalid or expired refresh token");let r=JSON.parse(e),s=r.email;if(!s)throw new Error("Invalid refresh token data");let i=r.username,n=r.role,o=ae.randomBytes(16).toString("hex"),a={sub:s,username:i,role:n,jti:o,lastLogin:r.lastLogin||r.createdAt,metadata:{ip:r.ipAddress}},c=this.jwtService.sign(a,{exp:this.config.auth.jwtExpirySeconds});return r.lastUsed=Date.now(),await this.storage.set(`refresh:${t}`,JSON.stringify(r),this.config.auth.refreshTokenExpirySeconds),{accessToken:c,refreshToken:t,exp:this.config.auth.jwtExpirySeconds,tokenType:"Bearer"}}catch(e){throw console.error("Token refresh error:",e),new Error("Token refresh failed")}}verify(t){try{return this.jwtService.verify(t)}catch{throw new Error("Invalid token")}}async logout(t){try{if(!t||typeof t!="string")throw new Error("Refresh token is required");let e=await this.storage.get(`refresh:${t}`);if(!e)return{message:Ue.logoutSuccess};let r=JSON.parse(e).email;if(!r)throw new Error("Invalid refresh token data");await this.storage.delete(`refresh:${t}`);let s=`sessions:${r}`;return await this.storage.removeFromCollection(s,t),{message:Ue.logoutSuccess}}catch(e){throw console.error("Logout error:",e),new Error("Logout failed")}}async getSessions(t){try{if(!t.user?.email)throw new Error("User not authenticated");let e=t.user.email,r=t.body?.refreshToken,s=`sessions:${e}`,i=(await this.storage.getCollection(s)).map(async o=>{try{let a=await this.storage.get(`refresh:${o}`);if(!a)return await this.storage.removeFromCollection(s,o),null;let c=JSON.parse(a);return{id:`${o.substring(0,8)}...`,createdAt:c.createdAt||0,lastLogin:c.lastLogin||c.createdAt||0,lastUsed:c.lastUsed||c.createdAt||0,metadata:{ip:c.ipAddress},isCurrentSession:o===r}}catch{return await this.storage.removeFromCollection(s,o),null}}),n=(await Promise.all(i)).filter(Boolean);return n.sort((o,a)=>a.createdAt-o.createdAt),{sessions:n}}catch(e){throw console.error("Get sessions error:",e),new Error("Failed to fetch sessions")}}async revokeSessions(t){try{if(!t.user?.email)throw new Error("User not authenticated");let e=t.user.email,r=t.body?.refreshToken,s=`sessions:${e}`,i=await this.storage.getCollection(s);for(let n of i)r&&n===r||await this.storage.delete(`refresh:${n}`);return await this.storage.delete(s),r&&await this.storage.get(`refresh:${r}`)&&await this.storage.addToCollection(s,r,this.config.auth.refreshTokenExpirySeconds),{message:Ue.revokedSuccess}}catch(e){throw console.error("Revoke sessions error:",e),new Error("Failed to revoke sessions")}}authenticate(t,e){try{let r=t.headers?.authorization;if(!r||!r.startsWith("Bearer "))throw new Error("Authentication required");let s=r.split(" ")[1];try{let i=this.verify(s);t.user={email:i.sub},e()}catch{throw new Error("Invalid or expired token")}}catch(r){e(r)}}},vi=class{key;algorithm="aes-256-gcm";keyLength=32;constructor(t){this.key=ti(t,"mikroauth-salt",this.keyLength)}encrypt(t){let e=ri(12),r=si(this.algorithm,this.key,e),s=Buffer.concat([r.update(t,"utf8"),r.final()]),i=r.getAuthTag();return`${e.toString("hex")}:${i.toString("hex")}:${s.toString("hex")}`}decrypt(t){let e=t.split(":");if(e.length!==3)throw new Error("Invalid encrypted data format");let[r,s,i]=e,n=Buffer.from(r,"hex"),o=Buffer.from(s,"hex"),a=Buffer.from(i,"hex"),c=ii(this.algorithm,this.key,n);return c.setAuthTag(o),Buffer.concat([c.update(a),c.final()]).toString("utf8")}},Kt=class{db;encryption;PREFIX_KV="kv:";PREFIX_COLLECTION="coll:";TABLE_NAME="mikroauth";constructor(t,e){this.db=t,e&&(this.encryption=new vi(e))}async start(){await this.db.start()}async close(){await this.db.close()}async set(t,e,r){let s=`${this.PREFIX_KV}${t}`,i=this.encryption?this.encryption.encrypt(e):e,n=r?Date.now()+r*1e3:void 0;await this.db.write(this.TABLE_NAME,s,i,n)}async get(t){let e=`${this.PREFIX_KV}${t}`,r=await this.db.get(this.TABLE_NAME,e);return r?this.encryption?this.encryption.decrypt(r):r:null}async delete(t){let e=`${this.PREFIX_KV}${t}`;await this.db.delete(this.TABLE_NAME,e)}async addToCollection(t,e,r){let s=`${this.PREFIX_COLLECTION}${t}`,i=await this.db.get(this.TABLE_NAME,s),n=[];if(i){let l=this.encryption?this.encryption.decrypt(i):i;n=JSON.parse(l)}n.includes(e)||n.push(e);let o=JSON.stringify(n),a=this.encryption?this.encryption.encrypt(o):o,c=r?Date.now()+r*1e3:void 0;await this.db.write(this.TABLE_NAME,s,a,c)}async removeFromCollection(t,e){let r=`${this.PREFIX_COLLECTION}${t}`,s=await this.db.get(this.TABLE_NAME,r);if(!s)return;let i=this.encryption?this.encryption.decrypt(s):s,n=JSON.parse(i);n=n.filter(c=>c!==e);let o=JSON.stringify(n),a=this.encryption?this.encryption.encrypt(o):o;await this.db.write(this.TABLE_NAME,r,a)}async getCollection(t){let e=`${this.PREFIX_COLLECTION}${t}`,r=await this.db.get(this.TABLE_NAME,e);if(!r)return[];let s=this.encryption?this.encryption.decrypt(r):r;return JSON.parse(s)}async getCollectionSize(t){return(await this.getCollection(t)).length}async removeOldestFromCollection(t){let e=`${this.PREFIX_COLLECTION}${t}`,r=await this.db.get(this.TABLE_NAME,e);if(!r)return null;let s=this.encryption?this.encryption.decrypt(r):r,i=JSON.parse(s);if(i.length===0)return null;let n=i.shift(),o=JSON.stringify(i),a=this.encryption?this.encryption.encrypt(o):o;return await this.db.write(this.TABLE_NAME,e,a),n}async findKeys(t){let e=t.replace(/\./g,"\\.").replace(/\*/g,".*").replace(/\?/g,"."),r=new RegExp(`^${e}$`),s=await this.db.get(this.TABLE_NAME);return Array.isArray(s)?s.filter(i=>{let n=i[0];return typeof n=="string"&&n.startsWith(this.PREFIX_KV)}).map(i=>i[0].substring(this.PREFIX_KV.length)).filter(i=>r.test(i)):[]}},Xt=class{email;sender;constructor(t){this.sender=t.user,this.email=new gt({config:t})}async sendMail(t){await this.email.send({from:this.sender,to:t.to,cc:t.cc,bcc:t.bcc,subject:t.subject,text:t.text,html:t.html})}};function He(t){if(!t.deflate&&!t.inflate)throw new Error("Dictionary must provide either deflate or inflate mapping");if(t.deflate&&t.inflate)throw new Error("Dictionary should provide only one of deflate or inflate (not both). The inverse will be auto-generated.");return t.deflate?{deflate:t.deflate,inflate:Yt(t.deflate)}:{deflate:Yt(t.inflate),inflate:t.inflate}}function Yt(t){let e={};for(let[r,s]of Object.entries(t))e[s]=r;return e}function me(t,e){if(t==null||typeof t!="object")return t;if(Array.isArray(t))return t.map(s=>me(s,e));let r={};for(let[s,i]of Object.entries(t)){let n=e[s]||s;r[n]=me(i,e)}return r}function ce(t){if(!t||typeof t!="string")throw new Error("Table name must be a non-empty string");if(t.length>255)throw new Error("Table name must not exceed 255 characters");if(t.includes("/")||t.includes("\\"))throw new Error("Table name must not contain path separators");if(t.includes(".."))throw new Error('Table name must not contain ".."');if(t.startsWith("."))throw new Error('Table name must not start with "."');if(t.includes("\0"))throw new Error("Table name must not contain null bytes");if(["CON","PRN","AUX","NUL","COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9","LPT1","LPT2","LPT3","LPT4","LPT5","LPT6","LPT7","LPT8","LPT9"].includes(t.toUpperCase()))throw new Error(`Table name "${t}" is reserved by the filesystem`)}function De(t){if(t==null)throw new Error("Key must be defined");if(typeof t!="string")throw new Error("Key must be a string");if(t.length===0)throw new Error("Key must not be empty");if(t.length>1024)throw new Error("Key must not exceed 1024 characters");if(t.includes("\0"))throw new Error("Key must not contain null bytes")}function Zt(t){if(t===void 0)throw new Error("Value must not be undefined (use null instead)");let e=typeof t;if(e==="function")throw new Error("Value must be JSON-serializable: functions are not supported");if(e==="symbol")throw new Error("Value must be JSON-serializable: symbols are not supported");try{if(JSON.stringify(t)===void 0)throw new Error("Value must be JSON-serializable: value cannot be serialized")}catch(r){throw new Error(`Value must be JSON-serializable: ${r instanceof Error?r.message:String(r)}`)}}import{existsSync as vt,mkdirSync as wi,readdirSync as Si,openSync as xi,closeSync as bi}from"fs";import{readFile as Ci,writeFile as Ii,rename as Ai,unlink as Qt,open as ki}from"fs/promises";import{join as wt,dirname as Pi}from"path";var J=class{data=new Map;databaseDirectory;dictionaries=new Map;useFsync;constructor(t){this.databaseDirectory=t.databaseDirectory,this.useFsync=t.durableWrites??!1,t.dictionaries&&Object.entries(t.dictionaries).forEach(([e,r])=>{let s=He(r);this.dictionaries.set(e,s)}),vt(this.databaseDirectory)||wi(this.databaseDirectory,{recursive:!0})}async start(){try{let t=Si(this.databaseDirectory);for(let e of t)!e.endsWith(".tmp")&&!e.startsWith(".")&&await this.loadTable(e)}catch(t){throw console.error("Failed to start database:",t),t}}async write(t,e,r,s,i){if(ce(t),De(e),Zt(r),i&&!this.dictionaries.has(i))throw new Error(`Dictionary "${i}" not found. Available dictionaries: ${Array.from(this.dictionaries.keys()).join(", ")||"none"}`);try{this.data.has(t)||this.data.set(t,new Map);let n=this.data.get(t),a=(n.get(e)?.version||0)+1,c={value:r,version:a,timestamp:Date.now(),expiration:s||null,dictionaryName:i||void 0};return n.set(e,c),await this.persistTable(t),!0}catch(n){return console.error(`Write failed for ${t}:${e}:`,n),!1}}async get(t,e){ce(t),e!==void 0&&De(e);try{this.data.has(t)||await this.loadTable(t);let r=this.data.get(t);if(!r)return e?void 0:[];if(e!==void 0){let n=r.get(e);if(!n)return;if(this.isExpired(n)){r.delete(e),await this.persistTable(t);return}return n.value}let s=[],i=[];for(let[n,o]of r.entries())this.isExpired(o)?i.push(n):s.push([n,o.value]);if(i.length>0){for(let n of i)r.delete(n);await this.persistTable(t)}return s}catch(r){return console.error(`Read failed for ${t}:${e}:`,r),e?void 0:[]}}async delete(t,e){ce(t),De(e);try{this.data.has(t)||await this.loadTable(t);let r=this.data.get(t);if(!r||!r.has(e))return!1;let s=r.get(e);return s?this.isExpired(s)?(r.delete(e),await this.persistTable(t),!1):(r.delete(e),await this.persistTable(t),!0):!1}catch(r){return console.error(`Delete failed for ${t}:${e}:`,r),!1}}async getTableSize(t){ce(t);try{this.data.has(t)||await this.loadTable(t);let e=this.data.get(t);if(!e)return 0;let r=0,s=[];for(let[i,n]of e.entries())this.isExpired(n)?s.push(i):r++;if(s.length>0){for(let i of s)e.delete(i);await this.persistTable(t)}return r}catch(e){return console.error(`Get table size failed for ${t}:`,e),0}}isExpired(t){return t.expiration===null?!1:Date.now()>t.expiration}async cleanupExpired(t){ce(t);try{this.data.has(t)||await this.loadTable(t);let e=this.data.get(t);if(!e)return 0;let r=[];for(let[s,i]of e.entries())this.isExpired(i)&&r.push(s);for(let s of r)e.delete(s);return r.length>0&&await this.persistTable(t),r.length}catch(e){return console.error(`Cleanup failed for ${t}:`,e),0}}async cleanupAllExpired(){let t=0;for(let e of this.data.keys())t+=await this.cleanupExpired(e);return t}async deleteTable(t){ce(t);try{this.data.delete(t);let e=wt(this.databaseDirectory,t);return vt(e)&&await Qt(e),!0}catch(e){return console.error(`Delete table failed for ${t}:`,e),!1}}listTables(){return Array.from(this.data.keys())}async flush(){try{let t=Array.from(this.data.keys()).map(e=>this.persistTable(e));await Promise.all(t)}catch(t){throw console.error("Flush failed:",t),t}}async close(){await this.flush()}addDictionary(t,e){let r=He(e);this.dictionaries.set(t,r)}removeDictionary(t){return this.dictionaries.delete(t)}listDictionaries(){return Array.from(this.dictionaries.keys())}async loadTable(t){let e=wt(this.databaseDirectory,t);if(!vt(e)){this.data.set(t,new Map);return}try{let r=await Ci(e);if(r.length===0){this.data.set(t,new Map);return}let s=this.deserializeTable(r);this.data.set(t,s)}catch(r){console.error(`Failed to load table ${t}:`,r),this.data.set(t,new Map)}}async persistTable(t){let e=this.data.get(t);if(!e)return;let r=this.serializeTable(e),s=wt(this.databaseDirectory,t),i=`${s}.tmp.${Date.now()}.${Math.random().toString(36).substring(7)}`;try{if(await Ii(i,r),this.useFsync){let n=await ki(i,"r+");try{await n.sync()}finally{await n.close()}}if(await Ai(i,s),this.useFsync){let n=Pi(s),o=xi(n,"r");try{bi(o)}catch{}}}catch(n){try{await Qt(i)}catch{}throw n}}serializeTable(t){let e=Array.from(t.entries()).map(([r,s])=>{let i=s.dictionaryName?this.dictionaries.get(s.dictionaryName):void 0,n={d:i?me(s.value,i.deflate):s.value,v:s.version,t:s.timestamp,x:s.expiration};return s.dictionaryName&&(n.n=s.dictionaryName),[r,n]});return Buffer.from(JSON.stringify(e),"utf8")}deserializeTable(t){let r=JSON.parse(t.toString("utf8")).map(([s,i])=>{let n=i.n,o=n?this.dictionaries.get(n):void 0;return[s,{value:o?me(i.d,o.inflate):i.d,version:i.v,timestamp:i.t,expiration:i.x,dictionaryName:n||void 0}]});return new Map(r)}};import{join as Mn}from"node:path";import An from"node:http";import{join as lt}from"node:path";var er=class{requests=new Map;limit;windowMs;constructor(t=100,e=60){this.limit=t,this.windowMs=e*1e3,setInterval(()=>this.cleanup(),this.windowMs)}getLimit(){return this.limit}isAllowed(t){let e=Date.now(),r=t||"unknown",s=this.requests.get(r);return(!s||s.resetTime<e)&&(s={count:0,resetTime:e+this.windowMs},this.requests.set(r,s)),s.count++,s.count<=this.limit}getRemainingRequests(t){let e=Date.now(),r=t||"unknown",s=this.requests.get(r);return!s||s.resetTime<e?this.limit:Math.max(0,this.limit-s.count)}getResetTime(t){let e=Date.now(),r=t||"unknown",s=this.requests.get(r);return!s||s.resetTime<e?Math.floor((e+this.windowMs)/1e3):Math.floor(s.resetTime/1e3)}cleanup(){let t=Date.now();for(let[e,r]of this.requests.entries())r.resetTime<t&&this.requests.delete(e)}};import{URL as Ei}from"url";var tr=class{routes=[];globalMiddlewares=[];pathPatterns=new Map;use(t){return this.globalMiddlewares.push(t),this}get(t,...e){let r=e.pop();return this.register("GET",t,r,e)}post(t,...e){let r=e.pop();return this.register("POST",t,r,e)}put(t,...e){let r=e.pop();return this.register("PUT",t,r,e)}delete(t,...e){let r=e.pop();return this.register("DELETE",t,r,e)}patch(t,...e){let r=e.pop();return this.register("PATCH",t,r,e)}any(t,...e){let r=e.pop(),s=e;return this.register("GET",t,r,s),this.register("POST",t,r,s),this.register("PUT",t,r,s),this.register("DELETE",t,r,s),this.register("PATCH",t,r,s),this.register("OPTIONS",t,r,s),this}options(t,...e){let r=e.pop();return this.register("OPTIONS",t,r,e)}match(t,e){for(let r of this.routes){if(r.method!==t)continue;let s=this.pathPatterns.get(r.path);if(!s)continue;let i=s.pattern.exec(e);if(!i)continue;let n={};return s.paramNames.forEach((o,a)=>{n[o]=i[a+1]||""}),{route:r,params:n}}return null}async handle(t,e){let r=t.method||"GET",s=new Ei(t.url||"/",`http://${t.headers.host}`),i=s.pathname,n=this.match(r,i);if(!n)return null;let{route:o,params:a}=n,c={};s.searchParams.forEach((p,m)=>{c[m]=p});let l={req:t,res:e,params:a,query:c,body:t.body||{},headers:t.headers,path:i,state:{},raw:()=>e,binary:(p,m="application/octet-stream",w=200)=>({statusCode:w,body:p,headers:{"Content-Type":m,"Content-Length":p.length.toString()},isRaw:!0}),text:(p,m=200)=>({statusCode:m,body:p,headers:{"Content-Type":"text/plain"}}),form:(p,m=200)=>({statusCode:m,body:p,headers:{"Content-Type":"application/x-www-form-urlencoded"}}),json:(p,m=200)=>({statusCode:m,body:p,headers:{"Content-Type":"application/json"}}),html:(p,m=200)=>({statusCode:m,body:p,headers:{"Content-Type":"text/html"}}),redirect:(p,m=302)=>({statusCode:m,body:null,headers:{Location:p}}),status:function(p){return{raw:()=>e,binary:(m,w="application/octet-stream")=>({statusCode:p,body:m,headers:{"Content-Type":w,"Content-Length":m.length.toString()},isRaw:!0}),text:m=>({statusCode:p,body:m,headers:{"Content-Type":"text/plain"}}),json:m=>({statusCode:p,body:m,headers:{"Content-Type":"application/json"}}),html:m=>({statusCode:p,body:m,headers:{"Content-Type":"text/html"}}),form:m=>({statusCode:p,body:m,headers:{"Content-Type":"application/x-www-form-urlencoded"}}),redirect:(m,w=302)=>({statusCode:w,body:null,headers:{Location:m}}),status:m=>this.status(m)}}},u=[...this.globalMiddlewares,...o.middlewares];return this.executeMiddlewareChain(l,u,o.handler)}register(t,e,r,s=[]){return this.routes.push({method:t,path:e,handler:r,middlewares:s}),this.pathPatterns.set(e,this.createPathPattern(e)),this}createPathPattern(t){let e=[],r=t.replace(/\/:[^/]+/g,s=>{let i=s.slice(2);return e.push(i),"/([^/]+)"});return r.endsWith("/*")?(r=`${r.slice(0,-2)}(?:/(.*))?`,e.push("wildcard")):r=r.replace(/\/$/,"/?"),{pattern:new RegExp(`^${r}$`),paramNames:e}}async executeMiddlewareChain(t,e,r){let s=0,i=async()=>{if(s<e.length){let n=e[s++];return n(t,i)}return r(t)};return i()}};var Le=()=>({port:Number(process.env.PORT)||3e3,host:process.env.HOST||"0.0.0.0",useHttps:!1,useHttp2:!1,sslCert:"",sslKey:"",sslCa:"",debug:Ti(process.env.DEBUG)||!1,maxBodySize:1048576,requestTimeout:3e4,rateLimit:{enabled:!0,requestsPerMinute:100},allowedDomains:["*"]});function Ti(t){return t==="true"||t===!0}var B=Le(),rr=t=>({configFilePath:"mikroserve.config.json",args:process.argv,options:[{flag:"--port",path:"port",defaultValue:B.port},{flag:"--host",path:"host",defaultValue:B.host},{flag:"--https",path:"useHttps",defaultValue:B.useHttps,isFlag:!0},{flag:"--http2",path:"useHttp2",defaultValue:B.useHttp2,isFlag:!0},{flag:"--cert",path:"sslCert",defaultValue:B.sslCert},{flag:"--key",path:"sslKey",defaultValue:B.sslKey},{flag:"--ca",path:"sslCa",defaultValue:B.sslCa},{flag:"--ratelimit",path:"rateLimit.enabled",defaultValue:B.rateLimit.enabled,isFlag:!0},{flag:"--rps",path:"rateLimit.requestsPerMinute",defaultValue:B.rateLimit.requestsPerMinute},{flag:"--allowed",path:"allowedDomains",defaultValue:B.allowedDomains,parser:oe.array},{flag:"--debug",path:"debug",defaultValue:B.debug,isFlag:!0},{flag:"--max-body-size",path:"maxBodySize",defaultValue:B.maxBodySize},{flag:"--request-timeout",path:"requestTimeout",defaultValue:B.requestTimeout}],config:t});function sr(t,e){let r=e.match(/boundary=(?:"([^"]+)"|([^;]+))/i);if(!r)throw new Error("Invalid multipart/form-data: missing boundary");let s=r[1]||r[2],i=Buffer.from(`--${s}`),n=Buffer.from(`--${s}--`),o={},a={},c=Ri(t,i);for(let l of c){if(l.length===0||l.equals(n.subarray(i.length)))continue;let u=ji(l);if(!u)continue;let{name:p,filename:m,contentType:w,data:b}=u;if(m){let N={filename:m,contentType:w||"application/octet-stream",data:b,size:b.length};a[p]?Array.isArray(a[p])?a[p].push(N):a[p]=[a[p],N]:a[p]=N}else{let N=b.toString("utf8");o[p]?Array.isArray(o[p])?o[p].push(N):o[p]=[o[p],N]:o[p]=N}}return{fields:o,files:a}}function Ri(t,e){let r=[],s=0;for(;s<t.length;){let i=t.indexOf(e,s);if(i===-1)break;s!==i&&r.push(t.subarray(s,i)),s=i+e.length,s<t.length&&t[s]===13&&t[s+1]===10&&(s+=2)}return r}function ji(t){let e=Buffer.from(`\r
112
112
  \r
113
113
  `),r=t.indexOf(e);if(r===-1)return null;let s=t.subarray(0,r),i=t.subarray(r+4),o=s.toString("utf8").split(`\r
114
- `),a="",c="",l,u;for(let m of o){let w=m.toLowerCase();if(w.startsWith("content-disposition:")){a=m.substring(20).trim();let b=a.match(/name="([^"]+)"/);b&&(c=b[1]);let N=a.match(/filename="([^"]+)"/);N&&(l=N[1])}else w.startsWith("content-type:")&&(u=m.substring(13).trim())}if(!c)return null;let p=i;return p.length>=2&&p[p.length-2]===13&&p[p.length-1]===10&&(p=p.subarray(0,p.length-2)),{disposition:a,name:c,filename:l,contentType:u,data:p}}import{readFileSync as he}from"fs";import St from"http";import $i from"http2";import Oi from"https";var ke=class{config;rateLimiter;router;shutdownHandlers=[];constructor(t){let e=new ne(rr(t||{})).get();e.debug&&console.log("Using configuration:",e),this.config=e,this.router=new tr;let r=e.rateLimit.requestsPerMinute||Le().rateLimit.requestsPerMinute;this.rateLimiter=new er(r,60),e.rateLimit.enabled===!0&&this.use(this.rateLimitMiddleware.bind(this))}use(t){return this.router.use(t),this}get(t,...e){return this.router.get(t,...e),this}post(t,...e){return this.router.post(t,...e),this}put(t,...e){return this.router.put(t,...e),this}delete(t,...e){return this.router.delete(t,...e),this}patch(t,...e){return this.router.patch(t,...e),this}any(t,...e){return this.router.any(t,...e),this}options(t,...e){return this.router.options(t,...e),this}start(){let t=this.createServer(),{port:e,host:r}=this.config;return this.setupGracefulShutdown(t),t.listen(e,r,()=>{let s=t.address(),i=this.config.useHttps||this.config.useHttp2?"https":"http";console.log(`MikroServe running at ${i}://${s.address!=="::"?s.address:"localhost"}:${s.port}`)}),t}createServer(){let t=this.requestHandler.bind(this);if(this.config.useHttp2){if(!this.config.sslCert||!this.config.sslKey)throw new Error("SSL certificate and key paths are required when useHttp2 is true");try{let e={key:he(this.config.sslKey),cert:he(this.config.sslCert),...this.config.sslCa?{ca:he(this.config.sslCa)}:{}};return $i.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:he(this.config.sslKey),cert:he(this.config.sslCert),...this.config.sslCa?{ca:he(this.config.sslCa)}:{}};return Oi.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 St.createServer(t)}async rateLimitMiddleware(t,e){let r=t.req.socket.remoteAddress||"unknown";return t.res.setHeader("X-RateLimit-Limit",this.rateLimiter.getLimit().toString()),t.res.setHeader("X-RateLimit-Remaining",this.rateLimiter.getRemainingRequests(r).toString()),t.res.setHeader("X-RateLimit-Reset",this.rateLimiter.getResetTime(r).toString()),this.rateLimiter.isAllowed(r)?e():{statusCode:429,body:{error:"Too Many Requests",message:"Rate limit exceeded, please try again later"},headers:{"Content-Type":"application/json"}}}async requestHandler(t,e){let r=Date.now(),s=t.method||"UNKNOWN",i=t.url||"/unknown",n=this.config.debug;try{if(this.setCorsHeaders(e,t),this.setSecurityHeaders(e,this.config.useHttps),n&&console.log(`${s} ${i}`),t.method==="OPTIONS"){if(e instanceof St.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(r,s,i)}}logDuration(t,e,r){let s=Date.now()-t;console.log(`${e} ${r} completed in ${s}ms`)}async parseBody(t){return new Promise((e,r)=>{let s=[],i=0,n=this.config.maxBodySize,o=!1,a=null,c=this.config.debug,l=t.headers["content-type"]||"";c&&console.log("Content-Type:",l),this.config.requestTimeout>0&&(a=setTimeout(()=>{o||(o=!0,c&&console.log("Request timeout exceeded"),r(new Error("Request timeout")))},this.config.requestTimeout));let u=()=>{a&&(clearTimeout(a),a=null)};t.on("data",p=>{if(!o){if(i+=p.length,c&&console.log(`Received chunk: ${p.length} bytes, total size: ${i}`),i>n){o=!0,u(),c&&console.log(`Body size exceeded limit: ${i} > ${n}`),r(new Error("Request body too large"));return}s.push(p)}}),t.on("end",()=>{if(!o){o=!0,u(),c&&console.log(`Request body complete: ${i} bytes`);try{if(s.length>0){let p=Buffer.concat(s);if(l.includes("application/json"))try{let m=p.toString("utf8");e(JSON.parse(m))}catch(m){r(new Error(`Invalid JSON in request body: ${m.message}`))}else if(l.includes("application/x-www-form-urlencoded")){let m=p.toString("utf8"),w={};new URLSearchParams(m).forEach((b,N)=>{w[N]=b}),e(w)}else if(l.includes("multipart/form-data"))try{let m=sr(p,l);e(m)}catch(m){r(new Error(`Invalid multipart form data: ${m.message}`))}else this.isBinaryContentType(l)?e(p):e(p.toString("utf8"))}else e({})}catch(p){r(new Error(`Invalid request body: ${p}`))}}}),t.on("error",p=>{o||(o=!0,u(),r(new Error(`Error reading request body: ${p.message}`)))}),t.on("close",()=>{u()})})}isBinaryContentType(t){return["application/octet-stream","application/pdf","application/zip","application/gzip","application/x-tar","application/x-rar-compressed","application/x-7z-compressed","image/","video/","audio/","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument","application/msword","application/vnd.ms-powerpoint"].some(r=>t.includes(r))}setCorsHeaders(t,e){let r=e.headers.origin,{allowedDomains:s=["*"]}=this.config;!r||s.length===0||s.includes("*")?t.setHeader("Access-Control-Allow-Origin","*"):s.includes(r)&&(t.setHeader("Access-Control-Allow-Origin",r),t.setHeader("Vary","Origin")),t.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, PATCH, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization"),t.setHeader("Access-Control-Max-Age","86400")}setSecurityHeaders(t,e=!1){let r={"X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","Content-Security-Policy":"default-src 'self'; script-src 'self'; object-src 'none'","X-XSS-Protection":"1; mode=block"};if((e||this.config.useHttp2)&&(r["Strict-Transport-Security"]="max-age=31536000; includeSubDomains"),t instanceof St.ServerResponse)Object.entries(r).forEach(([s,i])=>{t.setHeader(s,i)});else{let s=t;Object.entries(r).forEach(([i,n])=>{s.setHeader(i,n)})}}respond(t,e){let r={...e.headers||{}};(i=>typeof i.writeHead=="function"&&typeof i.end=="function")(t)?(t.writeHead(e.statusCode,r),e.body===null||e.body===void 0?t.end():e.isRaw||typeof e.body=="string"?t.end(e.body):t.end(JSON.stringify(e.body))):(console.warn("Unexpected response object type without writeHead/end methods"),t.writeHead?.(e.statusCode,r),e.body===null||e.body===void 0?t.end?.():e.isRaw||typeof e.body=="string"?t.end?.(e.body):t.end?.(JSON.stringify(e.body)))}setupGracefulShutdown(t){let e=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))})},r=()=>e(),s=()=>e(),i=o=>e(o),n=o=>e(o);this.shutdownHandlers=[r,s,i,n],process.on("SIGINT",r),process.on("SIGTERM",s),process.on("uncaughtException",i),process.on("unhandledRejection",n)}cleanupShutdownHandlers(){if(this.shutdownHandlers.length>0){let[t,e,r,s]=this.shutdownHandlers;process.removeListener("SIGINT",t),process.removeListener("SIGTERM",e),process.removeListener("uncaughtException",r),process.removeListener("unhandledRejection",s),this.shutdownHandlers=[]}}};import{timingSafeEqual as Mi}from"node:crypto";var le="x-molnos-cluster-secret";function ir(t,e){if(!t)return!1;let r=Buffer.from(t),s=Buffer.from(e);return r.length!==s.length?!1:Mi(r,s)}function Pe(t){return async(e,r)=>{let s=e.headers[le];return s?ir(s,t)?(e.state.isClusterRequest=!0,r()):e.json({success:!1,error:"Invalid cluster authentication"},403):r()}}function xt(t,e){return{...t,[le]:e}}var x=class extends Error{constructor(e){super(),this.name="ValidationError",this.message=e||"Invalid input",this.cause={statusCode:400}}},Ee=class extends Error{constructor(e){super(),this.name="IdentityAlreadyExistsError",this.message=e||"Identity already exists",this.cause={statusCode:400}}},q=class extends Error{constructor(e){super(),this.name="NotFoundError",this.message=e||"Resource not found",this.cause={statusCode:404}}},Ne=class extends Error{constructor(e){super(),this.name="InvalidInputError",this.message=e||"Invalid input",this.cause={statusCode:400}}};var K=class extends Error{constructor(e){super(),this.name="ConfigurationError",this.message=e||"Invalid configuration",this.cause={statusCode:400}}};var fe=class extends Error{constructor(e){super(),this.name="PermissionDeniedError",this.message=e||"Permission denied",this.cause={statusCode:403}}},G=class extends Error{constructor(e){super(),this.name="AlreadyExistsError",this.message=e||"Resource already exists",this.cause={statusCode:409}}},qe=class extends Error{constructor(e){super(),this.name="PortInUseError",this.message=e||"Port already in use",this.cause={statusCode:409}}},Te=class extends Error{constructor(e){super(),this.name="RoleNotFoundError",this.message=e||"Role not found",this.cause={statusCode:404}}},Fe=class extends Error{constructor(e){super(),this.name="ProtectedResourceError",this.message=e||"Cannot modify protected resource",this.cause={statusCode:403}}},_e=class extends Error{constructor(e){super(),this.name="ServiceRequestError",this.message=e||"Service request failed",this.cause={statusCode:502}}},Be=class extends Error{constructor(e){super(),this.name="WorkerUnavailableError",this.message=e||"Worker node is unavailable",this.cause={statusCode:503}}},Ve=class extends Error{constructor(e){super(),this.name="WorkerTimeoutError",this.message=e||"Worker node did not respond in time",this.cause={statusCode:504}}};var Ui=5e3;async function bt(t,e,r,s,i,n){let o=new URL(e,t.url),a=new Headers;for(let[p,m]of Object.entries(i)){let w=p.toLowerCase();w==="host"||w==="connection"||w==="keep-alive"||w==="transfer-encoding"||a.set(p,m)}n&&a.set(le,n);let c=t.timeoutMs||Ui,l=new AbortController,u=setTimeout(()=>l.abort(),c);try{let p;s&&(Buffer.isBuffer(s)?p=new Uint8Array(s):p=s);let m=await fetch(o.toString(),{method:r,headers:a,body:p,signal:l.signal});return clearTimeout(u),m}catch(p){throw clearTimeout(u),p.name==="AbortError"?new Ve(`Worker at ${t.url} did not respond within ${c}ms`):new Be(`Worker at ${t.url} is unavailable: ${p.message}`)}}async function Ct(t,e){let r=e.headers.get("content-type")||"",s=e.status;if(r.includes("application/json")){let o=await e.text();try{let a=JSON.parse(o);return t.json(a,s)}catch{return t.text(o,s)}}if(r.startsWith("text/")||r.includes("javascript")||r.includes("xml")){let o=await e.text();return t.text(o,s)}let i=await e.arrayBuffer(),n=t.binary(Buffer.from(i),r||"application/octet-stream");return s!==200?{...n,statusCode:s}:n}var Ge={healthCheckPath:"/health",healthCheckIntervalMs:3e4,timeoutMs:5e3,failureThreshold:3},Re=class{workers=new Map;timers=new Map;async registerWorkers(e){let r=Object.keys(e);for(let s of r){let i=e[s];i&&await this.registerWorker(s,i)}}async registerWorker(e,r){let s={url:r.url,capability:e,healthy:!0,consecutiveFailures:0,timeoutMs:r.timeoutMs||Ge.timeoutMs};this.workers.set(e,s);let i=r.healthCheckIntervalMs||Ge.healthCheckIntervalMs,n=r.healthCheckPath||Ge.healthCheckPath,o=setInterval(()=>this.checkHealth(e,n),i);this.timers.set(e,o),await this.checkHealth(e,n)}async checkHealth(e,r){let s=this.workers.get(e);if(s){try{let i=new AbortController,n=setTimeout(()=>i.abort(),s.timeoutMs),o=await fetch(`${s.url}${r}`,{method:"GET",signal:i.signal});clearTimeout(n),o.ok?this.handleSuccess(s):this.handleFailure(s)}catch{this.handleFailure(s)}s.lastHealthCheck=new Date}}handleSuccess(e){e.healthy=!0,e.consecutiveFailures=0}handleFailure(e){e.consecutiveFailures++,e.consecutiveFailures>=Ge.failureThreshold&&(e.healthy&&console.error(`[WorkerHealthChecker] Worker ${e.capability} at ${e.url} is now unhealthy (${e.consecutiveFailures} consecutive failures)`),e.healthy=!1)}isHealthy(e){return this.workers.get(e)?.healthy??!1}getWorkerState(e){return this.workers.get(e)}getAllWorkerStates(){return new Map(this.workers)}hasWorker(e){return this.workers.has(e)}shutdown(){for(let e of this.timers.values())clearInterval(e);this.timers.clear(),this.workers.clear()}};import _i from"node:crypto";import{getRandomValues as Hi}from"node:crypto";var It=class{options;defaultLength=16;defaultOnlyLowerCase=!1;defaultStyle="extended";defaultUrlSafe=!0;constructor(t){if(this.options={},t)for(let[e,r]of Object.entries(t))this.options[e]=this.generateConfig(r)}add(t){if(!t?.name)throw new Error("Missing name for the ID configuration");let e=this.generateConfig(t);this.options[t.name]=e}remove(t){if(!t?.name)throw new Error("Missing name for the ID configuration");delete this.options[t.name]}create(t,e,r,s){let i=this.generateConfig({length:t,style:e,onlyLowerCase:r,urlSafe:s});return this.generateId(i)}custom(t){if(this.options[t])return this.generateId(this.options[t]);throw new Error(`No configuration found with name: ${t}`)}generateConfig(t){return{name:t?.name||"",length:t?.length||this.defaultLength,onlyLowerCase:t?.onlyLowerCase??this.defaultOnlyLowerCase,style:t?.style||this.defaultStyle,urlSafe:t?.urlSafe??this.defaultUrlSafe}}getCharacterSet(t,e,r){if(t==="hex")return e?"0123456789abcdef":"0123456789ABCDEFabcdef";if(t==="alphanumeric")return e?"abcdefghijklmnopqrstuvwxyz0123456789":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";if(t==="extended")return r?e?"abcdefghijklmnopqrstuvwxyz0123456789-._~":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~":e?"abcdefghijklmnopqrstuvwxyz0123456789-._~!$()*+,;=:":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$()*+,;=:";throw new Error(`Unknown ID style "${t} provided. Must be one of "extended" (default), "alphanumeric", or "hex".`)}generateId(t){let{length:e,onlyLowerCase:r,style:s,urlSafe:i}=t;if(e<0||e===0)throw new Error("ID length cannot be negative");let n=this.getCharacterSet(s,r,i),o=(2<<Math.log(n.length-1)/Math.LN2)-1,a=Math.ceil(1.6*o*e/n.length),c="";for(;c.length<e;){let l=new Uint8Array(a);Hi(l);for(let u=0;u<a;u++){let p=l[u]&o;if(p<n.length&&(c+=n[p],c.length===e))break}}return c}};var Di=8,Li=40,Ni=/^[a-zA-Z0-9_-]{1,40}$/;function je(){return new It().create(Di,"alphanumeric",!1,!0)}function qi(t){return Ni.test(t)}function Fi(t){if(!qi(t))throw new Error(`Invalid ID format: "${t}". IDs must be 1-${Li} characters using only alphanumeric characters, underscores, and hyphens.`)}function ze(t){return t?(Fi(t),t):je()}function or(t,e,r){if(!r)return!1;let s=typeof t=="string"?[t]:t,i=typeof e=="string"?[e]:e;if(r.roles?.some(a=>a==="administrator"||a.id==="administrator"))return!0;let o=(r.roles||[]).flatMap(a=>typeof a=="string"?[]:(a.policies||[]).flatMap(l=>l?.permissions&&l?.targets?{permissions:l.permissions,targets:l.targets}:[]));for(let a of s)for(let c of i)if(!o.some(u=>nr(u?.permissions,a)&&nr(u?.targets,c)))return!1;return!0}function nr(t,e){return!t||t.length===0?!1:t.some(r=>{if(r==="*"||r===e)return!0;if(r.endsWith("*")&&r!=="*"){let s=r.slice(0,-1);return e.startsWith(s)}return!1})}var ue=class{id;name;type;roles;metadata;constructor(e){let{id:r,name:s,type:i,roles:n,metadata:o}=this.createIdentity(e);this.id=r,this.name=s,this.type=i,this.roles=n,this.metadata=o}createIdentity(e){let r=e?.id||this.createId(),s=e?.name||"",i=e?.type||"service_account",n=e?.metadata||{},o=e?.roles||["user"];return e&&this.validate({id:r,name:s,type:i,metadata:n,roles:o}),{id:r,name:s,type:i,metadata:{...n,createdAt:new Date().toISOString()},roles:o}}changeName(e){this.name=e}changeEmail(e){this.metadata||(this.metadata={}),this.metadata.email=e}updateMetadata(e){let r=this.metadata?JSON.parse(JSON.stringify(this.metadata)):{};this.metadata={...r,...e}}updateRoles(e){this.validateRoles(e),this.roles=e}createId(){return ze()}isValidRoleId(e){return typeof e!="string"||e.length===0?!1:/^[a-z0-9]+(-[a-z0-9]+)*$/.test(e)}isValidType(e){return["user","service_account"].includes(e)}validate(e){let r=e.id||"",s=e.name||"",i=e.type||"",n=e.metadata||{},o=e.roles||[];if(!r)throw new x("Missing ID");if(!s)throw new x("Missing name");if(!i||!this.isValidType(i))throw new x("Missing or invalid type");if(i==="user"&&!n?.email)throw new x("Missing email for user identity");if(!o||o.length===0)throw new x("Must have at least one role");this.validateRoles(o)}validateRoles(e){(e||[]).forEach(r=>{let s=r.id||r;if(!this.isValidRoleId(s))throw new x(`Invalid role ID '${s}'`)})}can(e,r,s){return or(e,r,s)}fromDTO(e){return this.validate(e),this.id=e.id,this.name=e.name,this.type=e.type,this.metadata=e.metadata||{},this.roles=e.roles,this}toDTO(){return{id:this.id,name:this.name,type:this.type,metadata:this.metadata,roles:this.roles}}};function ar(){return[{id:"administrator",name:"Administrator",description:"Full system administrator with all permissions",policies:[{permissions:["*"],targets:["*"]}],constraints:{assumable_by:{identities:[],roles:[],services:[]},assumption_constraints:{max_duration:3600,require_reason:!0,audit_level:"high"}}},{id:"user",name:"User",description:"Read-only access to resources",policies:[{permissions:["*.read"],targets:["*"]}],constraints:{assumable_by:{identities:[],roles:[],services:[]},assumption_constraints:{max_duration:3600,require_reason:!1,audit_level:"low"}}}]}var We=class{mikroAuth;db;tableName="identity_service";initialUser;roles;identities;serviceAccountTokens;constructor(e,r,s){this.mikroAuth=e,this.db=r,this.initialUser=s,this.roles=[],this.identities=[],this.serviceAccountTokens=new Map}async start(){await this.loadState(),this.roles.find(e=>e.id==="administrator")||this.createBaseRoles(),this.identities.length===0&&this.createInitialUser()}createBaseRoles(){let e=ar();for(let r of e)this.roles.push(r)}async createInitialUser(){let e=this.initialUser.email,r=this.initialUser.userName,s=await this.addUser(e,r,["administrator"]);return await this.mikroAuth.createMagicLink({email:e}),s}async getUserByEmail(e){let r=this.identities.find(s=>s.type==="user"&&s.metadata?.email===e&&s.metadata?.active!==!1);if(r)return this.enrichIdentityWithRoles(r)}async addUser(e,r,s=["user"],i=!0,n){if((await this.getUsers()).find(l=>l.metadata.email===e))throw new Ee(`User with email ${e} already exists`);let c=new ue({id:n,name:r,type:"user",metadata:{email:e,active:i},roles:s}).toDTO();return this.identities.push(c),await this.saveState(),this.enrichIdentityWithRoles(c)}async addServiceAccount(e,r,s,i){if((await this.getServiceAccounts()).find(l=>l.name===e))throw new Ee(`Service account with name ${e} already exists`);let a=new ue({id:i,name:e,type:"service_account",metadata:{description:r},roles:s}).toDTO(),c=this.generateServiceAccountToken();return this.serviceAccountTokens.set(c,a.id),this.identities.push(a),await this.saveState(),{...this.enrichIdentityWithRoles(a),apiKey:c}}async rotateServiceAccountKey(e){let r=await this.getIdentityById(e);if(!r||r.type!=="service_account")return;for(let[i,n]of this.serviceAccountTokens.entries())n===e&&this.serviceAccountTokens.delete(i);let s=this.generateServiceAccountToken();return this.serviceAccountTokens.set(s,e),await this.saveState(),s}async deleteIdentity(e){for(let[s,i]of this.serviceAccountTokens.entries())i===e&&this.serviceAccountTokens.delete(s);let r=this.identities.filter(s=>s.id!==e);this.identities=r,await this.saveState()}async updateIdentity(e,r){let s=await this.getIdentityById(e);if(!s)return;let i=new ue().fromDTO(s);r?.name&&i.changeName(r.name),r?.email&&i.changeEmail(r.email),r?.roles&&i.updateRoles(r.roles),r?.metadata&&i.updateMetadata(r.metadata);let n=i.toDTO();return this.updateIdentityList(n),await this.saveState(),this.enrichIdentityWithRoles(n)}updateIdentityList(e){if(!e)throw new x("Cannot update identity list: updatedIdentity is null or undefined");let r=JSON.parse(JSON.stringify(this.identities)),s=r.find(i=>i.id===e.id);s&&Object.assign(s,e),this.identities=r}generateServiceAccountToken(){return`sa.${je()}.${_i.randomBytes(32).toString("hex")}`}async getUserFromToken(e){if(e&&e.startsWith("Bearer ")){let r=e.split(" ")[1];if(r.startsWith("sa.")){let i=this.serviceAccountTokens.get(r);if(i){let n=this.identities.find(o=>o.id===i&&o.type==="service_account");if(n)return this.enrichIdentityWithRoles(n)}}else try{let i=this.mikroAuth.verify(r),n=i.email||i.sub;return this.getUserByEmail(n)}catch{let n=new Error("Invalid token");throw n.cause={statusCode:401},n}}}async getIdentityById(e){return this.identities.find(r=>r.id===e)}async getUserById(e){let r=await this.getIdentityById(e);if(!(!r||r.type!=="user"))return this.enrichIdentityWithRoles(r)}async getServiceAccountById(e){let r=await this.getIdentityById(e);if(!(!r||r.type!=="service_account"))return this.enrichIdentityWithRoles(r)}async updateUser(e,r){let s=await this.getIdentityById(e);if(!(!s||s.type!=="user"))return this.updateIdentity(e,r)}async updateServiceAccount(e,r){let s=await this.getIdentityById(e);if(!s||s.type!=="service_account")return;let i={...r};return r.description!==void 0&&(i.metadata={...i.metadata||{},description:r.description},delete i.description),this.updateIdentity(e,i)}async deleteUser(e){let r=await this.getIdentityById(e);return!r||r.type!=="user"?!1:(await this.deleteIdentity(e),!0)}async deleteServiceAccount(e){let r=await this.getIdentityById(e);return!r||r.type!=="service_account"?!1:(await this.deleteIdentity(e),!0)}enrichIdentityWithRoles(e){let r=JSON.parse(JSON.stringify(e));return e.roles?r.roles=e.roles.map(s=>this.roles.find(i=>i.id===s)).filter(Boolean):r.roles=[],r}async getIdentities(){return this.identities}async getUsers(){return this.identities.filter(e=>e.type==="user")}async getServiceAccounts(){return this.identities.filter(e=>e.type==="service_account")}can(e,r,s){return new ue(s).can(e,r,s)}async createCustomRole(e,r,s,i,n){if(this.roles.find(l=>l.id===e))throw new G(`Role with ID ${e} already exists`);let c={id:e,name:r,description:s,policies:[{permissions:i,targets:["*"]}],constraints:n||{assumable_by:{identities:[],roles:[],services:["functions"]},assumption_constraints:{max_duration:3600,require_reason:!1,audit_level:"medium"}}};this.roles.push(c),await this.saveState()}async updateRole(e,r){let s=this.roles.find(i=>i.id===e);if(!s)throw new Te(`Role with ID ${e} not found`);r.name!==void 0&&(s.name=r.name),r.description!==void 0&&(s.description=r.description),r.permissions!==void 0&&(s.policies=[{permissions:r.permissions,targets:["*"]}]),r.constraints!==void 0&&(s.constraints=r.constraints),await this.saveState()}async deleteRole(e){let r=this.roles.findIndex(s=>s.id===e);if(r===-1)throw new Te(`Role with ID ${e} not found`);if(e==="administrator"||e==="user")throw new Fe("Cannot delete base roles");this.roles.splice(r,1),await this.saveState()}async getRoles(){return this.roles}async getRole(e){return this.roles.find(r=>r.id===e)}async loadState(){let e=await this.load("identities");e&&(this.identities=e);let r=await this.load("roles");r&&(this.roles=r);let s=await this.load("serviceAccountTokens");if(s){let i=new Map(Object.entries(s));s&&Object.keys(s).length>0&&(this.serviceAccountTokens=i)}}async saveState(){let e=Object.fromEntries(this.serviceAccountTokens);await this.write("identities",this.identities),await this.write("roles",this.roles),await this.write("serviceAccountTokens",e)}async load(e){return await this.db.get(this.tableName,e)}async write(e,r){await this.db.write(this.tableName,e,r)}};import{existsSync as Bi}from"node:fs";import{spawn as Vi}from"node:child_process";import{createServer as Gi}from"node:net";var cr={storage:{name:"storage",path:"./storage.mjs",port:3001,prefix:"/storage",args:["--force"]},functions:{name:"functions",path:"./functions.mjs",port:3002,prefix:"/functions",args:["--force"]},sites:{name:"sites",path:"./sites.mjs",port:3003,prefix:"/sites",args:["--force"]},databases:{name:"databases",path:"./databases.mjs",port:3004,prefix:"/databases",args:["--force"]},observability:{name:"observability",path:"./observability.mjs",port:3005,prefix:"/observability",args:["--force"]}},ge=class{db;services=new Map;tableName="molnosmanagement";environmentVariables={};clusterConfig;setEnvironmentVariables(e){this.environmentVariables={...this.environmentVariables,...e}}setClusterConfig(e){this.clusterConfig=e}shouldSpawnLocally(e){if(!this.clusterConfig||this.clusterConfig.mode==="standalone")return!0;let r=e;return this.clusterConfig.mode==="core"?!this.clusterConfig.workers?.[r]:this.clusterConfig.mode==="worker"?this.clusterConfig.capabilities?.includes(r)??!1:!0}getWorkerEndpoint(e){if(!this.clusterConfig||this.clusterConfig.mode!=="core")return null;let r=e;return this.clusterConfig.workers?.[r]?.url??null}async forwardToWorker(e,r){let s=this.getWorkerEndpoint(e);if(!s)return console.error(`[ManagementService] No worker configured for capability: ${e}`),!1;let i=this.clusterConfig?.secret;if(!i)return console.error("[ManagementService] Cannot forward to worker: no cluster secret configured"),!1;let n=`${s}/management/service/${e}/${r}`,o=xt({"Content-Type":"application/json"},i);try{let a=await fetch(n,{method:"POST",headers:o});if(!a.ok){let l=await a.text();return console.error(`[ManagementService] Worker returned error for ${r} ${e}: ${l}`),!1}let c=await a.json();return c.isStarted??c.isStopped??c.isRestarted??!1}catch(a){return console.error(`[ManagementService] Failed to forward ${r} ${e} to worker:`,a),!1}}async isPortInUse(e){return new Promise(r=>{let s=Gi();s.once("error",i=>{i.code==="EADDRINUSE"?r(!0):r(!1)}),s.once("listening",()=>{s.close(),r(!1)}),s.listen(e,"127.0.0.1")})}constructor(e){this.db=new J({databaseDirectory:e.dbPath})}getServiceDefinition(e){let r=e.toLowerCase(),s=cr[r];if(!s)throw new q(`Unknown service: ${e}. Valid services are: ${Object.keys(cr).join(", ")}`);return s}async start(){await this.db.start();let e=await this.db.get(this.tableName,"services")||[];for(let r of e)r.restartPolicy&&(r.restartPolicy.attempts=0),r.healthCheck&&(r.healthCheck.consecutiveFailures=0,r.healthCheck.consecutiveSuccesses=0,r.healthCheck.healthy=!0),this.services.set(r.name,r),this.shouldSpawnLocally(r.name)&&r.active&&await this.startService(r.name)}async stopAllServices(){let e=[];for(let[r,s]of this.services.entries())(s.active||s.process)&&e.push(this.stopService(r));await Promise.all(e)}async shutdown(){await this.stopAllServices()}validateServiceConfig(e){if(!e.name||e.name.trim()==="")throw new x("Service name is required");if(!e.path||e.path.trim()==="")throw new x("Service path is required");if(!Bi(e.path))throw new K(`Service path does not exist: ${e.path}`);if(!e.port||e.port<1||e.port>65535)throw new x(`Invalid port: ${e.port}`);if(!e.prefix||!e.prefix.startsWith("/"))throw new x("Service prefix must start with /")}cleanServiceForStorage(e){let{process:r,...s}=e;if(s.healthCheck){let{timer:i,consecutiveFailures:n,consecutiveSuccesses:o,healthy:a,...c}=s.healthCheck;s.healthCheck=c}if(s.restartPolicy){let{attempts:i,...n}=s.restartPolicy;s.restartPolicy=n}return s}async registerService(e,r){let s;typeof e=="string"?s={...this.getServiceDefinition(e),...r}:s=e,this.validateServiceConfig(s);let i={...s,active:!1},n=await this.getServices(),o=[],a=[];if(n.forEach(l=>{o.push(l.name),a.push(l.port)}),a.includes(i.port))throw new qe(`Port ${i.port} already in use`);if(o.includes(i.name))throw new G(`Service with name '${i.name}' already exists`);i.restartPolicy&&(i.restartPolicy.attempts=0),i.healthCheck&&(i.healthCheck.consecutiveFailures=0,i.healthCheck.consecutiveSuccesses=0,i.healthCheck.healthy=!0),this.services.set(i.name,i);let c=await this.db.get(this.tableName,"services")||[];return c.push(this.cleanServiceForStorage(i)),await this.db.write(this.tableName,"services",c),i.name}async startService(e){if(!this.shouldSpawnLocally(e))return this.getWorkerEndpoint(e)?this.forwardToWorker(e,"start"):!1;let r=this.services.get(e);if(!r)return!1;if(r.process&&r.active)return!0;if(await this.isPortInUse(r.port))return console.error(`[ManagementService] Cannot start ${e}: Port ${r.port} is already in use. Please kill the process using this port.`),!1;try{let i={stdio:"pipe",detached:!1,env:{...process.env,...this.environmentVariables}},n=r.args||[],o=`--port=${r.port}`,a=Vi("node",[r.path,o,...n],i);r.process=a,r.restartPolicy&&(r.restartPolicy.attempts=0);let c=!1;return a.stdout.on("data",l=>{let u=l.toString();console.log(`[${e}] ${u}`)}),a.stderr.on("data",l=>{let u=l.toString();console.error(`[${e}] ERROR: ${u}`),(u.includes("EADDRINUSE")||u.includes("address already in use"))&&(c=!0)}),a.on("exit",l=>{r.active=!1,r.process=void 0,c&&console.error(`[ManagementService] Service ${e} failed to start due to startup error`),this.handleServiceExit(r,l||0)}),await new Promise(l=>setTimeout(l,500)),r.process&&!r.process.killed?(r.active=!0,await this.updateServiceStatus(e,!0),r.healthCheck&&this.startHealthCheck(r),!0):(console.error(`[ManagementService] Service ${e} exited immediately after spawn`),!1)}catch(i){return console.error(`[ManagementService] Failed to start ${e}:`,i),!1}}startHealthCheck(e){let r=e.healthCheck;if(!r)return;let s=async()=>{if(e.healthCheck)try{let i=new AbortController,n=setTimeout(()=>i.abort(),e.healthCheck.timeoutMs),o=await fetch(`http://127.0.0.1:${e.port}${e.healthCheck.path}`,{signal:i.signal});clearTimeout(n),o.ok&&e.healthCheck?(e.healthCheck.consecutiveSuccesses=(e.healthCheck.consecutiveSuccesses||0)+1,e.healthCheck.consecutiveFailures=0,e.healthCheck.consecutiveSuccesses>=e.healthCheck.successThreshold&&(e.healthCheck.healthy=!0)):this.handleHealthCheckFailure(e)}catch{this.handleHealthCheckFailure(e)}};r.timer=setInterval(s,r.intervalMs)}handleHealthCheckFailure(e){e.healthCheck&&(e.healthCheck.consecutiveFailures=(e.healthCheck.consecutiveFailures||0)+1,e.healthCheck.consecutiveSuccesses=0,e.healthCheck.consecutiveFailures>=e.healthCheck.failureThreshold&&(e.healthCheck.healthy=!1,e.healthCheck.restartOnFailure&&this.restartService(e.name).catch(()=>{})))}async handleServiceExit(e,r){if(await this.updateServiceStatus(e.name,!1),!e.restartPolicy||e.restartPolicy.type==="never"||e.restartPolicy.type==="on-failure"&&r===0||e.restartPolicy.maxAttempts>0&&(e.restartPolicy.attempts||0)>=e.restartPolicy.maxAttempts)return;e.restartPolicy.attempts=(e.restartPolicy.attempts||0)+1;let s=e.restartPolicy.backoffMs;setTimeout(()=>{this.startService(e.name).catch(()=>{})},s)}async stopService(e){if(!this.shouldSpawnLocally(e))return this.getWorkerEndpoint(e)?this.forwardToWorker(e,"stop"):!1;let r=this.services.get(e);if(!r)return!1;if(r.healthCheck?.timer&&(clearInterval(r.healthCheck.timer),r.healthCheck.timer=void 0),!r.process)return r.active&&(r.active=!1,await this.updateServiceStatus(e,!1)),!0;try{let s=i=>{try{return process.kill(i,0),!0}catch{return!1}};if(r.process?.pid){let i=r.process.pid;if(s(i))try{process.kill(i,"SIGTERM");let n=setTimeout(()=>{try{s(i)&&process.kill(i,"SIGKILL")}catch{}},5*1e3);await new Promise(o=>{if(!r.process){clearTimeout(n),o();return}let a=setTimeout(()=>{clearTimeout(n),o()},6*1e3);r.process.once("exit",()=>{clearTimeout(n),clearTimeout(a),o()})})}catch(n){if(n.code!=="ESRCH")throw n}}return r.active=!1,r.process=void 0,await this.updateServiceStatus(e,!1),!0}catch{return r.active&&(r.active=!1,r.process=void 0,await this.updateServiceStatus(e,!1)),!1}}async restartService(e){return this.shouldSpawnLocally(e)?(await this.stopService(e),await new Promise(r=>setTimeout(r,500)),this.startService(e)):this.getWorkerEndpoint(e)?this.forwardToWorker(e,"restart"):!1}async updateServiceStatus(e,r){let s=await this.db.get(this.tableName,"services")||[],i=s.findIndex(n=>n.name===e);if(i>=0){let n=this.services.get(e);n?(n.active=r,s[i]=this.cleanServiceForStorage(n)):s[i].active=r,await this.db.write(this.tableName,"services",s)}}async getService(e){return(await this.getServices()).find(s=>s.name===e)}async getServices(){return(await this.db.get(this.tableName,"services")||[]).map(({process:r,...s})=>s)}async getServiceStats(e){let r=this.services.get(e);return r?{name:r.name,active:r.active,health:r.healthCheck?{healthy:r.healthCheck.healthy||!1,consecutiveSuccesses:r.healthCheck.consecutiveSuccesses||0,consecutiveFailures:r.healthCheck.consecutiveFailures||0}:null,restarts:r.restartPolicy&&r.restartPolicy.attempts||0}:null}async updateService(e,r){let s=this.services.get(e);if(!s)return!1;let i=s.active;Object.assign(s,r);let n=await this.db.get(this.tableName,"services")||[],o=n.findIndex(a=>a.name===e);return o>=0?(n[o]=this.cleanServiceForStorage(s),await this.db.write(this.tableName,"services",n),i!==s.active&&(s.active?await this.startService(e):await this.stopService(e)),!0):!1}async removeService(e){let r=this.services.get(e);r?.healthCheck?.timer&&(clearInterval(r.healthCheck.timer),r.healthCheck.timer=void 0),await this.stopService(e),this.services.delete(e);let i=(await this.db.get(this.tableName,"services")||[]).filter(n=>n.name!==e);return await this.db.write(this.tableName,"services",i),!0}};var X=class{id;name;description;redirectUris;metadata;owners;constructor(e){let r=this.createApplication(e);this.id=r.id,this.name=r.name,this.description=r.description,this.redirectUris=r.redirectUris,this.metadata=r.metadata,this.owners=r.owners}createApplication(e){let r=e?.id||this.createId(),s=e?.name||"",i=e?.description,n=e?.redirectUris||[],o=e?.owners||[],a=new Date().toISOString(),c={...e?.metadata||{},createdAt:e?.metadata?.createdAt||a,updatedAt:a,createdBy:e?.metadata?.createdBy||o[0]||""};return e&&this.validate({id:r,name:s,description:i,redirectUris:n,metadata:c,owners:o}),{id:r,name:s,description:i,redirectUris:n,metadata:c,owners:o}}update(e){e.name!==void 0&&(this.name=e.name),e.description!==void 0&&(this.description=e.description),e.redirectUris!==void 0&&(this.validateRedirectUris(e.redirectUris),this.redirectUris=e.redirectUris),e.owners!==void 0&&(this.owners=e.owners),e.metadata!==void 0?this.metadata={...this.metadata,...e.metadata,updatedAt:new Date().toISOString()}:this.metadata.updatedAt=new Date().toISOString(),this.validate(this.toDTO())}isValidRedirectUri(e){return this.redirectUris.includes(e)}isOwner(e){return this.owners.includes(e)}createId(){return ze()}validate(e){let{id:r,name:s,redirectUris:i,metadata:n,owners:o}=e;if(!r)throw new x("Missing ID");if(!s||s.trim().length===0)throw new x("Missing or invalid name");if(!n)throw new x("Missing metadata");if(!o||o.length===0)throw new x("Application must have at least one owner");this.validateRedirectUris(i)}validateRedirectUris(e){if(!e||e.length===0)throw new x("At least one redirect URI is required");for(let r of e)try{let s=new URL(r);if(s.protocol!=="https:"&&s.protocol!=="http:"&&s.protocol!=="custom:")throw new x(`Invalid redirect URI protocol: ${r}. Must use https:, http: (localhost only), or custom: (for native apps)`);s.protocol==="http:"&&!s.hostname.match(/^(localhost|127\.0\.0\.1|\[::1\])$/)&&console.warn(`Warning: HTTP redirect URI detected for non-localhost: ${r}. HTTPS is recommended for production.`)}catch{throw new x(`Invalid redirect URI format: ${r}`)}}fromDTO(e){return this.validate(e),this.id=e.id,this.name=e.name,this.description=e.description,this.redirectUris=e.redirectUris,this.metadata=e.metadata,this.owners=e.owners,this}toDTO(){return{id:this.id,name:this.name,description:this.description,redirectUris:this.redirectUris,metadata:this.metadata,owners:this.owners}}};var Je=class{db;tableName="molnosapplications";key="applications";applications;constructor(e){this.db=new J({databaseDirectory:e.dbPath}),this.applications=[]}async start(){await this.db.start(),await this.loadState()}async loadState(){let e=await this.db.get(this.tableName,this.key)||[];this.applications=e}async saveState(){await this.db.write(this.tableName,this.key,this.applications)}async createApplication(e,r){let s=e.owners.includes(r)?e.owners:[...e.owners,r],n=new X({...e,owners:s,metadata:{...e.metadata,createdBy:r}}).toDTO();if(this.applications.find(a=>a.name===n.name))throw new G(`Application with name '${n.name}' already exists`);return this.applications.push(n),await this.saveState(),n}async getApplication(e,r){let s=this.applications.find(n=>n.id===e);if(!s)throw new q(`Application with ID '${e}' not found`);let i=new X().fromDTO(s);if(r&&!i.isOwner(r))throw new fe("Only application owners can view application details");return i.toDTO()}async getApplicationById(e){return this.applications.find(s=>s.id===e)||null}async listApplications(e){return this.applications.filter(r=>r.owners.includes(e)).map(r=>new X().fromDTO(r).toDTO())}async updateApplication(e,r,s){let i=this.applications.findIndex(a=>a.id===e);if(i===-1)throw new q(`Application with ID '${e}' not found`);let n=this.applications[i],o=new X().fromDTO(n);if(!o.isOwner(s))throw new fe("Only application owners can update the application");if(r.owners&&r.owners.length===0)throw new x("Application must have at least one owner");if(r.owners&&!r.owners.includes(s)&&n.owners.length===1&&n.owners[0]===s)throw new x("Cannot remove yourself as the last owner of the application");return o.update(r),this.applications[i]=o.toDTO(),await this.saveState(),this.applications[i]}async deleteApplication(e,r){let s=this.applications.findIndex(o=>o.id===e);if(s===-1)throw new q(`Application with ID '${e}' not found`);let i=this.applications[s];if(!new X().fromDTO(i).isOwner(r))throw new fe("Only application owners can delete the application");this.applications.splice(s,1),await this.saveState()}async validateRedirectUri(e,r){let s=await this.getApplicationById(e);return s?new X().fromDTO(s).isValidRedirectUri(r):!1}getAllApplicationsInternal(){return this.applications}};var zi=/^[a-z0-9][a-z0-9-]*[a-z0-9]$/,$e=class{name;version;description;schema;createdAt;updatedAt;constructor(e){let r=this.createSchema(e);this.name=r.name,this.version=r.version,this.description=r.description,this.schema=r.schema,this.createdAt=r.createdAt,this.updatedAt=r.updatedAt}createSchema(e){let r=e?.name||"",s=e?.version||1,i=e?.description,n=e?.schema||{properties:{}},o=new Date().toISOString(),a=e?.createdAt||o,c=o;return e&&this.validate({name:r,schema:n}),{name:r,version:s,description:i,schema:n,createdAt:a,updatedAt:c}}update(e){e.schema&&(this.validateSchemaDefinition(e.schema),this.schema=e.schema),e.description!==void 0&&(this.description=e.description),this.version+=1,this.updatedAt=new Date().toISOString()}validate(e){let{name:r,schema:s}=e;if(!r||r.trim().length===0)throw new x("Missing or invalid schema name");if(r.length<2||r.length>100)throw new x("Schema name must be between 2 and 100 characters");if(!zi.test(r))throw new x("Schema name must be kebab-case (lowercase alphanumeric and hyphens, cannot start or end with hyphen)");this.validateSchemaDefinition(s)}validateSchemaDefinition(e){if(!e||!e.properties)throw new x("Schema must have a properties object");if(Object.keys(e.properties).length===0)throw new x("Schema must define at least one property");let r=["string","number","boolean","array","object"];for(let[s,i]of Object.entries(e.properties))if(!i.type||!r.includes(i.type))throw new x(`Property '${s}' has invalid type. Must be one of: ${r.join(", ")}`)}fromDTO(e){return this.validate({name:e.name,schema:e.schema}),this.name=e.name,this.version=e.version,this.description=e.description,this.schema=e.schema,this.createdAt=e.createdAt,this.updatedAt=e.updatedAt,this}toDTO(){return{name:this.name,version:this.version,description:this.description,schema:this.schema,createdAt:this.createdAt,updatedAt:this.updatedAt}}};var Ke=class{db;tableName="molnosschemas";key="schemas";schemas;constructor(e){this.db=new J({databaseDirectory:e.dbPath}),this.schemas=[]}async start(){await this.db.start(),await this.loadState()}async loadState(){let e=await this.db.get(this.tableName,this.key)||[];this.schemas=e}async saveState(){await this.db.write(this.tableName,this.key,this.schemas)}async createSchema(e){if(this.schemas.find(n=>n.name===e.name))throw new G(`Schema with name '${e.name}' already exists`);let i=new $e(e).toDTO();return this.schemas.push(i),await this.saveState(),i}async getSchema(e,r){let s=this.findSchema(e,r);if(!s){let i=r?` version ${r}`:"";throw new q(`Schema '${e}'${i} not found`)}return s}async listSchemas(){return[...this.schemas]}async updateSchema(e,r){let s=this.schemas.findIndex(o=>o.name===e);if(s===-1)throw new q(`Schema '${e}' not found`);if(!r.schema)throw new x("Schema definition is required for update");let i=this.schemas[s],n=new $e().fromDTO(i);return n.update(r),this.schemas[s]=n.toDTO(),await this.saveState(),this.schemas[s]}async deleteSchema(e){let r=this.schemas.findIndex(s=>s.name===e);if(r===-1)throw new q(`Schema '${e}' not found`);this.schemas.splice(r,1),await this.saveState()}validate(e,r,s){let i=this.findSchema(r,s);return i?this.validateAgainstDefinition(e,i.schema):{valid:!1,errors:[{path:"",message:`Schema '${r}' not found in registry`}]}}findSchema(e,r){return r?this.schemas.find(s=>s.name===e&&s.version===r):this.schemas.find(s=>s.name===e)}validateAgainstDefinition(e,r){let s=[];if(typeof e!="object"||e===null||Array.isArray(e))return{valid:!1,errors:[{path:"",message:"Data must be a non-null object"}]};let i=e;if(r.required)for(let n of r.required)n in i||s.push({path:n,message:`Missing required field '${n}'`});for(let[n,o]of Object.entries(r.properties))o.required&&!(n in i)&&(r.required?.includes(n)||s.push({path:n,message:`Missing required field '${n}'`}));for(let[n,o]of Object.entries(i)){let a=r.properties[n];if(!a){r.additionalProperties===!1&&s.push({path:n,message:`Unexpected property '${n}'`});continue}let c=this.validatePropertyType(n,o,a);c&&s.push(c)}return{valid:s.length===0,errors:s.length>0?s:void 0}}validatePropertyType(e,r,s){if(r==null)return null;let i=Array.isArray(r)?"array":typeof r;if(s.type==="array"){if(!Array.isArray(r))return{path:e,message:`Expected type 'array', got '${typeof r}'`}}else if(s.type==="object"){if(typeof r!="object"||Array.isArray(r))return{path:e,message:`Expected type 'object', got '${i}'`}}else if(i!==s.type)return{path:e,message:`Expected type '${s.type}', got '${i}'`};return null}};async function S(t){return t.body||{}}function h(t,e="An error occurred"){let r=t?.message||t||e,s=t?.cause?.statusCode||t?.statusCode||400;return{message:r,status:s}}async function lr(t,e,r,s){try{let i=await S(t),{email:n,redirectUrl:o,applicationId:a}=i;if(!n)return t.json({error:"Email is required"},400);let c=n.trim().toLowerCase(),l;if(o){if(!a)return t.json({error:"applicationId is required when redirectUrl is provided"},400);if(!await s.validateRedirectUri(a,o))return t.json({error:"Invalid redirectUrl or applicationId. The redirect URI must be registered for this application."},400);l=(await s.getApplicationById(a))?.name}let u=!1;return await e.getUserByEmail(c)&&(u=!0),u&&await r.createMagicLink({email:c,subject:`Sign In To ${l||"MolnOS"}`,appUrl:o,metadata:{appName:l,redirectUrl:o,applicationId:a}}),t.json({success:!0,message:"If a matching account was found, a magic link has been sent."})}catch(i){let{message:n,status:o}=h(i,"Error during login");return t.json({error:n},o)}}async function ur(t,e,r){try{let s=t.query.token,i=t.query.email;if(!s)return t.json({error:"Token is required as query parameter"},400);if(!i)return t.json({error:"Email is required as query parameter"},400);try{let n=await e.verifyToken({token:s,email:i});if(!n)return t.json({error:"Invalid or expired token"},401);let o=n.metadata;if(o?.redirectUrl&&o?.applicationId)if(await r.validateRedirectUri(o.applicationId,o.redirectUrl)){let c=new URL(o.redirectUrl);return c.searchParams.set("access_token",n.accessToken),c.searchParams.set("refresh_token",n.refreshToken),c.searchParams.set("expires_in",n.expiresIn.toString()),t.redirect(c.toString(),302)}else return console.warn(`Redirect URL validation failed for applicationId: ${o.applicationId}`),t.json({...n,warning:"Redirect URL validation failed. Tokens provided but redirect was not performed."},200);return t.json(n,200)}catch{return t.json({error:"Invalid or expired token"},401)}}catch(s){let{message:i,status:n}=h(s,"Error verifying token");return t.json({error:i},n)}}async function dr(t,e){try{let s=(await S(t)).refreshToken;if(!s)return t.json({error:"Value for refreshToken is required"},400);try{let i=await e.refreshAccessToken(s);return t.json(i,200)}catch{return t.json({error:"Invalid or expired token"},401)}}catch(r){let{message:s,status:i}=h(r,"Error refreshing token");return t.json({error:s},i)}}async function pr(t){try{let e=t.state.user;return t.json(e)}catch(e){let{message:r,status:s}=h(e,"Error getting user info");return t.json({error:r},s)}}function g(t,e,r={}){let s=Array.isArray(e)?e:[e];if(!t||!t.roles||!Array.isArray(t.roles)){let o=new Error("Unauthorized: User or roles missing");throw o.cause={statusCode:403},o}let i=t.roles.flatMap(o=>o?.policies?.flatMap(a=>(a?.permissions||[]).flatMap(l=>typeof l=="string"?l:l&&typeof l=="object"&&l.actions?l.actions:[]))||[]);if(!s.every(o=>i.includes(o)||i.includes("*")?!0:i.some(a=>{if(a.endsWith(".*")){let c=a.slice(0,-2);return o.startsWith(`${c}.`)}return!1}))){let o=new Error("Unauthorized");throw o.cause={statusCode:403},o}return!0}async function mr(t,e){try{let r=t.state.user;g(r,"identity.identities.get",{});let s=await e.getIdentities();return t.json(s)}catch(r){let{message:s,status:i}=h(r,"Error getting identities");return t.json({error:s},i)}}var $=class{isSilent;propertyPath="";constructor(t=!1){this.isSilent=t}test(t,e){if(!e)throw new Error("Missing input!");this.updatePropertyPath();let{results:r,errors:s}=this.validate(t.properties,e),i=this.compileErrors(r,s),n=this.isSuccessful(r,i);return{errors:i,success:n}}compileErrors(t,e){let r=t.filter(s=>s.success===!1);return[...e,...r].flatMap(s=>s)}isSuccessful(t,e){return t.every(r=>r.success===!0)&&e.length===0}validate(t,e,r=[],s=[]){let i=t?.additionalProperties??!0,n=t?.required||[];s=this.checkForRequiredKeysErrors(n,e,s),s=this.checkForDisallowedProperties(Object.keys(e),Object.keys(t),s,i);for(let o in t){let a=n.includes(o)&&o!=="required",c=t[o],l=e[o],u=c.additionalProperties??!0;a&&(s=this.checkForRequiredKeysErrors(c.required||[],l,s)),this.isDefined(l)&&(this.handleValidation(o,l,c,r),s=this.checkForDisallowedProperties(Object.keys(l),Object.keys(c),s,u),this.handleNestedObject(l,c,r,s))}return{results:r,errors:s}}updatePropertyPath(t,e=""){if(!t){this.propertyPath="";return}e&&(this.propertyPath=e),this.propertyPath=`${this.propertyPath}.${t}`,this.propertyPath.startsWith(".")&&(this.propertyPath=this.propertyPath.substring(1,this.propertyPath.length))}isDefined(t){return!!(typeof t=="number"&&t===0||t||t===""||typeof t=="boolean")}checkForRequiredKeysErrors(t,e,r){if(!this.areRequiredKeysPresent(t,e)){let s=e?Object.keys(e):[],i=this.findNonOverlappingElements(t,s),n=i.length>0?`Missing the required key: '${i.join(", ")}'!`:`Missing values for required keys: '${s.filter(o=>!e[o]).join(", ")}'!`;r.push({key:"",value:e,success:!1,error:n})}return r}checkForDisallowedProperties(t,e,r,s){if(!s){let i=this.findNonOverlappingElements(t,e);i.length>0&&r.push({key:`${e}`,value:t,success:!1,error:`Has additional (disallowed) properties: '${i.join(", ")}'!`})}return r}handleValidation(t,e,r,s){this.updatePropertyPath(t);let i=this.validateProperty(this.propertyPath,r,e);s.push(...i);let n=(a,c)=>{a.forEach(l=>{let u=this.validateProperty(this.propertyPath,c.items,l);s.push(...u)}),this.updatePropertyPath()},o=a=>{let c=Object.keys(a),l=this.propertyPath;c.forEach(u=>{if(this.updatePropertyPath(u,l),this.isArray(a[u])&&r[u]?.items!=null)n(a[u],r[u]);else{let p=this.validateProperty(this.propertyPath,r[u],a[u]);s.push(...p)}})};this.isArray(e)&&r.items!=null?n(e,r):this.isObject(e)?o(e):this.updatePropertyPath()}handleNestedObject(t,e,r,s){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,r,s)}}}getNestedObjects(t){return Object.keys(t).filter(e=>{if(this.isObject(t))return e})}findNonOverlappingElements(t,e){return t.filter(r=>!e.includes(r))}areRequiredKeysPresent(t,e=[]){return t.every(r=>Object.keys(e).includes(r)?this.isDefined(e[r]):!1)}validateProperty(t,e,r){return this.validateInput(e,r).map(i=>{let{success:n,error:o}=i;return{key:t,value:r,success:n,error:o??""}})}validateInput(t,e){if(t){let r=[{condition:()=>t.type,validator:()=>this.isCorrectType(t.type,e),error:"Invalid type"},{condition:()=>t.format,validator:()=>this.isCorrectFormat(t.format,e),error:"Invalid format"},{condition:()=>t.minLength,validator:()=>this.isMinimumLength(t.minLength,e),error:"Length too short"},{condition:()=>t.maxLength,validator:()=>this.isMaximumLength(t.maxLength,e),error:"Length too long"},{condition:()=>t.minValue,validator:()=>this.isMinimumValue(t.minValue,e),error:"Value too small"},{condition:()=>t.maxValue,validator:()=>this.isMaximumValue(t.maxValue,e),error:"Value too large"},{condition:()=>t.matchesPattern,validator:()=>this.matchesPattern(t.matchesPattern,e),error:"Pattern does not match"}],s=[];for(let i of r)i.condition()&&!i.validator()&&s.push({success:!1,error:i.error});return s}else this.isSilent||console.warn(`Missing property '${t}' for match '${e}'. Skipping...`);return[{success:!0}]}isCorrectType(t,e){return Array.isArray(t)||(t=[t]),t.some(r=>{switch(r){case"string":return typeof e=="string";case"number":return typeof e=="number"&&!isNaN(e);case"boolean":return typeof e=="boolean";case"object":return this.isObject(e);case"array":return this.isArray(e)}})}isObject(t){return t!==null&&!this.isArray(t)&&typeof t=="object"&&t instanceof Object&&Object.prototype.toString.call(t)==="[object Object]"}isArray(t){return Array.isArray(t)}isCorrectFormat(t,e){switch(t){case"alphanumeric":return new RegExp(/^[a-zA-Z0-9]+$/).test(e);case"numeric":return new RegExp(/^-?\d+(\.\d+)?$/).test(e);case"email":return new RegExp(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/).test(e);case"date":return new RegExp(/^\d{4}-\d{2}-\d{2}$/).test(e);case"url":return new RegExp(/^(https?):\/\/[^\s$.?#].[^\s]*$/).test(e);case"hexColor":return new RegExp(/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i).test(e)}}isMinimumLength(t,e){return Array.isArray(e)?e.length>=t:e?.toString().length>=t}isMaximumLength(t,e){return Array.isArray(e)?e.length<=t:e.toString().length<=t}isMinimumValue(t,e){return e>=t}isMaximumValue(t,e){return e<=t}matchesPattern(t,e){return new RegExp(t).test(e)}schemaFrom(t){let e={properties:{additionalProperties:!1,required:[]}};for(let r in t){let s=t[r];e.properties.required.push(r),Array.isArray(s)?e.properties[r]=this.generateArraySchema(s):typeof s=="object"&&s!==null?e.properties[r]=this.generateNestedObjectSchema(s):e.properties[r]=this.generatePropertySchema(s)}return e}generateArraySchema(t){let e={type:"array"},r=t.filter(s=>s);if(r.length>0){let s=r[0];r.every(n=>typeof n==typeof s)?typeof s=="object"&&!Array.isArray(s)?e.items=this.generateNestedObjectSchema(s):e.items=this.generatePropertySchema(s):console.warn("All elements in array are not of the same type. Unable to generate a schema for these elements.")}return e}generateNestedObjectSchema(t){let e={type:"object",additionalProperties:!1,required:[]};for(let r in t){let s=t[r];e.required.push(r),typeof s=="object"&&!Array.isArray(s)&&s!==null?e[r]=this.generateNestedObjectSchema(s):e[r]=this.generatePropertySchema(s)}return e}generatePropertySchema(t){let e=typeof t,r={type:e};return e==="string"&&(r.minLength=1),r}};var hr={properties:{id:{type:"string",minLength:1,maxLength:40,pattern:"^[a-zA-Z0-9_-]{1,40}$"},email:{type:"string",format:"email",minLength:3},name:{type:"string",minLength:1},roles:{type:"array",items:{type:"string"}},verified:{type:"boolean"}},required:["email","name","roles"],additionalProperties:!1};var Ji=new $(!0);async function fr(t,e){try{let r=t.state.user,s=await S(t),i=Ji.test(hr,s);if(!i.success)return t.json({error:"Invalid input",details:i.errors},400);g(r,"identity.user.create",{});let{id:n,email:o,name:a,roles:c,verified:l}=s,u=await e.addUser(o,a,c,l,n);return t.json(u,201)}catch(r){let{message:s,status:i}=h(r,"Error creating user");return t.json({error:s},i)}}async function gr(t,e){try{let r=t.state.user;g(r,"identity.user.get",{});let s=await e.getUsers();return t.json(s)}catch(r){let{message:s,status:i}=h(r,"Error getting users");return t.json({error:s},i)}}function P(t){return t.params}async function yr(t,e){try{let r=t.state.user,s=P(t),{userId:i}=s;g(r,"identity.user.get",{userId:i});let n=await e.getUserById(i);return n?t.json(n):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error getting user");return t.json({error:s},i)}}var vr={properties:{name:{type:"string",minLength:1},roles:{type:"array",items:{type:"string"}}},additionalProperties:!1};var Xi=new $(!0);async function wr(t,e){try{let r=t.state.user,s=P(t),{userId:i}=s,n=await S(t),o=Xi.test(vr,n);if(!o.success)return t.json({error:"Invalid input",details:o.errors},400);g(r,"identity.user.update",{userId:i});let{name:a,roles:c}=n,l=await e.updateUser(i,{name:a,roles:c});return l?t.json(l):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error updating user");return t.json({error:s},i)}}async function Sr(t,e){try{let r=t.state.user,s=P(t),{userId:i}=s;return g(r,"identity.user.delete",{userId:i}),await e.deleteUser(i)?t.body(null,204):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error deleting user");return t.json({error:s},i)}}async function xr(t,e){try{let r=t.state.user,s=await S(t);if(!s.name||!s.description||!s.roles||!Array.isArray(s.roles))return t.json({error:"Invalid input: name, description, and roles are required"},400);if(!["user","administrator"].every(l=>s.roles.includes(l)||!s.roles.includes(l)))return t.json({error:"Invalid input: roles must be user or administrator"},400);g(r,"identity.service-account.create",{});let{id:i,name:n,description:o,roles:a}=s,c=await e.addServiceAccount(n,o,a,i);return t.json(c,201)}catch(r){let{message:s,status:i}=h(r,"Error creating service account");return t.json({error:s},i)}}async function br(t,e){try{let r=t.state.user;g(r,"identity.service-account.get",{});let s=await e.getServiceAccounts();return t.json(s)}catch(r){let{message:s,status:i}=h(r,"Error getting service accounts");return t.json({error:s},i)}}async function Cr(t,e){try{let r=t.state.user,s=P(t),{serviceAccountId:i}=s;g(r,"identity.service-account.get",{serviceAccountId:i});let n=await e.getServiceAccountById(i);return n?t.json(n):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error getting service account");return t.json({error:s},i)}}var Ir={properties:{name:{type:"string",minLength:1,maxLength:100},description:{type:"string",minLength:1,maxLength:500},roles:{type:"array",items:{type:"string"}}},additionalProperties:!1};var Zi=new $(!0);async function Ar(t,e){try{let r=t.state.user,s=P(t),{serviceAccountId:i}=s,n=await S(t),o=Zi.test(Ir,n);if(!o.success)return t.json({error:"Invalid input",details:o.errors},400);g(r,"identity.service-account.update",{serviceAccountId:i});let{name:a,description:c,roles:l}=n,u=await e.updateServiceAccount(i,{name:a,description:c,roles:l});return u?t.json(u):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error updating service account");return t.json({error:s},i)}}async function kr(t,e){try{let r=t.state.user,s=P(t),{serviceAccountId:i}=s;return g(r,"identity.service-account.delete",{serviceAccountId:i}),await e.deleteServiceAccount(i)?t.body(null,204):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error deleting service account");return t.json({error:s},i)}}async function Pr(t,e){try{let r=t.state.user,s=P(t),{serviceAccountId:i}=s;g(r,"identity.service-account.update",{serviceAccountId:i});let n=await e.rotateServiceAccountKey(i);return n?t.json({apiKey:n}):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error rotating service account key");return t.json({error:s},i)}}async function Er(t,e){try{let r=t.state.user;g(r,"identity.role.get",{});let s=await e.getRoles();return t.json(s)}catch(r){let{message:s,status:i}=h(r,"Error getting roles");return t.json({error:s},i)}}async function Tr(t,e){try{let r=t.state.user;g(r,"identity.role.get",{});let s=t.params.roleId;if(!s)return t.text("Missing role ID",400);let i=await e.getRole(s);return i?t.json(i):t.text("Role not found",404)}catch(r){let{message:s,status:i}=h(r,"Error getting role");return t.json({error:s},i)}}async function Rr(t,e){try{let r=t.state.user;g(r,"identity.role.create",{});let s=await S(t),{roleId:i,name:n,description:o,permissions:a,constraints:c}=s;if(!i||!n||!o)return t.text("Missing required fields: roleId, name, description",400);if(!a||!Array.isArray(a))return t.text("Permissions must be a non-empty array",400);await e.createCustomRole(i,n,o,a,c);let l=await e.getRole(i);return t.json(l,201)}catch(r){let{message:s,status:i}=h(r,"Error creating role");return t.json({error:s},i)}}async function jr(t,e){try{let r=t.state.user;g(r,"identity.role.update",{});let s=t.params.roleId;if(!s)return t.text("Missing role ID",400);let i=await S(t),{name:n,description:o,permissions:a,constraints:c}=i;await e.updateRole(s,{name:n,description:o,permissions:a,constraints:c});let l=await e.getRole(s);return t.json(l)}catch(r){let{message:s,status:i}=h(r,"Error updating role");return t.json({error:s},i)}}async function $r(t,e){try{let r=t.state.user;g(r,"identity.role.delete",{});let s=t.params.roleId;return s?s==="administrator"||s==="user"?t.text("Cannot delete base roles",403):(await e.deleteRole(s),t.json({message:"Role deleted successfully"})):t.text("Missing role ID",400)}catch(r){let{message:s,status:i}=h(r,"Error deleting role");return t.json({error:s},i)}}async function Or(t,e){try{let r=t.state.user;g(r,"management.services.get",{});let s=await e.getServices();return t.json(s)}catch(r){let{message:s,status:i}=h(r,"Error getting services");return t.json({error:s},i)}}async function Mr(t,e){try{let r=t.state.user,s=P(t),{serviceName:i}=s;g(r,"management.service.get",{serviceName:i});let n=await e.getService(i);return n?t.json(n):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error getting service");return t.json({error:s},i)}}var Ur={properties:{name:{type:"string",minLength:1},path:{type:"string"},port:{type:"number",minValue:1,maxValue:65535},prefix:{type:"string"},healthCheckPath:{type:"string"},healthCheckInterval:{type:"number",minValue:1e3}},required:["name"],additionalProperties:!0};var en=new $(!0);async function Hr(t,e){try{let r=t.state.user,s=await S(t),i=en.test(Ur,s);if(!i.success)return t.json({error:"Invalid input",details:i.errors},400);if(g(r,"management.service.create",{}),["storage","functions","sites","databases","observability"].includes(s.name.toLowerCase())){let{name:a,...c}=s;await e.registerService(a,c)}else{if(!s.path||!s.port||!s.prefix)return t.json({error:"Custom services require: name, path, port, and prefix"},400);await e.registerService(s)}return t.text("",201)}catch(r){let{message:s,status:i}=h(r,"Error creating service");return t.json({error:s},i)}}var Dr={properties:{name:{type:"string",minLength:1},path:{type:"string"},port:{type:"number",minValue:1,maxValue:65535},prefix:{type:"string"},healthCheckPath:{type:"string"},healthCheckInterval:{type:"number",minValue:1e3}},required:["name"],additionalProperties:!0};var rn=new $(!0);async function Lr(t,e){try{let r=t.state.user,s=P(t),i=await S(t),n=i.name,o=rn.test(Dr,i);return o.success?(g(r,"management.service.update",{serviceName:n}),n!==s.serviceName?t.json({error:"Service name in body must match path parameter"},400):(await e.updateService(n,i),t.body(null,204))):t.json({error:"Invalid input",details:o.errors},400)}catch(r){let{message:s,status:i}=h(r,"Error updating service");return t.json({error:s},i)}}async function Nr(t,e){try{let r=t.state.user,s=P(t),{serviceName:i}=s;return g(r,"management.service.delete",{serviceName:i}),await e.getService(i)?(await e.removeService(i),t.body(null,204)):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error deleting service");return t.json({error:s},i)}}async function qr(t,e){try{let r=t.state.user,s=P(t),{serviceName:i}=s;if(g(r,"management.service.start",{serviceName:i}),!await e.getService(i))return t.text("Not Found",404);let o=await e.startService(i);return t.json({serviceName:i,isStarted:o})}catch(r){let{message:s,status:i}=h(r,"Error starting service");return t.json({error:s},i)}}async function Fr(t,e){try{let r=t.state.user,s=P(t),{serviceName:i}=s;if(g(r,"management.service.stop",{serviceName:i}),!await e.getService(i))return t.text("Not Found",404);let o=await e.stopService(i);return t.json({serviceName:i,isStopped:o})}catch(r){let{message:s,status:i}=h(r,"Error stopping service");return t.json({error:s},i)}}async function _r(t,e){try{let r=t.state.user,s=P(t),{serviceName:i}=s;if(g(r,"management.service.get",{serviceName:i}),!await e.getService(i))return t.text("Not Found",404);let o=new URL("http://127.0.0.1:3005/events");o.searchParams.set("service",i),t.query.startTime&&o.searchParams.set("startTime",t.query.startTime),t.query.endTime&&o.searchParams.set("endTime",t.query.endTime),t.query.level&&o.searchParams.set("level",t.query.level),t.query.limit&&o.searchParams.set("limit",t.query.limit),t.query.offset&&o.searchParams.set("offset",t.query.offset);let a=await fetch(o.toString());if(!a.ok)throw new _e(`Observability service error: ${a.statusText}`);let c=await a.json();return t.json({serviceName:i,logs:c.events,count:c.count})}catch(r){let{message:s,status:i}=h(r,"Error getting service logs");return t.json({error:s},i)}}async function Br(t,e){try{let r=t.state.user,s=P(t),{serviceName:i}=s;if(g(r,"management.service.start",{serviceName:i}),!await e.getService(i))return t.text("Not Found",404);let o=await e.restartService(i);return t.json({serviceName:i,restarted:o})}catch(r){let{message:s,status:i}=h(r,"Error restarting service");return t.json({error:s},i)}}function Vr(t,e,r,s,i){let n=t.find(c=>c.service===e);if(!n){let c=new Error(`Function bindings do not include access to service: ${e}`);throw c.cause={statusCode:403},c}if(!n.permissions||n.permissions.length===0)return;for(let c of n.permissions)if(!(c.resource&&c.resource!==r)){if(!c.resource||!c.actions||c.actions.length===0)return;if(c.actions.includes(s)){if(c.targets&&c.targets.length>0){if(!i)return;if(!c.targets.includes(i))continue}return}}let o=i?`:${i}`:"",a=new Error(`Function bindings do not allow: ${e}.${r}.${s}${o}`);throw a.cause={statusCode:403},a}import{readFileSync as sn,existsSync as nn}from"node:fs";function Xe(){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||!nn(t))return e;try{let r=sn(t,"utf-8");return JSON.parse(r)}catch(r){return console.error("[loadRuntimeConfig] Failed to load runtime config:",r),e}}async function v(t,e,r,s,i,n,o){if(!e)return null;let a=t.headers["x-molnos-service-token"];if(a){let u=Xe();if(u.internalServiceSecret&&a===u.internalServiceSecret)return null}let c=t.state.user;if(!c){let u=t.headers.authorization;if(!u){let m=new Error("Unauthorized: No authentication provided");throw m.cause={statusCode:401},m}let p=u.replace(/^Bearer\s+/i,"");if(c=await e.getUserFromToken(p),!c){let m=new Error("Unauthorized: Invalid token");throw m.cause={statusCode:401},m}}g(c,r,{});let l=t.headers["x-function-bindings"];if(l)try{let u=Array.isArray(l)?l[0]:l,p=JSON.parse(u);Vr(p,s,i,n,o)}catch(u){if(u.cause?.statusCode===403)throw u;let p=new Error("Invalid function bindings header");throw p.cause={statusCode:400},p}return c}async function Gr(t,e,r){try{let s=await S(t),i=t.state.requestingIdentity;if(!i)return t.json({error:"Authentication required"},401);let{id:n,name:o,description:a,redirectUris:c,metadata:l}=s;if(!o||!c)return t.json({error:"Missing required fields: name and redirectUris are required"},400);await v(t,r,"applications.application.create","applications","application","create",o);let u={id:n,name:o,description:a,redirectUris:Array.isArray(c)?c:[c],metadata:l,owners:[i.id]},p=await e.createApplication(u,i.id);return t.json(p,201)}catch(s){let{message:i,status:n}=h(s,"Error creating application");return t.json({error:i},n)}}async function zr(t,e,r){try{let s=t.params.id,i=t.state.requestingIdentity;if(!s)return t.json({error:"Application ID is required"},400);await v(t,r,"applications.application.read","applications","application","read",s);let n=await e.getApplication(s,i?.id);return t.json(n,200)}catch(s){let{message:i,status:n}=h(s,"Error retrieving application");return t.json({error:i},n)}}async function Wr(t,e,r){try{let s=t.state.requestingIdentity;if(!s)return t.json({error:"Authentication required"},401);await v(t,r,"applications.application.list","applications","application","list");let i=await e.listApplications(s.id);return t.json({applications:i,total:i.length},200)}catch(s){let{message:i,status:n}=h(s,"Error listing applications");return t.json({error:i},n)}}async function Jr(t,e,r){try{let s=t.params.id,i=await S(t),n=t.state.requestingIdentity;if(!n)return t.json({error:"Authentication required"},401);if(!s)return t.json({error:"Application ID is required"},400);await v(t,r,"applications.application.update","applications","application","update",s);let o=await e.updateApplication(s,i,n.id);return t.json(o,200)}catch(s){let{message:i,status:n}=h(s,"Error updating application");return t.json({error:i},n)}}async function Kr(t,e,r){try{let s=t.params.id,i=t.state.requestingIdentity;return i?s?(await v(t,r,"applications.application.delete","applications","application","delete",s),await e.deleteApplication(s,i.id),t.json({success:!0,message:"Application deleted"},200)):t.json({error:"Application ID is required"},400):t.json({error:"Authentication required"},401)}catch(s){let{message:i,status:n}=h(s,"Error deleting application");return t.json({error:i},n)}}async function Xr(t,e,r){try{let s=await S(t),{name:i,description:n,schema:o}=s;if(!i||!o)return t.json({error:"Missing required fields: name and schema are required"},400);await v(t,r,"schemas.schema.create","schemas","schema","create",i);let a=await e.createSchema({name:i,description:n,schema:o});return t.json(a,201)}catch(s){let{message:i,status:n}=h(s,"Error creating schema");return t.json({error:i},n)}}async function At(t,e,r){try{let s=t.params.name,i=t.params.version;if(!s)return t.json({error:"Schema name is required"},400);await v(t,r,"schemas.schema.read","schemas","schema","read",s);let n=i?parseInt(i,10):void 0,o=await e.getSchema(s,n);return t.json(o,200)}catch(s){let{message:i,status:n}=h(s,"Error retrieving schema");return t.json({error:i},n)}}async function Yr(t,e,r){try{await v(t,r,"schemas.schema.list","schemas","schema","list");let s=await e.listSchemas();return t.json({schemas:s,total:s.length},200)}catch(s){let{message:i,status:n}=h(s,"Error listing schemas");return t.json({error:i},n)}}async function Zr(t,e,r){try{let s=t.params.name,i=await S(t);if(!s)return t.json({error:"Schema name is required"},400);if(!i.schema)return t.json({error:"Missing required field: schema is required for update"},400);await v(t,r,"schemas.schema.update","schemas","schema","update",s);let n=await e.updateSchema(s,{description:i.description,schema:i.schema});return t.json(n,200)}catch(s){let{message:i,status:n}=h(s,"Error updating schema");return t.json({error:i},n)}}async function Qr(t,e,r){try{let s=t.params.name;return s?(await v(t,r,"schemas.schema.delete","schemas","schema","delete",s),await e.deleteSchema(s),t.json({success:!0,message:"Schema deleted"},200)):t.json({error:"Schema name is required"},400)}catch(s){let{message:i,status:n}=h(s,"Error deleting schema");return t.json({error:i},n)}}async function es(t,e,r){try{await v(t,r,"contexts.context.get","contexts","context","get");let i=e.listContexts().map(n=>{let o=e.getContextResources(n.name);return{...n,resourceCount:{functions:o.functions.length,databases:o.databases.length,storage:o.storage.length,sites:o.sites.length,users:o.users.length,serviceAccounts:o.serviceAccounts.length}}});return t.json({success:!0,contexts:i},200)}catch(s){let{message:i,status:n}=h(s,"Error listing contexts");return t.json({error:i},n)}}async function ts(t,e,r){try{let s=t.params.contextName;if(!s)return t.json({error:"contextName parameter is required"},400);await v(t,r,"contexts.context.get","contexts","context","get",s);let i=e.getContextWithResources(s);return t.json({success:!0,context:i},200)}catch(s){let{message:i,status:n}=h(s,"Error getting context");return t.json({error:i},n)}}var on=new $(!0),an={properties:{name:{type:"string",minLength:1,maxLength:64},intent:{type:"string",maxLength:1e3},attributes:{type:"object"}},required:["name"],additionalProperties:!1};async function rs(t,e,r){try{let s=await S(t),i=on.test(an,s);if(!i.success)return t.json({error:"Invalid input",details:i.errors},400);await v(t,r,"contexts.context.create","contexts","context","create");let{name:n,intent:o,attributes:a}=s,c=await e.createContext({name:n,intent:o,attributes:a});return t.json({success:!0,context:c},201)}catch(s){let{message:i,status:n}=h(s,"Error creating context");return t.json({error:i},n)}}var cn=new $(!0),ln={properties:{intent:{type:"string",maxLength:1e3},attributes:{type:"object"}},additionalProperties:!1};async function ss(t,e,r){try{let s=t.params.contextName;if(!s)return t.json({error:"contextName parameter is required"},400);let i=await S(t),n=cn.test(ln,i||{});if(!n.success)return t.json({error:"Invalid input",details:n.errors},400);await v(t,r,"contexts.context.update","contexts","context","update",s);let{intent:o,attributes:a}=i||{},c=await e.updateContext(s,{intent:o,attributes:a});return t.json({success:!0,context:c},200)}catch(s){let{message:i,status:n}=h(s,"Error updating context");return t.json({error:i},n)}}async function is(t,e,r){try{let s=t.params.contextName;if(!s)return t.json({error:"contextName parameter is required"},400);if(s==="default")return t.json({error:"Cannot delete the default context"},400);await v(t,r,"contexts.context.delete","contexts","context","delete",s);let i=e.getContextResources(s);return await e.deleteContext(s),t.json({success:!0,message:`Context '${s}' deleted`,orphanedResources:i},200)}catch(s){let{message:i,status:n}=h(s,"Error deleting context");return t.json({error:i},n)}}async function ns(t,e,r,s){try{let i=t.params.contextName;if(!i)return t.json({error:"contextName parameter is required"},400);await v(t,r,"contexts.context.delete-resources","contexts","context","delete-resources",i);let n=t.headers.authorization,o=n?.startsWith("Bearer ")?n.slice(7):n,a=s(o),c=e.getContextResources(i),l={success:!0,context:i,deleted:[],errors:[],summary:{totalResources:0,deletedCount:0,failedCount:0}};if(l.summary.totalResources=c.functions.length+c.databases.length+c.storage.length+c.sites.length+c.applications.length+c.users.length+c.serviceAccounts.length,a.functions){let p=await a.functions.list();for(let m of c.functions)try{let w=p.find(b=>b.id===m);w&&(await a.functions.delete(m),await e.unregisterResource(i,"function",m),l.deleted.push({type:"function",name:w.name}))}catch(w){l.errors.push({type:"function",name:m,error:w.message||"Unknown error"}),l.success=!1}}if(a.databases)for(let p of c.databases)try{await a.databases.deleteTable(p),await e.unregisterResource(i,"database",p),l.deleted.push({type:"database",name:p})}catch(m){l.errors.push({type:"database",name:p,error:m.message||"Unknown error"}),l.success=!1}if(a.storage)for(let p of c.storage)try{await a.storage.deleteBucket(p),await e.unregisterResource(i,"storage",p),l.deleted.push({type:"storage",name:p})}catch(m){l.errors.push({type:"storage",name:p,error:m.message||"Unknown error"}),l.success=!1}if(a.sites)for(let p of c.sites)try{await a.sites.deleteProject(p),await e.unregisterResource(i,"site",p),l.deleted.push({type:"site",name:p})}catch(m){l.errors.push({type:"site",name:p,error:m.message||"Unknown error"}),l.success=!1}if(a.applications){let p=await a.applications.list();for(let m of c.applications)try{let w=p.find(b=>b.id===m);w&&(await a.applications.delete(m),await e.unregisterResource(i,"application",m),l.deleted.push({type:"application",name:w.name}))}catch(w){l.errors.push({type:"application",name:m,error:w.message||"Unknown error"}),l.success=!1}}if(a.identity)for(let p of c.users)try{let m=await a.identity.getUser(p);m&&(await a.identity.deleteUser(m.id),await e.unregisterResource(i,"user",p),l.deleted.push({type:"user",name:p}))}catch(m){l.errors.push({type:"user",name:p,error:m.message||"Unknown error"}),l.success=!1}if(a.identity)for(let p of c.serviceAccounts)try{let m=await a.identity.getServiceAccount(p);m&&(await a.identity.deleteServiceAccount(m.id),await e.unregisterResource(i,"serviceAccount",p),l.deleted.push({type:"serviceAccount",name:p}))}catch(m){l.errors.push({type:"serviceAccount",name:p,error:m.message||"Unknown error"}),l.success=!1}l.summary.deletedCount=l.deleted.length,l.summary.failedCount=l.errors.length;let u=l.success?200:207;return t.json(l,u)}catch(i){let{message:n,status:o}=h(i,"Error deleting context resources");return t.json({error:n},o)}}async function os(t,e,r){try{await v(t,r,"iac.config.get","iac","config","get");let s=await S(t);if(!s)return t.json({error:"Request body is required"},400);let i=s,o=e().validate(i);return t.json({success:!0,valid:o.valid,errors:o.errors,warnings:o.warnings},200)}catch(s){let{message:i,status:n}=h(s,"Error validating IaC");return t.json({error:i},n)}}async function as(t,e,r){try{await v(t,r,"iac.config.create","iac","config","create");let s=await S(t);if(!s)return t.json({error:"Request body is required"},400);let i=s,n=t.headers.authorization,o=n?.startsWith("Bearer ")?n.slice(7):n,a=e(o),c=t.query?.prune==="true",l=await a.apply(i,{prune:c}),u=l.success?200:207;return t.json({success:l.success,context:l.context,created:l.created,updated:l.updated,unchanged:l.unchanged,deleted:l.deleted,errors:l.errors},u)}catch(s){let{message:i,status:n}=h(s,"Error applying IaC");return t.json({error:i},n)}}var Y="default",Ye=class{db;tableName="context_service";contexts;resourceMappings;constructor(e){this.db=e,this.contexts=[],this.resourceMappings=[]}async start(){await this.loadState()}async loadState(){try{let e=await this.db.get(this.tableName,"state");e&&(this.contexts=e.contexts||[],this.resourceMappings=e.resourceMappings||[])}catch{this.contexts=[],this.resourceMappings=[]}}async saveState(){await this.db.write(this.tableName,"state",{contexts:this.contexts,resourceMappings:this.resourceMappings})}async createContext(e){let r=e.name;if(this.contexts.find(n=>n.name===r))throw new G(`Context '${r}' already exists`);let s=new Date().toISOString(),i={name:r,intent:e.intent,attributes:e.attributes,createdAt:s,updatedAt:s};return this.contexts.push(i),await this.saveState(),i}getContext(e){let r=this.contexts.find(s=>s.name===e);if(!r)throw new q(`Context '${e}' not found`);return r}getContextWithResources(e){let r=this.getContext(e),s=this.getContextResources(e);return{...r,resources:s}}async updateContext(e,r){let s=this.contexts.findIndex(o=>o.name===e);if(s===-1)throw new q(`Context '${e}' not found`);let i=this.contexts[s],n={...i,intent:r.intent??i.intent,attributes:r.attributes??i.attributes,updatedAt:new Date().toISOString()};return this.contexts[s]=n,await this.saveState(),n}async deleteContext(e){let r=this.contexts.findIndex(s=>s.name===e);if(r===-1)throw new q(`Context '${e}' not found`);this.contexts.splice(r,1),this.resourceMappings=this.resourceMappings.filter(s=>s.context!==e),await this.saveState()}contextExists(e){return this.contexts.some(r=>r.name===e)}listContexts(){return[...this.contexts].sort((e,r)=>e.name.localeCompare(r.name))}async ensureContext(e){let r=e||Y;return this.contextExists(r)||await this.createContext({name:r,intent:r===Y?"Default context for resources without explicit context assignment.":void 0}),r}async registerResource(e,r,s){await this.ensureContext(e),this.resourceMappings.find(n=>n.context===e&&n.resourceType===r&&n.resourceName===s)||(this.resourceMappings.push({context:e,resourceType:r,resourceName:s,createdAt:new Date().toISOString()}),await this.saveState())}async unregisterResource(e,r,s){this.resourceMappings=this.resourceMappings.filter(i=>!(i.context===e&&i.resourceType===r&&i.resourceName===s)),await this.saveState()}getContextResources(e){let r=this.resourceMappings.filter(i=>i.context===e),s={functions:[],databases:[],storage:[],sites:[],users:[],serviceAccounts:[],applications:[],schemas:[]};for(let i of r)switch(i.resourceType){case"function":s.functions.push(i.resourceName);break;case"database":s.databases.push(i.resourceName);break;case"storage":s.storage.push(i.resourceName);break;case"site":s.sites.push(i.resourceName);break;case"user":s.users.push(i.resourceName);break;case"serviceAccount":s.serviceAccounts.push(i.resourceName);break;case"application":s.applications.push(i.resourceName);break;case"schema":s.schemas.push(i.resourceName);break}return s}getResourceContext(e,r){return this.resourceMappings.find(i=>i.resourceType===e&&i.resourceName===r)?.context||Y}async moveResource(e,r,s,i){await this.unregisterResource(s,e,r),await this.registerResource(i,e,r)}listResourcesByType(e,r){return this.resourceMappings.filter(s=>s.context===e&&s.resourceType===r).map(s=>s.resourceName)}};async function cs(t,e,r){try{await v(t,r,"iac.config.get","iac","config","get");let s=await S(t);if(!s)return t.json({error:"Request body is required"},400);let i=s,n=t.headers.authorization,o=n?.startsWith("Bearer ")?n.slice(7):n,a=e(o),c=a.validate(i);if(!c.valid)return t.json({success:!1,valid:!1,errors:c.errors,warnings:c.warnings},400);let l=await a.diff(i);return t.json({success:!0,context:i.context?.name||Y,toCreate:l.toCreate,toUpdate:l.toUpdate,toDelete:l.toDelete,unchanged:l.unchanged,warnings:c.warnings},200)}catch(s){let{message:i,status:n}=h(s,"Error generating IaC diff");return t.json({error:i},n)}}var un=new $(!0),dn={type:"object",properties:{intent:{type:"string",minLength:1,maxLength:1e4},intentAttributes:{type:"object"},resourceTypes:{type:"array",items:{type:"string",enum:["functions","sites"]}},files:{type:"array",items:{type:"object",properties:{path:{type:"string"},content:{type:"string"}},required:["path","content"]}},iacConfig:{type:"object"},iterationFeedback:{type:"string"},previousAttemptId:{type:"string"},providerOverride:{type:"string"},modelOverride:{type:"string"},userApiKey:{type:"string"}},additionalProperties:!1};async function ls(t,e,r){try{let s=t.params.contextName;if(!s)return t.json({error:"Context name is required"},400);await v(t,r,"ai.generation.generate","ai","generation","generate",s);let i=await S(t),n=un.test(dn,i);if(!n.success)return t.json({error:"Invalid input",details:n.errors},400);if(!e.isAvailable())return t.json({error:"AI generation is not enabled. Please configure AI in molnos.config.json or provide your own API key."},503);let o=null;if(i.previousAttemptId&&(o=e.getGeneration(i.previousAttemptId),!o))return t.json({error:"Previous generation not found"},404);let a=await e.generate({contextName:s,intent:i.intent,intentAttributes:i.intentAttributes,resourceTypes:i.resourceTypes,files:i.files,iacConfig:i.iacConfig,iterationFeedback:i.iterationFeedback,previousAttempt:o||void 0,providerOverride:i.providerOverride,modelOverride:i.modelOverride,userApiKey:i.userApiKey});return t.json({success:!0,generation:a},201)}catch(s){let{message:i,status:n}=h(s,"Error generating code");return t.json({error:i},n)}}async function us(t,e,r){try{let s=t.params.generationId;if(!s)return t.json({error:"Generation ID is required"},400);await v(t,r,"ai.generation.read","ai","generation","read",s);let i=e.getGeneration(s);return i?t.json({success:!0,generation:i}):t.json({error:"Generation not found or expired"},404)}catch(s){let{message:i,status:n}=h(s,"Error retrieving generation");return t.json({error:i},n)}}async function ds(t,e,r){try{let s=t.params.contextName;if(!s)return t.json({error:"Context name is required"},400);await v(t,r,"ai.generation.read","ai","generation","read",s);let i=e.listGenerations(s);return t.json({success:!0,generations:i})}catch(s){let{message:i,status:n}=h(s,"Error listing generations");return t.json({error:i},n)}}async function ps(t,e,r){try{let s=t.params.generationId;if(!s)return t.json({error:"Generation ID is required"},400);await v(t,r,"ai.generation.apply","ai","generation","apply",s);let i=t.headers.authorization?.replace("Bearer ",""),n=await e.applyGeneration(s,i);if(!n.success)return t.json({error:"Failed to apply IAC configuration",details:n.errors},400);let o=e.getGeneration(s);return t.json({success:!0,generation:o,applyResult:n})}catch(s){let{message:i,status:n}=h(s,"Error applying generation");return t.json({error:i},n)}}async function ms(t,e,r){try{let s=t.params.generationId;return s?(await v(t,r,"ai.generation.discard","ai","generation","discard",s),e.getGeneration(s)?e.discardGeneration(s)?t.json({success:!0,message:"Generation discarded"}):t.json({error:"Failed to discard generation"},500):t.json({error:"Generation not found or expired"},404)):t.json({error:"Generation ID is required"},400)}catch(s){let{message:i,status:n}=h(s,"Error discarding generation");return t.json({error:i},n)}}async function hs(t,e,r){try{let s=t.params.generationId;return s?(await v(t,r,"ai.generation.delete","ai","generation","delete",s),e.getGeneration(s)?e.deleteGeneration(s)?t.json({success:!0,message:"Generation deleted"}):t.json({error:"Failed to delete generation"},500):t.json({error:"Generation not found or expired"},404)):t.json({error:"Generation ID is required"},400)}catch(s){let{message:i,status:n}=h(s,"Error deleting generation");return t.json({error:i},n)}}import{promises as Ze}from"node:fs";import{join as kt,resolve as mn}from"node:path";var fs={$schema:"https://json-schema.org/draft-07/schema#",$id:"https://schemas.molnos.cloud/schema-iac-v1.json",title:"MolnOS IaC Configuration",description:"Infrastructure-as-Code configuration file for MolnOS contexts",type:"object",properties:{$schema:{type:"string",description:"JSON Schema reference for editor support"},version:{type:"string",enum:["1"],default:"1",description:'IaC schema version (defaults to "1" if not specified)'},context:{type:"object",description:"Context definition (optional, defaults to 'default' context)",properties:{name:{type:"string",minLength:1,maxLength:64,pattern:"^[a-z][a-z0-9-]*$",description:"Context name (lowercase, alphanumeric with hyphens)"},intent:{type:"string",maxLength:1e3,description:"Human-readable description of what this context does"},attributes:{type:"object",description:"Freeform intent attributes for policy hints and visualization"}},required:["name"]},resources:{type:"object",description:"Resource declarations",properties:{functions:{type:"object",description:"Function deployments"},databases:{type:"object",description:"Database table declarations"},storage:{type:"object",description:"Storage bucket declarations"},sites:{type:"object",description:"Static site declarations"},schemas:{type:"object",description:"Schema registry declarations"}}},identities:{type:"object",description:"Identity declarations",properties:{users:{type:"object",description:"User declarations"},serviceAccounts:{type:"object",description:"Service account declarations"}}}},required:[]};var hn=new $(!0),Qe=class{contextService;clients;constructor(e,r){this.contextService=e,this.clients=r}async loadConfiguration(e){let r=mn(e);try{let s=await Ze.readFile(r,"utf-8");return JSON.parse(s)}catch(s){throw s.code==="ENOENT"?new x(`IaC file not found: ${e}`):s instanceof SyntaxError?new x(`Invalid JSON in IaC file: ${s.message}`):s}}validate(e){let r=[],s=[];e.version||(e.version="1");let i=hn.test(fs,e);if(!i.success)for(let n of i.errors||[])r.push({path:n.key||"",message:n.error||"Validation error"});if(e.version!=="1"&&r.push({path:"version",message:`Unsupported IaC version: ${e.version}. Only version "1" is supported.`}),e.resources?.functions){for(let[n,o]of Object.entries(e.resources.functions))if(o.bindings)for(let a of o.bindings){let c=a.resource;c.includes(":")||(a.service==="databases"?e.resources?.databases?.[c]||s.push({path:`resources.functions.${n}.bindings`,message:`Database '${c}' is not declared in this configuration`}):a.service==="storage"&&(e.resources?.storage?.[c]||s.push({path:`resources.functions.${n}.bindings`,message:`Storage bucket '${c}' is not declared in this configuration`})))}}return{valid:r.length===0,errors:r,warnings:s}}async apply(e,r={}){let s=this.validate(e);if(!s.valid)return{success:!1,context:e.context?.name||Y,created:[],updated:[],unchanged:[],deleted:[],errors:s.errors.map(o=>({type:"validation",name:o.path,error:o.message}))};let i=e.context?.name||Y,n={success:!0,context:i,created:[],updated:[],unchanged:[],deleted:[],errors:[]};if(await this.contextService.ensureContext(i),e.context)try{await this.contextService.contextExists(i)&&await this.contextService.updateContext(i,{intent:e.context.intent,attributes:e.context.attributes})}catch{}if(e.resources?.databases&&this.clients.databases)for(let[o]of Object.entries(e.resources.databases))try{await this.clients.databases.tableExists(o)?n.unchanged.push({type:"database",name:o}):(await this.clients.databases.createTable(o),await this.contextService.registerResource(i,"database",o),n.created.push({type:"database",name:o}))}catch(a){n.errors.push({type:"database",name:o,error:a.message||"Unknown error"}),n.success=!1}if(e.resources?.storage&&this.clients.storage)for(let[o,a]of Object.entries(e.resources.storage))try{await this.clients.storage.bucketExists(o)?await this.clients.storage.isBucketPublic(o)!==(a.public||!1)?(await this.clients.storage.updateBucket(o,{public:a.public}),n.updated.push({type:"storage",name:o})):n.unchanged.push({type:"storage",name:o}):(await this.clients.storage.createBucket(o,a.public||!1),await this.contextService.registerResource(i,"storage",o),n.created.push({type:"storage",name:o}))}catch(c){n.errors.push({type:"storage",name:o,error:c.message||"Unknown error"}),n.success=!1}if(e.resources?.functions&&this.clients.functions)for(let[o,a]of Object.entries(e.resources.functions))try{let c;if(a.code)c=a.code;else if(a.source){let u=r.basePath?kt(r.basePath,a.source):a.source;try{c=await Ze.readFile(u,"utf-8")}catch{throw new Error(`Cannot read function source: ${a.source}`)}}else throw new Error('Function must have either "code" or "source" defined');let l=await this.clients.functions.get(o);if(l)await this.clients.functions.update(l.id,{code:c,methods:a.methods,bindings:a.bindings,triggers:a.triggers,allowUnauthenticated:a.allowUnauthenticated,passAllHeaders:a.passAllHeaders}),n.updated.push({type:"function",name:o});else{let u=await this.clients.functions.deploy(o,c,{id:a.id,methods:a.methods,bindings:a.bindings,triggers:a.triggers,allowUnauthenticated:a.allowUnauthenticated,passAllHeaders:a.passAllHeaders});await this.contextService.registerResource(i,"function",u.id),n.created.push({type:"function",name:o})}}catch(c){n.errors.push({type:"function",name:o,error:c.message||"Unknown error"}),n.success=!1}if(e.resources?.sites&&this.clients.sites)for(let[o,a]of Object.entries(e.resources.sites))try{let c;if(a.files&&a.files.length>0)c=a.files;else if(a.source){let u=r.basePath?kt(r.basePath,a.source):a.source;if(c=await this.loadSiteFiles(u),c.length===0)throw new Error(`No files found in site source: ${a.source}`)}else throw new Error('Site must have either "files" or "source" defined');let l=await this.clients.sites.getProject(o);await this.clients.sites.uploadProject(c,o),await this.contextService.registerResource(i,"site",o),l?n.updated.push({type:"site",name:o}):n.created.push({type:"site",name:o})}catch(c){n.errors.push({type:"site",name:o,error:c.message||"Unknown error"}),n.success=!1}if(e.identities?.users&&this.clients.identity)for(let[o,a]of Object.entries(e.identities.users))try{let c=await this.clients.identity.getUser(a.email);c?(await this.clients.identity.updateUser(c.id,{roles:a.roles}),n.updated.push({type:"user",name:a.email})):(await this.clients.identity.createUser(a.email,o,a.roles,{id:a.id}),await this.contextService.registerResource(i,"user",a.email),n.created.push({type:"user",name:a.email}))}catch(c){n.errors.push({type:"user",name:a.email,error:c.message||"Unknown error"}),n.success=!1}if(e.identities?.serviceAccounts&&this.clients.identity)for(let[o,a]of Object.entries(e.identities.serviceAccounts))try{let c=await this.clients.identity.getServiceAccount(o);c?(await this.clients.identity.updateServiceAccount(c.id,{roles:a.roles,description:a.description}),n.updated.push({type:"serviceAccount",name:o})):(await this.clients.identity.createServiceAccount(o,a.roles,a.description,{id:a.id}),await this.contextService.registerResource(i,"serviceAccount",o),n.created.push({type:"serviceAccount",name:o}))}catch(c){n.errors.push({type:"serviceAccount",name:o,error:c.message||"Unknown error"}),n.success=!1}if(e.resources?.applications&&this.clients.applications)for(let[o,a]of Object.entries(e.resources.applications))try{let c=await this.clients.applications.get(o);if(c)await this.clients.applications.update(c.id,{description:a.description,redirectUris:a.redirectUris}),n.updated.push({type:"application",name:o});else{let l=await this.clients.applications.create(o,a.description,a.redirectUris,{id:a.id});await this.contextService.registerResource(i,"application",l.id),n.created.push({type:"application",name:o})}}catch(c){n.errors.push({type:"application",name:o,error:c.message||"Unknown error"}),n.success=!1}if(e.resources?.schemas&&this.clients.schemas)for(let[o,a]of Object.entries(e.resources.schemas))try{await this.clients.schemas.get(o)?(await this.clients.schemas.update(o,a.schema,a.description),n.updated.push({type:"schema",name:o})):(await this.clients.schemas.create(o,a.schema,a.description),await this.contextService.registerResource(i,"schema",o),n.created.push({type:"schema",name:o}))}catch(c){n.errors.push({type:"schema",name:o,error:c.message||"Unknown error"}),n.success=!1}if(r.prune){let o=await this.contextService.getContextResources(i);if(this.clients.functions){let a=Object.keys(e.resources?.functions||{}),c=await this.clients.functions.list();for(let l of o.functions){let u=c.find(p=>p.id===l);if(u&&!a.includes(u.name))try{await this.clients.functions.delete(l),await this.contextService.unregisterResource(i,"function",l),n.deleted.push({type:"function",name:u.name})}catch(p){n.errors.push({type:"function",name:u.name,error:`Failed to delete: ${p.message||"Unknown error"}`}),n.success=!1}}}if(this.clients.databases){let a=Object.keys(e.resources?.databases||{});for(let c of o.databases)if(!a.includes(c))try{await this.clients.databases.deleteTable(c),await this.contextService.unregisterResource(i,"database",c),n.deleted.push({type:"database",name:c})}catch(l){n.errors.push({type:"database",name:c,error:`Failed to delete: ${l.message||"Unknown error"}`}),n.success=!1}}if(this.clients.storage){let a=Object.keys(e.resources?.storage||{});for(let c of o.storage)if(!a.includes(c))try{await this.clients.storage.deleteBucket(c),await this.contextService.unregisterResource(i,"storage",c),n.deleted.push({type:"storage",name:c})}catch(l){n.errors.push({type:"storage",name:c,error:`Failed to delete: ${l.message||"Unknown error"}`}),n.success=!1}}if(this.clients.sites){let a=Object.keys(e.resources?.sites||{});for(let c of o.sites)if(!a.includes(c))try{await this.clients.sites.deleteProject(c),await this.contextService.unregisterResource(i,"site",c),n.deleted.push({type:"site",name:c})}catch(l){n.errors.push({type:"site",name:c,error:`Failed to delete: ${l.message||"Unknown error"}`}),n.success=!1}}if(this.clients.applications){let a=Object.keys(e.resources?.applications||{}),c=await this.clients.applications.list();for(let l of o.applications){let u=c.find(p=>p.id===l);if(u&&!a.includes(u.name))try{await this.clients.applications.delete(l),await this.contextService.unregisterResource(i,"application",l),n.deleted.push({type:"application",name:u.name})}catch(p){n.errors.push({type:"application",name:u.name,error:`Failed to delete: ${p.message||"Unknown error"}`}),n.success=!1}}}if(this.clients.identity){let a=Object.values(e.identities?.users||{}).map(c=>c.email);for(let c of o.users)if(!a.includes(c))try{let l=await this.clients.identity.getUser(c);l&&(await this.clients.identity.deleteUser(l.id),await this.contextService.unregisterResource(i,"user",c),n.deleted.push({type:"user",name:c}))}catch(l){n.errors.push({type:"user",name:c,error:`Failed to delete: ${l.message||"Unknown error"}`}),n.success=!1}}if(this.clients.identity){let a=Object.keys(e.identities?.serviceAccounts||{});for(let c of o.serviceAccounts)if(!a.includes(c))try{let l=await this.clients.identity.getServiceAccount(c);l&&(await this.clients.identity.deleteServiceAccount(l.id),await this.contextService.unregisterResource(i,"serviceAccount",c),n.deleted.push({type:"serviceAccount",name:c}))}catch(l){n.errors.push({type:"serviceAccount",name:c,error:`Failed to delete: ${l.message||"Unknown error"}`}),n.success=!1}}if(this.clients.schemas){let a=Object.keys(e.resources?.schemas||{});for(let c of o.schemas)if(!a.includes(c))try{await this.clients.schemas.delete(c),await this.contextService.unregisterResource(i,"schema",c),n.deleted.push({type:"schema",name:c})}catch(l){n.errors.push({type:"schema",name:c,error:`Failed to delete: ${l.message||"Unknown error"}`}),n.success=!1}}}return n}async loadSiteFiles(e,r=""){let s=[];try{let i=await Ze.readdir(e,{withFileTypes:!0});for(let n of i){let o=kt(e,n.name),a=r?`${r}/${n.name}`:n.name;if(n.isDirectory()){let c=await this.loadSiteFiles(o,a);s.push(...c)}else if(n.isFile()){let l=(await Ze.readFile(o)).toString("base64");s.push({path:a,content:l})}}}catch(i){if(i.code!=="ENOENT")throw i}return s}async diff(e){let r=e.context?.name||Y,s=[],i=[],n=[],o=[],a=await this.contextService.getContextResources(r);if(this.clients.databases){let c=Object.keys(e.resources?.databases||{});for(let l of c)await this.clients.databases.tableExists(l)?o.push({type:"database",name:l}):s.push({type:"database",name:l});for(let l of a.databases)c.includes(l)||n.push({type:"database",name:l})}if(this.clients.storage){let c=Object.keys(e.resources?.storage||{});for(let l of c)if(await this.clients.storage.bucketExists(l)){let p=e.resources?.storage?.[l];await this.clients.storage.isBucketPublic(l)!==(p?.public||!1)?i.push({type:"storage",name:l}):o.push({type:"storage",name:l})}else s.push({type:"storage",name:l});for(let l of a.storage)c.includes(l)||n.push({type:"storage",name:l})}if(this.clients.functions){let c=Object.keys(e.resources?.functions||{});for(let l of c)await this.clients.functions.get(l)?i.push({type:"function",name:l}):s.push({type:"function",name:l});for(let l of a.functions)c.includes(l)||n.push({type:"function",name:l})}if(this.clients.sites){let c=Object.keys(e.resources?.sites||{});for(let l of c)await this.clients.sites.getProject(l)?i.push({type:"site",name:l}):s.push({type:"site",name:l});for(let l of a.sites)c.includes(l)||n.push({type:"site",name:l})}if(this.clients.applications){let c=Object.keys(e.resources?.applications||{});for(let l of c)await this.clients.applications.get(l)?i.push({type:"application",name:l}):s.push({type:"application",name:l});for(let l of a.applications)c.includes(l)||n.push({type:"application",name:l})}if(this.clients.schemas){let c=Object.keys(e.resources?.schemas||{});for(let l of c)await this.clients.schemas.get(l)?i.push({type:"schema",name:l}):s.push({type:"schema",name:l});for(let l of a.schemas)c.includes(l)||n.push({type:"schema",name:l})}return{toCreate:s,toUpdate:i,toDelete:n,unchanged:o}}};var Z=class{constructor(e,r){this.baseUrl=e;this.authToken=r}async request(e,r,s,i){let n=`${this.baseUrl}${r}`;if(i){let p=new URLSearchParams(i);n+=`?${p.toString()}`}let o={"Content-Type":"application/json"};this.authToken&&(o.Authorization=`Bearer ${this.authToken}`);let a={method:e,headers:o};s&&(a.body=JSON.stringify(s));let c=await fetch(n,a),l=c.headers.get("content-type"),u;if(l?.includes("application/json")?u=await c.json():u=await c.text(),!c.ok){let p=typeof u=="object"&&u.error?u.error:typeof u=="string"?u:JSON.stringify(u);throw new Error(p)}return u}},Pt=class extends Z{async createTable(e){await this.request("POST",`/tables/${e}`)}async tableExists(e){try{return((await this.request("GET","/tables")).tables||[]).some(i=>i.name===e)}catch{return!1}}async deleteTable(e){await this.request("DELETE",`/tables/${e}`)}async listTables(){return((await this.request("GET","/tables")).tables||[]).map(s=>s.name)}},Et=class extends Z{async createBucket(e,r){await this.request("POST",`/buckets/${e}`,{public:r})}async bucketExists(e){try{return await this.request("GET",`/buckets/${e}`),!0}catch{return!1}}async updateBucket(e,r){await this.request("PATCH",`/buckets/${e}`,r)}async deleteBucket(e){await this.request("DELETE",`/buckets/${e}`)}async listBuckets(){return(await this.request("GET","/buckets")).buckets||[]}async isBucketPublic(e){try{return(await this.request("GET",`/buckets/${e}`)).public===!0}catch{return!1}}},Tt=class extends Z{async deploy(e,r,s){let i=await this.request("POST","/deploy",{name:e,code:r,id:s.id,methods:s.methods,bindings:s.bindings,triggers:s.triggers,allowUnauthenticated:s.allowUnauthenticated,passAllHeaders:s.passAllHeaders,env:s.env});return i.function||i}async get(e){try{return((await this.request("GET","/list")).functions||[]).find(i=>i.name===e)||null}catch{return null}}async update(e,r){let s=await this.request("PUT",`/${e}`,r);return s.function||s}async delete(e){await this.request("DELETE",`/${e}`)}async list(){return(await this.request("GET","/list")).functions||[]}},Rt=class extends Z{async uploadProject(e,r){return await this.request("POST","/projects",{files:e,projectId:r})}async getProject(e){try{return((await this.request("GET","/projects")).projects||[]).find(i=>i.projectId===e)||null}catch{return null}}async deleteProject(e){await this.request("DELETE",`/projects/${e}`)}async listProjects(){return(await this.request("GET","/projects")).projects||[]}},jt=class extends Z{async createUser(e,r,s,i){let n=await this.request("POST","/identity/users",{email:e,name:r,roles:s,id:i?.id});return n.user||n}async getUser(e){try{return((await this.request("GET","/identity/users")).users||[]).find(i=>i.metadata?.email===e)||null}catch{return null}}async updateUser(e,r){let s=await this.request("PATCH",`/identity/users/${e}`,r);return s.user||s}async deleteUser(e){await this.request("DELETE",`/identity/users/${e}`)}async listUsers(){return(await this.request("GET","/identity/users")).users||[]}async createServiceAccount(e,r,s,i){let n=await this.request("POST","/identity/service-accounts",{name:e,roles:r,description:s,id:i?.id});return n.serviceAccount||n}async getServiceAccount(e){try{return((await this.request("GET","/identity/service-accounts")).serviceAccounts||[]).find(i=>i.name===e)||null}catch{return null}}async updateServiceAccount(e,r){let s=await this.request("PATCH",`/identity/service-accounts/${e}`,r);return s.serviceAccount||s}async deleteServiceAccount(e){await this.request("DELETE",`/identity/service-accounts/${e}`)}async listServiceAccounts(){return(await this.request("GET","/identity/service-accounts")).serviceAccounts||[]}},$t=class extends Z{async create(e,r,s,i){return await this.request("POST","/applications",{name:e,description:r,redirectUris:s,id:i?.id})}async get(e){try{return((await this.request("GET","/applications")).applications||[]).find(i=>i.name===e)||null}catch{return null}}async update(e,r){return await this.request("PATCH",`/applications/${e}`,r)}async delete(e){await this.request("DELETE",`/applications/${e}`)}async list(){return(await this.request("GET","/applications")).applications||[]}},Ot=class extends Z{async create(e,r,s){return await this.request("POST","",{name:e,schema:r,description:s})}async get(e){try{return await this.request("GET",`/${e}`)}catch{return null}}async update(e,r,s){return await this.request("PUT",`/${e}`,{schema:r,description:s})}async delete(e){await this.request("DELETE",`/${e}`)}async list(){return(await this.request("GET","")).schemas||[]}};function Mt(t){let{serviceUrls:e,authToken:r}=t,s={};return e.databases&&(s.databases=new Pt(e.databases,r)),e.storage&&(s.storage=new Et(e.storage,r)),e.functions&&(s.functions=new Tt(e.functions,r)),e.sites&&(s.sites=new Rt(e.sites,r)),e.identity&&(s.identity=new jt(e.identity,r)),e.applications&&(s.applications=new $t(e.applications,r)),e.schemas&&(s.schemas=new Ot(e.schemas,r)),s}import ys from"crypto";var gs="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var fn=128,de,ye,gn=t=>{!de||de.length<t?(de=Buffer.allocUnsafe(t*fn),ys.randomFillSync(de),ye=0):ye+t>de.length&&(ys.randomFillSync(de),ye=0),ye+=t};var vs=(t=21)=>{gn(t|=0);let e="";for(let r=ye-t;r<ye;r++)e+=gs[de[r]&63];return e};var et=class{generations=new Map;cleanupInterval=null;ttlHours;constructor(e=24){this.ttlHours=e}start(){this.cleanupInterval||(this.cleanupInterval=setInterval(()=>{this.cleanup()},3600*1e3))}stop(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=null)}store(e){let r=vs(12),s=new Date().toISOString(),i=new Date(Date.now()+this.ttlHours*60*60*1e3).toISOString(),n={id:r,timestamp:s,expiresAt:i,...e};return this.generations.set(r,n),n}get(e){let r=this.generations.get(e);return r?new Date(r.expiresAt)<new Date?(this.generations.delete(e),null):r:null}updateStatus(e,r){let s=this.get(e);return s?(s.status=r,this.generations.set(e,s),!0):!1}delete(e){return this.generations.delete(e)}listByContext(e){let r=[];for(let s of this.generations.values())s.contextId===e&&new Date(s.expiresAt)>=new Date&&r.push(s);return r.sort((s,i)=>new Date(i.timestamp).getTime()-new Date(s.timestamp).getTime())}listPendingByContext(e){return this.listByContext(e).filter(r=>r.status==="pending")}getStats(){let e=0,r=0,s=0,i={};for(let n of this.generations.values())new Date(n.expiresAt)<new Date||(n.status==="pending"?e++:n.status==="applied"?r++:n.status==="discarded"&&s++,i[n.contextId]=(i[n.contextId]||0)+1);return{total:e+r+s,pending:e,applied:r,discarded:s,byContext:i}}cleanup(){let e=new Date,r=[];for(let[s,i]of this.generations.entries())new Date(i.expiresAt)<e&&r.push(s);for(let s of r)this.generations.delete(s);r.length>0&&console.log(`[GenerationStorage] Cleaned up ${r.length} expired generations`)}clear(){this.generations.clear()}size(){return this.generations.size}};var tt=class{constructor(e){this.config=e;if(!e.apiKey)throw new Error("Anthropic API key is required");e.model||(this.config.model="claude-sonnet-4-5"),e.baseUrl||(this.config.baseUrl="https://api.anthropic.com"),e.maxTokens||(this.config.maxTokens=32e3)}name="anthropic";async validateConfig(){try{let e=await fetch(`${this.config.baseUrl}/v1/messages`,{method:"POST",headers:{"x-api-key":this.config.apiKey,"anthropic-version":"2023-06-01","content-type":"application/json"},body:JSON.stringify({model:this.config.model,max_tokens:1,messages:[{role:"user",content:"test"}]})});return e.ok||e.status===400}catch{return!1}}async complete(e){let{messages:r,tools:s,systemPrompt:i,config:n}=e,o={...this.config,...n},a=this.transformMessages(r),c={model:o.model,max_tokens:o.maxTokens||32e3,messages:a};i&&(c.system=i),s&&s.length>0&&(c.tools=this.transformTools(s)),o.temperature!==void 0&&(c.temperature=o.temperature);let l=await fetch(`${o.baseUrl}/v1/messages`,{method:"POST",headers:{"x-api-key":o.apiKey,"anthropic-version":"2023-06-01","content-type":"application/json"},body:JSON.stringify(c)});if(!l.ok){let p=await l.text();throw new Error(`Anthropic API error (${l.status}): ${p}`)}let u=await l.json();return this.transformResponse(u)}transformMessages(e){return e.map(r=>Array.isArray(r.content)?{role:r.role==="system"?"user":r.role,content:r.content}:{role:r.role==="system"?"user":r.role,content:r.content})}transformTools(e){return e.map(r=>({name:r.name,description:r.description,input_schema:r.input_schema}))}transformResponse(e){let r={content:"",stopReason:e.stop_reason},s=e.content.filter(n=>n.type==="text");r.content=s.map(n=>n.text).join(`
114
+ `),a="",c="",l,u;for(let m of o){let w=m.toLowerCase();if(w.startsWith("content-disposition:")){a=m.substring(20).trim();let b=a.match(/name="([^"]+)"/);b&&(c=b[1]);let N=a.match(/filename="([^"]+)"/);N&&(l=N[1])}else w.startsWith("content-type:")&&(u=m.substring(13).trim())}if(!c)return null;let p=i;return p.length>=2&&p[p.length-2]===13&&p[p.length-1]===10&&(p=p.subarray(0,p.length-2)),{disposition:a,name:c,filename:l,contentType:u,data:p}}import{readFileSync as he}from"fs";import St from"http";import $i from"http2";import Oi from"https";var ke=class{config;rateLimiter;router;shutdownHandlers=[];constructor(t){let e=new ne(rr(t||{})).get();e.debug&&console.log("Using configuration:",e),this.config=e,this.router=new tr;let r=e.rateLimit.requestsPerMinute||Le().rateLimit.requestsPerMinute;this.rateLimiter=new er(r,60),e.rateLimit.enabled===!0&&this.use(this.rateLimitMiddleware.bind(this))}use(t){return this.router.use(t),this}get(t,...e){return this.router.get(t,...e),this}post(t,...e){return this.router.post(t,...e),this}put(t,...e){return this.router.put(t,...e),this}delete(t,...e){return this.router.delete(t,...e),this}patch(t,...e){return this.router.patch(t,...e),this}any(t,...e){return this.router.any(t,...e),this}options(t,...e){return this.router.options(t,...e),this}start(){let t=this.createServer(),{port:e,host:r}=this.config;return this.setupGracefulShutdown(t),t.listen(e,r,()=>{let s=t.address(),i=this.config.useHttps||this.config.useHttp2?"https":"http";console.log(`MikroServe running at ${i}://${s.address!=="::"?s.address:"localhost"}:${s.port}`)}),t}createServer(){let t=this.requestHandler.bind(this);if(this.config.useHttp2){if(!this.config.sslCert||!this.config.sslKey)throw new Error("SSL certificate and key paths are required when useHttp2 is true");try{let e={key:he(this.config.sslKey),cert:he(this.config.sslCert),...this.config.sslCa?{ca:he(this.config.sslCa)}:{}};return $i.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:he(this.config.sslKey),cert:he(this.config.sslCert),...this.config.sslCa?{ca:he(this.config.sslCa)}:{}};return Oi.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 St.createServer(t)}async rateLimitMiddleware(t,e){let r=t.req.socket.remoteAddress||"unknown";return t.res.setHeader("X-RateLimit-Limit",this.rateLimiter.getLimit().toString()),t.res.setHeader("X-RateLimit-Remaining",this.rateLimiter.getRemainingRequests(r).toString()),t.res.setHeader("X-RateLimit-Reset",this.rateLimiter.getResetTime(r).toString()),this.rateLimiter.isAllowed(r)?e():{statusCode:429,body:{error:"Too Many Requests",message:"Rate limit exceeded, please try again later"},headers:{"Content-Type":"application/json"}}}async requestHandler(t,e){let r=Date.now(),s=t.method||"UNKNOWN",i=t.url||"/unknown",n=this.config.debug;try{if(this.setCorsHeaders(e,t),this.setSecurityHeaders(e,this.config.useHttps),n&&console.log(`${s} ${i}`),t.method==="OPTIONS"){if(e instanceof St.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(r,s,i)}}logDuration(t,e,r){let s=Date.now()-t;console.log(`${e} ${r} completed in ${s}ms`)}async parseBody(t){return new Promise((e,r)=>{let s=[],i=0,n=this.config.maxBodySize,o=!1,a=null,c=this.config.debug,l=t.headers["content-type"]||"";c&&console.log("Content-Type:",l),this.config.requestTimeout>0&&(a=setTimeout(()=>{o||(o=!0,c&&console.log("Request timeout exceeded"),r(new Error("Request timeout")))},this.config.requestTimeout));let u=()=>{a&&(clearTimeout(a),a=null)};t.on("data",p=>{if(!o){if(i+=p.length,c&&console.log(`Received chunk: ${p.length} bytes, total size: ${i}`),i>n){o=!0,u(),c&&console.log(`Body size exceeded limit: ${i} > ${n}`),r(new Error("Request body too large"));return}s.push(p)}}),t.on("end",()=>{if(!o){o=!0,u(),c&&console.log(`Request body complete: ${i} bytes`);try{if(s.length>0){let p=Buffer.concat(s);if(l.includes("application/json"))try{let m=p.toString("utf8");e(JSON.parse(m))}catch(m){r(new Error(`Invalid JSON in request body: ${m.message}`))}else if(l.includes("application/x-www-form-urlencoded")){let m=p.toString("utf8"),w={};new URLSearchParams(m).forEach((b,N)=>{w[N]=b}),e(w)}else if(l.includes("multipart/form-data"))try{let m=sr(p,l);e(m)}catch(m){r(new Error(`Invalid multipart form data: ${m.message}`))}else this.isBinaryContentType(l)?e(p):e(p.toString("utf8"))}else e({})}catch(p){r(new Error(`Invalid request body: ${p}`))}}}),t.on("error",p=>{o||(o=!0,u(),r(new Error(`Error reading request body: ${p.message}`)))}),t.on("close",()=>{u()})})}isBinaryContentType(t){return["application/octet-stream","application/pdf","application/zip","application/gzip","application/x-tar","application/x-rar-compressed","application/x-7z-compressed","image/","video/","audio/","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument","application/msword","application/vnd.ms-powerpoint"].some(r=>t.includes(r))}setCorsHeaders(t,e){let r=e.headers.origin,{allowedDomains:s=["*"]}=this.config;!r||s.length===0||s.includes("*")?t.setHeader("Access-Control-Allow-Origin","*"):s.includes(r)&&(t.setHeader("Access-Control-Allow-Origin",r),t.setHeader("Vary","Origin")),t.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, PATCH, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization"),t.setHeader("Access-Control-Max-Age","86400")}setSecurityHeaders(t,e=!1){let r={"X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","Content-Security-Policy":"default-src 'self'; script-src 'self'; object-src 'none'","X-XSS-Protection":"1; mode=block"};if((e||this.config.useHttp2)&&(r["Strict-Transport-Security"]="max-age=31536000; includeSubDomains"),t instanceof St.ServerResponse)Object.entries(r).forEach(([s,i])=>{t.setHeader(s,i)});else{let s=t;Object.entries(r).forEach(([i,n])=>{s.setHeader(i,n)})}}respond(t,e){let r={...e.headers||{}};(i=>typeof i.writeHead=="function"&&typeof i.end=="function")(t)?(t.writeHead(e.statusCode,r),e.body===null||e.body===void 0?t.end():e.isRaw||typeof e.body=="string"?t.end(e.body):t.end(JSON.stringify(e.body))):(console.warn("Unexpected response object type without writeHead/end methods"),t.writeHead?.(e.statusCode,r),e.body===null||e.body===void 0?t.end?.():e.isRaw||typeof e.body=="string"?t.end?.(e.body):t.end?.(JSON.stringify(e.body)))}setupGracefulShutdown(t){let e=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))})},r=()=>e(),s=()=>e(),i=o=>e(o),n=o=>e(o);this.shutdownHandlers=[r,s,i,n],process.on("SIGINT",r),process.on("SIGTERM",s),process.on("uncaughtException",i),process.on("unhandledRejection",n)}cleanupShutdownHandlers(){if(this.shutdownHandlers.length>0){let[t,e,r,s]=this.shutdownHandlers;process.removeListener("SIGINT",t),process.removeListener("SIGTERM",e),process.removeListener("uncaughtException",r),process.removeListener("unhandledRejection",s),this.shutdownHandlers=[]}}};import{timingSafeEqual as Mi}from"node:crypto";var le="x-molnos-cluster-secret";function ir(t,e){if(!t)return!1;let r=Buffer.from(t),s=Buffer.from(e);return r.length!==s.length?!1:Mi(r,s)}function Pe(t){return async(e,r)=>{let s=e.headers[le];return s?ir(s,t)?(e.state.isClusterRequest=!0,r()):e.json({success:!1,error:"Invalid cluster authentication"},403):r()}}function xt(t,e){return{...t,[le]:e}}var x=class extends Error{constructor(e){super(),this.name="ValidationError",this.message=e||"Invalid input",this.cause={statusCode:400}}},Ee=class extends Error{constructor(e){super(),this.name="IdentityAlreadyExistsError",this.message=e||"Identity already exists",this.cause={statusCode:400}}},q=class extends Error{constructor(e){super(),this.name="NotFoundError",this.message=e||"Resource not found",this.cause={statusCode:404}}},Ne=class extends Error{constructor(e){super(),this.name="InvalidInputError",this.message=e||"Invalid input",this.cause={statusCode:400}}};var K=class extends Error{constructor(e){super(),this.name="ConfigurationError",this.message=e||"Invalid configuration",this.cause={statusCode:400}}};var fe=class extends Error{constructor(e){super(),this.name="PermissionDeniedError",this.message=e||"Permission denied",this.cause={statusCode:403}}},G=class extends Error{constructor(e){super(),this.name="AlreadyExistsError",this.message=e||"Resource already exists",this.cause={statusCode:409}}},qe=class extends Error{constructor(e){super(),this.name="PortInUseError",this.message=e||"Port already in use",this.cause={statusCode:409}}},Te=class extends Error{constructor(e){super(),this.name="RoleNotFoundError",this.message=e||"Role not found",this.cause={statusCode:404}}},Fe=class extends Error{constructor(e){super(),this.name="ProtectedResourceError",this.message=e||"Cannot modify protected resource",this.cause={statusCode:403}}},_e=class extends Error{constructor(e){super(),this.name="ServiceRequestError",this.message=e||"Service request failed",this.cause={statusCode:502}}},Be=class extends Error{constructor(e){super(),this.name="WorkerUnavailableError",this.message=e||"Worker node is unavailable",this.cause={statusCode:503}}},Ve=class extends Error{constructor(e){super(),this.name="WorkerTimeoutError",this.message=e||"Worker node did not respond in time",this.cause={statusCode:504}}};var Ui=5e3;async function bt(t,e,r,s,i,n){let o=new URL(e,t.url),a=new Headers;for(let[p,m]of Object.entries(i)){let w=p.toLowerCase();w==="host"||w==="connection"||w==="keep-alive"||w==="transfer-encoding"||a.set(p,m)}n&&a.set(le,n);let c=t.timeoutMs||Ui,l=new AbortController,u=setTimeout(()=>l.abort(),c);try{let p;s&&(Buffer.isBuffer(s)?p=new Uint8Array(s):p=s);let m=await fetch(o.toString(),{method:r,headers:a,body:p,signal:l.signal});return clearTimeout(u),m}catch(p){throw clearTimeout(u),p.name==="AbortError"?new Ve(`Worker at ${t.url} did not respond within ${c}ms`):new Be(`Worker at ${t.url} is unavailable: ${p.message}`)}}async function Ct(t,e){let r=e.headers.get("content-type")||"",s=e.status;if(r.includes("application/json")){let o=await e.text();try{let a=JSON.parse(o);return t.json(a,s)}catch{return t.text(o,s)}}if(r.startsWith("text/")||r.includes("javascript")||r.includes("xml")){let o=await e.text();return t.text(o,s)}let i=await e.arrayBuffer(),n=t.binary(Buffer.from(i),r||"application/octet-stream");return s!==200?{...n,statusCode:s}:n}var Ge={healthCheckPath:"/health",healthCheckIntervalMs:3e4,timeoutMs:5e3,failureThreshold:3},Re=class{workers=new Map;timers=new Map;async registerWorkers(e){let r=Object.keys(e);for(let s of r){let i=e[s];i&&await this.registerWorker(s,i)}}async registerWorker(e,r){let s={url:r.url,capability:e,healthy:!0,consecutiveFailures:0,timeoutMs:r.timeoutMs||Ge.timeoutMs};this.workers.set(e,s);let i=r.healthCheckIntervalMs||Ge.healthCheckIntervalMs,n=r.healthCheckPath||Ge.healthCheckPath,o=setInterval(()=>this.checkHealth(e,n),i);this.timers.set(e,o),await this.checkHealth(e,n)}async checkHealth(e,r){let s=this.workers.get(e);if(s){try{let i=new AbortController,n=setTimeout(()=>i.abort(),s.timeoutMs),o=await fetch(`${s.url}${r}`,{method:"GET",signal:i.signal});clearTimeout(n),o.ok?this.handleSuccess(s):this.handleFailure(s)}catch{this.handleFailure(s)}s.lastHealthCheck=new Date}}handleSuccess(e){e.healthy=!0,e.consecutiveFailures=0}handleFailure(e){e.consecutiveFailures++,e.consecutiveFailures>=Ge.failureThreshold&&(e.healthy&&console.error(`[WorkerHealthChecker] Worker ${e.capability} at ${e.url} is now unhealthy (${e.consecutiveFailures} consecutive failures)`),e.healthy=!1)}isHealthy(e){return this.workers.get(e)?.healthy??!1}getWorkerState(e){return this.workers.get(e)}getAllWorkerStates(){return new Map(this.workers)}hasWorker(e){return this.workers.has(e)}shutdown(){for(let e of this.timers.values())clearInterval(e);this.timers.clear(),this.workers.clear()}};import _i from"node:crypto";import{getRandomValues as Hi}from"node:crypto";var It=class{options;defaultLength=16;defaultOnlyLowerCase=!1;defaultStyle="extended";defaultUrlSafe=!0;constructor(t){if(this.options={},t)for(let[e,r]of Object.entries(t))this.options[e]=this.generateConfig(r)}add(t){if(!t?.name)throw new Error("Missing name for the ID configuration");let e=this.generateConfig(t);this.options[t.name]=e}remove(t){if(!t?.name)throw new Error("Missing name for the ID configuration");delete this.options[t.name]}create(t,e,r,s){let i=this.generateConfig({length:t,style:e,onlyLowerCase:r,urlSafe:s});return this.generateId(i)}custom(t){if(this.options[t])return this.generateId(this.options[t]);throw new Error(`No configuration found with name: ${t}`)}generateConfig(t){return{name:t?.name||"",length:t?.length||this.defaultLength,onlyLowerCase:t?.onlyLowerCase??this.defaultOnlyLowerCase,style:t?.style||this.defaultStyle,urlSafe:t?.urlSafe??this.defaultUrlSafe}}getCharacterSet(t,e,r){if(t==="hex")return e?"0123456789abcdef":"0123456789ABCDEFabcdef";if(t==="alphanumeric")return e?"abcdefghijklmnopqrstuvwxyz0123456789":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";if(t==="extended")return r?e?"abcdefghijklmnopqrstuvwxyz0123456789-._~":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~":e?"abcdefghijklmnopqrstuvwxyz0123456789-._~!$()*+,;=:":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$()*+,;=:";throw new Error(`Unknown ID style "${t} provided. Must be one of "extended" (default), "alphanumeric", or "hex".`)}generateId(t){let{length:e,onlyLowerCase:r,style:s,urlSafe:i}=t;if(e<0||e===0)throw new Error("ID length cannot be negative");let n=this.getCharacterSet(s,r,i),o=(2<<Math.log(n.length-1)/Math.LN2)-1,a=Math.ceil(1.6*o*e/n.length),c="";for(;c.length<e;){let l=new Uint8Array(a);Hi(l);for(let u=0;u<a;u++){let p=l[u]&o;if(p<n.length&&(c+=n[p],c.length===e))break}}return c}};var Di=8,Li=40,Ni=/^[a-zA-Z0-9_-]{1,40}$/;function je(){return new It().create(Di,"alphanumeric",!1,!0)}function qi(t){return Ni.test(t)}function Fi(t){if(!qi(t))throw new Error(`Invalid ID format: "${t}". IDs must be 1-${Li} characters using only alphanumeric characters, underscores, and hyphens.`)}function ze(t){return t?(Fi(t),t):je()}function or(t,e,r){if(!r)return!1;let s=typeof t=="string"?[t]:t,i=typeof e=="string"?[e]:e;if(r.roles?.some(a=>a==="administrator"||a.id==="administrator"))return!0;let o=(r.roles||[]).flatMap(a=>typeof a=="string"?[]:(a.policies||[]).flatMap(l=>l?.permissions&&l?.targets?{permissions:l.permissions,targets:l.targets}:[]));for(let a of s)for(let c of i)if(!o.some(u=>nr(u?.permissions,a)&&nr(u?.targets,c)))return!1;return!0}function nr(t,e){return!t||t.length===0?!1:t.some(r=>{if(r==="*"||r===e)return!0;if(r.endsWith("*")&&r!=="*"){let s=r.slice(0,-1);return e.startsWith(s)}return!1})}var ue=class{id;name;type;roles;metadata;constructor(e){let{id:r,name:s,type:i,roles:n,metadata:o}=this.createIdentity(e);this.id=r,this.name=s,this.type=i,this.roles=n,this.metadata=o}createIdentity(e){let r=e?.id||this.createId(),s=e?.name||"",i=e?.type||"service_account",n=e?.metadata||{},o=e?.roles||["user"];return e&&this.validate({id:r,name:s,type:i,metadata:n,roles:o}),{id:r,name:s,type:i,metadata:{...n,createdAt:new Date().toISOString()},roles:o}}changeName(e){this.name=e}changeEmail(e){this.metadata||(this.metadata={}),this.metadata.email=e}updateMetadata(e){let r=this.metadata?JSON.parse(JSON.stringify(this.metadata)):{};this.metadata={...r,...e}}updateRoles(e){this.validateRoles(e),this.roles=e}createId(){return ze()}isValidRoleId(e){return typeof e!="string"||e.length===0?!1:/^[a-z0-9]+(-[a-z0-9]+)*$/.test(e)}isValidType(e){return["user","service_account"].includes(e)}validate(e){let r=e.id||"",s=e.name||"",i=e.type||"",n=e.metadata||{},o=e.roles||[];if(!r)throw new x("Missing ID");if(!s)throw new x("Missing name");if(!i||!this.isValidType(i))throw new x("Missing or invalid type");if(i==="user"&&!n?.email)throw new x("Missing email for user identity");if(!o||o.length===0)throw new x("Must have at least one role");this.validateRoles(o)}validateRoles(e){(e||[]).forEach(r=>{let s=r.id||r;if(!this.isValidRoleId(s))throw new x(`Invalid role ID '${s}'`)})}can(e,r,s){return or(e,r,s)}fromDTO(e){return this.validate(e),this.id=e.id,this.name=e.name,this.type=e.type,this.metadata=e.metadata||{},this.roles=e.roles,this}toDTO(){return{id:this.id,name:this.name,type:this.type,metadata:this.metadata,roles:this.roles}}};function ar(){return[{id:"administrator",name:"Administrator",description:"Full system administrator with all permissions",policies:[{permissions:["*"],targets:["*"]}],constraints:{assumable_by:{identities:[],roles:[],services:[]},assumption_constraints:{max_duration:3600,require_reason:!0,audit_level:"high"}}},{id:"user",name:"User",description:"Read-only access to resources",policies:[{permissions:["*.read"],targets:["*"]}],constraints:{assumable_by:{identities:[],roles:[],services:[]},assumption_constraints:{max_duration:3600,require_reason:!1,audit_level:"low"}}}]}var We=class{mikroAuth;db;tableName="identity_service";initialUser;roles;identities;serviceAccountTokens;constructor(e,r,s){this.mikroAuth=e,this.db=r,this.initialUser=s,this.roles=[],this.identities=[],this.serviceAccountTokens=new Map}async start(){await this.loadState(),this.roles.find(e=>e.id==="administrator")||this.createBaseRoles(),this.identities.length===0&&this.createInitialUser()}createBaseRoles(){let e=ar();for(let r of e)this.roles.push(r)}async createInitialUser(){let e=this.initialUser.email,r=this.initialUser.userName,s=await this.addUser(e,r,["administrator"]);return await this.mikroAuth.createMagicLink({email:e}),s}async getUserByEmail(e){let r=this.identities.find(s=>s.type==="user"&&s.metadata?.email===e&&s.metadata?.active!==!1);if(r)return this.enrichIdentityWithRoles(r)}async addUser(e,r,s=["user"],i=!0,n){if((await this.getUsers()).find(l=>l.metadata.email===e))throw new Ee(`User with email ${e} already exists`);let c=new ue({id:n,name:r,type:"user",metadata:{email:e,active:i},roles:s}).toDTO();return this.identities.push(c),await this.saveState(),this.enrichIdentityWithRoles(c)}async addServiceAccount(e,r,s,i){if((await this.getServiceAccounts()).find(l=>l.name===e))throw new Ee(`Service account with name ${e} already exists`);let a=new ue({id:i,name:e,type:"service_account",metadata:{description:r},roles:s}).toDTO(),c=this.generateServiceAccountToken();return this.serviceAccountTokens.set(c,a.id),this.identities.push(a),await this.saveState(),{...this.enrichIdentityWithRoles(a),apiKey:c}}async rotateServiceAccountKey(e){let r=await this.getIdentityById(e);if(!r||r.type!=="service_account")return;for(let[i,n]of this.serviceAccountTokens.entries())n===e&&this.serviceAccountTokens.delete(i);let s=this.generateServiceAccountToken();return this.serviceAccountTokens.set(s,e),await this.saveState(),s}async deleteIdentity(e){for(let[s,i]of this.serviceAccountTokens.entries())i===e&&this.serviceAccountTokens.delete(s);let r=this.identities.filter(s=>s.id!==e);this.identities=r,await this.saveState()}async updateIdentity(e,r){let s=await this.getIdentityById(e);if(!s)return;let i=new ue().fromDTO(s);r?.name&&i.changeName(r.name),r?.email&&i.changeEmail(r.email),r?.roles&&i.updateRoles(r.roles),r?.metadata&&i.updateMetadata(r.metadata);let n=i.toDTO();return this.updateIdentityList(n),await this.saveState(),this.enrichIdentityWithRoles(n)}updateIdentityList(e){if(!e)throw new x("Cannot update identity list: updatedIdentity is null or undefined");let r=JSON.parse(JSON.stringify(this.identities)),s=r.find(i=>i.id===e.id);s&&Object.assign(s,e),this.identities=r}generateServiceAccountToken(){return`sa.${je()}.${_i.randomBytes(32).toString("hex")}`}async getUserFromToken(e){if(e&&e.startsWith("Bearer ")){let r=e.split(" ")[1];if(r.startsWith("sa.")){let i=this.serviceAccountTokens.get(r);if(i){let n=this.identities.find(o=>o.id===i&&o.type==="service_account");if(n)return this.enrichIdentityWithRoles(n)}}else try{let i=this.mikroAuth.verify(r),n=i.email||i.sub;return this.getUserByEmail(n)}catch{let n=new Error("Invalid token");throw n.cause={statusCode:401},n}}}async getIdentityById(e){return this.identities.find(r=>r.id===e)}async getUserById(e){let r=await this.getIdentityById(e);if(!(!r||r.type!=="user"))return this.enrichIdentityWithRoles(r)}async getServiceAccountById(e){let r=await this.getIdentityById(e);if(!(!r||r.type!=="service_account"))return this.enrichIdentityWithRoles(r)}async updateUser(e,r){let s=await this.getIdentityById(e);if(!(!s||s.type!=="user"))return this.updateIdentity(e,r)}async updateServiceAccount(e,r){let s=await this.getIdentityById(e);if(!s||s.type!=="service_account")return;let i={...r};return r.description!==void 0&&(i.metadata={...i.metadata||{},description:r.description},delete i.description),this.updateIdentity(e,i)}async deleteUser(e){let r=await this.getIdentityById(e);return!r||r.type!=="user"?!1:(await this.deleteIdentity(e),!0)}async deleteServiceAccount(e){let r=await this.getIdentityById(e);return!r||r.type!=="service_account"?!1:(await this.deleteIdentity(e),!0)}enrichIdentityWithRoles(e){let r=JSON.parse(JSON.stringify(e));return e.roles?r.roles=e.roles.map(s=>this.roles.find(i=>i.id===s)).filter(Boolean):r.roles=[],r}async getIdentities(){return this.identities}async getUsers(){return this.identities.filter(e=>e.type==="user")}async getServiceAccounts(){return this.identities.filter(e=>e.type==="service_account")}can(e,r,s){return new ue(s).can(e,r,s)}async createCustomRole(e,r,s,i,n){if(this.roles.find(l=>l.id===e))throw new G(`Role with ID ${e} already exists`);let c={id:e,name:r,description:s,policies:[{permissions:i,targets:["*"]}],constraints:n||{assumable_by:{identities:[],roles:[],services:["functions"]},assumption_constraints:{max_duration:3600,require_reason:!1,audit_level:"medium"}}};this.roles.push(c),await this.saveState()}async updateRole(e,r){let s=this.roles.find(i=>i.id===e);if(!s)throw new Te(`Role with ID ${e} not found`);r.name!==void 0&&(s.name=r.name),r.description!==void 0&&(s.description=r.description),r.permissions!==void 0&&(s.policies=[{permissions:r.permissions,targets:["*"]}]),r.constraints!==void 0&&(s.constraints=r.constraints),await this.saveState()}async deleteRole(e){let r=this.roles.findIndex(s=>s.id===e);if(r===-1)throw new Te(`Role with ID ${e} not found`);if(e==="administrator"||e==="user")throw new Fe("Cannot delete base roles");this.roles.splice(r,1),await this.saveState()}async getRoles(){return this.roles}async getRole(e){return this.roles.find(r=>r.id===e)}async loadState(){let e=await this.load("identities");e&&(this.identities=e);let r=await this.load("roles");r&&(this.roles=r);let s=await this.load("serviceAccountTokens");if(s){let i=new Map(Object.entries(s));s&&Object.keys(s).length>0&&(this.serviceAccountTokens=i)}}async saveState(){let e=Object.fromEntries(this.serviceAccountTokens);await this.write("identities",this.identities),await this.write("roles",this.roles),await this.write("serviceAccountTokens",e)}async load(e){return await this.db.get(this.tableName,e)}async write(e,r){await this.db.write(this.tableName,e,r)}};import{existsSync as Bi}from"node:fs";import{spawn as Vi}from"node:child_process";import{createServer as Gi}from"node:net";var cr={storage:{name:"storage",path:"./storage.mjs",port:3001,prefix:"/storage",args:["--force"]},functions:{name:"functions",path:"./functions.mjs",port:3002,prefix:"/functions",args:["--force"]},sites:{name:"sites",path:"./sites.mjs",port:3003,prefix:"/sites",args:["--force"]},databases:{name:"databases",path:"./databases.mjs",port:3004,prefix:"/databases",args:["--force"]},observability:{name:"observability",path:"./observability.mjs",port:3005,prefix:"/observability",args:["--force"]}},ge=class{db;services=new Map;tableName="molnosmanagement";environmentVariables={};clusterConfig;setEnvironmentVariables(e){this.environmentVariables={...this.environmentVariables,...e}}setClusterConfig(e){this.clusterConfig=e}shouldSpawnLocally(e){if(!this.clusterConfig||this.clusterConfig.mode==="standalone")return!0;let r=e;return this.clusterConfig.mode==="core"?!this.clusterConfig.workers?.[r]:this.clusterConfig.mode==="worker"?this.clusterConfig.capabilities?.includes(r)??!1:!0}getWorkerEndpoint(e){if(!this.clusterConfig||this.clusterConfig.mode!=="core")return null;let r=e;return this.clusterConfig.workers?.[r]?.url??null}async forwardToWorker(e,r){let s=this.getWorkerEndpoint(e);if(!s)return console.error(`[ManagementService] No worker configured for capability: ${e}`),!1;let i=this.clusterConfig?.secret;if(!i)return console.error("[ManagementService] Cannot forward to worker: no cluster secret configured"),!1;let n=`${s}/management/service/${e}/${r}`,o=xt({"Content-Type":"application/json"},i);try{let a=await fetch(n,{method:"POST",headers:o});if(!a.ok){let l=await a.text();return console.error(`[ManagementService] Worker returned error for ${r} ${e}: ${l}`),!1}let c=await a.json();return c.isStarted??c.isStopped??c.isRestarted??!1}catch(a){return console.error(`[ManagementService] Failed to forward ${r} ${e} to worker:`,a),!1}}async isPortInUse(e){return new Promise(r=>{let s=Gi();s.once("error",i=>{i.code==="EADDRINUSE"?r(!0):r(!1)}),s.once("listening",()=>{s.close(),r(!1)}),s.listen(e,"127.0.0.1")})}constructor(e){this.db=new J({databaseDirectory:e.dbPath})}getServiceDefinition(e){let r=e.toLowerCase(),s=cr[r];if(!s)throw new q(`Unknown service: ${e}. Valid services are: ${Object.keys(cr).join(", ")}`);return s}async start(){await this.db.start();let e=await this.db.get(this.tableName,"services")||[];for(let r of e)r.restartPolicy&&(r.restartPolicy.attempts=0),r.healthCheck&&(r.healthCheck.consecutiveFailures=0,r.healthCheck.consecutiveSuccesses=0,r.healthCheck.healthy=!0),this.services.set(r.name,r),this.shouldSpawnLocally(r.name)&&r.active&&await this.startService(r.name)}async stopAllServices(){let e=[];for(let[r,s]of this.services.entries())(s.active||s.process)&&e.push(this.stopService(r));await Promise.all(e)}async shutdown(){await this.stopAllServices()}validateServiceConfig(e){if(!e.name||e.name.trim()==="")throw new x("Service name is required");if(!e.path||e.path.trim()==="")throw new x("Service path is required");if(!Bi(e.path))throw new K(`Service path does not exist: ${e.path}`);if(!e.port||e.port<1||e.port>65535)throw new x(`Invalid port: ${e.port}`);if(!e.prefix||!e.prefix.startsWith("/"))throw new x("Service prefix must start with /")}cleanServiceForStorage(e){let{process:r,...s}=e;if(s.healthCheck){let{timer:i,consecutiveFailures:n,consecutiveSuccesses:o,healthy:a,...c}=s.healthCheck;s.healthCheck=c}if(s.restartPolicy){let{attempts:i,...n}=s.restartPolicy;s.restartPolicy=n}return s}async registerService(e,r){let s;typeof e=="string"?s={...this.getServiceDefinition(e),...r}:s=e,this.validateServiceConfig(s);let i={...s,active:!1},n=await this.getServices(),o=[],a=[];if(n.forEach(l=>{o.push(l.name),a.push(l.port)}),a.includes(i.port))throw new qe(`Port ${i.port} already in use`);if(o.includes(i.name))throw new G(`Service with name '${i.name}' already exists`);i.restartPolicy&&(i.restartPolicy.attempts=0),i.healthCheck&&(i.healthCheck.consecutiveFailures=0,i.healthCheck.consecutiveSuccesses=0,i.healthCheck.healthy=!0),this.services.set(i.name,i);let c=await this.db.get(this.tableName,"services")||[];return c.push(this.cleanServiceForStorage(i)),await this.db.write(this.tableName,"services",c),i.name}async startService(e){if(!this.shouldSpawnLocally(e))return this.getWorkerEndpoint(e)?this.forwardToWorker(e,"start"):!1;let r=this.services.get(e);if(!r)return!1;if(r.process&&r.active)return!0;if(await this.isPortInUse(r.port))return console.error(`[ManagementService] Cannot start ${e}: Port ${r.port} is already in use. Please kill the process using this port.`),!1;try{let i={stdio:"pipe",detached:!1,env:{...process.env,...this.environmentVariables}},n=r.args||[],o=`--port=${r.port}`,a=Vi("node",[r.path,o,...n],i);r.process=a,r.restartPolicy&&(r.restartPolicy.attempts=0);let c=!1;return a.stdout.on("data",l=>{let u=l.toString();console.log(`[${e}] ${u}`)}),a.stderr.on("data",l=>{let u=l.toString();console.error(`[${e}] ERROR: ${u}`),(u.includes("EADDRINUSE")||u.includes("address already in use"))&&(c=!0)}),a.on("exit",l=>{r.active=!1,r.process=void 0,c&&console.error(`[ManagementService] Service ${e} failed to start due to startup error`),this.handleServiceExit(r,l||0)}),await new Promise(l=>setTimeout(l,500)),r.process&&!r.process.killed?(r.active=!0,await this.updateServiceStatus(e,!0),r.healthCheck&&this.startHealthCheck(r),!0):(console.error(`[ManagementService] Service ${e} exited immediately after spawn`),!1)}catch(i){return console.error(`[ManagementService] Failed to start ${e}:`,i),!1}}startHealthCheck(e){let r=e.healthCheck;if(!r)return;let s=async()=>{if(e.healthCheck)try{let i=new AbortController,n=setTimeout(()=>i.abort(),e.healthCheck.timeoutMs),o=await fetch(`http://127.0.0.1:${e.port}${e.healthCheck.path}`,{signal:i.signal});clearTimeout(n),o.ok&&e.healthCheck?(e.healthCheck.consecutiveSuccesses=(e.healthCheck.consecutiveSuccesses||0)+1,e.healthCheck.consecutiveFailures=0,e.healthCheck.consecutiveSuccesses>=e.healthCheck.successThreshold&&(e.healthCheck.healthy=!0)):this.handleHealthCheckFailure(e)}catch{this.handleHealthCheckFailure(e)}};r.timer=setInterval(s,r.intervalMs)}handleHealthCheckFailure(e){e.healthCheck&&(e.healthCheck.consecutiveFailures=(e.healthCheck.consecutiveFailures||0)+1,e.healthCheck.consecutiveSuccesses=0,e.healthCheck.consecutiveFailures>=e.healthCheck.failureThreshold&&(e.healthCheck.healthy=!1,e.healthCheck.restartOnFailure&&this.restartService(e.name).catch(()=>{})))}async handleServiceExit(e,r){if(await this.updateServiceStatus(e.name,!1),!e.restartPolicy||e.restartPolicy.type==="never"||e.restartPolicy.type==="on-failure"&&r===0||e.restartPolicy.maxAttempts>0&&(e.restartPolicy.attempts||0)>=e.restartPolicy.maxAttempts)return;e.restartPolicy.attempts=(e.restartPolicy.attempts||0)+1;let s=e.restartPolicy.backoffMs;setTimeout(()=>{this.startService(e.name).catch(()=>{})},s)}async stopService(e){if(!this.shouldSpawnLocally(e))return this.getWorkerEndpoint(e)?this.forwardToWorker(e,"stop"):!1;let r=this.services.get(e);if(!r)return!1;if(r.healthCheck?.timer&&(clearInterval(r.healthCheck.timer),r.healthCheck.timer=void 0),!r.process)return r.active&&(r.active=!1,await this.updateServiceStatus(e,!1)),!0;try{let s=i=>{try{return process.kill(i,0),!0}catch{return!1}};if(r.process?.pid){let i=r.process.pid;if(s(i))try{process.kill(i,"SIGTERM");let n=setTimeout(()=>{try{s(i)&&process.kill(i,"SIGKILL")}catch{}},5*1e3);await new Promise(o=>{if(!r.process){clearTimeout(n),o();return}let a=setTimeout(()=>{clearTimeout(n),o()},6*1e3);r.process.once("exit",()=>{clearTimeout(n),clearTimeout(a),o()})})}catch(n){if(n.code!=="ESRCH")throw n}}return r.active=!1,r.process=void 0,await this.updateServiceStatus(e,!1),!0}catch{return r.active&&(r.active=!1,r.process=void 0,await this.updateServiceStatus(e,!1)),!1}}async restartService(e){return this.shouldSpawnLocally(e)?(await this.stopService(e),await new Promise(r=>setTimeout(r,500)),this.startService(e)):this.getWorkerEndpoint(e)?this.forwardToWorker(e,"restart"):!1}async updateServiceStatus(e,r){let s=await this.db.get(this.tableName,"services")||[],i=s.findIndex(n=>n.name===e);if(i>=0){let n=this.services.get(e);n?(n.active=r,s[i]=this.cleanServiceForStorage(n)):s[i].active=r,await this.db.write(this.tableName,"services",s)}}async getService(e){return(await this.getServices()).find(s=>s.name===e)}async getServices(){return(await this.db.get(this.tableName,"services")||[]).map(({process:r,...s})=>s)}async getServiceStats(e){let r=this.services.get(e);return r?{name:r.name,active:r.active,health:r.healthCheck?{healthy:r.healthCheck.healthy||!1,consecutiveSuccesses:r.healthCheck.consecutiveSuccesses||0,consecutiveFailures:r.healthCheck.consecutiveFailures||0}:null,restarts:r.restartPolicy&&r.restartPolicy.attempts||0}:null}async updateService(e,r){let s=this.services.get(e);if(!s)return!1;let i=s.active;Object.assign(s,r);let n=await this.db.get(this.tableName,"services")||[],o=n.findIndex(a=>a.name===e);return o>=0?(n[o]=this.cleanServiceForStorage(s),await this.db.write(this.tableName,"services",n),i!==s.active&&(s.active?await this.startService(e):await this.stopService(e)),!0):!1}async removeService(e){let r=this.services.get(e);r?.healthCheck?.timer&&(clearInterval(r.healthCheck.timer),r.healthCheck.timer=void 0),await this.stopService(e),this.services.delete(e);let i=(await this.db.get(this.tableName,"services")||[]).filter(n=>n.name!==e);return await this.db.write(this.tableName,"services",i),!0}};var X=class{id;name;description;redirectUris;metadata;owners;constructor(e){let r=this.createApplication(e);this.id=r.id,this.name=r.name,this.description=r.description,this.redirectUris=r.redirectUris,this.metadata=r.metadata,this.owners=r.owners}createApplication(e){let r=e?.id||this.createId(),s=e?.name||"",i=e?.description,n=e?.redirectUris||[],o=e?.owners||[],a=new Date().toISOString(),c={...e?.metadata||{},createdAt:e?.metadata?.createdAt||a,updatedAt:a,createdBy:e?.metadata?.createdBy||o[0]||""};return e&&this.validate({id:r,name:s,description:i,redirectUris:n,metadata:c,owners:o}),{id:r,name:s,description:i,redirectUris:n,metadata:c,owners:o}}update(e){e.name!==void 0&&(this.name=e.name),e.description!==void 0&&(this.description=e.description),e.redirectUris!==void 0&&(this.validateRedirectUris(e.redirectUris),this.redirectUris=e.redirectUris),e.owners!==void 0&&(this.owners=e.owners),e.metadata!==void 0?this.metadata={...this.metadata,...e.metadata,updatedAt:new Date().toISOString()}:this.metadata.updatedAt=new Date().toISOString(),this.validate(this.toDTO())}isValidRedirectUri(e){return this.redirectUris.includes(e)}isOwner(e){return this.owners.includes(e)}createId(){return ze()}validate(e){let{id:r,name:s,redirectUris:i,metadata:n,owners:o}=e;if(!r)throw new x("Missing ID");if(!s||s.trim().length===0)throw new x("Missing or invalid name");if(!n)throw new x("Missing metadata");if(!o||o.length===0)throw new x("Application must have at least one owner");this.validateRedirectUris(i)}validateRedirectUris(e){if(!e||e.length===0)throw new x("At least one redirect URI is required");for(let r of e)try{let s=new URL(r);if(s.protocol!=="https:"&&s.protocol!=="http:"&&s.protocol!=="custom:")throw new x(`Invalid redirect URI protocol: ${r}. Must use https:, http: (localhost only), or custom: (for native apps)`);s.protocol==="http:"&&!s.hostname.match(/^(localhost|127\.0\.0\.1|\[::1\])$/)&&console.warn(`Warning: HTTP redirect URI detected for non-localhost: ${r}. HTTPS is recommended for production.`)}catch{throw new x(`Invalid redirect URI format: ${r}`)}}fromDTO(e){return this.validate(e),this.id=e.id,this.name=e.name,this.description=e.description,this.redirectUris=e.redirectUris,this.metadata=e.metadata,this.owners=e.owners,this}toDTO(){return{id:this.id,name:this.name,description:this.description,redirectUris:this.redirectUris,metadata:this.metadata,owners:this.owners}}};var Je=class{db;tableName="molnosapplications";key="applications";applications;constructor(e){this.db=new J({databaseDirectory:e.dbPath}),this.applications=[]}async start(){await this.db.start(),await this.loadState()}async loadState(){let e=await this.db.get(this.tableName,this.key)||[];this.applications=e}async saveState(){await this.db.write(this.tableName,this.key,this.applications)}async createApplication(e,r){let s=e.owners.includes(r)?e.owners:[...e.owners,r],n=new X({...e,owners:s,metadata:{...e.metadata,createdBy:r}}).toDTO();if(this.applications.find(a=>a.name===n.name))throw new G(`Application with name '${n.name}' already exists`);return this.applications.push(n),await this.saveState(),n}async getApplication(e,r){let s=this.applications.find(n=>n.id===e);if(!s)throw new q(`Application with ID '${e}' not found`);let i=new X().fromDTO(s);if(r&&!i.isOwner(r))throw new fe("Only application owners can view application details");return i.toDTO()}async getApplicationById(e){return this.applications.find(s=>s.id===e)||null}async listApplications(e){return this.applications.filter(r=>r.owners.includes(e)).map(r=>new X().fromDTO(r).toDTO())}async updateApplication(e,r,s){let i=this.applications.findIndex(a=>a.id===e);if(i===-1)throw new q(`Application with ID '${e}' not found`);let n=this.applications[i],o=new X().fromDTO(n);if(!o.isOwner(s))throw new fe("Only application owners can update the application");if(r.owners&&r.owners.length===0)throw new x("Application must have at least one owner");if(r.owners&&!r.owners.includes(s)&&n.owners.length===1&&n.owners[0]===s)throw new x("Cannot remove yourself as the last owner of the application");return o.update(r),this.applications[i]=o.toDTO(),await this.saveState(),this.applications[i]}async deleteApplication(e,r){let s=this.applications.findIndex(o=>o.id===e);if(s===-1)throw new q(`Application with ID '${e}' not found`);let i=this.applications[s];if(!new X().fromDTO(i).isOwner(r))throw new fe("Only application owners can delete the application");this.applications.splice(s,1),await this.saveState()}async validateRedirectUri(e,r){let s=await this.getApplicationById(e);return s?new X().fromDTO(s).isValidRedirectUri(r):!1}getAllApplicationsInternal(){return this.applications}};var zi=/^[a-z0-9][a-z0-9-]*[a-z0-9]$/,$e=class{name;version;description;schema;createdAt;updatedAt;constructor(e){let r=this.createSchema(e);this.name=r.name,this.version=r.version,this.description=r.description,this.schema=r.schema,this.createdAt=r.createdAt,this.updatedAt=r.updatedAt}createSchema(e){let r=e?.name||"",s=e?.version||1,i=e?.description,n=e?.schema||{properties:{}},o=new Date().toISOString(),a=e?.createdAt||o,c=o;return e&&this.validate({name:r,schema:n}),{name:r,version:s,description:i,schema:n,createdAt:a,updatedAt:c}}update(e){e.schema&&(this.validateSchemaDefinition(e.schema),this.schema=e.schema),e.description!==void 0&&(this.description=e.description),this.version+=1,this.updatedAt=new Date().toISOString()}validate(e){let{name:r,schema:s}=e;if(!r||r.trim().length===0)throw new x("Missing or invalid schema name");if(r.length<2||r.length>100)throw new x("Schema name must be between 2 and 100 characters");if(!zi.test(r))throw new x("Schema name must be kebab-case (lowercase alphanumeric and hyphens, cannot start or end with hyphen)");this.validateSchemaDefinition(s)}validateSchemaDefinition(e){if(!e||!e.properties)throw new x("Schema must have a properties object");if(Object.keys(e.properties).length===0)throw new x("Schema must define at least one property");let r=["string","number","boolean","array","object"];for(let[s,i]of Object.entries(e.properties))if(!i.type||!r.includes(i.type))throw new x(`Property '${s}' has invalid type. Must be one of: ${r.join(", ")}`)}fromDTO(e){return this.validate({name:e.name,schema:e.schema}),this.name=e.name,this.version=e.version,this.description=e.description,this.schema=e.schema,this.createdAt=e.createdAt,this.updatedAt=e.updatedAt,this}toDTO(){return{name:this.name,version:this.version,description:this.description,schema:this.schema,createdAt:this.createdAt,updatedAt:this.updatedAt}}};var Ke=class{db;tableName="molnosschemas";key="schemas";schemas;constructor(e){this.db=new J({databaseDirectory:e.dbPath}),this.schemas=[]}async start(){await this.db.start(),await this.loadState()}async loadState(){let e=await this.db.get(this.tableName,this.key)||[];this.schemas=e}async saveState(){await this.db.write(this.tableName,this.key,this.schemas)}async createSchema(e){if(this.schemas.find(n=>n.name===e.name))throw new G(`Schema with name '${e.name}' already exists`);let i=new $e(e).toDTO();return this.schemas.push(i),await this.saveState(),i}async getSchema(e,r){let s=this.findSchema(e,r);if(!s){let i=r?` version ${r}`:"";throw new q(`Schema '${e}'${i} not found`)}return s}async listSchemas(){return[...this.schemas]}async updateSchema(e,r){let s=this.schemas.findIndex(o=>o.name===e);if(s===-1)throw new q(`Schema '${e}' not found`);if(!r.schema)throw new x("Schema definition is required for update");let i=this.schemas[s],n=new $e().fromDTO(i);return n.update(r),this.schemas[s]=n.toDTO(),await this.saveState(),this.schemas[s]}async deleteSchema(e){let r=this.schemas.findIndex(s=>s.name===e);if(r===-1)throw new q(`Schema '${e}' not found`);this.schemas.splice(r,1),await this.saveState()}validate(e,r,s){let i=this.findSchema(r,s);return i?this.validateAgainstDefinition(e,i.schema):{valid:!1,errors:[{path:"",message:`Schema '${r}' not found in registry`}]}}findSchema(e,r){return r?this.schemas.find(s=>s.name===e&&s.version===r):this.schemas.find(s=>s.name===e)}validateAgainstDefinition(e,r){let s=[];if(typeof e!="object"||e===null||Array.isArray(e))return{valid:!1,errors:[{path:"",message:"Data must be a non-null object"}]};let i=e;if(r.required)for(let n of r.required)n in i||s.push({path:n,message:`Missing required field '${n}'`});for(let[n,o]of Object.entries(r.properties))o.required&&!(n in i)&&(r.required?.includes(n)||s.push({path:n,message:`Missing required field '${n}'`}));for(let[n,o]of Object.entries(i)){let a=r.properties[n];if(!a){r.additionalProperties===!1&&s.push({path:n,message:`Unexpected property '${n}'`});continue}let c=this.validatePropertyType(n,o,a);c&&s.push(c)}return{valid:s.length===0,errors:s.length>0?s:void 0}}validatePropertyType(e,r,s){if(r==null)return null;let i=Array.isArray(r)?"array":typeof r;if(s.type==="array"){if(!Array.isArray(r))return{path:e,message:`Expected type 'array', got '${typeof r}'`}}else if(s.type==="object"){if(typeof r!="object"||Array.isArray(r))return{path:e,message:`Expected type 'object', got '${i}'`}}else if(i!==s.type)return{path:e,message:`Expected type '${s.type}', got '${i}'`};return null}};async function S(t){return t.body||{}}function h(t,e="An error occurred"){let r=t?.message||t||e,s=t?.cause?.statusCode||t?.statusCode||400;return{message:r,status:s}}async function lr(t,e,r,s){try{let i=await S(t),{email:n,redirectUrl:o,applicationId:a}=i;if(!n)return t.json({error:"Email is required"},400);let c=n.trim().toLowerCase(),l;if(o){if(!a)return t.json({error:"applicationId is required when redirectUrl is provided"},400);if(!await s.validateRedirectUri(a,o))return t.json({error:"Invalid redirectUrl or applicationId. The redirect URI must be registered for this application."},400);l=(await s.getApplicationById(a))?.name}let u=!1;return await e.getUserByEmail(c)&&(u=!0),u&&await r.createMagicLink({email:c,subject:`Sign In To ${l||"MolnOS"}`,appUrl:o,metadata:{appName:l,redirectUrl:o,applicationId:a}}),t.json({success:!0,message:"If a matching account was found, a magic link has been sent."})}catch(i){let{message:n,status:o}=h(i,"Error during login");return t.json({error:n},o)}}async function ur(t,e,r){try{let s=t.query.token,i=t.query.email;if(!s)return t.json({error:"Token is required as query parameter"},400);if(!i)return t.json({error:"Email is required as query parameter"},400);try{let n=await e.verifyToken({token:s,email:i});if(!n)return t.json({error:"Invalid or expired token"},401);let o=n.metadata;if(o?.redirectUrl&&o?.applicationId)if(await r.validateRedirectUri(o.applicationId,o.redirectUrl)){let c=new URL(o.redirectUrl);return c.searchParams.set("access_token",n.accessToken),c.searchParams.set("refresh_token",n.refreshToken),c.searchParams.set("expires_in",n.expiresIn.toString()),t.redirect(c.toString(),302)}else return console.warn(`Redirect URL validation failed for applicationId: ${o.applicationId}`),t.json({...n,warning:"Redirect URL validation failed. Tokens provided but redirect was not performed."},200);return t.json(n,200)}catch{return t.json({error:"Invalid or expired token"},401)}}catch(s){let{message:i,status:n}=h(s,"Error verifying token");return t.json({error:i},n)}}async function dr(t,e){try{let s=(await S(t)).refreshToken;if(!s)return t.json({error:"Value for refreshToken is required"},400);try{let i=await e.refreshAccessToken(s);return t.json(i,200)}catch{return t.json({error:"Invalid or expired token"},401)}}catch(r){let{message:s,status:i}=h(r,"Error refreshing token");return t.json({error:s},i)}}async function pr(t){try{let e=t.state.user;return t.json(e)}catch(e){let{message:r,status:s}=h(e,"Error getting user info");return t.json({error:r},s)}}function g(t,e,r={}){let s=Array.isArray(e)?e:[e];if(!t||!t.roles||!Array.isArray(t.roles)){let o=new Error("Unauthorized: User or roles missing");throw o.cause={statusCode:403},o}let i=t.roles.flatMap(o=>o?.policies?.flatMap(a=>(a?.permissions||[]).flatMap(l=>typeof l=="string"?l:l&&typeof l=="object"&&l.actions?l.actions:[]))||[]);if(!s.every(o=>i.includes(o)||i.includes("*")?!0:i.some(a=>{if(a.endsWith(".*")){let c=a.slice(0,-2);return o.startsWith(`${c}.`)}return!1}))){let o=new Error("Unauthorized");throw o.cause={statusCode:403},o}return!0}async function mr(t,e){try{let r=t.state.user;g(r,"identity.identities.get",{});let s=await e.getIdentities();return t.json(s)}catch(r){let{message:s,status:i}=h(r,"Error getting identities");return t.json({error:s},i)}}var $=class{isSilent;propertyPath="";constructor(t=!1){this.isSilent=t}test(t,e){if(!e)throw new Error("Missing input!");this.updatePropertyPath();let{results:r,errors:s}=this.validate(t.properties,e),i=this.compileErrors(r,s),n=this.isSuccessful(r,i);return{errors:i,success:n}}compileErrors(t,e){let r=t.filter(s=>s.success===!1);return[...e,...r].flatMap(s=>s)}isSuccessful(t,e){return t.every(r=>r.success===!0)&&e.length===0}validate(t,e,r=[],s=[]){let i=t?.additionalProperties??!0,n=t?.required||[];s=this.checkForRequiredKeysErrors(n,e,s),s=this.checkForDisallowedProperties(Object.keys(e),Object.keys(t),s,i);for(let o in t){let a=n.includes(o)&&o!=="required",c=t[o],l=e[o],u=c.additionalProperties??!0;a&&(s=this.checkForRequiredKeysErrors(c.required||[],l,s)),this.isDefined(l)&&(this.handleValidation(o,l,c,r),s=this.checkForDisallowedProperties(Object.keys(l),Object.keys(c),s,u),this.handleNestedObject(l,c,r,s))}return{results:r,errors:s}}updatePropertyPath(t,e=""){if(!t){this.propertyPath="";return}e&&(this.propertyPath=e),this.propertyPath=`${this.propertyPath}.${t}`,this.propertyPath.startsWith(".")&&(this.propertyPath=this.propertyPath.substring(1,this.propertyPath.length))}isDefined(t){return!!(typeof t=="number"&&t===0||t||t===""||typeof t=="boolean")}checkForRequiredKeysErrors(t,e,r){if(!this.areRequiredKeysPresent(t,e)){let s=e?Object.keys(e):[],i=this.findNonOverlappingElements(t,s),n=i.length>0?`Missing the required key: '${i.join(", ")}'!`:`Missing values for required keys: '${s.filter(o=>!e[o]).join(", ")}'!`;r.push({key:"",value:e,success:!1,error:n})}return r}checkForDisallowedProperties(t,e,r,s){if(!s){let i=this.findNonOverlappingElements(t,e);i.length>0&&r.push({key:`${e}`,value:t,success:!1,error:`Has additional (disallowed) properties: '${i.join(", ")}'!`})}return r}handleValidation(t,e,r,s){this.updatePropertyPath(t);let i=this.validateProperty(this.propertyPath,r,e);s.push(...i);let n=(a,c)=>{a.forEach(l=>{let u=this.validateProperty(this.propertyPath,c.items,l);s.push(...u)}),this.updatePropertyPath()},o=a=>{let c=Object.keys(a),l=this.propertyPath;c.forEach(u=>{if(this.updatePropertyPath(u,l),this.isArray(a[u])&&r[u]?.items!=null)n(a[u],r[u]);else{let p=this.validateProperty(this.propertyPath,r[u],a[u]);s.push(...p)}})};this.isArray(e)&&r.items!=null?n(e,r):this.isObject(e)?o(e):this.updatePropertyPath()}handleNestedObject(t,e,r,s){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,r,s)}}}getNestedObjects(t){return Object.keys(t).filter(e=>{if(this.isObject(t))return e})}findNonOverlappingElements(t,e){return t.filter(r=>!e.includes(r))}areRequiredKeysPresent(t,e=[]){return t.every(r=>Object.keys(e).includes(r)?this.isDefined(e[r]):!1)}validateProperty(t,e,r){return this.validateInput(e,r).map(i=>{let{success:n,error:o}=i;return{key:t,value:r,success:n,error:o??""}})}validateInput(t,e){if(t){let r=[{condition:()=>t.type,validator:()=>this.isCorrectType(t.type,e),error:"Invalid type"},{condition:()=>t.format,validator:()=>this.isCorrectFormat(t.format,e),error:"Invalid format"},{condition:()=>t.minLength,validator:()=>this.isMinimumLength(t.minLength,e),error:"Length too short"},{condition:()=>t.maxLength,validator:()=>this.isMaximumLength(t.maxLength,e),error:"Length too long"},{condition:()=>t.minValue,validator:()=>this.isMinimumValue(t.minValue,e),error:"Value too small"},{condition:()=>t.maxValue,validator:()=>this.isMaximumValue(t.maxValue,e),error:"Value too large"},{condition:()=>t.matchesPattern,validator:()=>this.matchesPattern(t.matchesPattern,e),error:"Pattern does not match"}],s=[];for(let i of r)i.condition()&&!i.validator()&&s.push({success:!1,error:i.error});return s}else this.isSilent||console.warn(`Missing property '${t}' for match '${e}'. Skipping...`);return[{success:!0}]}isCorrectType(t,e){return Array.isArray(t)||(t=[t]),t.some(r=>{switch(r){case"string":return typeof e=="string";case"number":return typeof e=="number"&&!isNaN(e);case"boolean":return typeof e=="boolean";case"object":return this.isObject(e);case"array":return this.isArray(e)}})}isObject(t){return t!==null&&!this.isArray(t)&&typeof t=="object"&&t instanceof Object&&Object.prototype.toString.call(t)==="[object Object]"}isArray(t){return Array.isArray(t)}isCorrectFormat(t,e){switch(t){case"alphanumeric":return new RegExp(/^[a-zA-Z0-9]+$/).test(e);case"numeric":return new RegExp(/^-?\d+(\.\d+)?$/).test(e);case"email":return new RegExp(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/).test(e);case"date":return new RegExp(/^\d{4}-\d{2}-\d{2}$/).test(e);case"url":return new RegExp(/^(https?):\/\/[^\s$.?#].[^\s]*$/).test(e);case"hexColor":return new RegExp(/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i).test(e)}}isMinimumLength(t,e){return Array.isArray(e)?e.length>=t:e?.toString().length>=t}isMaximumLength(t,e){return Array.isArray(e)?e.length<=t:e.toString().length<=t}isMinimumValue(t,e){return e>=t}isMaximumValue(t,e){return e<=t}matchesPattern(t,e){return new RegExp(t).test(e)}schemaFrom(t){let e={properties:{additionalProperties:!1,required:[]}};for(let r in t){let s=t[r];e.properties.required.push(r),Array.isArray(s)?e.properties[r]=this.generateArraySchema(s):typeof s=="object"&&s!==null?e.properties[r]=this.generateNestedObjectSchema(s):e.properties[r]=this.generatePropertySchema(s)}return e}generateArraySchema(t){let e={type:"array"},r=t.filter(s=>s);if(r.length>0){let s=r[0];r.every(n=>typeof n==typeof s)?typeof s=="object"&&!Array.isArray(s)?e.items=this.generateNestedObjectSchema(s):e.items=this.generatePropertySchema(s):console.warn("All elements in array are not of the same type. Unable to generate a schema for these elements.")}return e}generateNestedObjectSchema(t){let e={type:"object",additionalProperties:!1,required:[]};for(let r in t){let s=t[r];e.required.push(r),typeof s=="object"&&!Array.isArray(s)&&s!==null?e[r]=this.generateNestedObjectSchema(s):e[r]=this.generatePropertySchema(s)}return e}generatePropertySchema(t){let e=typeof t,r={type:e};return e==="string"&&(r.minLength=1),r}};var hr={properties:{id:{type:"string",minLength:1,maxLength:40,pattern:"^[a-zA-Z0-9_-]{1,40}$"},email:{type:"string",format:"email",minLength:3},name:{type:"string",minLength:1},roles:{type:"array",items:{type:"string"}},verified:{type:"boolean"}},required:["email","name","roles"],additionalProperties:!1};var Ji=new $(!0);async function fr(t,e){try{let r=t.state.user,s=await S(t),i=Ji.test(hr,s);if(!i.success)return t.json({error:"Invalid input",details:i.errors},400);g(r,"identity.user.create",{});let{id:n,email:o,name:a,roles:c,verified:l}=s,u=await e.addUser(o,a,c,l,n);return t.json(u,201)}catch(r){let{message:s,status:i}=h(r,"Error creating user");return t.json({error:s},i)}}async function gr(t,e){try{let r=t.state.user;g(r,"identity.user.get",{});let s=await e.getUsers();return t.json(s)}catch(r){let{message:s,status:i}=h(r,"Error getting users");return t.json({error:s},i)}}function P(t){return t.params}async function yr(t,e){try{let r=t.state.user,s=P(t),{userId:i}=s;g(r,"identity.user.get",{userId:i});let n=await e.getUserById(i);return n?t.json(n):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error getting user");return t.json({error:s},i)}}var vr={properties:{name:{type:"string",minLength:1},roles:{type:"array",items:{type:"string"}}},additionalProperties:!1};var Xi=new $(!0);async function wr(t,e){try{let r=t.state.user,s=P(t),{userId:i}=s,n=await S(t),o=Xi.test(vr,n);if(!o.success)return t.json({error:"Invalid input",details:o.errors},400);g(r,"identity.user.update",{userId:i});let{name:a,roles:c}=n,l=await e.updateUser(i,{name:a,roles:c});return l?t.json(l):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error updating user");return t.json({error:s},i)}}async function Sr(t,e){try{let r=t.state.user,s=P(t),{userId:i}=s;return g(r,"identity.user.delete",{userId:i}),await e.deleteUser(i)?t.text("",204):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error deleting user");return t.json({error:s},i)}}async function xr(t,e){try{let r=t.state.user,s=await S(t);if(!s.name||!s.description||!s.roles||!Array.isArray(s.roles))return t.json({error:"Invalid input: name, description, and roles are required"},400);if(!["user","administrator"].every(l=>s.roles.includes(l)||!s.roles.includes(l)))return t.json({error:"Invalid input: roles must be user or administrator"},400);g(r,"identity.service-account.create",{});let{id:i,name:n,description:o,roles:a}=s,c=await e.addServiceAccount(n,o,a,i);return t.json(c,201)}catch(r){let{message:s,status:i}=h(r,"Error creating service account");return t.json({error:s},i)}}async function br(t,e){try{let r=t.state.user;g(r,"identity.service-account.get",{});let s=await e.getServiceAccounts();return t.json(s)}catch(r){let{message:s,status:i}=h(r,"Error getting service accounts");return t.json({error:s},i)}}async function Cr(t,e){try{let r=t.state.user,s=P(t),{serviceAccountId:i}=s;g(r,"identity.service-account.get",{serviceAccountId:i});let n=await e.getServiceAccountById(i);return n?t.json(n):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error getting service account");return t.json({error:s},i)}}var Ir={properties:{name:{type:"string",minLength:1,maxLength:100},description:{type:"string",minLength:1,maxLength:500},roles:{type:"array",items:{type:"string"}}},additionalProperties:!1};var Zi=new $(!0);async function Ar(t,e){try{let r=t.state.user,s=P(t),{serviceAccountId:i}=s,n=await S(t),o=Zi.test(Ir,n);if(!o.success)return t.json({error:"Invalid input",details:o.errors},400);g(r,"identity.service-account.update",{serviceAccountId:i});let{name:a,description:c,roles:l}=n,u=await e.updateServiceAccount(i,{name:a,description:c,roles:l});return u?t.json(u):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error updating service account");return t.json({error:s},i)}}async function kr(t,e){try{let r=t.state.user,s=P(t),{serviceAccountId:i}=s;return g(r,"identity.service-account.delete",{serviceAccountId:i}),await e.deleteServiceAccount(i)?t.text("",204):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error deleting service account");return t.json({error:s},i)}}async function Pr(t,e){try{let r=t.state.user,s=P(t),{serviceAccountId:i}=s;g(r,"identity.service-account.update",{serviceAccountId:i});let n=await e.rotateServiceAccountKey(i);return n?t.json({apiKey:n}):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error rotating service account key");return t.json({error:s},i)}}async function Er(t,e){try{let r=t.state.user;g(r,"identity.role.get",{});let s=await e.getRoles();return t.json(s)}catch(r){let{message:s,status:i}=h(r,"Error getting roles");return t.json({error:s},i)}}async function Tr(t,e){try{let r=t.state.user;g(r,"identity.role.get",{});let s=t.params.roleId;if(!s)return t.text("Missing role ID",400);let i=await e.getRole(s);return i?t.json(i):t.text("Role not found",404)}catch(r){let{message:s,status:i}=h(r,"Error getting role");return t.json({error:s},i)}}async function Rr(t,e){try{let r=t.state.user;g(r,"identity.role.create",{});let s=await S(t),{roleId:i,name:n,description:o,permissions:a,constraints:c}=s;if(!i||!n||!o)return t.text("Missing required fields: roleId, name, description",400);if(!a||!Array.isArray(a))return t.text("Permissions must be a non-empty array",400);await e.createCustomRole(i,n,o,a,c);let l=await e.getRole(i);return t.json(l,201)}catch(r){let{message:s,status:i}=h(r,"Error creating role");return t.json({error:s},i)}}async function jr(t,e){try{let r=t.state.user;g(r,"identity.role.update",{});let s=t.params.roleId;if(!s)return t.text("Missing role ID",400);let i=await S(t),{name:n,description:o,permissions:a,constraints:c}=i;await e.updateRole(s,{name:n,description:o,permissions:a,constraints:c});let l=await e.getRole(s);return t.json(l)}catch(r){let{message:s,status:i}=h(r,"Error updating role");return t.json({error:s},i)}}async function $r(t,e){try{let r=t.state.user;g(r,"identity.role.delete",{});let s=t.params.roleId;return s?s==="administrator"||s==="user"?t.text("Cannot delete base roles",403):(await e.deleteRole(s),t.json({message:"Role deleted successfully"})):t.text("Missing role ID",400)}catch(r){let{message:s,status:i}=h(r,"Error deleting role");return t.json({error:s},i)}}async function Or(t,e){try{let r=t.state.user;g(r,"management.services.get",{});let s=await e.getServices();return t.json(s)}catch(r){let{message:s,status:i}=h(r,"Error getting services");return t.json({error:s},i)}}async function Mr(t,e){try{let r=t.state.user,s=P(t),{serviceName:i}=s;g(r,"management.service.get",{serviceName:i});let n=await e.getService(i);return n?t.json(n):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error getting service");return t.json({error:s},i)}}var Ur={properties:{name:{type:"string",minLength:1},path:{type:"string"},port:{type:"number",minValue:1,maxValue:65535},prefix:{type:"string"},healthCheckPath:{type:"string"},healthCheckInterval:{type:"number",minValue:1e3}},required:["name"],additionalProperties:!0};var en=new $(!0);async function Hr(t,e){try{let r=t.state.user,s=await S(t),i=en.test(Ur,s);if(!i.success)return t.json({error:"Invalid input",details:i.errors},400);if(g(r,"management.service.create",{}),["storage","functions","sites","databases","observability"].includes(s.name.toLowerCase())){let{name:a,...c}=s;await e.registerService(a,c)}else{if(!s.path||!s.port||!s.prefix)return t.json({error:"Custom services require: name, path, port, and prefix"},400);await e.registerService(s)}return t.text("",201)}catch(r){let{message:s,status:i}=h(r,"Error creating service");return t.json({error:s},i)}}var Dr={properties:{name:{type:"string",minLength:1},path:{type:"string"},port:{type:"number",minValue:1,maxValue:65535},prefix:{type:"string"},healthCheckPath:{type:"string"},healthCheckInterval:{type:"number",minValue:1e3}},required:["name"],additionalProperties:!0};var rn=new $(!0);async function Lr(t,e){try{let r=t.state.user,s=P(t),i=await S(t),n=i.name,o=rn.test(Dr,i);return o.success?(g(r,"management.service.update",{serviceName:n}),n!==s.serviceName?t.json({error:"Service name in body must match path parameter"},400):(await e.updateService(n,i),t.text("",204))):t.json({error:"Invalid input",details:o.errors},400)}catch(r){let{message:s,status:i}=h(r,"Error updating service");return t.json({error:s},i)}}async function Nr(t,e){try{let r=t.state.user,s=P(t),{serviceName:i}=s;return g(r,"management.service.delete",{serviceName:i}),await e.getService(i)?(await e.removeService(i),t.text("",204)):t.text("Not Found",404)}catch(r){let{message:s,status:i}=h(r,"Error deleting service");return t.json({error:s},i)}}async function qr(t,e){try{let r=t.state.user,s=P(t),{serviceName:i}=s;if(g(r,"management.service.start",{serviceName:i}),!await e.getService(i))return t.text("Not Found",404);let o=await e.startService(i);return t.json({serviceName:i,isStarted:o})}catch(r){let{message:s,status:i}=h(r,"Error starting service");return t.json({error:s},i)}}async function Fr(t,e){try{let r=t.state.user,s=P(t),{serviceName:i}=s;if(g(r,"management.service.stop",{serviceName:i}),!await e.getService(i))return t.text("Not Found",404);let o=await e.stopService(i);return t.json({serviceName:i,isStopped:o})}catch(r){let{message:s,status:i}=h(r,"Error stopping service");return t.json({error:s},i)}}async function _r(t,e){try{let r=t.state.user,s=P(t),{serviceName:i}=s;if(g(r,"management.service.get",{serviceName:i}),!await e.getService(i))return t.text("Not Found",404);let o=new URL("http://127.0.0.1:3005/events");o.searchParams.set("service",i),t.query.startTime&&o.searchParams.set("startTime",t.query.startTime),t.query.endTime&&o.searchParams.set("endTime",t.query.endTime),t.query.level&&o.searchParams.set("level",t.query.level),t.query.limit&&o.searchParams.set("limit",t.query.limit),t.query.offset&&o.searchParams.set("offset",t.query.offset);let a=await fetch(o.toString());if(!a.ok)throw new _e(`Observability service error: ${a.statusText}`);let c=await a.json();return t.json({serviceName:i,logs:c.events,count:c.count})}catch(r){let{message:s,status:i}=h(r,"Error getting service logs");return t.json({error:s},i)}}async function Br(t,e){try{let r=t.state.user,s=P(t),{serviceName:i}=s;if(g(r,"management.service.start",{serviceName:i}),!await e.getService(i))return t.text("Not Found",404);let o=await e.restartService(i);return t.json({serviceName:i,restarted:o})}catch(r){let{message:s,status:i}=h(r,"Error restarting service");return t.json({error:s},i)}}function Vr(t,e,r,s,i){let n=t.find(c=>c.service===e);if(!n){let c=new Error(`Function bindings do not include access to service: ${e}`);throw c.cause={statusCode:403},c}if(!n.permissions||n.permissions.length===0)return;for(let c of n.permissions)if(!(c.resource&&c.resource!==r)){if(!c.resource||!c.actions||c.actions.length===0)return;if(c.actions.includes(s)){if(c.targets&&c.targets.length>0){if(!i)return;if(!c.targets.includes(i))continue}return}}let o=i?`:${i}`:"",a=new Error(`Function bindings do not allow: ${e}.${r}.${s}${o}`);throw a.cause={statusCode:403},a}import{readFileSync as sn,existsSync as nn}from"node:fs";function Xe(){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||!nn(t))return e;try{let r=sn(t,"utf-8");return JSON.parse(r)}catch(r){return console.error("[loadRuntimeConfig] Failed to load runtime config:",r),e}}async function v(t,e,r,s,i,n,o){if(!e)return null;let a=t.headers["x-molnos-service-token"];if(a){let u=Xe();if(u.internalServiceSecret&&a===u.internalServiceSecret)return null}let c=t.state.user;if(!c){let u=t.headers.authorization;if(!u){let m=new Error("Unauthorized: No authentication provided");throw m.cause={statusCode:401},m}let p=u.replace(/^Bearer\s+/i,"");if(c=await e.getUserFromToken(p),!c){let m=new Error("Unauthorized: Invalid token");throw m.cause={statusCode:401},m}}g(c,r,{});let l=t.headers["x-function-bindings"];if(l)try{let u=Array.isArray(l)?l[0]:l,p=JSON.parse(u);Vr(p,s,i,n,o)}catch(u){if(u.cause?.statusCode===403)throw u;let p=new Error("Invalid function bindings header");throw p.cause={statusCode:400},p}return c}async function Gr(t,e,r){try{let s=await S(t),i=t.state.requestingIdentity;if(!i)return t.json({error:"Authentication required"},401);let{id:n,name:o,description:a,redirectUris:c,metadata:l}=s;if(!o||!c)return t.json({error:"Missing required fields: name and redirectUris are required"},400);await v(t,r,"applications.application.create","applications","application","create",o);let u={id:n,name:o,description:a,redirectUris:Array.isArray(c)?c:[c],metadata:l,owners:[i.id]},p=await e.createApplication(u,i.id);return t.json(p,201)}catch(s){let{message:i,status:n}=h(s,"Error creating application");return t.json({error:i},n)}}async function zr(t,e,r){try{let s=t.params.id,i=t.state.requestingIdentity;if(!s)return t.json({error:"Application ID is required"},400);await v(t,r,"applications.application.read","applications","application","read",s);let n=await e.getApplication(s,i?.id);return t.json(n,200)}catch(s){let{message:i,status:n}=h(s,"Error retrieving application");return t.json({error:i},n)}}async function Wr(t,e,r){try{let s=t.state.requestingIdentity;if(!s)return t.json({error:"Authentication required"},401);await v(t,r,"applications.application.list","applications","application","list");let i=await e.listApplications(s.id);return t.json({applications:i,total:i.length},200)}catch(s){let{message:i,status:n}=h(s,"Error listing applications");return t.json({error:i},n)}}async function Jr(t,e,r){try{let s=t.params.id,i=await S(t),n=t.state.requestingIdentity;if(!n)return t.json({error:"Authentication required"},401);if(!s)return t.json({error:"Application ID is required"},400);await v(t,r,"applications.application.update","applications","application","update",s);let o=await e.updateApplication(s,i,n.id);return t.json(o,200)}catch(s){let{message:i,status:n}=h(s,"Error updating application");return t.json({error:i},n)}}async function Kr(t,e,r){try{let s=t.params.id,i=t.state.requestingIdentity;return i?s?(await v(t,r,"applications.application.delete","applications","application","delete",s),await e.deleteApplication(s,i.id),t.json({success:!0,message:"Application deleted"},200)):t.json({error:"Application ID is required"},400):t.json({error:"Authentication required"},401)}catch(s){let{message:i,status:n}=h(s,"Error deleting application");return t.json({error:i},n)}}async function Xr(t,e,r){try{let s=await S(t),{name:i,description:n,schema:o}=s;if(!i||!o)return t.json({error:"Missing required fields: name and schema are required"},400);await v(t,r,"schemas.schema.create","schemas","schema","create",i);let a=await e.createSchema({name:i,description:n,schema:o});return t.json(a,201)}catch(s){let{message:i,status:n}=h(s,"Error creating schema");return t.json({error:i},n)}}async function At(t,e,r){try{let s=t.params.name,i=t.params.version;if(!s)return t.json({error:"Schema name is required"},400);await v(t,r,"schemas.schema.read","schemas","schema","read",s);let n=i?parseInt(i,10):void 0,o=await e.getSchema(s,n);return t.json(o,200)}catch(s){let{message:i,status:n}=h(s,"Error retrieving schema");return t.json({error:i},n)}}async function Yr(t,e,r){try{await v(t,r,"schemas.schema.list","schemas","schema","list");let s=await e.listSchemas();return t.json({schemas:s,total:s.length},200)}catch(s){let{message:i,status:n}=h(s,"Error listing schemas");return t.json({error:i},n)}}async function Zr(t,e,r){try{let s=t.params.name,i=await S(t);if(!s)return t.json({error:"Schema name is required"},400);if(!i.schema)return t.json({error:"Missing required field: schema is required for update"},400);await v(t,r,"schemas.schema.update","schemas","schema","update",s);let n=await e.updateSchema(s,{description:i.description,schema:i.schema});return t.json(n,200)}catch(s){let{message:i,status:n}=h(s,"Error updating schema");return t.json({error:i},n)}}async function Qr(t,e,r){try{let s=t.params.name;return s?(await v(t,r,"schemas.schema.delete","schemas","schema","delete",s),await e.deleteSchema(s),t.json({success:!0,message:"Schema deleted"},200)):t.json({error:"Schema name is required"},400)}catch(s){let{message:i,status:n}=h(s,"Error deleting schema");return t.json({error:i},n)}}async function es(t,e,r){try{await v(t,r,"contexts.context.get","contexts","context","get");let i=e.listContexts().map(n=>{let o=e.getContextResources(n.name);return{...n,resourceCount:{functions:o.functions.length,databases:o.databases.length,storage:o.storage.length,sites:o.sites.length,users:o.users.length,serviceAccounts:o.serviceAccounts.length}}});return t.json({success:!0,contexts:i},200)}catch(s){let{message:i,status:n}=h(s,"Error listing contexts");return t.json({error:i},n)}}async function ts(t,e,r){try{let s=t.params.contextName;if(!s)return t.json({error:"contextName parameter is required"},400);await v(t,r,"contexts.context.get","contexts","context","get",s);let i=e.getContextWithResources(s);return t.json({success:!0,context:i},200)}catch(s){let{message:i,status:n}=h(s,"Error getting context");return t.json({error:i},n)}}var on=new $(!0),an={properties:{name:{type:"string",minLength:1,maxLength:64},intent:{type:"string",maxLength:1e3},attributes:{type:"object"}},required:["name"],additionalProperties:!1};async function rs(t,e,r){try{let s=await S(t),i=on.test(an,s);if(!i.success)return t.json({error:"Invalid input",details:i.errors},400);await v(t,r,"contexts.context.create","contexts","context","create");let{name:n,intent:o,attributes:a}=s,c=await e.createContext({name:n,intent:o,attributes:a});return t.json({success:!0,context:c},201)}catch(s){let{message:i,status:n}=h(s,"Error creating context");return t.json({error:i},n)}}var cn=new $(!0),ln={properties:{intent:{type:"string",maxLength:1e3},attributes:{type:"object"}},additionalProperties:!1};async function ss(t,e,r){try{let s=t.params.contextName;if(!s)return t.json({error:"contextName parameter is required"},400);let i=await S(t),n=cn.test(ln,i||{});if(!n.success)return t.json({error:"Invalid input",details:n.errors},400);await v(t,r,"contexts.context.update","contexts","context","update",s);let{intent:o,attributes:a}=i||{},c=await e.updateContext(s,{intent:o,attributes:a});return t.json({success:!0,context:c},200)}catch(s){let{message:i,status:n}=h(s,"Error updating context");return t.json({error:i},n)}}async function is(t,e,r){try{let s=t.params.contextName;if(!s)return t.json({error:"contextName parameter is required"},400);if(s==="default")return t.json({error:"Cannot delete the default context"},400);await v(t,r,"contexts.context.delete","contexts","context","delete",s);let i=e.getContextResources(s);return await e.deleteContext(s),t.json({success:!0,message:`Context '${s}' deleted`,orphanedResources:i},200)}catch(s){let{message:i,status:n}=h(s,"Error deleting context");return t.json({error:i},n)}}async function ns(t,e,r,s){try{let i=t.params.contextName;if(!i)return t.json({error:"contextName parameter is required"},400);await v(t,r,"contexts.context.delete-resources","contexts","context","delete-resources",i);let n=t.headers.authorization,o=n?.startsWith("Bearer ")?n.slice(7):n,a=s(o),c=e.getContextResources(i),l={success:!0,context:i,deleted:[],errors:[],summary:{totalResources:0,deletedCount:0,failedCount:0}};if(l.summary.totalResources=c.functions.length+c.databases.length+c.storage.length+c.sites.length+c.applications.length+c.users.length+c.serviceAccounts.length,a.functions){let p=await a.functions.list();for(let m of c.functions)try{let w=p.find(b=>b.id===m);w&&(await a.functions.delete(m),await e.unregisterResource(i,"function",m),l.deleted.push({type:"function",name:w.name}))}catch(w){l.errors.push({type:"function",name:m,error:w.message||"Unknown error"}),l.success=!1}}if(a.databases)for(let p of c.databases)try{await a.databases.deleteTable(p),await e.unregisterResource(i,"database",p),l.deleted.push({type:"database",name:p})}catch(m){l.errors.push({type:"database",name:p,error:m.message||"Unknown error"}),l.success=!1}if(a.storage)for(let p of c.storage)try{await a.storage.deleteBucket(p),await e.unregisterResource(i,"storage",p),l.deleted.push({type:"storage",name:p})}catch(m){l.errors.push({type:"storage",name:p,error:m.message||"Unknown error"}),l.success=!1}if(a.sites)for(let p of c.sites)try{await a.sites.deleteProject(p),await e.unregisterResource(i,"site",p),l.deleted.push({type:"site",name:p})}catch(m){l.errors.push({type:"site",name:p,error:m.message||"Unknown error"}),l.success=!1}if(a.applications){let p=await a.applications.list();for(let m of c.applications)try{let w=p.find(b=>b.id===m);w&&(await a.applications.delete(m),await e.unregisterResource(i,"application",m),l.deleted.push({type:"application",name:w.name}))}catch(w){l.errors.push({type:"application",name:m,error:w.message||"Unknown error"}),l.success=!1}}if(a.identity)for(let p of c.users)try{let m=await a.identity.getUser(p);m&&(await a.identity.deleteUser(m.id),await e.unregisterResource(i,"user",p),l.deleted.push({type:"user",name:p}))}catch(m){l.errors.push({type:"user",name:p,error:m.message||"Unknown error"}),l.success=!1}if(a.identity)for(let p of c.serviceAccounts)try{let m=await a.identity.getServiceAccount(p);m&&(await a.identity.deleteServiceAccount(m.id),await e.unregisterResource(i,"serviceAccount",p),l.deleted.push({type:"serviceAccount",name:p}))}catch(m){l.errors.push({type:"serviceAccount",name:p,error:m.message||"Unknown error"}),l.success=!1}l.summary.deletedCount=l.deleted.length,l.summary.failedCount=l.errors.length;let u=l.success?200:207;return t.json(l,u)}catch(i){let{message:n,status:o}=h(i,"Error deleting context resources");return t.json({error:n},o)}}async function os(t,e,r){try{await v(t,r,"iac.config.get","iac","config","get");let s=await S(t);if(!s)return t.json({error:"Request body is required"},400);let i=s,o=e().validate(i);return t.json({success:!0,valid:o.valid,errors:o.errors,warnings:o.warnings},200)}catch(s){let{message:i,status:n}=h(s,"Error validating IaC");return t.json({error:i},n)}}async function as(t,e,r){try{await v(t,r,"iac.config.create","iac","config","create");let s=await S(t);if(!s)return t.json({error:"Request body is required"},400);let i=s,n=t.headers.authorization,o=n?.startsWith("Bearer ")?n.slice(7):n,a=e(o),c=t.query?.prune==="true",l=await a.apply(i,{prune:c}),u=l.success?200:207;return t.json({success:l.success,context:l.context,created:l.created,updated:l.updated,unchanged:l.unchanged,deleted:l.deleted,errors:l.errors},u)}catch(s){let{message:i,status:n}=h(s,"Error applying IaC");return t.json({error:i},n)}}var Y="default",Ye=class{db;tableName="context_service";contexts;resourceMappings;constructor(e){this.db=e,this.contexts=[],this.resourceMappings=[]}async start(){await this.loadState()}async loadState(){try{let e=await this.db.get(this.tableName,"state");e&&(this.contexts=e.contexts||[],this.resourceMappings=e.resourceMappings||[])}catch{this.contexts=[],this.resourceMappings=[]}}async saveState(){await this.db.write(this.tableName,"state",{contexts:this.contexts,resourceMappings:this.resourceMappings})}async createContext(e){let r=e.name;if(this.contexts.find(n=>n.name===r))throw new G(`Context '${r}' already exists`);let s=new Date().toISOString(),i={name:r,intent:e.intent,attributes:e.attributes,createdAt:s,updatedAt:s};return this.contexts.push(i),await this.saveState(),i}getContext(e){let r=this.contexts.find(s=>s.name===e);if(!r)throw new q(`Context '${e}' not found`);return r}getContextWithResources(e){let r=this.getContext(e),s=this.getContextResources(e);return{...r,resources:s}}async updateContext(e,r){let s=this.contexts.findIndex(o=>o.name===e);if(s===-1)throw new q(`Context '${e}' not found`);let i=this.contexts[s],n={...i,intent:r.intent??i.intent,attributes:r.attributes??i.attributes,updatedAt:new Date().toISOString()};return this.contexts[s]=n,await this.saveState(),n}async deleteContext(e){let r=this.contexts.findIndex(s=>s.name===e);if(r===-1)throw new q(`Context '${e}' not found`);this.contexts.splice(r,1),this.resourceMappings=this.resourceMappings.filter(s=>s.context!==e),await this.saveState()}contextExists(e){return this.contexts.some(r=>r.name===e)}listContexts(){return[...this.contexts].sort((e,r)=>e.name.localeCompare(r.name))}async ensureContext(e){let r=e||Y;return this.contextExists(r)||await this.createContext({name:r,intent:r===Y?"Default context for resources without explicit context assignment.":void 0}),r}async registerResource(e,r,s){await this.ensureContext(e),this.resourceMappings.find(n=>n.context===e&&n.resourceType===r&&n.resourceName===s)||(this.resourceMappings.push({context:e,resourceType:r,resourceName:s,createdAt:new Date().toISOString()}),await this.saveState())}async unregisterResource(e,r,s){this.resourceMappings=this.resourceMappings.filter(i=>!(i.context===e&&i.resourceType===r&&i.resourceName===s)),await this.saveState()}getContextResources(e){let r=this.resourceMappings.filter(i=>i.context===e),s={functions:[],databases:[],storage:[],sites:[],users:[],serviceAccounts:[],applications:[],schemas:[]};for(let i of r)switch(i.resourceType){case"function":s.functions.push(i.resourceName);break;case"database":s.databases.push(i.resourceName);break;case"storage":s.storage.push(i.resourceName);break;case"site":s.sites.push(i.resourceName);break;case"user":s.users.push(i.resourceName);break;case"serviceAccount":s.serviceAccounts.push(i.resourceName);break;case"application":s.applications.push(i.resourceName);break;case"schema":s.schemas.push(i.resourceName);break}return s}getResourceContext(e,r){return this.resourceMappings.find(i=>i.resourceType===e&&i.resourceName===r)?.context||Y}async moveResource(e,r,s,i){await this.unregisterResource(s,e,r),await this.registerResource(i,e,r)}listResourcesByType(e,r){return this.resourceMappings.filter(s=>s.context===e&&s.resourceType===r).map(s=>s.resourceName)}};async function cs(t,e,r){try{await v(t,r,"iac.config.get","iac","config","get");let s=await S(t);if(!s)return t.json({error:"Request body is required"},400);let i=s,n=t.headers.authorization,o=n?.startsWith("Bearer ")?n.slice(7):n,a=e(o),c=a.validate(i);if(!c.valid)return t.json({success:!1,valid:!1,errors:c.errors,warnings:c.warnings},400);let l=await a.diff(i);return t.json({success:!0,context:i.context?.name||Y,toCreate:l.toCreate,toUpdate:l.toUpdate,toDelete:l.toDelete,unchanged:l.unchanged,warnings:c.warnings},200)}catch(s){let{message:i,status:n}=h(s,"Error generating IaC diff");return t.json({error:i},n)}}var un=new $(!0),dn={type:"object",properties:{intent:{type:"string",minLength:1,maxLength:1e4},intentAttributes:{type:"object"},resourceTypes:{type:"array",items:{type:"string",enum:["functions","sites"]}},files:{type:"array",items:{type:"object",properties:{path:{type:"string"},content:{type:"string"}},required:["path","content"]}},iacConfig:{type:"object"},iterationFeedback:{type:"string"},previousAttemptId:{type:"string"},providerOverride:{type:"string"},modelOverride:{type:"string"},userApiKey:{type:"string"}},additionalProperties:!1};async function ls(t,e,r){try{let s=t.params.contextName;if(!s)return t.json({error:"Context name is required"},400);await v(t,r,"ai.generation.generate","ai","generation","generate",s);let i=await S(t),n=un.test(dn,i);if(!n.success)return t.json({error:"Invalid input",details:n.errors},400);if(!e.isAvailable())return t.json({error:"AI generation is not enabled. Please configure AI in molnos.config.json or provide your own API key."},503);let o=null;if(i.previousAttemptId&&(o=e.getGeneration(i.previousAttemptId),!o))return t.json({error:"Previous generation not found"},404);let a=await e.generate({contextName:s,intent:i.intent,intentAttributes:i.intentAttributes,resourceTypes:i.resourceTypes,files:i.files,iacConfig:i.iacConfig,iterationFeedback:i.iterationFeedback,previousAttempt:o||void 0,providerOverride:i.providerOverride,modelOverride:i.modelOverride,userApiKey:i.userApiKey});return t.json({success:!0,generation:a},201)}catch(s){let{message:i,status:n}=h(s,"Error generating code");return t.json({error:i},n)}}async function us(t,e,r){try{let s=t.params.generationId;if(!s)return t.json({error:"Generation ID is required"},400);await v(t,r,"ai.generation.read","ai","generation","read",s);let i=e.getGeneration(s);return i?t.json({success:!0,generation:i}):t.json({error:"Generation not found or expired"},404)}catch(s){let{message:i,status:n}=h(s,"Error retrieving generation");return t.json({error:i},n)}}async function ds(t,e,r){try{let s=t.params.contextName;if(!s)return t.json({error:"Context name is required"},400);await v(t,r,"ai.generation.read","ai","generation","read",s);let i=e.listGenerations(s);return t.json({success:!0,generations:i})}catch(s){let{message:i,status:n}=h(s,"Error listing generations");return t.json({error:i},n)}}async function ps(t,e,r){try{let s=t.params.generationId;if(!s)return t.json({error:"Generation ID is required"},400);await v(t,r,"ai.generation.apply","ai","generation","apply",s);let i=t.headers.authorization?.replace("Bearer ",""),n=await e.applyGeneration(s,i);if(!n.success)return t.json({error:"Failed to apply IAC configuration",details:n.errors},400);let o=e.getGeneration(s);return t.json({success:!0,generation:o,applyResult:n})}catch(s){let{message:i,status:n}=h(s,"Error applying generation");return t.json({error:i},n)}}async function ms(t,e,r){try{let s=t.params.generationId;return s?(await v(t,r,"ai.generation.discard","ai","generation","discard",s),e.getGeneration(s)?e.discardGeneration(s)?t.json({success:!0,message:"Generation discarded"}):t.json({error:"Failed to discard generation"},500):t.json({error:"Generation not found or expired"},404)):t.json({error:"Generation ID is required"},400)}catch(s){let{message:i,status:n}=h(s,"Error discarding generation");return t.json({error:i},n)}}async function hs(t,e,r){try{let s=t.params.generationId;return s?(await v(t,r,"ai.generation.delete","ai","generation","delete",s),e.getGeneration(s)?e.deleteGeneration(s)?t.json({success:!0,message:"Generation deleted"}):t.json({error:"Failed to delete generation"},500):t.json({error:"Generation not found or expired"},404)):t.json({error:"Generation ID is required"},400)}catch(s){let{message:i,status:n}=h(s,"Error deleting generation");return t.json({error:i},n)}}import{promises as Ze}from"node:fs";import{join as kt,resolve as mn}from"node:path";var fs={$schema:"https://json-schema.org/draft-07/schema#",$id:"https://schemas.molnos.cloud/schema-iac-v1.json",title:"MolnOS IaC Configuration",description:"Infrastructure-as-Code configuration file for MolnOS contexts",type:"object",properties:{$schema:{type:"string",description:"JSON Schema reference for editor support"},version:{type:"string",enum:["1"],default:"1",description:'IaC schema version (defaults to "1" if not specified)'},context:{type:"object",description:"Context definition (optional, defaults to 'default' context)",properties:{name:{type:"string",minLength:1,maxLength:64,pattern:"^[a-z][a-z0-9-]*$",description:"Context name (lowercase, alphanumeric with hyphens)"},intent:{type:"string",maxLength:1e3,description:"Human-readable description of what this context does"},attributes:{type:"object",description:"Freeform intent attributes for policy hints and visualization"}},required:["name"]},resources:{type:"object",description:"Resource declarations",properties:{functions:{type:"object",description:"Function deployments"},databases:{type:"object",description:"Database table declarations"},storage:{type:"object",description:"Storage bucket declarations"},sites:{type:"object",description:"Static site declarations"},schemas:{type:"object",description:"Schema registry declarations"}}},identities:{type:"object",description:"Identity declarations",properties:{users:{type:"object",description:"User declarations"},serviceAccounts:{type:"object",description:"Service account declarations"}}}},required:[]};var hn=new $(!0),Qe=class{contextService;clients;constructor(e,r){this.contextService=e,this.clients=r}async loadConfiguration(e){let r=mn(e);try{let s=await Ze.readFile(r,"utf-8");return JSON.parse(s)}catch(s){throw s.code==="ENOENT"?new x(`IaC file not found: ${e}`):s instanceof SyntaxError?new x(`Invalid JSON in IaC file: ${s.message}`):s}}validate(e){let r=[],s=[];e.version||(e.version="1");let i=hn.test(fs,e);if(!i.success)for(let n of i.errors||[])r.push({path:n.key||"",message:n.error||"Validation error"});if(e.version!=="1"&&r.push({path:"version",message:`Unsupported IaC version: ${e.version}. Only version "1" is supported.`}),e.resources?.functions){for(let[n,o]of Object.entries(e.resources.functions))if(o.bindings)for(let a of o.bindings){let c=a.resource;c.includes(":")||(a.service==="databases"?e.resources?.databases?.[c]||s.push({path:`resources.functions.${n}.bindings`,message:`Database '${c}' is not declared in this configuration`}):a.service==="storage"&&(e.resources?.storage?.[c]||s.push({path:`resources.functions.${n}.bindings`,message:`Storage bucket '${c}' is not declared in this configuration`})))}}return{valid:r.length===0,errors:r,warnings:s}}async apply(e,r={}){let s=this.validate(e);if(!s.valid)return{success:!1,context:e.context?.name||Y,created:[],updated:[],unchanged:[],deleted:[],errors:s.errors.map(o=>({type:"validation",name:o.path,error:o.message}))};let i=e.context?.name||Y,n={success:!0,context:i,created:[],updated:[],unchanged:[],deleted:[],errors:[]};if(await this.contextService.ensureContext(i),e.context)try{await this.contextService.contextExists(i)&&await this.contextService.updateContext(i,{intent:e.context.intent,attributes:e.context.attributes})}catch{}if(e.resources?.databases&&this.clients.databases)for(let[o]of Object.entries(e.resources.databases))try{await this.clients.databases.tableExists(o)?n.unchanged.push({type:"database",name:o}):(await this.clients.databases.createTable(o),await this.contextService.registerResource(i,"database",o),n.created.push({type:"database",name:o}))}catch(a){n.errors.push({type:"database",name:o,error:a.message||"Unknown error"}),n.success=!1}if(e.resources?.storage&&this.clients.storage)for(let[o,a]of Object.entries(e.resources.storage))try{await this.clients.storage.bucketExists(o)?await this.clients.storage.isBucketPublic(o)!==(a.public||!1)?(await this.clients.storage.updateBucket(o,{public:a.public}),n.updated.push({type:"storage",name:o})):n.unchanged.push({type:"storage",name:o}):(await this.clients.storage.createBucket(o,a.public||!1),await this.contextService.registerResource(i,"storage",o),n.created.push({type:"storage",name:o}))}catch(c){n.errors.push({type:"storage",name:o,error:c.message||"Unknown error"}),n.success=!1}if(e.resources?.functions&&this.clients.functions)for(let[o,a]of Object.entries(e.resources.functions))try{let c;if(a.code)c=a.code;else if(a.source){let u=r.basePath?kt(r.basePath,a.source):a.source;try{c=await Ze.readFile(u,"utf-8")}catch{throw new Error(`Cannot read function source: ${a.source}`)}}else throw new Error('Function must have either "code" or "source" defined');let l=await this.clients.functions.get(o);if(l)await this.clients.functions.update(l.id,{code:c,methods:a.methods,bindings:a.bindings,triggers:a.triggers,allowUnauthenticated:a.allowUnauthenticated,passAllHeaders:a.passAllHeaders}),n.updated.push({type:"function",name:o});else{let u=await this.clients.functions.deploy(o,c,{id:a.id,methods:a.methods,bindings:a.bindings,triggers:a.triggers,allowUnauthenticated:a.allowUnauthenticated,passAllHeaders:a.passAllHeaders});await this.contextService.registerResource(i,"function",u.id),n.created.push({type:"function",name:o})}}catch(c){n.errors.push({type:"function",name:o,error:c.message||"Unknown error"}),n.success=!1}if(e.resources?.sites&&this.clients.sites)for(let[o,a]of Object.entries(e.resources.sites))try{let c;if(a.files&&a.files.length>0)c=a.files;else if(a.source){let u=r.basePath?kt(r.basePath,a.source):a.source;if(c=await this.loadSiteFiles(u),c.length===0)throw new Error(`No files found in site source: ${a.source}`)}else throw new Error('Site must have either "files" or "source" defined');let l=await this.clients.sites.getProject(o);await this.clients.sites.uploadProject(c,o),await this.contextService.registerResource(i,"site",o),l?n.updated.push({type:"site",name:o}):n.created.push({type:"site",name:o})}catch(c){n.errors.push({type:"site",name:o,error:c.message||"Unknown error"}),n.success=!1}if(e.identities?.users&&this.clients.identity)for(let[o,a]of Object.entries(e.identities.users))try{let c=await this.clients.identity.getUser(a.email);c?(await this.clients.identity.updateUser(c.id,{roles:a.roles}),n.updated.push({type:"user",name:a.email})):(await this.clients.identity.createUser(a.email,o,a.roles,{id:a.id}),await this.contextService.registerResource(i,"user",a.email),n.created.push({type:"user",name:a.email}))}catch(c){n.errors.push({type:"user",name:a.email,error:c.message||"Unknown error"}),n.success=!1}if(e.identities?.serviceAccounts&&this.clients.identity)for(let[o,a]of Object.entries(e.identities.serviceAccounts))try{let c=await this.clients.identity.getServiceAccount(o);c?(await this.clients.identity.updateServiceAccount(c.id,{roles:a.roles,description:a.description}),n.updated.push({type:"serviceAccount",name:o})):(await this.clients.identity.createServiceAccount(o,a.roles,a.description,{id:a.id}),await this.contextService.registerResource(i,"serviceAccount",o),n.created.push({type:"serviceAccount",name:o}))}catch(c){n.errors.push({type:"serviceAccount",name:o,error:c.message||"Unknown error"}),n.success=!1}if(e.resources?.applications&&this.clients.applications)for(let[o,a]of Object.entries(e.resources.applications))try{let c=await this.clients.applications.get(o);if(c)await this.clients.applications.update(c.id,{description:a.description,redirectUris:a.redirectUris}),n.updated.push({type:"application",name:o});else{let l=await this.clients.applications.create(o,a.description,a.redirectUris,{id:a.id});await this.contextService.registerResource(i,"application",l.id),n.created.push({type:"application",name:o})}}catch(c){n.errors.push({type:"application",name:o,error:c.message||"Unknown error"}),n.success=!1}if(e.resources?.schemas&&this.clients.schemas)for(let[o,a]of Object.entries(e.resources.schemas))try{await this.clients.schemas.get(o)?(await this.clients.schemas.update(o,a.schema,a.description),n.updated.push({type:"schema",name:o})):(await this.clients.schemas.create(o,a.schema,a.description),await this.contextService.registerResource(i,"schema",o),n.created.push({type:"schema",name:o}))}catch(c){n.errors.push({type:"schema",name:o,error:c.message||"Unknown error"}),n.success=!1}if(r.prune){let o=await this.contextService.getContextResources(i);if(this.clients.functions){let a=Object.keys(e.resources?.functions||{}),c=await this.clients.functions.list();for(let l of o.functions){let u=c.find(p=>p.id===l);if(u&&!a.includes(u.name))try{await this.clients.functions.delete(l),await this.contextService.unregisterResource(i,"function",l),n.deleted.push({type:"function",name:u.name})}catch(p){n.errors.push({type:"function",name:u.name,error:`Failed to delete: ${p.message||"Unknown error"}`}),n.success=!1}}}if(this.clients.databases){let a=Object.keys(e.resources?.databases||{});for(let c of o.databases)if(!a.includes(c))try{await this.clients.databases.deleteTable(c),await this.contextService.unregisterResource(i,"database",c),n.deleted.push({type:"database",name:c})}catch(l){n.errors.push({type:"database",name:c,error:`Failed to delete: ${l.message||"Unknown error"}`}),n.success=!1}}if(this.clients.storage){let a=Object.keys(e.resources?.storage||{});for(let c of o.storage)if(!a.includes(c))try{await this.clients.storage.deleteBucket(c),await this.contextService.unregisterResource(i,"storage",c),n.deleted.push({type:"storage",name:c})}catch(l){n.errors.push({type:"storage",name:c,error:`Failed to delete: ${l.message||"Unknown error"}`}),n.success=!1}}if(this.clients.sites){let a=Object.keys(e.resources?.sites||{});for(let c of o.sites)if(!a.includes(c))try{await this.clients.sites.deleteProject(c),await this.contextService.unregisterResource(i,"site",c),n.deleted.push({type:"site",name:c})}catch(l){n.errors.push({type:"site",name:c,error:`Failed to delete: ${l.message||"Unknown error"}`}),n.success=!1}}if(this.clients.applications){let a=Object.keys(e.resources?.applications||{}),c=await this.clients.applications.list();for(let l of o.applications){let u=c.find(p=>p.id===l);if(u&&!a.includes(u.name))try{await this.clients.applications.delete(l),await this.contextService.unregisterResource(i,"application",l),n.deleted.push({type:"application",name:u.name})}catch(p){n.errors.push({type:"application",name:u.name,error:`Failed to delete: ${p.message||"Unknown error"}`}),n.success=!1}}}if(this.clients.identity){let a=Object.values(e.identities?.users||{}).map(c=>c.email);for(let c of o.users)if(!a.includes(c))try{let l=await this.clients.identity.getUser(c);l&&(await this.clients.identity.deleteUser(l.id),await this.contextService.unregisterResource(i,"user",c),n.deleted.push({type:"user",name:c}))}catch(l){n.errors.push({type:"user",name:c,error:`Failed to delete: ${l.message||"Unknown error"}`}),n.success=!1}}if(this.clients.identity){let a=Object.keys(e.identities?.serviceAccounts||{});for(let c of o.serviceAccounts)if(!a.includes(c))try{let l=await this.clients.identity.getServiceAccount(c);l&&(await this.clients.identity.deleteServiceAccount(l.id),await this.contextService.unregisterResource(i,"serviceAccount",c),n.deleted.push({type:"serviceAccount",name:c}))}catch(l){n.errors.push({type:"serviceAccount",name:c,error:`Failed to delete: ${l.message||"Unknown error"}`}),n.success=!1}}if(this.clients.schemas){let a=Object.keys(e.resources?.schemas||{});for(let c of o.schemas)if(!a.includes(c))try{await this.clients.schemas.delete(c),await this.contextService.unregisterResource(i,"schema",c),n.deleted.push({type:"schema",name:c})}catch(l){n.errors.push({type:"schema",name:c,error:`Failed to delete: ${l.message||"Unknown error"}`}),n.success=!1}}}return n}async loadSiteFiles(e,r=""){let s=[];try{let i=await Ze.readdir(e,{withFileTypes:!0});for(let n of i){let o=kt(e,n.name),a=r?`${r}/${n.name}`:n.name;if(n.isDirectory()){let c=await this.loadSiteFiles(o,a);s.push(...c)}else if(n.isFile()){let l=(await Ze.readFile(o)).toString("base64");s.push({path:a,content:l})}}}catch(i){if(i.code!=="ENOENT")throw i}return s}async diff(e){let r=e.context?.name||Y,s=[],i=[],n=[],o=[],a=await this.contextService.getContextResources(r);if(this.clients.databases){let c=Object.keys(e.resources?.databases||{});for(let l of c)await this.clients.databases.tableExists(l)?o.push({type:"database",name:l}):s.push({type:"database",name:l});for(let l of a.databases)c.includes(l)||n.push({type:"database",name:l})}if(this.clients.storage){let c=Object.keys(e.resources?.storage||{});for(let l of c)if(await this.clients.storage.bucketExists(l)){let p=e.resources?.storage?.[l];await this.clients.storage.isBucketPublic(l)!==(p?.public||!1)?i.push({type:"storage",name:l}):o.push({type:"storage",name:l})}else s.push({type:"storage",name:l});for(let l of a.storage)c.includes(l)||n.push({type:"storage",name:l})}if(this.clients.functions){let c=Object.keys(e.resources?.functions||{});for(let l of c)await this.clients.functions.get(l)?i.push({type:"function",name:l}):s.push({type:"function",name:l});for(let l of a.functions)c.includes(l)||n.push({type:"function",name:l})}if(this.clients.sites){let c=Object.keys(e.resources?.sites||{});for(let l of c)await this.clients.sites.getProject(l)?i.push({type:"site",name:l}):s.push({type:"site",name:l});for(let l of a.sites)c.includes(l)||n.push({type:"site",name:l})}if(this.clients.applications){let c=Object.keys(e.resources?.applications||{});for(let l of c)await this.clients.applications.get(l)?i.push({type:"application",name:l}):s.push({type:"application",name:l});for(let l of a.applications)c.includes(l)||n.push({type:"application",name:l})}if(this.clients.schemas){let c=Object.keys(e.resources?.schemas||{});for(let l of c)await this.clients.schemas.get(l)?i.push({type:"schema",name:l}):s.push({type:"schema",name:l});for(let l of a.schemas)c.includes(l)||n.push({type:"schema",name:l})}return{toCreate:s,toUpdate:i,toDelete:n,unchanged:o}}};var Z=class{constructor(e,r){this.baseUrl=e;this.authToken=r}async request(e,r,s,i){let n=`${this.baseUrl}${r}`;if(i){let p=new URLSearchParams(i);n+=`?${p.toString()}`}let o={"Content-Type":"application/json"};this.authToken&&(o.Authorization=`Bearer ${this.authToken}`);let a={method:e,headers:o};s&&(a.body=JSON.stringify(s));let c=await fetch(n,a),l=c.headers.get("content-type"),u;if(l?.includes("application/json")?u=await c.json():u=await c.text(),!c.ok){let p=typeof u=="object"&&u.error?u.error:typeof u=="string"?u:JSON.stringify(u);throw new Error(p)}return u}},Pt=class extends Z{async createTable(e){await this.request("POST",`/tables/${e}`)}async tableExists(e){try{return((await this.request("GET","/tables")).tables||[]).some(i=>i.name===e)}catch{return!1}}async deleteTable(e){await this.request("DELETE",`/tables/${e}`)}async listTables(){return((await this.request("GET","/tables")).tables||[]).map(s=>s.name)}},Et=class extends Z{async createBucket(e,r){await this.request("POST",`/buckets/${e}`,{public:r})}async bucketExists(e){try{return await this.request("GET",`/buckets/${e}`),!0}catch{return!1}}async updateBucket(e,r){await this.request("PATCH",`/buckets/${e}`,r)}async deleteBucket(e){await this.request("DELETE",`/buckets/${e}`)}async listBuckets(){return(await this.request("GET","/buckets")).buckets||[]}async isBucketPublic(e){try{return(await this.request("GET",`/buckets/${e}`)).public===!0}catch{return!1}}},Tt=class extends Z{async deploy(e,r,s){let i=await this.request("POST","/deploy",{name:e,code:r,id:s.id,methods:s.methods,bindings:s.bindings,triggers:s.triggers,allowUnauthenticated:s.allowUnauthenticated,passAllHeaders:s.passAllHeaders,env:s.env});return i.function||i}async get(e){try{return((await this.request("GET","/list")).functions||[]).find(i=>i.name===e)||null}catch{return null}}async update(e,r){let s=await this.request("PUT",`/${e}`,r);return s.function||s}async delete(e){await this.request("DELETE",`/${e}`)}async list(){return(await this.request("GET","/list")).functions||[]}},Rt=class extends Z{async uploadProject(e,r){return await this.request("POST","/projects",{files:e,projectId:r})}async getProject(e){try{return((await this.request("GET","/projects")).projects||[]).find(i=>i.projectId===e)||null}catch{return null}}async deleteProject(e){await this.request("DELETE",`/projects/${e}`)}async listProjects(){return(await this.request("GET","/projects")).projects||[]}},jt=class extends Z{async createUser(e,r,s,i){let n=await this.request("POST","/identity/users",{email:e,name:r,roles:s,id:i?.id});return n.user||n}async getUser(e){try{return((await this.request("GET","/identity/users")).users||[]).find(i=>i.metadata?.email===e)||null}catch{return null}}async updateUser(e,r){let s=await this.request("PATCH",`/identity/users/${e}`,r);return s.user||s}async deleteUser(e){await this.request("DELETE",`/identity/users/${e}`)}async listUsers(){return(await this.request("GET","/identity/users")).users||[]}async createServiceAccount(e,r,s,i){let n=await this.request("POST","/identity/service-accounts",{name:e,roles:r,description:s,id:i?.id});return n.serviceAccount||n}async getServiceAccount(e){try{return((await this.request("GET","/identity/service-accounts")).serviceAccounts||[]).find(i=>i.name===e)||null}catch{return null}}async updateServiceAccount(e,r){let s=await this.request("PATCH",`/identity/service-accounts/${e}`,r);return s.serviceAccount||s}async deleteServiceAccount(e){await this.request("DELETE",`/identity/service-accounts/${e}`)}async listServiceAccounts(){return(await this.request("GET","/identity/service-accounts")).serviceAccounts||[]}},$t=class extends Z{async create(e,r,s,i){return await this.request("POST","/applications",{name:e,description:r,redirectUris:s,id:i?.id})}async get(e){try{return((await this.request("GET","/applications")).applications||[]).find(i=>i.name===e)||null}catch{return null}}async update(e,r){return await this.request("PATCH",`/applications/${e}`,r)}async delete(e){await this.request("DELETE",`/applications/${e}`)}async list(){return(await this.request("GET","/applications")).applications||[]}},Ot=class extends Z{async create(e,r,s){return await this.request("POST","",{name:e,schema:r,description:s})}async get(e){try{return await this.request("GET",`/${e}`)}catch{return null}}async update(e,r,s){return await this.request("PUT",`/${e}`,{schema:r,description:s})}async delete(e){await this.request("DELETE",`/${e}`)}async list(){return(await this.request("GET","")).schemas||[]}};function Mt(t){let{serviceUrls:e,authToken:r}=t,s={};return e.databases&&(s.databases=new Pt(e.databases,r)),e.storage&&(s.storage=new Et(e.storage,r)),e.functions&&(s.functions=new Tt(e.functions,r)),e.sites&&(s.sites=new Rt(e.sites,r)),e.identity&&(s.identity=new jt(e.identity,r)),e.applications&&(s.applications=new $t(e.applications,r)),e.schemas&&(s.schemas=new Ot(e.schemas,r)),s}import ys from"crypto";var gs="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var fn=128,de,ye,gn=t=>{!de||de.length<t?(de=Buffer.allocUnsafe(t*fn),ys.randomFillSync(de),ye=0):ye+t>de.length&&(ys.randomFillSync(de),ye=0),ye+=t};var vs=(t=21)=>{gn(t|=0);let e="";for(let r=ye-t;r<ye;r++)e+=gs[de[r]&63];return e};var et=class{generations=new Map;cleanupInterval=null;ttlHours;constructor(e=24){this.ttlHours=e}start(){this.cleanupInterval||(this.cleanupInterval=setInterval(()=>{this.cleanup()},3600*1e3))}stop(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=null)}store(e){let r=vs(12),s=new Date().toISOString(),i=new Date(Date.now()+this.ttlHours*60*60*1e3).toISOString(),n={id:r,timestamp:s,expiresAt:i,...e};return this.generations.set(r,n),n}get(e){let r=this.generations.get(e);return r?new Date(r.expiresAt)<new Date?(this.generations.delete(e),null):r:null}updateStatus(e,r){let s=this.get(e);return s?(s.status=r,this.generations.set(e,s),!0):!1}delete(e){return this.generations.delete(e)}listByContext(e){let r=[];for(let s of this.generations.values())s.contextId===e&&new Date(s.expiresAt)>=new Date&&r.push(s);return r.sort((s,i)=>new Date(i.timestamp).getTime()-new Date(s.timestamp).getTime())}listPendingByContext(e){return this.listByContext(e).filter(r=>r.status==="pending")}getStats(){let e=0,r=0,s=0,i={};for(let n of this.generations.values())new Date(n.expiresAt)<new Date||(n.status==="pending"?e++:n.status==="applied"?r++:n.status==="discarded"&&s++,i[n.contextId]=(i[n.contextId]||0)+1);return{total:e+r+s,pending:e,applied:r,discarded:s,byContext:i}}cleanup(){let e=new Date,r=[];for(let[s,i]of this.generations.entries())new Date(i.expiresAt)<e&&r.push(s);for(let s of r)this.generations.delete(s);r.length>0&&console.log(`[GenerationStorage] Cleaned up ${r.length} expired generations`)}clear(){this.generations.clear()}size(){return this.generations.size}};var tt=class{constructor(e){this.config=e;if(!e.apiKey)throw new Error("Anthropic API key is required");e.model||(this.config.model="claude-sonnet-4-5"),e.baseUrl||(this.config.baseUrl="https://api.anthropic.com"),e.maxTokens||(this.config.maxTokens=32e3)}name="anthropic";async validateConfig(){try{let e=await fetch(`${this.config.baseUrl}/v1/messages`,{method:"POST",headers:{"x-api-key":this.config.apiKey,"anthropic-version":"2023-06-01","content-type":"application/json"},body:JSON.stringify({model:this.config.model,max_tokens:1,messages:[{role:"user",content:"test"}]})});return e.ok||e.status===400}catch{return!1}}async complete(e){let{messages:r,tools:s,systemPrompt:i,config:n}=e,o={...this.config,...n},a=this.transformMessages(r),c={model:o.model,max_tokens:o.maxTokens||32e3,messages:a};i&&(c.system=i),s&&s.length>0&&(c.tools=this.transformTools(s)),o.temperature!==void 0&&(c.temperature=o.temperature);let l=await fetch(`${o.baseUrl}/v1/messages`,{method:"POST",headers:{"x-api-key":o.apiKey,"anthropic-version":"2023-06-01","content-type":"application/json"},body:JSON.stringify(c)});if(!l.ok){let p=await l.text();throw new Error(`Anthropic API error (${l.status}): ${p}`)}let u=await l.json();return this.transformResponse(u)}transformMessages(e){return e.map(r=>Array.isArray(r.content)?{role:r.role==="system"?"user":r.role,content:r.content}:{role:r.role==="system"?"user":r.role,content:r.content})}transformTools(e){return e.map(r=>({name:r.name,description:r.description,input_schema:r.input_schema}))}transformResponse(e){let r={content:"",stopReason:e.stop_reason},s=e.content.filter(n=>n.type==="text");r.content=s.map(n=>n.text).join(`
115
115
  `);let i=e.content.filter(n=>n.type==="tool_use");return i.length>0&&(r.toolCalls=i.map(n=>({id:n.id,name:n.name,input:n.input}))),e.usage&&(r.usage={inputTokens:e.usage.input_tokens||0,outputTokens:e.usage.output_tokens||0,totalTokens:(e.usage.input_tokens||0)+(e.usage.output_tokens||0)}),r}};var rt=class{constructor(e){this.config=e;if(!e.apiKey)throw new Error("OpenAI API key is required");e.model||(this.config.model="gpt-4-turbo"),e.baseUrl||(this.config.baseUrl="https://api.openai.com/v1"),e.maxTokens||(this.config.maxTokens=32e3)}name="openai";async validateConfig(){try{return(await fetch(`${this.config.baseUrl}/models`,{method:"GET",headers:{Authorization:`Bearer ${this.config.apiKey}`}})).ok}catch{return!1}}async complete(e){let{messages:r,tools:s,systemPrompt:i,config:n}=e,o={...this.config,...n},a=this.transformMessages(r,i),c={model:o.model,max_tokens:o.maxTokens||32e3,messages:a};s&&s.length>0&&(c.tools=this.transformTools(s),c.tool_choice="auto"),o.temperature!==void 0&&(c.temperature=o.temperature);let l=await fetch(`${o.baseUrl}/chat/completions`,{method:"POST",headers:{Authorization:`Bearer ${o.apiKey}`,"content-type":"application/json"},body:JSON.stringify(c)});if(!l.ok){let p=await l.text();throw new Error(`OpenAI API error (${l.status}): ${p}`)}let u=await l.json();return this.transformResponse(u)}transformMessages(e,r){let s=[];r&&s.push({role:"system",content:r});for(let i of e)if(Array.isArray(i.content)){let n=i.content.filter(c=>c.type==="tool_use");if(n.length>0&&i.role==="assistant"){s.push({role:"assistant",content:null,tool_calls:n.map(c=>({id:c.tool_use_id||`call_${Date.now()}`,type:"function",function:{name:c.tool_name||"",arguments:JSON.stringify(c.tool_input||{})}}))});continue}let o=i.content.filter(c=>c.type==="tool_result");if(o.length>0&&i.role==="user"){for(let c of o)s.push({role:"tool",tool_call_id:c.tool_use_id||"",content:c.content||""});continue}let a=i.content.filter(c=>c.type==="text");a.length>0&&s.push({role:i.role==="system"?"system":i.role,content:a.map(c=>c.text).join(`
116
116
  `)})}else s.push({role:i.role==="system"?"system":i.role,content:i.content});return s}transformTools(e){return e.map(r=>({type:"function",function:{name:r.name,description:r.description,parameters:r.input_schema}}))}transformResponse(e){let r=e.choices[0],s=r.message,i={content:s.content||"",stopReason:r.finish_reason};return s.tool_calls&&s.tool_calls.length>0&&(i.toolCalls=s.tool_calls.map(n=>({id:n.id,name:n.function.name,input:JSON.parse(n.function.arguments)}))),e.usage&&(i.usage={inputTokens:e.usage.prompt_tokens||0,outputTokens:e.usage.completion_tokens||0,totalTokens:e.usage.total_tokens||0}),i}};var st=class{constructor(e){this.config=e;e.endpoint||(this.config.endpoint="http://localhost:11434"),e.model||(this.config.model="codellama:13b"),e.maxTokens||(this.config.maxTokens=32e3)}name="ollama";async validateConfig(){try{let e=await fetch(`${this.config.endpoint}/api/tags`);return e.ok?((await e.json()).models||[]).some(n=>n.name===this.config.model||n.name.startsWith(this.config.model)):!1}catch{return!1}}async complete(e){let{messages:r,tools:s,systemPrompt:i,config:n}=e,o={...this.config,...n},a=this.transformMessages(r,i),c={model:o.model,messages:a,stream:!1};o.maxTokens&&(c.options={num_predict:o.maxTokens}),o.temperature!==void 0&&(c.options={...c.options,temperature:o.temperature}),s&&s.length>0&&(c.tools=this.transformTools(s));let l=await fetch(`${o.endpoint}/api/chat`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(c)});if(!l.ok){let p=await l.text();throw new Error(`Ollama API error (${l.status}): ${p}`)}let u=await l.json();return this.transformResponse(u)}transformMessages(e,r){let s=[];r&&s.push({role:"system",content:r});for(let i of e)if(Array.isArray(i.content)){let n=i.content.filter(c=>c.type==="tool_use");if(n.length>0&&i.role==="assistant"){let c=n.map(l=>`Calling tool: ${l.tool_name}
117
117
  Input: ${JSON.stringify(l.tool_input,null,2)}`).join(`
@@ -164,6 +164,7 @@ ${bn}
164
164
  "myFunction": {
165
165
  "code": "export async function handler(req, context) { return { message: 'Hello' }; }",
166
166
  "methods": ["GET"],
167
+ "triggers": [{ "type": "http" }],
167
168
  "allowUnauthenticated": false
168
169
  },
169
170
  "myEventHandler": {
@@ -195,7 +196,7 @@ ${bn}
195
196
 
196
197
  ### Signature (REQUIRED)
197
198
 
198
- **HTTP-triggered functions (default):**
199
+ **HTTP-triggered functions (when triggers include \`{ "type": "http" }\`):**
199
200
  \`\`\`js
200
201
  export async function handler(req, context) { <function code here> }
201
202
  \`\`\`
@@ -273,7 +274,7 @@ To make a function execute when an event is emitted, add \`triggers\`:
273
274
  "triggers": [{ "type": "event", "eventName": "order.created" }]
274
275
  }
275
276
  \`\`\`
276
- A function can subscribe to multiple events. Default trigger type is \`"http"\` (standard HTTP-invoked function).
277
+ A function can subscribe to multiple events. If no triggers are specified, the function defaults to HTTP-accessible for backward compatibility, but it is recommended to always set triggers explicitly.
277
278
 
278
279
  **Disabling HTTP access**: If \`triggers\` are specified and none have \`type: "http"\`, the function is event-only and not accessible via HTTP. To keep HTTP access alongside event triggers, include \`{ "type": "http" }\`:
279
280
  \`\`\`json
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.0",
4
+ "version": "1.4.2",
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-f924fefb-57ad-41da-b5b5-7ac4704159e2","creationInfo":{"licenseListVersion":"3.27","creators":["Organization: Anchore, Inc","Tool: syft-1.41.1"],"created":"2026-02-02T08:05:20Z"},"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-7e15da1c712a21d3","versionInfo":"1.4.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.4.0:*:*:*:*:*:*:*"},{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:npm/molnos@1.4.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:139a94443ebe7e9616bd6ddb2cd92a398808e24ab2f7e77569acbcb8fda49aa3","supplier":"NOASSERTION","downloadLocation":"NOASSERTION","filesAnalyzed":false,"checksums":[{"algorithm":"SHA256","checksumValue":"139a94443ebe7e9616bd6ddb2cd92a398808e24ab2f7e77569acbcb8fda49aa3"}],"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":"ad4c10d085c0d585088dd26a1b6e22bf53473a47"},{"algorithm":"SHA256","checksumValue":"139a94443ebe7e9616bd6ddb2cd92a398808e24ab2f7e77569acbcb8fda49aa3"}],"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-7e15da1c712a21d3","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-7e15da1c712a21d3","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikrovalid-2873df526a8a0901","relatedSpdxElement":"SPDXRef-Package-npm-molnos-7e15da1c712a21d3","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-7e15da1c712a21d3","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-7e15da1c712a21d3","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroevent-5bd10e41dccc0f47","relatedSpdxElement":"SPDXRef-Package-npm-molnos-7e15da1c712a21d3","relationshipType":"DEPENDENCY_OF"},{"spdxElementId":"SPDXRef-Package-npm-mikroauth-7520a9fae77ac01a","relatedSpdxElement":"SPDXRef-Package-npm-molnos-7e15da1c712a21d3","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-7e15da1c712a21d3","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-7e15da1c712a21d3","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-7e15da1c712a21d3","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-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"}]}