@kyro-cms/core 0.12.21 → 0.12.23

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.
Files changed (36) hide show
  1. package/README.md +7 -0
  2. package/dist/api-handler-graphql.cjs +1 -1
  3. package/dist/api-handler-graphql.js +1 -1
  4. package/dist/api-handler-trpc.cjs +1 -1
  5. package/dist/api-handler-trpc.js +1 -1
  6. package/dist/api-handler.cjs +1 -1
  7. package/dist/api-handler.js +1 -1
  8. package/dist/{bootstrap-KFGRTJSD.js → bootstrap-6G6HI26Z.js} +1 -1
  9. package/dist/bootstrap-ETJ6QNGR.cjs +1 -0
  10. package/dist/{chunk-4D6FG2J6.js → chunk-3IOJVXWI.js} +1 -1
  11. package/dist/chunk-4XZABBHF.cjs +1 -0
  12. package/dist/chunk-6MSPBK3W.js +1 -0
  13. package/dist/{chunk-GXVCCKOL.js → chunk-6ROHVUXF.js} +1 -1
  14. package/dist/{chunk-QJZQOLRN.js → chunk-HY5FILVL.js} +1 -1
  15. package/dist/{chunk-O3OYZQN7.cjs → chunk-MR5BDZKI.cjs} +2 -2
  16. package/dist/{chunk-BVG6VSAJ.cjs → chunk-QCA3AP3M.cjs} +1 -1
  17. package/dist/{chunk-XALG5H27.cjs → chunk-RHNLFONF.cjs} +1 -1
  18. package/dist/{chunk-YVM5BDRD.js → chunk-YYL2U3HJ.js} +1 -1
  19. package/dist/{chunk-XTRY75KC.cjs → chunk-ZLGWJ4TK.cjs} +2 -2
  20. package/dist/cli/index.cjs +3 -3
  21. package/dist/cli/index.js +3 -3
  22. package/dist/index.cjs +3 -3
  23. package/dist/index.d.cts +6 -3
  24. package/dist/index.d.ts +6 -3
  25. package/dist/index.js +1 -1
  26. package/dist/mongo-auth-adapter-5TJO5J5U.js +1 -0
  27. package/dist/{mongo-auth-adapter-C62QYCYV.cjs → mongo-auth-adapter-JVE5M3S4.cjs} +1 -1
  28. package/dist/mongodb/index.cjs +1 -1
  29. package/dist/mongodb/index.js +1 -1
  30. package/dist/rest/index.cjs +1 -1
  31. package/dist/rest/index.js +1 -1
  32. package/package.json +2 -2
  33. package/dist/bootstrap-4WXRKXMO.cjs +0 -1
  34. package/dist/chunk-KJT6VTTN.cjs +0 -1
  35. package/dist/chunk-OOQGI3T7.js +0 -1
  36. package/dist/mongo-auth-adapter-AIMZTNG6.js +0 -1
@@ -1 +1 @@
1
- 'use strict';var h=require('bcryptjs'),crypto=require('crypto');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var h__default=/*#__PURE__*/_interopDefault(h);var p=class{db;adapter;prefix;sessionTTL;refreshTokenTTL;indexesEnsured=false;constructor(e){this.db=e.db,this.adapter=e.adapter,this.prefix=e.collectionPrefix||"",this.sessionTTL=e.sessionTTL||86400,this.refreshTokenTTL=e.refreshTokenTTL||604800;}getDatabase(){let e=typeof this.db=="function"?this.db():this.db;if(!e&&this.adapter&&(this.adapter.db?e=this.adapter.db:this.adapter.client&&(this.adapter.db=this.adapter.client.db(this.adapter.database||"kyro_cms"),e=this.adapter.db)),!e)throw new Error("MongoDB database not initialized");return e}col(e){return this.getDatabase().collection(`${this.prefix}${e}`)}async connect(){this.indexesEnsured||await this.ensureIndexes();}async disconnect(){}async ensureIndexes(){await this.col("users").createIndex({email:1},{unique:true}),await this.col("users").createIndex({tenantId:1}),await this.col("users").createIndex({role:1}),await this.col("sessions").createIndex({token:1},{unique:true}),await this.col("sessions").createIndex({refreshToken:1}),await this.col("sessions").createIndex({userId:1}),await this.col("sessions").createIndex({expiresAt:1},{expireAfterSeconds:0}),await this.col("audit_logs").createIndex({timestamp:-1}),await this.col("audit_logs").createIndex({userId:1}),await this.col("audit_logs").createIndex({action:1}),await this.col("audit_logs").createIndex({resource:1}),await this.col("password_history").createIndex({userId:1,createdAt:-1}),await this.col("lockouts").createIndex({userId:1},{unique:true}),await this.col("lockouts").createIndex({lockedUntil:1}),this.indexesEnsured=true;}async createUser(e){let s=crypto.randomUUID(),t=new Date,i=await this.hashPassword(e.password),n={_id:s,name:e.name||null,email:e.email.toLowerCase(),passwordHash:i,role:e.role||"customer",avatar:e.avatar||null,tenantId:e.tenantId||null,emailVerified:false,locked:false,lastLogin:null,failedLoginAttempts:0,createdAt:t,updatedAt:t};return await this.col("users").insertOne(n),this.docToAuthUser(n)}async findUserByEmail(e){let s=await this.col("users").findOne({email:e.toLowerCase()});return s?this.docToAuthUser(s):null}async findUserById(e){let s=await this.col("users").findOne({_id:e});return s?this.docToAuthUser(s):null}async updateUser(e,s){let t={updatedAt:new Date};s.name!==void 0&&(t.name=s.name),s.email!==void 0&&(t.email=s.email),s.passwordHash!==void 0&&(t.passwordHash=s.passwordHash),s.role!==void 0&&(t.role=s.role),s.avatar!==void 0&&(t.avatar=s.avatar),s.tenantId!==void 0&&(t.tenantId=s.tenantId),s.emailVerified!==void 0&&(t.emailVerified=s.emailVerified),s.locked!==void 0&&(t.locked=s.locked),s.lastLogin!==void 0&&(t.lastLogin=s.lastLogin?new Date(s.lastLogin):null),s.failedLoginAttempts!==void 0&&(t.failedLoginAttempts=s.failedLoginAttempts);let i=await this.col("users").findOneAndUpdate({_id:e},{$set:t},{returnDocument:"after"});return i?this.docToAuthUser(i):null}async deleteUser(e){return (await this.col("users").deleteOne({_id:e})).deletedCount>0}async verifyPassword(e,s){let t=await this.findUserByEmail(e);if(!t)return null;let i=await this.col("users").findOne({email:e.toLowerCase()},{projection:{passwordHash:1}});return i?.passwordHash&&await h__default.default.compare(s,i.passwordHash)?t:null}async hashPassword(e){return h__default.default.hash(e,12)}async createSession(e,s){let t=crypto.randomUUID(),i=crypto.randomBytes(32).toString("base64url"),n=crypto.randomBytes(32).toString("base64url"),o=new Date,u=new Date(o.getTime()+this.sessionTTL*1e3),d={_id:t,userId:e,token:i,refreshToken:n,ipAddress:s?.ipAddress||null,userAgent:s?.userAgent||null,expiresAt:u,createdAt:o};return await this.col("sessions").insertOne(d),this.docToSession(d)}async findSessionByToken(e){let s=await this.col("sessions").findOne({token:e,expiresAt:{$gt:new Date}});return s?this.docToSession(s):null}async findSessionByRefreshToken(e){let s=await this.col("sessions").findOne({refreshToken:e,expiresAt:{$gt:new Date}});return s?this.docToSession(s):null}async deleteSession(e){return (await this.col("sessions").deleteOne({_id:e})).deletedCount>0}async deleteUserSessions(e){return (await this.col("sessions").deleteMany({userId:e})).deletedCount}async hasAnyUsers(){return await this.col("users").countDocuments()>0}async addPasswordToHistory(e,s){await this.col("password_history").insertOne({userId:e,passwordHash:s,createdAt:new Date});}async getPasswordHistory(e,s=5){return (await this.col("password_history").find({userId:e}).sort({createdAt:-1}).limit(s).toArray()).map(i=>i.passwordHash)}async isPasswordInHistory(e,s,t=5){let i=await this.getPasswordHistory(s,t);for(let n of i)if(await h__default.default.compare(e,n))return true;return false}async findAuditLogs(e){let{limit:s=50,offset:t=0,userId:i,action:n,resource:o,resourceId:u,success:d,startDate:c,endDate:f}=e,a={};i&&(a.userId=i),n&&(Array.isArray(n)?a.action={$in:n}:a.action=n),o&&(a.resource=o),u&&(a.resourceId=u),d!==void 0&&(a.success=d),(c||f)&&(a.timestamp={},c&&(a.timestamp.$gte=c),f&&(a.timestamp.$lte=f));let w=await this.col("audit_logs").countDocuments(a);return {logs:(await this.col("audit_logs").find(a).sort({timestamp:-1}).skip(t).limit(s).toArray()).map(r=>({id:r._id,timestamp:r.timestamp,action:r.action,userId:r.userId||void 0,userEmail:r.userEmail||void 0,role:r.role||void 0,resource:r.resource,resourceId:r.resourceId||void 0,changes:r.changes||void 0,ipAddress:r.ipAddress||void 0,userAgent:r.userAgent||void 0,success:r.success,error:r.error||void 0,metadata:r.metadata||void 0})),total:w}}async createAuditLog(e){let s=crypto.randomUUID(),t=new Date;return await this.col("audit_logs").insertOne({_id:s,action:e.action,userId:e.userId||null,userEmail:e.userEmail||null,role:e.role||null,resource:e.resource,resourceId:e.resourceId||null,changes:e.changes||null,ipAddress:e.ipAddress||null,userAgent:e.userAgent||null,success:e.success,error:e.error||null,metadata:e.metadata||null,timestamp:t}),{...e,id:s,timestamp:t}}docToAuthUser(e){return {id:e._id,name:e.name||void 0,email:e.email,passwordHash:e.passwordHash||void 0,role:e.role,tenantId:e.tenantId||void 0,avatar:e.avatar||void 0,emailVerified:e.emailVerified||false,locked:e.locked||false,lastLogin:e.lastLogin?.toISOString?.()||e.lastLogin||void 0,failedLoginAttempts:e.failedLoginAttempts||0,createdAt:e.createdAt?.toISOString?.()||e.createdAt,updatedAt:e.updatedAt?.toISOString?.()||e.updatedAt}}docToSession(e){return {id:e._id,userId:e.userId,token:e.token,refreshToken:e.refreshToken||void 0,expiresAt:e.expiresAt?.toISOString?.()||e.expiresAt,createdAt:e.createdAt?.toISOString?.()||e.createdAt,ipAddress:e.ipAddress||void 0,userAgent:e.userAgent||void 0}}async createEmailVerificationToken(e){let s=crypto.randomBytes(32).toString("hex"),t=new Date(Date.now()+1440*60*1e3);return await this.db.collection("email_verifications").insertOne({userId:new(await import('mongodb')).ObjectId(e),token:s,expiresAt:t,createdAt:new Date}),{token:s,expiresAt:t}}async verifyEmailToken(e){let s=await this.db.collection("email_verifications").findOne({token:e});return s?s.expiresAt<new Date?{success:false,error:"Verification token has expired"}:(await this.db.collection("users").updateOne({_id:s.userId},{$set:{emailVerified:true}}),await this.db.collection("email_verifications").deleteOne({_id:s._id}),{success:true,userId:s.userId.toString()}):{success:false,error:"Invalid verification token"}}async createPasswordResetToken(e){let s=await this.findUserByEmail(e);if(!s)return {token:"",expiresAt:new Date,error:"User not found"};let t=crypto.randomBytes(32).toString("hex"),i=new Date(Date.now()+3600*1e3);return await this.db.collection("password_resets").insertOne({userId:new(await import('mongodb')).ObjectId(s.id),token:t,expiresAt:i,createdAt:new Date}),{token:t,expiresAt:i}}async resetPasswordWithToken(e,s){let t=await this.db.collection("password_resets").findOne({token:e});if(!t)return {success:false,error:"Invalid reset token"};if(t.expiresAt<new Date)return {success:false,error:"Reset token has expired"};if(t.usedAt)return {success:false,error:"Reset token has already been used"};let i=await this.hashPassword(s);return await this.db.collection("users").updateOne({_id:t.userId},{$set:{passwordHash:i,updatedAt:new Date}}),await this.db.collection("password_resets").updateOne({_id:t._id},{$set:{usedAt:new Date}}),await this.db.collection("sessions").deleteMany({userId:t.userId}),{success:true}}};exports.a=p;
1
+ 'use strict';var h=require('bcryptjs'),crypto=require('crypto');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var h__default=/*#__PURE__*/_interopDefault(h);var p=class{db;adapter;prefix;sessionTTL;refreshTokenTTL;indexesEnsured=false;constructor(e){this.db=e.db,this.adapter=e.adapter,this.prefix=e.collectionPrefix||"",this.sessionTTL=e.sessionTTL||86400,this.refreshTokenTTL=e.refreshTokenTTL||604800;}getDatabase(){let e=typeof this.db=="function"?this.db():this.db;if(!e&&this.adapter&&(this.adapter.db?e=this.adapter.db:this.adapter.client&&(this.adapter.db=this.adapter.client.db(this.adapter.database||"kyro_cms"),e=this.adapter.db)),!e)throw new Error("MongoDB database not initialized");return e}col(e){return this.getDatabase().collection(`${this.prefix}${e}`)}async connect(){this.indexesEnsured||await this.ensureIndexes();}async disconnect(){}async ensureIndexes(){await this.col("users").createIndex({email:1},{unique:true}),await this.col("users").createIndex({tenantId:1}),await this.col("users").createIndex({role:1}),await this.col("sessions").createIndex({token:1},{unique:true}),await this.col("sessions").createIndex({refreshToken:1}),await this.col("sessions").createIndex({userId:1}),await this.col("sessions").createIndex({expiresAt:1},{expireAfterSeconds:0}),await this.col("audit_logs").createIndex({timestamp:-1}),await this.col("audit_logs").createIndex({userId:1}),await this.col("audit_logs").createIndex({action:1}),await this.col("audit_logs").createIndex({resource:1}),await this.col("password_history").createIndex({userId:1,createdAt:-1}),await this.col("lockouts").createIndex({userId:1},{unique:true}),await this.col("lockouts").createIndex({lockedUntil:1}),this.indexesEnsured=true;}async createUser(e){let s=crypto.randomUUID(),t=new Date,i=await this.hashPassword(e.password),r={_id:s,name:e.name||null,email:e.email.toLowerCase(),passwordHash:i,role:e.role||"customer",avatar:e.avatar||null,tenantId:e.tenantId||null,emailVerified:false,locked:false,lastLogin:null,failedLoginAttempts:0,createdAt:t,updatedAt:t};return await this.col("users").insertOne(r),this.docToAuthUser(r)}async findUserByEmail(e){let s=await this.col("users").findOne({email:e.toLowerCase()});return s?this.docToAuthUser(s):null}async findUserById(e){let s=await this.col("users").findOne({_id:e});return s?this.docToAuthUser(s):null}async updateUser(e,s){let t={updatedAt:new Date};s.name!==void 0&&(t.name=s.name),s.email!==void 0&&(t.email=s.email),s.passwordHash!==void 0&&(t.passwordHash=s.passwordHash),s.role!==void 0&&(t.role=s.role),s.avatar!==void 0&&(t.avatar=s.avatar),s.tenantId!==void 0&&(t.tenantId=s.tenantId),s.emailVerified!==void 0&&(t.emailVerified=s.emailVerified),s.locked!==void 0&&(t.locked=s.locked),s.lastLogin!==void 0&&(t.lastLogin=s.lastLogin?new Date(s.lastLogin):null),s.failedLoginAttempts!==void 0&&(t.failedLoginAttempts=s.failedLoginAttempts);let i=await this.col("users").findOneAndUpdate({_id:e},{$set:t},{returnDocument:"after"});return i?this.docToAuthUser(i):null}async deleteUser(e){return (await this.col("users").deleteOne({_id:e})).deletedCount>0}async verifyPassword(e,s){let t=await this.findUserByEmail(e);if(!t)return null;let i=await this.col("users").findOne({email:e.toLowerCase()},{projection:{passwordHash:1}});return i?.passwordHash&&await h__default.default.compare(s,i.passwordHash)?t:null}async hashPassword(e){return h__default.default.hash(e,12)}async createSession(e,s){let t=crypto.randomUUID(),i=crypto.randomBytes(32).toString("base64url"),r=crypto.randomBytes(32).toString("base64url"),o=new Date,u=new Date(o.getTime()+this.sessionTTL*1e3),d={_id:t,userId:e,token:i,refreshToken:r,ipAddress:s?.ipAddress||null,userAgent:s?.userAgent||null,expiresAt:u,createdAt:o};return await this.col("sessions").insertOne(d),this.docToSession(d)}async findSessionByToken(e){let s=await this.col("sessions").findOne({token:e,expiresAt:{$gt:new Date}});return s?this.docToSession(s):null}async findSessionByRefreshToken(e){let s=await this.col("sessions").findOne({refreshToken:e,expiresAt:{$gt:new Date}});return s?this.docToSession(s):null}async deleteSession(e){return (await this.col("sessions").deleteOne({_id:e})).deletedCount>0}async deleteUserSessions(e){return (await this.col("sessions").deleteMany({userId:e})).deletedCount}async hasAnyUsers(){return await this.col("users").countDocuments()>0}async addPasswordToHistory(e,s){await this.col("password_history").insertOne({userId:e,passwordHash:s,createdAt:new Date});}async getPasswordHistory(e,s=5){return (await this.col("password_history").find({userId:e}).sort({createdAt:-1}).limit(s).toArray()).map(i=>i.passwordHash)}async isPasswordInHistory(e,s,t=5){let i=await this.getPasswordHistory(s,t);for(let r of i)if(await h__default.default.compare(e,r))return true;return false}async findAuditLogs(e){let{limit:s=50,offset:t=0,userId:i,action:r,resource:o,resourceId:u,success:d,startDate:c,endDate:f}=e,a={};i&&(a.userId=i),r&&(Array.isArray(r)?a.action={$in:r}:a.action=r),o&&(a.resource=o),u&&(a.resourceId=u),d!==void 0&&(a.success=d),(c||f)&&(a.timestamp={},c&&(a.timestamp.$gte=c),f&&(a.timestamp.$lte=f));let g=await this.col("audit_logs").countDocuments(a);return {logs:(await this.col("audit_logs").find(a).sort({timestamp:-1}).skip(t).limit(s).toArray()).map(n=>({id:n._id,timestamp:n.timestamp,action:n.action,userId:n.userId||void 0,userEmail:n.userEmail||void 0,role:n.role||void 0,resource:n.resource,resourceId:n.resourceId||void 0,changes:n.changes||void 0,ipAddress:n.ipAddress||void 0,userAgent:n.userAgent||void 0,success:n.success,error:n.error||void 0,metadata:n.metadata||void 0})),total:g}}async createAuditLog(e){let s=crypto.randomUUID(),t=new Date;return await this.col("audit_logs").insertOne({_id:s,action:e.action,userId:e.userId||null,userEmail:e.userEmail||null,role:e.role||null,resource:e.resource,resourceId:e.resourceId||null,changes:e.changes||null,ipAddress:e.ipAddress||null,userAgent:e.userAgent||null,success:e.success,error:e.error||null,metadata:e.metadata||null,timestamp:t}),{...e,id:s,timestamp:t}}docToAuthUser(e){return {id:e._id,name:e.name||void 0,email:e.email,passwordHash:e.passwordHash||void 0,role:e.role,tenantId:e.tenantId||void 0,avatar:e.avatar||void 0,emailVerified:e.emailVerified||false,locked:e.locked||false,lastLogin:e.lastLogin?.toISOString?.()||e.lastLogin||void 0,failedLoginAttempts:e.failedLoginAttempts||0,createdAt:e.createdAt?.toISOString?.()||e.createdAt,updatedAt:e.updatedAt?.toISOString?.()||e.updatedAt}}docToSession(e){return {id:e._id,userId:e.userId,token:e.token,refreshToken:e.refreshToken||void 0,expiresAt:e.expiresAt?.toISOString?.()||e.expiresAt,createdAt:e.createdAt?.toISOString?.()||e.createdAt,ipAddress:e.ipAddress||void 0,userAgent:e.userAgent||void 0}}async createEmailVerificationToken(e){let s=crypto.randomBytes(32).toString("hex"),t=new Date(Date.now()+1440*60*1e3),i=await import('mongodb');return await this.db.collection("email_verifications").insertOne({userId:new i.ObjectId(e),token:s,expiresAt:t,createdAt:new Date}),{token:s,expiresAt:t}}async verifyEmailToken(e){let s=await this.db.collection("email_verifications").findOne({token:e});return s?s.expiresAt<new Date?{success:false,error:"Verification token has expired"}:(await this.db.collection("users").updateOne({_id:s.userId},{$set:{emailVerified:true}}),await this.db.collection("email_verifications").deleteOne({_id:s._id}),{success:true,userId:s.userId.toString()}):{success:false,error:"Invalid verification token"}}async createPasswordResetToken(e){let s=await this.findUserByEmail(e);if(!s)return {token:"",expiresAt:new Date,error:"User not found"};let t=crypto.randomBytes(32).toString("hex"),i=new Date(Date.now()+3600*1e3),r=await import('mongodb');return await this.db.collection("password_resets").insertOne({userId:new r.ObjectId(s.id),token:t,expiresAt:i,createdAt:new Date}),{token:t,expiresAt:i}}async resetPasswordWithToken(e,s){let t=await this.db.collection("password_resets").findOne({token:e});if(!t)return {success:false,error:"Invalid reset token"};if(t.expiresAt<new Date)return {success:false,error:"Reset token has expired"};if(t.usedAt)return {success:false,error:"Reset token has already been used"};let i=await this.hashPassword(s);return await this.db.collection("users").updateOne({_id:t.userId},{$set:{passwordHash:i,updatedAt:new Date}}),await this.db.collection("password_resets").updateOne({_id:t._id},{$set:{usedAt:new Date}}),await this.db.collection("sessions").deleteMany({userId:t.userId}),{success:true}}};exports.a=p;
@@ -1 +1 @@
1
- 'use strict';var chunkO3OYZQN7_cjs=require('./chunk-O3OYZQN7.cjs'),chunkKJT6VTTN_cjs=require('./chunk-KJT6VTTN.cjs'),chunkHOP4D5XZ_cjs=require('./chunk-HOP4D5XZ.cjs'),chunkWG3UQEV7_cjs=require('./chunk-WG3UQEV7.cjs'),chunkGYQMNXXW_cjs=require('./chunk-GYQMNXXW.cjs'),chunk3Q2WUG63_cjs=require('./chunk-3Q2WUG63.cjs'),chunkBVG6VSAJ_cjs=require('./chunk-BVG6VSAJ.cjs'),m=require('kyro:config');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var m__default=/*#__PURE__*/_interopDefault(m);exports.a=null;var n=null;async function b(){if(!exports.a){if(globalThis.__KYRO_INSTANCE__)try{await globalThis.__KYRO_INSTANCE__.shutdown();}catch{}try{let t=m__default.default.default||m__default.default;exports.a=chunkO3OYZQN7_cjs.z(t),await exports.a.init(),await exports.a.loadSettings();let a=exports.a.db,r;if(a instanceof chunkWG3UQEV7_cjs.c){if(a.dialect==="postgres")r=new chunkGYQMNXXW_cjs.a({db:a.client});else if(a.dialect==="sqlite"){let s=process.env.KYRO_AUTH_DB_PATH||"./data/auth.db";r=new chunkHOP4D5XZ_cjs.a({path:s});}}else if(a instanceof chunkO3OYZQN7_cjs.A){let s=process.env.KYRO_AUTH_DB_PATH||"./data/auth.db";r=new chunkHOP4D5XZ_cjs.a({path:s});}else a instanceof chunk3Q2WUG63_cjs.a&&(r=new chunkBVG6VSAJ_cjs.a({db:a.db}));r?.connect&&await r.connect(),(await chunkKJT6VTTN_cjs.d(r))?.success,typeof exports.a.startWebSocket=="function"&&exports.a.startWebSocket().catch(s=>{console.error("[Kyro] WebSocket auto-start failed:",s);}),globalThis.__KYRO_INSTANCE__=exports.a;}catch(t){throw exports.a=null,n=null,console.error("[Kyro API] Init failed, will retry:",t),t}}}async function O(){n||(n=b()),await n;}var g={graphqlEnabled:false,trpcEnabled:false,wsEnabled:false,requireAuth:false};async function A(t){try{return (await exports.a.db.findOne({collection:"_globals_access-settings",where:{},draft:!0}))?.apiAccess?.[t]??g[t]??!0}catch{return true}}var q=async t=>{if(!exports.a){n||(n=b());try{await Promise.race([n,new Promise((l,o)=>setTimeout(()=>o(new Error("Initialization timeout")),3e4))]);}catch{return new Response(JSON.stringify({error:"Service Unavailable",message:"Kyro CMS is still starting up. Please try again in a moment."}),{status:503,headers:{"Content-Type":"application/json","Retry-After":"5"}})}}let r=new URL(t.request.url).pathname,i=__KYRO_API_PATH__;if(r===`${i}/graphql`&&typeof exports.a.getGraphQL=="function"){if(!await A("graphqlEnabled"))return new Response(JSON.stringify({error:"GraphQL is disabled"}),{status:503,headers:{"Content-Type":"application/json"}});let o=await exports.a.getGraphQL().fetch(t.request,t.locals);return new Response(o.body,o)}if(r.startsWith(`${i}/trpc/`)&&typeof exports.a.getTRPC=="function"){if(!await A("trpcEnabled"))return new Response(JSON.stringify({error:"tRPC is disabled"}),{status:503,headers:{"Content-Type":"application/json"}});let o=await exports.a.getTRPC().fetch(t.request,t.locals);return new Response(o.body,o)}return exports.a.getREST().fetch(t.request,t.locals)};exports.b=O;exports.c=q;
1
+ 'use strict';var chunkMR5BDZKI_cjs=require('./chunk-MR5BDZKI.cjs'),chunk4XZABBHF_cjs=require('./chunk-4XZABBHF.cjs'),chunkHOP4D5XZ_cjs=require('./chunk-HOP4D5XZ.cjs'),chunkWG3UQEV7_cjs=require('./chunk-WG3UQEV7.cjs'),chunkGYQMNXXW_cjs=require('./chunk-GYQMNXXW.cjs'),chunk3Q2WUG63_cjs=require('./chunk-3Q2WUG63.cjs'),chunkQCA3AP3M_cjs=require('./chunk-QCA3AP3M.cjs'),m=require('kyro:config');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var m__default=/*#__PURE__*/_interopDefault(m);exports.a=null;var n=null;async function b(){if(!exports.a){if(globalThis.__KYRO_INSTANCE__)try{await globalThis.__KYRO_INSTANCE__.shutdown();}catch{}try{let t=m__default.default.default||m__default.default;exports.a=chunkMR5BDZKI_cjs.z(t),await exports.a.init(),await exports.a.loadSettings();let a=exports.a.db,r;if(a instanceof chunkWG3UQEV7_cjs.c){if(a.dialect==="postgres")r=new chunkGYQMNXXW_cjs.a({db:a.client});else if(a.dialect==="sqlite"){let s=process.env.KYRO_AUTH_DB_PATH||"./data/auth.db";r=new chunkHOP4D5XZ_cjs.a({path:s});}}else if(a instanceof chunkMR5BDZKI_cjs.A){let s=process.env.KYRO_AUTH_DB_PATH||"./data/auth.db";r=new chunkHOP4D5XZ_cjs.a({path:s});}else a instanceof chunk3Q2WUG63_cjs.a&&(r=new chunkQCA3AP3M_cjs.a({db:a.db}));r?.connect&&await r.connect(),(await chunk4XZABBHF_cjs.d(r))?.success,typeof exports.a.startWebSocket=="function"&&exports.a.startWebSocket().catch(s=>{console.error("[Kyro] WebSocket auto-start failed:",s);}),globalThis.__KYRO_INSTANCE__=exports.a;}catch(t){throw exports.a=null,n=null,console.error("[Kyro API] Init failed, will retry:",t),t}}}async function O(){n||(n=b()),await n;}var g={graphqlEnabled:false,trpcEnabled:false,wsEnabled:false,requireAuth:false};async function A(t){try{return (await exports.a.db.findOne({collection:"_globals_access-settings",where:{},draft:!0}))?.apiAccess?.[t]??g[t]??!0}catch{return true}}var q=async t=>{if(!exports.a){n||(n=b());try{await Promise.race([n,new Promise((l,o)=>setTimeout(()=>o(new Error("Initialization timeout")),3e4))]);}catch{return new Response(JSON.stringify({error:"Service Unavailable",message:"Kyro CMS is still starting up. Please try again in a moment."}),{status:503,headers:{"Content-Type":"application/json","Retry-After":"5"}})}}let r=new URL(t.request.url).pathname,i=__KYRO_API_PATH__;if(r===`${i}/graphql`&&typeof exports.a.getGraphQL=="function"){if(!await A("graphqlEnabled"))return new Response(JSON.stringify({error:"GraphQL is disabled"}),{status:503,headers:{"Content-Type":"application/json"}});let o=await exports.a.getGraphQL().fetch(t.request,t.locals);return new Response(o.body,o)}if(r.startsWith(`${i}/trpc/`)&&typeof exports.a.getTRPC=="function"){if(!await A("trpcEnabled"))return new Response(JSON.stringify({error:"tRPC is disabled"}),{status:503,headers:{"Content-Type":"application/json"}});let o=await exports.a.getTRPC().fetch(t.request,t.locals);return new Response(o.body,o)}return exports.a.getREST().fetch(t.request,t.locals)};exports.b=O;exports.c=q;
@@ -1,4 +1,4 @@
1
- import {l,j,k}from'./chunk-6J27P5D6.js';import {a as a$2}from'./chunk-IETGL7WJ.js';import {a as a$8}from'./chunk-IKOXCJYO.js';import {a as a$1}from'./chunk-NRLIGDYF.js';import {d,a as a$4,b as b$1,c as c$2}from'./chunk-FVZ5RFLO.js';import {d as d$1,i,j as j$1,f,e as e$1,g}from'./chunk-HLSB2MCK.js';import {e,c as c$1}from'./chunk-DKESD4HI.js';import {a as a$6}from'./chunk-RHCWCG3O.js';import {a as a$7}from'./chunk-GXVCCKOL.js';import {a as a$5}from'./chunk-4RMFCTWH.js';import {a as a$3}from'./chunk-KDNYHLD2.js';import {a,b,c}from'./chunk-5J6HXUF6.js';import mr,{randomBytes,createHash,createHmac}from'crypto';import {createStorage}from'unstorage';import yr from'unstorage/drivers/fs';import {Hono}from'hono';import {verify,sign}from'hono/jwt';import ze,{join,resolve,basename,extname}from'path';import {existsSync,readFileSync}from'fs';import {mkdir,readdir,stat,rename,unlink,writeFile}from'fs/promises';import Er from'process';import {S3Client,ListObjectsV2Command,DeleteObjectsCommand,DeleteObjectCommand,PutObjectCommand,HeadObjectCommand,CopyObjectCommand}from'@aws-sdk/client-s3';import {NodeHttpHandler}from'@smithy/node-http-handler';import {Readable}from'stream';import {Client}from'basic-ftp';import {zodToJsonSchema}from'zod-to-json-schema';function Qr(d){et=d;}async function Nt(){if(et)try{let d=await et.findOne({collection:"_globals_system",where:{}});if(d){de={appSecret:d.appSecret||null,encryptionKey:d.encryptionKey||null,sessionConfig:d.sessionMaxAge||d.maxSessionsPerUser?{maxAge:(d.sessionMaxAge||7)*24*60*60*1e3,maxSessionsPerUser:d.maxSessionsPerUser||3}:null};return}}catch{}de={appSecret:process.env.APP_SECRET||"development-secret-key",encryptionKey:null,sessionConfig:null};}function gr(){return de?.appSecret?de.appSecret:process.env.APP_SECRET||"development-secret-key"}function es(){if(de?.encryptionKey)return de.encryptionKey;let d=gr();return mr.createHash("sha256").update(d).digest("hex")}function Ot(){return de?.sessionConfig?de.sessionConfig:{maxAge:10080*60*1e3,maxSessionsPerUser:3}}var et,de,tt=a(()=>{et=null,de=null;});var Bt={};b(Bt,{SESSION_CONFIG:()=>ie,clearSessionCookie:()=>it,createSession:()=>ot,deleteSession:()=>ve,getClientIp:()=>st,getCurrentUser:()=>ee,getSession:()=>fe,getSessionIdFromRequest:()=>se,getUserSessions:()=>Ie,invalidateAllUserSessions:()=>Ar,refreshSession:()=>_e,setSessionCookie:()=>at,updateSessionName:()=>lt,validateSession:()=>Le});async function ce(){return $e||($e=createStorage({driver:yr({base:".astro/sessions"})}),$e)}function wr(){return mr.randomUUID()}function Mt(d){let e="Unknown",t="Unknown",s="Unknown";return d.includes("Firefox")?e="Firefox":d.includes("Edg/")?e="Edge":d.includes("Chrome")?e="Chrome":d.includes("Safari")&&!d.includes("Chrome")&&(e="Safari"),d.includes("iPhone")?(t="iPhone",s="iOS"):d.includes("iPad")?(t="iPad",s="iOS"):d.includes("Mac")?(t="MacBook",s="macOS"):d.includes("Windows")?(t="Windows PC",s="Windows"):d.includes("Linux")?(t="Linux PC",s="Linux"):d.includes("Android")&&(t="Android Phone",s="Android"),{browser:e,device:t,platform:s}}function br(d){if(!d?.userAgent)return "Session";let{browser:e,device:t}=Mt(d.userAgent);return `${t} - ${e}`}function se(d){let e=d.headers.get("Cookie");return e&&Object.fromEntries(e.split("; ").map(s=>s.split("=")))[rt]||null}function st(d){let e=d.headers.get("x-forwarded-for");return e?e.split(",")[0].trim():d.headers.get("x-real-ip")||"unknown"}function at(d,e){let s=process.env.NODE_ENV==="production"?"Secure; ":"",n=new Headers(d.headers);return n.append("Set-Cookie",`${rt}=${e}; HttpOnly; Path=/; Max-Age=${ie.absoluteMaxAge/1e3}; SameSite=Strict; ${s}`),new Response(d.body,{status:d.status,statusText:d.statusText,headers:n})}function it(d){let t=process.env.NODE_ENV==="production"?"Secure; ":"",s=new Headers(d.headers);return s.append("Set-Cookie",`${rt}=; HttpOnly; Path=/; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Strict; ${t}`),new Response(d.body,{status:d.status,statusText:d.statusText,headers:s})}async function Ce(d){return await(await ce()).getItem(`user:${d}`)||[]}async function nt(d,e){let t=await ce();e.length>0?await t.setItem(`user:${d}`,e):await t.removeItem(`user:${d}`);}async function ot(d,e){let t=await ce(),s=await Ce(d.id);for(;s.length>=ie.maxSessionsPerUser;){let x=s.shift();x&&await t.removeItem(`session:${x}`);}let n=wr(),c=Date.now(),l=e?.headers.get("user-agent"),u=e?st(e):"unknown",f=l?{userAgent:l,ip:u,...Mt(l)}:{ip:u},y={id:n,userId:d.id,email:d.email,role:d.role,tenantId:d.tenantId,permissions:d.permissions,createdAt:c,expiresAt:c+ie.absoluteMaxAge,lastActivityAt:c,deviceInfo:f,sessionName:br(f)};return await t.setItem(`session:${n}`,y,{ttl:Math.floor(ie.absoluteMaxAge/1e3)}),s.push(n),await nt(d.id,s),n}async function fe(d){return await(await ce()).getItem(`session:${d}`)||null}async function Le(d){let e=await fe(d);return e?e.expiresAt<Date.now()?(await ve(d),{valid:false,reason:"Session expired"}):{valid:true}:{valid:false,reason:"Session not found"}}async function _e(d,e){let t=await ce(),s=await fe(d);if(!s)return null;let n=Date.now(),c=s.expiresAt-n,l=s.deviceInfo;if(e){let y=st(e);y!==s.deviceInfo?.ip&&(l={...s.deviceInfo,ip:y});}let u={...s,lastActivityAt:n,expiresAt:c<ie.refreshThreshold?n+ie.absoluteMaxAge:s.expiresAt,deviceInfo:l},f=c<ie.refreshThreshold?ie.absoluteMaxAge:void 0;return await t.setItem(`session:${d}`,u,f?{ttl:Math.floor(f/1e3)}:void 0),u}async function ve(d){let e=await ce(),t=await fe(d);if(t){let n=(await Ce(t.userId)).filter(c=>c!==d);await nt(t.userId,n);}await e.removeItem(`session:${d}`),await e.removeItem(`activity:${d}`);}async function Ar(d){let e=await Ce(d),t=await ce();for(let s of e)await t.removeItem(`session:${s}`),await t.removeItem(`activity:${s}`);await nt(d,[]);}async function Ie(d,e){let t=await Ce(d),s=[];for(let n of t){let c=await fe(n);c&&s.push({id:c.id,sessionName:c.sessionName||"Session",deviceInfo:c.deviceInfo,createdAt:c.createdAt,lastActivityAt:c.lastActivityAt,currentSession:c.id===e});}return s.sort((n,c)=>c.lastActivityAt-n.lastActivityAt),s}async function lt(d,e){let t=await fe(d);return t?(await(await ce()).setItem(`session:${d}`,{...t,sessionName:e}),true):false}async function ee(d){let e=se(d);if(!e||!(await Le(e)).valid)return null;let s=await fe(e);return s?(await _e(e,d),s):null}var Ft,ie,rt,$e,Ne=a(()=>{tt();Ft=Ot(),ie={absoluteMaxAge:Ft.maxAge,maxSessionsPerUser:Ft.maxSessionsPerUser,refreshThreshold:300*1e3,activityDebounce:30*1e3,pollInterval:30*1e3},rt="kyro-session",$e=null;});function ge(d,e){for(let t of d){if(t.name===e)return t;if(t.type==="group"||t.type==="array"){let s=ge(t.fields||[],e);if(s)return s}if(t.type==="blocks")for(let s of t.blocks||[]){let n=ge(s.fields||[],e);if(n)return n}if(t.type==="tabs")for(let s of t.tabs||[]){let n=ge(s.fields||[],e);if(n)return n}if(t.type==="collapsible"||t.type==="row"){let s=ge(t.fields||[],e);if(s)return s}}return null}Ne();function zt(d){let{db:t,userLookup:s}=d;return async function(c){let l=f(c);if(l&&t){let f=await e$1(l,t,s);if(f.valid&&f.user)return {user:f.user,tenantContext:Kt(f.user),apiKeyContext:g(f),status:200,authType:"apikey"};if(f.error)return {status:401,error:f.error}}let u=se(c);if(u)try{let f=await Le(u);if(!f.valid)return {status:401,error:f.reason||"Session invalid"};let y=await ee(c);if(y){let x=s?await s(y.userId):null;if(x)return {user:x,tenantContext:Kt(x),status:200,authType:"session"}}}catch(f){console.error("Session validation error:",f);}return {status:401,error:"Authentication required"}}}function Kt(d){return {tenantId:d.tenantId||"default",userId:d.id||"anonymous",role:d.role||"guest",roles:[d.role||"guest"],permissions:[],isSuperAdmin:d.role==="super_admin"}}tt();var Oe=class{storage=new Map;userStorage=new Map;limits;userLimits;constructor(e,t){this.limits={...xr,...e},this.userLimits=t||{"user:api":{window:6e4,max:500},"user:write":{window:36e5,max:100}};}getKey(e,t){return `${e}:${t}`}getUserKey(e,t,s){return `user:${e}:${t}:${s}`}cleanupOldEntries(e,t){let n=Date.now()-t;for(;e.length>0&&e[0].timestamp<n;)e.shift();}async check(e,t){let s=this.limits[e]||this.limits["api:general"],n=this.getKey(e,t),c=this.storage.get(n);c||(c=[],this.storage.set(n,c)),this.cleanupOldEntries(c,s.window);let l=Date.now(),u=c.reduce((f,y)=>f+y.count,0);if(c.push({timestamp:l,count:1}),u>=s.max){let y=c.reduce((x,h)=>x.timestamp<h.timestamp?x:h,c[0]).timestamp+s.window;return {allowed:false,remaining:0,resetAt:y,retryAfter:Math.ceil((y-l)/1e3)}}return {allowed:true,remaining:s.max-u-1,resetAt:l+s.window}}async checkUser(e,t,s){let n=this.userLimits[e]||this.userLimits["user:api"],c=this.userStorage.get(t),l=[];c?l=c.get(this.getKey(e,s))||[]:(this.userStorage.has(t)||this.userStorage.set(t,new Map),this.userStorage.get(t).set(this.getKey(e,s),l)),this.cleanupOldEntries(l,n.window);let u=Date.now(),f=l.reduce((y,x)=>y+x.count,0);if(l.push({timestamp:u,count:1}),f>=n.max){let x=l.reduce((h,E)=>h.timestamp<E.timestamp?h:E,l[0]).timestamp+n.window;return {allowed:false,remaining:0,resetAt:x,retryAfter:Math.ceil((x-u)/1e3)}}return {allowed:true,remaining:n.max-f-1,resetAt:u+n.window}}async reset(e,t){let s=this.getKey(e,t);this.storage.delete(s);}async resetUser(e,t,s){let n=this.userStorage.get(t);if(n){let c=this.getKey(e,s);n.delete(c);}}async getStatus(e,t){let s=this.limits[e]||this.limits["api:general"],n=this.getKey(e,t),c=this.storage.get(n);c||(c=[],this.storage.set(n,c)),this.cleanupOldEntries(c,s.window);let l=Date.now(),u=c.reduce((f,y)=>f+y.count,0);return {count:u,limit:s.max,remaining:Math.max(0,s.max-u),resetAt:l+s.window}}setLimit(e,t){this.limits[e]=t;}setUserLimit(e,t){this.userLimits[e]=t;}},xr={"auth:login":{window:9e5,max:5},"auth:register":{window:36e5,max:3},"auth:forgot":{window:36e5,max:3},"auth:reset":{window:36e5,max:5},"auth:verify":{window:36e5,max:5},"api:general":{window:6e4,max:100},"api:authenticated":{window:6e4,max:200}};var dt={retentionDays:30};var Wt=class{redis;prefix;retentionDays;constructor(e,t=30,s="kyro:audit:"){this.redis=e,this.prefix=s,this.retentionDays=t;}async log(e){let t=randomBytes(16).toString("hex"),s=new Date,n={...e,id:t,timestamp:s},c=this.getKeyForDate(s),l=`${this.prefix}log:${t}`;await this.redis.hset(l,this.serializeLog(n)),await this.redis.expire(l,this.retentionDays*24*60*60+3600),await this.redis.zadd(c,s.getTime(),t),await this.redis.expire(c,this.retentionDays*24*60*60+3600);let u=e.userId?`${this.prefix}user:${e.userId}`:null;return u&&(await this.redis.zadd(u,s.getTime(),t),await this.redis.expire(u,this.retentionDays*24*60*60+3600)),t}async get(e){let t=`${this.prefix}log:${e}`,s=await this.redis.hgetall(t);return !s||Object.keys(s).length===0?null:this.deserializeLog(s)}async query(e={}){let{limit:t=50,offset:s=0}=e,n=[];if(e.userId)n.push(`${this.prefix}user:${e.userId}`);else if(e.startDate||e.endDate)n=this.getKeysForDateRange(e.startDate,e.endDate);else {let f=new Date;n=this.getKeysForDateRange(new Date(f.getTime()-this.retentionDays*24*60*60*1e3),f);}let c=[];for(let f of n){let y=await this.redis.zrange(f,0,-1,"WITHSCORES");for(let x=0;x<y.length;x+=2)c.push([y[x],parseInt(y[x+1],10)]);}c.sort((f,y)=>y[1]-f[1]);let l=c.length;c=c.slice(s,s+t);let u=[];for(let[f]of c){let y=await this.get(f);y&&this.matchesFilter(y,e)&&u.push(y);}return {logs:u,total:l}}async getRecent(e=50){let t=[],s=new Date,n=this.getKeysForDateRange(new Date(s.getTime()-10080*60*1e3),s),c=[];for(let l of n){let u=await this.redis.zrange(l,0,-1,"WITHSCORES");for(let f=0;f<u.length;f+=2)c.push([u[f],parseInt(u[f+1],10)]);}c.sort((l,u)=>u[1]-l[1]);for(let[l]of c.slice(0,e)){let u=await this.get(l);u&&t.push(u);}return t}async getUserActivity(e,t=50){let s=`${this.prefix}user:${e}`,n=await this.redis.zrange(s,0,t-1),c=[];for(let l of n){let u=await this.get(l);u&&c.push(u);}return c}async getStats(e,t){let s=this.getKeysForDateRange(e||new Date(Date.now()-2592e6),t||new Date),n={},c=0,l=0,u=0,f=new Set;for(let y of s){let x=await this.redis.zrange(y,0,-1);for(let h of x){let E=await this.get(h);E&&(c++,n[E.action]=(n[E.action]||0)+1,E.success&&u++,E.action==="login_failed"&&l++,E.userId&&f.add(E.userId));}}return {totalEvents:c,byAction:n,successRate:c>0?u/c:1,failedLogins:l,uniqueUsers:f}}async cleanup(){let e=Date.now()-this.retentionDays*24*60*60*1e3,t=await this.redis.keys(`${this.prefix}date:*`),s=0;for(let n of t){let c=await this.redis.zrangebyscore(n,0,e);for(let l of c)await this.redis.del(`${this.prefix}log:${l}`),s++;await this.redis.zremrangebyscore(n,0,e);}return s}getKeyForDate(e){let t=e.getFullYear(),s=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return `${this.prefix}date:${t}-${s}-${n}`}getKeysForDateRange(e,t){let s=[],n=e||new Date(Date.now()-this.retentionDays*24*60*60*1e3),c=t||new Date,l=new Date(n);for(;l<=c;)s.push(this.getKeyForDate(l)),l.setDate(l.getDate()+1);return s}matchesFilter(e,t){return !(t.action&&!(Array.isArray(t.action)?t.action:[t.action]).includes(e.action)||t.resource&&e.resource!==t.resource||t.resourceId&&e.resourceId!==t.resourceId||t.success!==void 0&&e.success!==t.success)}serializeLog(e){let t={id:e.id,timestamp:new Date(e.timestamp).toISOString(),action:e.action,resource:e.resource,success:e.success?"1":"0"};return e.userId&&(t.userId=e.userId),e.userEmail&&(t.userEmail=e.userEmail),e.role&&(t.role=e.role),e.resourceId&&(t.resourceId=e.resourceId),e.ipAddress&&(t.ipAddress=e.ipAddress),e.userAgent&&(t.userAgent=e.userAgent),e.error&&(t.error=e.error),e.changes&&(t.changes=JSON.stringify(e.changes)),e.metadata&&(t.metadata=JSON.stringify(e.metadata)),t}deserializeLog(e){return {id:e.id,timestamp:new Date(e.timestamp),action:e.action,userId:e.userId,userEmail:e.userEmail,role:e.role,resource:e.resource,resourceId:e.resourceId,ipAddress:e.ipAddress,userAgent:e.userAgent,success:e.success==="1",error:e.error,changes:e.changes?JSON.parse(e.changes):void 0,metadata:e.metadata?JSON.parse(e.metadata):void 0}}};function gs(d){return {ipAddress:d.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||d.headers.get("x-real-ip")||"unknown",userAgent:d.headers.get("user-agent")||"unknown"}}var Ht=class{logs=[];retentionDays;constructor(e=dt.retentionDays){this.retentionDays=e;}async log(e){let t=randomBytes(16).toString("hex"),n={...e,id:t,timestamp:new Date};return this.logs.push(n),this.cleanupOldLogs(),t}async get(e){return this.logs.find(t=>t.id===e)||null}async query(e={}){let{limit:t=50,offset:s=0}=e,n=[...this.logs];if(e.userId&&(n=n.filter(y=>y.userId===e.userId)),e.action){let y=Array.isArray(e.action)?e.action:[e.action];n=n.filter(x=>y.includes(x.action));}e.resource&&(n=n.filter(y=>y.resource===e.resource)),e.resourceId&&(n=n.filter(y=>y.resourceId===e.resourceId)),e.success!==void 0&&(n=n.filter(y=>y.success===e.success));let c=e.startDate,l=e.endDate;c!==void 0&&(n=n.filter(y=>y.timestamp>=c)),l!==void 0&&(n=n.filter(y=>y.timestamp<=l)),n.sort((y,x)=>x.timestamp.getTime()-y.timestamp.getTime());let u=n.length;return {logs:n.slice(s,s+t),total:u}}async getRecent(e=50){let t=new Date(Date.now()-6048e5);return this.logs.filter(n=>n.timestamp>=t).sort((n,c)=>c.timestamp.getTime()-n.timestamp.getTime()).slice(0,e)}async getUserActivity(e,t=50){return this.logs.filter(n=>n.userId===e).sort((n,c)=>c.timestamp.getTime()-n.timestamp.getTime()).slice(0,t)}async getStats(e,t){let s=e||new Date(Date.now()-2592e6),n=t||new Date,c=this.logs.filter(h=>h.timestamp>=s&&h.timestamp<=n),l={},u=0,f=0,y=0,x=new Set;for(let h of c){u++;let E=h.action;l[E]=(l[E]||0)+1,h.success&&y++,h.action==="login_failed"&&f++,h.userId&&x.add(h.userId);}return {totalEvents:u,byAction:l,successRate:u>0?y/u:1,failedLogins:f,uniqueUsers:x}}async cleanup(){let e=new Date(Date.now()-this.retentionDays*24*60*60*1e3),t=this.logs.length;return this.logs=this.logs.filter(s=>s.timestamp>=e),t-this.logs.length}cleanupOldLogs(){let e=new Date(Date.now()-this.retentionDays*24*60*60*1e3);this.logs.length;this.logs=this.logs.filter(s=>s.timestamp>=e);}};Ne();var Me=class{authAdapter;email;passwordPolicy;lockout;rateLimiter;auditLogger;baseUrl;emailVerificationRequired;constructor(e){this.authAdapter=e.redis,this.email=e.email,this.passwordPolicy=e.passwordPolicy||new l,this.lockout=e.lockout,this.rateLimiter=e.rateLimiter,this.auditLogger=e.auditLogger,this.baseUrl=e.baseUrl||"http://localhost:4321",this.emailVerificationRequired=e.emailVerificationRequired??true;}getBaseUrl(e){if(e)try{let t=e.headers.get("x-forwarded-proto")||(e.url.startsWith("https")?"https":"http"),s=e.headers.get("x-forwarded-host")||e.headers.get("host");return s?`${t}://${s}`:new URL(e.url).origin}catch{}return process.env.KYRO_BASE_URL||process.env.SERVER_URL||process.env.PUBLIC_URL||process.env.SITE_URL||this.baseUrl||"http://localhost:4321"}async register(e){let{ipAddress:t,userAgent:s}=a$1(e);if(this.rateLimiter){let n=await this.rateLimiter.check("auth:register",t);if(!n.allowed)return this.rateLimitResponse(n)}try{let n=await e.json();if(!n.email||!n.password)return this.errorResponse("Email and password are required",400);if(n.password!==n.confirmPassword)return this.errorResponse("Passwords do not match",400);let c=this.passwordPolicy.validate(n.password);if(!c.valid)return this.errorResponse(c.errors.join(". "),400);let l=await this.authAdapter.findUserByEmail(n.email);if(l){if(!l.emailVerified&&this.emailVerificationRequired&&this.email){let y=(await this.authAdapter.createEmailVerificationToken?.(l.id))?.token||randomBytes(32).toString("hex"),h=`${this.getBaseUrl(e)}/admin/auth/verify-email?token=${y}`,E=this.email.getTemplates().verifyEmail(h,n.email);return await this.email.send({to:n.email,...E}),this.jsonResponse({success:!0,message:"An unverified account already exists with this email. We have resent the confirmation link to your inbox.",requiresVerification:!0},200)}return this.errorResponse("Email already registered",400)}let u=await this.authAdapter.createUser({email:n.email,password:n.password,role:n.role||"customer",tenantId:n.tenantId});if(this.emailVerificationRequired&&this.email){let f=randomBytes(32).toString("hex"),x=`${this.getBaseUrl(e)}/admin/auth/verify-email?token=${f}`;await this.authAdapter.createSession(u.id,{ipAddress:t,userAgent:s});let h=this.email.getTemplates().verifyEmail(x,n.email);await this.email.send({to:n.email,...h});}return this.auditLogger&&await this.auditLogger.log({action:"register",userId:u.id,userEmail:u.email,resource:"auth",ipAddress:t,userAgent:s,success:!0}),this.jsonResponse({success:!0,message:"Registration successful",user:this.sanitizeUser(u),requiresVerification:this.emailVerificationRequired&&!!this.email},201)}catch(n){return console.error("[AuthRoutes.register] Registration error:",n),this.errorResponse("Registration failed",500)}}async login(e){let{ipAddress:t,userAgent:s}=a$1(e);if(this.rateLimiter){let n=await this.rateLimiter.check("auth:login",t);if(!n.allowed)return this.rateLimitResponse(n)}try{let n=await e.json();if(!n.email||!n.password)return this.errorResponse("Email and password are required",400);let c=await this.authAdapter.findUserByEmail(n.email);if(!c)return await this.recordFailedLogin(t,s),this.errorResponse("Invalid credentials",401);if(c.locked)return this.auditLogger&&await this.auditLogger.log({action:"login_failed",userId:c.id,userEmail:c.email,resource:"auth",ipAddress:t,userAgent:s,success:!1,error:"Account locked"}),this.errorResponse("Account locked. Contact an administrator.",403);if(this.lockout){let x=await this.lockout.checkLockout(c.id);if(x.locked)return this.auditLogger&&await this.auditLogger.log({action:"login_failed",userId:c.id,userEmail:c.email,resource:"auth",ipAddress:t,userAgent:s,success:!1,error:"Account locked"}),this.errorResponse(`Account locked. Try again in ${Math.ceil((x.lockedUntil.getTime()-Date.now())/6e4)} minutes`,423)}let l=await this.authAdapter.verifyPassword(n.email,n.password);if(!l)return await this.recordFailedLogin(t,s,c.id,c.email),this.errorResponse("Invalid credentials",401);if(this.emailVerificationRequired&&l.emailVerified===!1){if(this.email){let h=(await this.authAdapter.createEmailVerificationToken?.(l.id))?.token||randomBytes(32).toString("hex"),_=`${this.getBaseUrl(e)}/admin/auth/verify-email?token=${h}`,R=this.email.getTemplates().verifyEmail(_,l.email);await this.email.send({to:l.email,...R});}return this.errorResponse("Your email address is not verified yet. We have sent a new confirmation link to your email inbox.",403)}this.lockout&&await this.lockout.resetAttempts(c.id),this.auditLogger&&await this.auditLogger.log({action:"login",userId:c.id,userEmail:c.email,role:c.role,resource:"auth",ipAddress:t,userAgent:s,success:!0}),await this.authAdapter.updateUser(c.id,{lastLogin:new Date().toISOString()});let u=await ot({id:c.id,email:c.email,role:c.role,tenantId:c.tenantId}),f={success:!0,user:this.sanitizeUser(c)},y=this.jsonResponse(f);return at(y,u)}catch(n){return console.error("[Auth] Login error:",n),this.errorResponse("Login failed",500)}}async logout(e){let t=se(e);if(!t)return this.errorResponse("No session to logout",401);let{ipAddress:s,userAgent:n}=a$1(e);try{let c=await ee(e);c&&(await ve(t),this.auditLogger&&await this.auditLogger.log({action:"logout",userId:c.userId,userEmail:c.email,resource:"auth",ipAddress:s,userAgent:n,success:!0}));let l=this.jsonResponse({success:!0,message:"Logged out successfully"});return it(l)}catch{return this.errorResponse("Logout failed",500)}}async refresh(e){try{let t=se(e);if(!t)return this.errorResponse("Not authenticated",401);let s=await _e(t,e);return s?this.jsonResponse({success:!0,expiresAt:s.expiresAt}):this.errorResponse("Session not found",404)}catch(t){return console.error("[Auth] Session refresh error:",t),this.errorResponse("Session refresh failed",500)}}async me(e){let t=await ee(e);return t?this.jsonResponse({success:true,user:{id:t.userId,email:t.email,role:t.role,tenantId:t.tenantId}}):this.errorResponse("Not authenticated",401)}async changePassword(e){let t=await ee(e);if(!t)return this.errorResponse("Not authenticated",401);let{ipAddress:s,userAgent:n}=a$1(e);try{let c=await e.json(),{currentPassword:l,newPassword:u,confirmPassword:f}=c;if(!l||!u)return this.errorResponse("Current and new password required",400);if(u!==f)return this.errorResponse("Passwords do not match",400);let y=this.passwordPolicy.validate(u);if(!y.valid)return this.errorResponse(y.errors.join(". "),400);let x=await this.authAdapter.findUserById(t.userId);if(!x)return this.errorResponse("User not found",404);if(!(x.passwordHash?await this.authAdapter.verifyPassword(l,x.passwordHash):!1))return this.errorResponse("Current password is incorrect",401);let E=await this.authAdapter.getPasswordHistory?.(x.id,5);if(await this.authAdapter.isPasswordInHistory?.(u,x.id,5))return this.errorResponse("Password was recently used. Please choose a different password",400);let R=await this.authAdapter.hashPassword(u);if(x.passwordHash&&await this.authAdapter.addPasswordToHistory?.(x.id,x.passwordHash),await this.authAdapter.updateUser(x.id,{passwordHash:R}),await this.authAdapter.deleteUserSessions(x.id),this.email&&this.email.getTemplates){let q=this.email.getTemplates().passwordChanged(x.email);await this.email.send({to:x.email,...q});}return this.auditLogger&&await this.auditLogger.log({action:"password_change",userId:x.id,userEmail:x.email,resource:"auth",ipAddress:s,userAgent:n,success:!0}),this.jsonResponse({success:!0,message:"Password changed successfully"})}catch{return this.errorResponse("Password change failed",500)}}async forgotPassword(e){let{ipAddress:t,userAgent:s}=a$1(e);if(this.rateLimiter){let n=await this.rateLimiter.check("auth:forgot",t);if(!n.allowed)return this.rateLimitResponse(n)}try{let n=await e.json(),{email:c}=n;if(!c)return this.errorResponse("Email required",400);let l=await this.authAdapter.findUserByEmail(c);if(!l)return this.jsonResponse({success:!0,message:"If the email exists, a reset link has been sent"});if(this.email){let u=randomBytes(32).toString("hex");if(this.authAdapter.createPasswordResetToken){let h=await this.authAdapter.createPasswordResetToken(l.email);h.token&&(u=h.token);}let y=`${this.getBaseUrl(e)}/admin/auth/reset-password?token=${u}`,x=this.email.getTemplates().resetPassword(y,l.email);await this.email.send({to:l.email,...x});}return this.auditLogger&&await this.auditLogger.log({action:"password_reset",userId:l.id,userEmail:l.email,resource:"auth",ipAddress:t,userAgent:s,success:!0}),this.jsonResponse({success:!0,message:"If the email exists, a reset link has been sent"})}catch{return this.errorResponse("Password reset request failed",500)}}async resetPassword(e){let{ipAddress:t,userAgent:s}=a$1(e);if(this.rateLimiter){let n=await this.rateLimiter.check("auth:reset",t);if(!n.allowed)return this.rateLimitResponse(n)}try{let n=await e.json(),{token:c,newPassword:l,confirmPassword:u}=n;if(!c||!l)return this.errorResponse("Reset token and new password are required",400);if(l!==u)return this.errorResponse("Passwords do not match",400);let f=this.passwordPolicy.validate(l);if(!f.valid)return this.errorResponse(f.errors.join(". "),400);if(this.authAdapter.resetPasswordWithToken){let y=await this.authAdapter.resetPasswordWithToken(c,l);if(!y.success)return this.errorResponse(y.error||"Password reset failed or token expired",400)}return this.jsonResponse({success:!0,message:"Password reset successful. You can now log in with your new password."})}catch(n){return console.error("[AuthRoutes.resetPassword] Error:",n),this.errorResponse("Password reset failed",500)}}async verifyEmail(e){let s=new URL(e.url).searchParams.get("token");if(!s)return this.errorResponse("Verification token required",400);try{if(this.authAdapter.verifyEmailToken){let n=await this.authAdapter.verifyEmailToken(s);if(!n.success)return this.errorResponse(n.error||"Invalid or expired verification token",400);if(n.userId&&this.email){let c=await this.authAdapter.findUserById(n.userId);if(c){let l=this.email.getTemplates().welcome(c.email);await this.email.send({to:c.email,...l});}}}return this.jsonResponse({success:!0,message:"Email address verified successfully"})}catch(n){return console.error("[AuthRoutes.verifyEmail] Error:",n),this.errorResponse("Email verification failed",500)}}async recordFailedLogin(e,t,s,n){this.lockout&&await this.lockout.recordFailedAttempt(s||e),this.auditLogger&&await this.auditLogger.log({action:"login_failed",userId:s,userEmail:n,resource:"auth",ipAddress:e,userAgent:t,success:false,error:"Invalid credentials"});}sanitizeUser(e){let{passwordHash:t,...s}=e;return s}jsonResponse(e,t=200){return new Response(JSON.stringify(e),{status:t,headers:{"Content-Type":"application/json","Cache-Control":"no-store, no-cache, must-revalidate, max-age=0"}})}async listSessions(e){let t=await ee(e);if(!t)return this.errorResponse("Not authenticated",401);try{let s=await Ie(t.userId,se(e)??void 0);return this.jsonResponse({sessions:s})}catch(s){return console.error("[AuthRoutes.listSessions] Error:",s),this.errorResponse("Failed to list sessions",500)}}async revokeSession(e,t){let s=await ee(e);if(!s)return this.errorResponse("Not authenticated",401);try{let c=(await Ie(s.userId)).find(l=>l.id===t);return c?c.currentSession?this.errorResponse("Cannot revoke current session",400):(await ve(t),this.jsonResponse({success:!0,message:"Session revoked"})):this.errorResponse("Session not found",404)}catch(n){return console.error("[AuthRoutes.revokeSession] Error:",n),this.errorResponse("Failed to revoke session",500)}}async revokeOtherSessions(e){let t=await ee(e);if(!t)return this.errorResponse("Not authenticated",401);try{let s=await Ie(t.userId),n=se(e);for(let c of s)c.currentSession||await ve(c.id);return this.jsonResponse({success:!0,message:"Other sessions revoked"})}catch(s){return console.error("[AuthRoutes.revokeOtherSessions] Error:",s),this.errorResponse("Failed to revoke sessions",500)}}async renameSession(e,t){let s=await ee(e);if(!s)return this.errorResponse("Not authenticated",401);try{if(!(await Ie(s.userId)).find(f=>f.id===t))return this.errorResponse("Session not found",404);let l=await e.json(),{name:u}=l;return !u||typeof u!="string"||u.trim().length===0?this.errorResponse("Invalid session name",400):(await lt(t,u.trim()),this.jsonResponse({success:!0,message:"Session renamed"}))}catch(n){return console.error("[AuthRoutes.renameSession] Error:",n),this.errorResponse("Failed to rename session",500)}}async refreshSession(e){let t=se(e);if(!t)return this.errorResponse("No session",401);try{let s=await(Ne(),c(Bt)).refreshSession(t,e);return s?this.jsonResponse({success:!0,expiresAt:s.expiresAt}):this.errorResponse("Session not found",404)}catch(s){return console.error("[AuthRoutes.refreshSession] Error:",s),this.errorResponse("Failed to refresh session",500)}}errorResponse(e,t){return new Response(JSON.stringify({success:false,error:e}),{status:t,headers:{"Content-Type":"application/json"}})}async rateLimitResponse(e){return new Response(JSON.stringify({success:false,error:"Too many requests",retryAfter:e.retryAfter}),{status:429,headers:{"Content-Type":"application/json","Retry-After":String(e.retryAfter||60)}})}};function he(d){let{uploadDir:e=join(Er.cwd(),"public","uploads"),baseUrl:t="/uploads"}=d;async function s(l){existsSync(l)||await mkdir(l,{recursive:true});}function n(l){let u=extname(l).toLowerCase();return {".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".webp":"image/webp",".avif":"image/avif",".svg":"image/svg+xml",".mp4":"video/mp4",".webm":"video/webm",".mov":"video/quicktime",".avi":"video/x-msvideo",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip",".rar":"application/vnd.rar",".7z":"application/x-7z-compressed"}[u]||"application/octet-stream"}async function c(l){try{let u=l.toString("hex",0,8);if(u.startsWith("89504e47")){let f=l.readUInt32BE(16),y=l.readUInt32BE(20);return {width:f,height:y}}if(u.startsWith("ffd8")){let f=2;for(;f<l.length&&l[f]===255;){let y=l[f+1];if(y===192||y===194){let x=l.readUInt16BE(f+5);return {width:l.readUInt16BE(f+7),height:x}}f+=2+l.readUInt16BE(f+2);}}}catch{}return {}}return ue({name:"local",displayName:"Local Storage",supportsDynamicResize:true,async upload(l,u){await s(e);let f=Buffer.from(await l.arrayBuffer()),y=createHash("md5").update(f).digest("hex"),x=extname(l.name),h=u?.filename||`${y}${x}`,E=u?.folder||"",_=E?join(e,E):e;await s(_);let R=join(_,h);await writeFile(R,f);let q=l.type.startsWith("image/")?await c(f):{},W=t||"/uploads",V=E?`/${E}/${h}`:`/${h}`,ne=W+V;return {id:y,filename:h,originalName:l.name,mimeType:l.type||n(l.name),size:f.length,url:ne,thumbnailUrl:l.type.startsWith("image/")?ne:void 0,folder:E||void 0,provider:"local",metadata:{...q,...u?.metadata},createdAt:new Date().toISOString()}},async uploadFromUrl(l,u){let f=await fetch(l);if(!f.ok)throw new Error(`Failed to fetch file: ${f.statusText}`);let y=await f.blob(),x=f.headers.get("content-disposition"),h=u?.filename;if(!h&&x){let _=x.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);_&&(h=_[1].replace(/['"]/g,""));}h||(h=basename(new URL(l).pathname));let E=new File([y],h,{type:y.type||n(h)});return this.upload(E,u)},async delete(l){let u=join(e,l.replace(t+"/",""));try{await unlink(u);}catch{}},async rename(l,u){let f=join(e,l.replace(t+"/","")),y=join(e,u);return await rename(f,y),`${t}/${u}`},async list(l){let u=l?join(e,l):e;if(!existsSync(u))return [];let f=[],y=await readdir(u,{withFileTypes:true});for(let x of y)if(x.isFile()){let h=join(u,x.name),E=await stat(h),_=`${t}${l?`/${l}`:""}/${x.name}`;f.push({id:createHash("md5").update(x.name).digest("hex"),filename:x.name,originalName:x.name,mimeType:n(x.name),size:E.size,url:_,provider:"local",createdAt:E.birthtime.toISOString()});}return f},async exists(l){let u=join(e,l.replace(t+"/",""));return existsSync(u)},async createFolder(l){let u=join(e,l);await mkdir(u,{recursive:true});},async deleteFolder(l){let u=join(e,l);if(existsSync(u)){let{rm:f}=await import('fs/promises');await f(u,{recursive:true,force:true});}}})}function ct(d){let e=(t,s)=>{if(!d.signKey)return t;let n=createHmac("sha256",d.signKey).update(t+s.toString()).digest("hex");return s.set("s",n),t};return {name:"imgix",displayName:"Imgix",supportsDynamicResize:true,async upload(t,s){throw new Error("Imgix is a transformation service. Use another provider for uploads.")},async uploadFromUrl(t,s){let n=s?.filename||t.split("/").pop()||"file",c=await fetch(t);if(!c.ok)throw new Error(`Failed to fetch: ${c.statusText}`);let l=await c.blob();new File([l],n,{type:l.type});return {id:Buffer.from(t).toString("base64").slice(0,20),filename:n,originalName:n,mimeType:l.type,size:l.size,url:this.getImageUrl(t),thumbnailUrl:this.getImageUrl(t,{width:200,height:200,fit:"crop"}),provider:"imgix",createdAt:new Date().toISOString()}},async delete(t){},async rename(t,s){return `https://${d.domain}/${s}`},getImageUrl(t,s){let n=new URL(t),c=new URLSearchParams(n.search);d.defaultParameters&&Object.entries(d.defaultParameters).forEach(([u,f])=>{c.has(u)||c.set(u,f);}),s&&(s.width&&c.set("w",String(s.width)),s.height&&c.set("h",String(s.height)),s.quality&&c.set("q",String(s.quality)),s.format&&c.set("fm",s.format),s.fit&&c.set("fit",s.fit),s.blur&&c.set("blur",String(s.blur)),s.sharpen&&c.set("sharp",String(s.sharpen))),c.set("auto","compress,format");n.pathname+"?"+c.toString();return d.signKey&&(e(n.pathname+c.toString(),c)),`https://${d.domain}${n.pathname}${c.toString()?"?"+c.toString():""}`},async generateThumbnail(t){return this.getImageUrl(t.url,{width:200,height:200,fit:"crop"})},async list(){return []},async exists(t){try{return (await fetch(t,{method:"HEAD"})).ok}catch{return false}},async createFolder(){},async deleteFolder(){}}}function Ke(d,e){return e.cdnUrl?`${e.cdnUrl.replace(/\/$/,"")}/${d}`:`https://${e.storageZone}.b-cdn.net/${d}`}function ut(d){return d.cdnUrl?d.cdnUrl.replace(/\/$/,"")+"/":`https://${d.storageZone}.b-cdn.net/`}function pt(d){let e=`https://storage.bunnycdn.com/${d.storageZone}`,t=s=>`${d.prefix?`${d.prefix}/`:""}${s}`.replace(/\/+/g,"/");return ue({name:"bunny",displayName:"Bunny.net Storage",supportsDynamicResize:true,async upload(s,n){let c=t(`${n?.folder?`${n.folder}/`:""}${n?.filename||s.name}`),l=Buffer.from(await s.arrayBuffer()),u=await fetch(`${e}/${c}`,{method:"PUT",headers:{AccessKey:d.apiKey,"Content-Type":s.type},body:l});if(!u.ok){let f=await u.text();throw new Error(`Bunny.net upload failed: ${u.status} ${f}`)}return {id:Buffer.from(c).toString("base64url"),filename:n?.filename||s.name,originalName:s.name,mimeType:s.type,size:l.length,url:Ke(c,d),thumbnailUrl:s.type.startsWith("image/")?Ke(c,d):void 0,folder:n?.folder,provider:"bunny",metadata:n?.metadata,createdAt:new Date().toISOString()}},async delete(s){let n=s.replace(ut(d),""),c=await fetch(`${e}/${n}`,{method:"DELETE",headers:{AccessKey:d.apiKey}});if(!c.ok&&c.status!==404){let l=await c.text();throw new Error(`Bunny.net delete failed: ${c.status} ${l}`)}},async rename(s,n){let c=s.replace(ut(d),""),l=d.prefix?`${d.prefix}/${n}`:n,u=await fetch(`${e}/${c}`,{method:"GET",headers:{AccessKey:d.apiKey}});if(!u.ok)throw new Error("Bunny.net rename failed: could not read old file");let f=await u.arrayBuffer();return await fetch(`${e}/${l}`,{method:"PUT",headers:{AccessKey:d.apiKey,"Content-Type":u.headers.get("Content-Type")||"application/octet-stream"},body:f}),await this.delete(s),Ke(l,d)},async list(s){let n=t(s||""),c=await fetch(`${e}/${n}`,{method:"GET",headers:{AccessKey:d.apiKey}});if(!c.ok){let u=await c.text();throw new Error(`Bunny.net list failed: ${c.status} ${u}`)}return (await c.json()).map(u=>({id:Buffer.from(u.ObjectName||"").toString("base64url"),filename:u.ObjectName?.split("/").pop()||"",originalName:u.ObjectName?.split("/").pop()||"",mimeType:"application/octet-stream",size:u.Length||0,url:Ke(u.ObjectName||"",d),provider:"bunny",createdAt:u.LastChanged||new Date().toISOString()}))},async exists(s){let n=s.replace(ut(d),"");return (await fetch(`${e}/${n}`,{method:"HEAD",headers:{AccessKey:d.apiKey}})).ok},async createFolder(s){let n=t(`${s}/`);await fetch(`${e}/${n}`,{method:"PUT",headers:{AccessKey:d.apiKey,"Content-Length":"0"},body:""});},async deleteFolder(s){let n=t(`${s}/`);await fetch(`${e}/${n}`,{method:"DELETE",headers:{AccessKey:d.apiKey}});}})}var gt=class{providers=new Map;providerToPlugin=new Map;disabledPlugins=new Set;constructor(){this.registerLocal(),this.registerImgix(),this.registerBunny();}registerLocal(){this.register({type:"local",displayName:"Local Server",configKey:"local",configFields:[{name:"uploadDir",type:"text",label:"Upload Directory",defaultValue:"./public/uploads"},{name:"baseUrl",type:"text",label:"Base URL",defaultValue:"/uploads"}],extractConfig:(e,t)=>e[t]||{},extractRawConfig:e=>{let t=e?.local||e,s=(t?.uploadDir||"").trim(),n;s?ze.isAbsolute(s)?n=s:s.includes("/")||s.includes("\\")?n=ze.resolve(process.cwd(),s):n=ze.join(process.cwd(),"public",s):n=ze.join(process.cwd(),"public","uploads");let c=(t?.baseUrl||"").trim(),l;return c?l=c.startsWith("/")?c:`/${c}`:l="/uploads",{uploadDir:n,baseUrl:l}},factory:e=>he(e)});}registerImgix(){this.register({type:"imgix",displayName:"Imgix",configKey:"imgix",configFields:[{name:"domain",type:"text",label:"Domain",required:true},{name:"signKey",type:"password",label:"Sign Key"}],extractConfig:(e,t)=>e[t]||{},extractRawConfig:e=>e?.imgix||e,factory:e=>ct(e)});}registerBunny(){this.register({type:"bunny",displayName:"Bunny.net",configKey:"bunny",configFields:[{name:"storageZone",type:"text",label:"Storage Zone",required:true},{name:"apiKey",type:"password",label:"API Key",required:true},{name:"cdnUrl",type:"text",label:"CDN URL"},{name:"prefix",type:"text",label:"Path Prefix"}],extractConfig:(e,t)=>e[t]||{},extractRawConfig:e=>e?.bunny||e,factory:e=>pt(e)});}register(e){if(this.providers.has(e.type)){console.warn(`[StorageRegistry] Provider "${e.type}" already registered, skipping`);return}e.pluginName&&this.providerToPlugin.set(e.type,e.pluginName),this.providers.set(e.type,e);}unregister(e){this.providers.delete(e),this.providerToPlugin.delete(e);}get(e){return this.providers.get(e)}getAll(){return Array.from(this.providers.values())}getAllAvailable(e){let t=this.getAll();return e?t.filter(s=>s.pluginName?e(s.pluginName):true):t}has(e){return this.providers.has(e)}async resolve(e,t){let s=this.providers.get(e);if(!s)throw new Error(`Unknown storage provider type: "${e}". Is the plugin that provides it enabled?`);if(s.pluginName&&this.disabledPlugins.has(s.pluginName))throw new Error(`Storage provider "${e}" is not available (plugin "${s.pluginName}" is disabled)`);let n=s.configKey||e,c=s.extractConfig(t,n);return s.factory(c)}async resolveWithConfig(e,t){let s=this.providers.get(e);if(!s)throw new Error(`Unknown storage provider type: "${e}". Is the plugin that provides it enabled?`);if(s.pluginName&&this.disabledPlugins.has(s.pluginName))throw new Error(`Storage provider "${e}" is not available (plugin "${s.pluginName}" is disabled)`);let n=s.extractRawConfig(t);return s.factory(n)}getProviderPluginName(e){return this.providerToPlugin.get(e)}getAllPluginNames(){return Array.from(new Set(this.providerToPlugin.values()))}setPluginEnabled(e,t){t?this.disabledPlugins.delete(e):this.disabledPlugins.add(e);}isPluginEnabled(e){return !this.disabledPlugins.has(e)}},mt=null;function ft(){return mt||(mt=new gt),mt}function Qt(d){if(!d)return "";if(d.startsWith("pub-"))return d;let e=d.match(/pub-[a-zA-Z0-9]+/i);return e?e[0]:""}function Lr(d,e){let t=d.startsWith("/")?d.slice(1):d;if(e.cdnUrl)return `${e.cdnUrl.replace(/\/$/,"")}/${t}`;switch(e.provider){case "r2":{let s=Qt(e.publicDevUrl);return s?`https://${s}.r2.dev/${t}`:`https://${e.bucket}.${e.accountId}.r2.cloudflarestorage.com/${t}`}case "gcs":return `https://storage.googleapis.com/${e.bucket}/${t}`;case "digitalocean":return `https://${e.bucket}.${e.region}.cdn.digitaloceanspaces.com/${t}`;case "backblaze":return `https://${e.bucket}.s3.backblazeb2.com/${t}`;case "wasabi":return `https://${e.bucket}.s3.wasabisys.com/${t}`;default:return `https://${e.bucket}.s3.${e.region}.amazonaws.com/${t}`}}function yt(d){if(d.cdnUrl)return d.cdnUrl.replace(/\/$/,"")+"/";switch(d.provider){case "r2":{let e=Qt(d.publicDevUrl);return e?`https://${e}.r2.dev/`:`https://${d.bucket}.${d.accountId}.r2.cloudflarestorage.com/`}case "gcs":return `https://storage.googleapis.com/${d.bucket}/`;case "digitalocean":return `https://${d.bucket}.${d.region}.cdn.digitaloceanspaces.com/`;case "backblaze":return `https://${d.bucket}.s3.backblazeb2.com/`;case "wasabi":return `https://${d.bucket}.s3.wasabisys.com/`;default:return `https://${d.bucket}.s3.${d.region}.amazonaws.com/`}}function _r(d){switch(d){case "r2":return "Cloudflare R2";case "gcs":return "Google Cloud Storage";case "digitalocean":return "DigitalOcean Spaces";case "backblaze":return "Backblaze B2";case "wasabi":return "Wasabi";default:return "AWS S3"}}function Nr(d){let e=new S3Client({region:d.region||"auto",endpoint:d.endpoint,credentials:{accessKeyId:d.accessKeyId,secretAccessKey:d.secretAccessKey},forcePathStyle:true,tls:true,...d.provider==="r2"&&{requestHandler:new NodeHttpHandler}}),t=n=>`${d.prefix?`${d.prefix}/`:""}${n}`.replace(/\/+/g,"/"),s=n=>Lr(n,d);return ue({name:d.provider,displayName:_r(d.provider),supportsDynamicResize:true,async upload(n,c){let l=t(`${c?.folder?`${c.folder}/`:""}${c?.filename||n.name}`),u=Buffer.from(await n.arrayBuffer());await e.send(new PutObjectCommand({Bucket:d.bucket,Key:l,Body:u,ContentType:n.type,Metadata:c?.metadata}));let f=await e.send(new HeadObjectCommand({Bucket:d.bucket,Key:l}));return {id:Buffer.from(l).toString("base64url"),filename:c?.filename||n.name,originalName:n.name,mimeType:n.type,size:u.length,url:s(l),thumbnailUrl:n.type.startsWith("image/")?s(l):void 0,folder:c?.folder,provider:d.provider,metadata:{...c?.metadata,etag:f.ETag},createdAt:new Date().toISOString()}},async delete(n){let c=n.replace(yt(d),"");await e.send(new DeleteObjectCommand({Bucket:d.bucket,Key:c}));},async rename(n,c){let l=n.replace(yt(d),""),u=d.prefix?`${d.prefix}/${c}`:c;return await e.send(new CopyObjectCommand({Bucket:d.bucket,CopySource:`${d.bucket}/${l}`,Key:u})),await e.send(new DeleteObjectCommand({Bucket:d.bucket,Key:l})),s(u)},async list(n){let c=t(n||"");return ((await e.send(new ListObjectsV2Command({Bucket:d.bucket,Prefix:c}))).Contents||[]).map(u=>({id:Buffer.from(u.Key||"").toString("base64url"),filename:u.Key?.split("/").pop()||"",originalName:u.Key?.split("/").pop()||"",mimeType:"application/octet-stream",size:u.Size||0,url:s(u.Key||""),provider:d.provider,createdAt:u.LastModified?.toISOString()||new Date().toISOString()}))},async exists(n){try{let c=n.replace(yt(d),"");return await e.send(new HeadObjectCommand({Bucket:d.bucket,Key:c})),!0}catch{return false}},async createFolder(n){let c=t(`${n}/`);await e.send(new PutObjectCommand({Bucket:d.bucket,Key:c,Body:""}));},async deleteFolder(n){let c=t(`${n}/`),l;do{let u=await e.send(new ListObjectsV2Command({Bucket:d.bucket,Prefix:c,ContinuationToken:l}));if(u.Contents?.length){let f=u.Contents.map(y=>({Key:y.Key}));await e.send(new DeleteObjectsCommand({Bucket:d.bucket,Delete:{Objects:f}}));}l=u.IsTruncated?u.NextContinuationToken:void 0;}while(l);await e.send(new DeleteObjectCommand({Bucket:d.bucket,Key:c}));}})}function Or(d){let e=()=>`https://api.cloudinary.com/v1_1/${d.cloudName}/upload`,t=async s=>{let n=await import('crypto'),c=Object.keys(s).sort().map(l=>`${l}=${s[l]}`).join("&");return n.createHash("sha256").update(c+d.apiSecret).digest("hex")};return {name:"cloudinary",displayName:"Cloudinary",supportsDynamicResize:true,async upload(s,n){let c=new FormData;if(c.append("file",s),d.uploadPreset)c.append("upload_preset",d.uploadPreset);else {let f=Math.round(Date.now()/1e3),y={timestamp:String(f)};(n?.folder||d.folder)&&(y.folder=n?.folder||d.folder||"");let x=await t(y);c.append("timestamp",String(f)),c.append("signature",x),c.append("api_key",d.apiKey);}(n?.folder||d.folder)&&c.append("folder",n?.folder||d.folder||"");let l=await fetch(e(),{method:"POST",body:c});if(!l.ok){let f=await l.json();throw new Error(`Cloudinary upload failed: ${f.error?.message||l.statusText}`)}let u=await l.json();return {id:u.public_id,filename:`${u.public_id}.${u.format}`,originalName:u.original_filename||s.name,mimeType:s.type||`image/${u.format}`,size:u.bytes,url:u.secure_url,thumbnailUrl:this.getImageUrl(u.secure_url,{width:200,height:200,fit:"crop"}),width:u.width,height:u.height,folder:n?.folder||d.folder,provider:"cloudinary",createdAt:new Date().toISOString()}},async uploadFromUrl(s,n){let c=new FormData;c.append("file",s),c.append("upload_preset","ml_default"),(n?.folder||d.folder)&&c.append("folder",n?.folder||d.folder||"");let l=await fetch(e(),{method:"POST",body:c});if(!l.ok)throw new Error("Cloudinary upload failed");let u=await l.json();return {id:u.public_id,filename:`${u.public_id}.${u.format}`,originalName:u.original_filename||s.split("/").pop()||"file",mimeType:`image/${u.format}`,size:u.bytes,url:u.secure_url,thumbnailUrl:this.getImageUrl(u.secure_url,{width:200,height:200,fit:"crop"}),width:u.width,height:u.height,provider:"cloudinary",createdAt:new Date().toISOString()}},async delete(s){try{let n=s.split("/image/upload/");if(n.length!==2){console.warn("[Cloudinary delete] Could not parse URL:",s);return}let c=n[1].replace(/^v\d+\//,"").replace(/\.[^.]+$/,""),l=Math.round(Date.now()/1e3),u={timestamp:String(l),public_id:c},f=Object.keys(u).sort().map(R=>`${R}=${u[R]}`).join("&"),x=(await import('crypto')).createHash("sha256").update(f+d.apiSecret).digest("hex"),h=`https://api.cloudinary.com/v1_1/${d.cloudName}/image/destroy`,E=new FormData;E.append("public_id",c),E.append("timestamp",String(l)),E.append("signature",x),E.append("api_key",d.apiKey);let _=await fetch(h,{method:"POST",body:E});if(!_.ok){let R=await _.json();console.warn("[Cloudinary delete] Failed:",R);}}catch(n){console.warn("[Cloudinary delete] Error:",n.message);}},async rename(s,n){let c="",l=n.replace(/\.[^.]+$/,""),u="";try{let f=s.split("/image/upload/");if(f.length!==2)return console.warn("[Cloudinary rename] Could not parse old URL:",s),s;let y=f[1],x=y.match(/^(v\d+)\//);c=x?x[1]:"";let h=y.replace(/^v\d+\//,"").replace(/\.[^.]+$/,""),E=h.split("/");u=E.length>1?E.slice(0,-1).join("/"):"";let _=n.replace(/\.[^.]+$/,"");l=u?`${u}/${_}`:_;let R=Math.round(Date.now()/1e3),q={from_public_id:h,to_public_id:l,timestamp:String(R)},W=Object.keys(q).sort().map(Z=>`${Z}=${q[Z]}`).join("&"),ne=(await import('crypto')).createHash("sha256").update(W+d.apiSecret).digest("hex"),$=new FormData;$.append("from_public_id",h),$.append("to_public_id",l),$.append("timestamp",String(R)),$.append("signature",ne),$.append("api_key",d.apiKey);let pe=await fetch(`https://api.cloudinary.com/v1_1/${d.cloudName}/image/rename`,{method:"POST",body:$});if(pe.ok)return (await pe.json()).secure_url;{let Z=await pe.json();console.warn("[Cloudinary rename] Failed:",Z);let k=c?`/${c}/`:"/";return `https://res.cloudinary.com/${d.cloudName}/image/upload${k}${l}.${n.split(".").pop()}`}}catch(f){console.warn("[Cloudinary rename] Error:",f.message);let y=c?`/${c}/`:"/";return `https://res.cloudinary.com/${d.cloudName}/image/upload${y}${l}.${n.split(".").pop()}`}},getImageUrl(s,n){if(!n)return s;let c=s.split("/upload/");if(c.length!==2)return s;let l=[];if(n.width&&l.push(`w_${n.width}`),n.height&&l.push(`h_${n.height}`),n.fit){let f={crop:"c_fill",clip:"c_fit",scale:"c_scale",fill:"c_fill"};l.push(f[n.fit]||"c_limit");}n.quality&&l.push(`q_${n.quality}`),n.format&&l.push(`f_${n.format}`);let u=l.join(",");return `${c[0]}/upload/${u}/${c[1]}`},async generateThumbnail(s){return this.getImageUrl(s.url,{width:200,height:200,fit:"crop"})},async list(){return []},async exists(s){return (await fetch(s,{method:"HEAD"})).ok},async createFolder(){},async deleteFolder(){}}}function Br(d){let e=null;async function t(){return e||(e=new Client(6e4,{allowSeparateTransferHost:true}),e.ftp.verbose=false,await e.access({host:d.host,port:d.port||21,user:d.user,password:d.password,secure:d.secure,secureOptions:{}})),e}let s=l=>`${d.prefix?`${d.prefix}/`:""}${l}`.replace(/\/+/g,"/"),n=l=>`${d.baseUrl.replace(/\/$/,"")}/${l}`,c=()=>d.baseUrl.replace(/\/$/,"")+"/";return ue({name:d.type,displayName:d.type==="sftp"?"SFTP Storage":"FTP Storage",supportsDynamicResize:false,async upload(l,u){let f=await t(),y=s(`${u?.folder?`${u.folder}/`:""}${u?.filename||l.name}`),x=Buffer.from(await l.arrayBuffer()),h=y.split("/").slice(0,-1),E="";for(let R of h){E=E?`${E}/${R}`:R;try{await f.ensureDir(E);}catch{}}let _=Readable.from(x);return await f.uploadFrom(_,y),{id:Buffer.from(y).toString("base64url"),filename:u?.filename||l.name,originalName:l.name,mimeType:l.type,size:x.length,url:n(y),thumbnailUrl:l.type.startsWith("image/")?n(y):void 0,folder:u?.folder,provider:d.type,metadata:u?.metadata,createdAt:new Date().toISOString()}},async delete(l){let u=await t(),f=l.replace(c(),"");await u.remove(f);},async rename(l,u){let f=await t(),y=l.replace(c(),""),x=d.prefix?`${d.prefix}/${u}`:u;return await f.rename(y,x),n(x)},async list(l){let u=await t(),f=s(l||""),y;try{y=await u.list(f);}catch{return []}return y.filter(x=>x.type===0).map(x=>({id:Buffer.from(`${f}/${x.name}`).toString("base64url"),filename:x.name,originalName:x.name,mimeType:"application/octet-stream",size:Number(x.size)||0,url:n(`${f}/${x.name}`.replace(/\/+/g,"/")),provider:d.type,createdAt:x.modifiedAt?x.modifiedAt.toISOString():new Date().toISOString()}))},async exists(l){let u=await t(),f=l.replace(c(),"");try{return await u.size(f),!0}catch{return false}},async createFolder(l){let u=await t(),f=s(l);await u.ensureDir(f);},async deleteFolder(l){let u=await t(),f=s(l);await u.removeDir(f);}})}async function er(d){let e=d.getStorageConfig(),t=ft();try{return await t.resolve(e.type,e)}catch(s){return console.warn(`[resolveProvider] ${s.message} \u2014 falling back to local storage`),he({uploadDir:ze.join(process.cwd(),"public","uploads"),baseUrl:"/uploads"})}}function ue(d){return {async uploadFromUrl(e,t){let s=await fetch(e);if(!s.ok)throw new Error(`Failed to fetch: ${s.statusText}`);let n=await s.blob(),c=e.split("/").pop()||"file",l=new File([n],c,{type:n.type});return this.upload(l,t)},getImageUrl(e,t){if(!t||Object.keys(t).length===0)return e;let s=new URLSearchParams({url:e});return t.width&&s.set("w",String(t.width)),t.height&&s.set("h",String(t.height)),t.quality&&s.set("q",String(t.quality)),t.format&&s.set("f",t.format),t.cropWidth&&t.cropHeight&&(s.set("cx",String(t.cropX??0)),s.set("cy",String(t.cropY??0)),s.set("cw",String(t.cropWidth)),s.set("ch",String(t.cropHeight))),`/api/media/resize?${s.toString()}`},async generateThumbnail(e){return this.getImageUrl(e.url,{width:400,height:400})},...d}}async function tr(d){if(!d)return console.warn("[resolveProviderWithConfig] No config, using local"),he({uploadDir:ze.join(process.cwd(),"public","uploads"),baseUrl:"/uploads"});let e=d.type||"local",t=ft();try{return await t.resolveWithConfig(e,d)}catch(s){return console.warn(`[resolveProviderWithConfig] ${s.message} \u2014 falling back to local storage`),he({uploadDir:ze.join(process.cwd(),"public","uploads"),baseUrl:"/uploads"})}}function rr(){return typeof globalThis>"u"?false:typeof globalThis.EdgeRuntime=="string"||typeof globalThis.WebSocketPair<"u"||typeof globalThis.Deno<"u"||typeof process<"u"&&process.env?.NEXT_RUNTIME==="edge"}async function sr(d){if(!rr())try{let{default:e}=await import('sharp'),t=await e(d).metadata(),s=e(d).webp({quality:85}),n=e(d).resize({width:500,withoutEnlargement:!0}).webp({quality:80});return {buffer:await s.toBuffer(),thumbnailBuffer:await n.toBuffer(),width:t.width,height:t.height,format:"webp"}}catch{}return {buffer:d,thumbnailBuffer:d,format:"passthrough"}}var bt=false;function ke(d){if(typeof d!="string")return d;let e=d.replace(/-/g,"").toLowerCase();return e.length===32?`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`:d}var We=class d{db;storage;dialect;genId;mediaTable="media";foldersTable="media_folders";constructor(e$1,t,s){this.db=e$1,this.storage=t,this.dialect=s?.dialect||"sqlite",this.genId=s?.genId||e;}static async init(e,t){let s;if(t?.storageConfig)s=await tr(t.storageConfig);else {let c=new j(e);await c.load(),s=await er(c);}let n=new d(e,s,t);return await n.ensureTables(),n}async ensureTables(){if(this.dialect==="mongodb"){let e=this.db.db;await e.collection(this.mediaTable).createIndex({filename:1},{unique:true}),await e.collection(this.foldersTable).createIndex({path:1},{unique:true}),bt=true;return}if(this.dialect==="sqlite"){this.db.exec(`
1
+ import {l,j,k}from'./chunk-6J27P5D6.js';import {a as a$2}from'./chunk-IETGL7WJ.js';import {a as a$8}from'./chunk-IKOXCJYO.js';import {a as a$1}from'./chunk-NRLIGDYF.js';import {d,a as a$4,b as b$1,c as c$2}from'./chunk-FVZ5RFLO.js';import {d as d$1,i,j as j$1,f,e as e$1,g}from'./chunk-HLSB2MCK.js';import {e,c as c$1}from'./chunk-DKESD4HI.js';import {a as a$6}from'./chunk-RHCWCG3O.js';import {a as a$7}from'./chunk-6ROHVUXF.js';import {a as a$5}from'./chunk-4RMFCTWH.js';import {a as a$3}from'./chunk-KDNYHLD2.js';import {a,b,c}from'./chunk-5J6HXUF6.js';import mr,{randomBytes,createHash,createHmac}from'crypto';import {createStorage}from'unstorage';import yr from'unstorage/drivers/fs';import {Hono}from'hono';import {verify,sign}from'hono/jwt';import ze,{join,resolve,basename,extname}from'path';import {existsSync,readFileSync}from'fs';import {mkdir,readdir,stat,rename,unlink,writeFile}from'fs/promises';import Er from'process';import {S3Client,ListObjectsV2Command,DeleteObjectsCommand,DeleteObjectCommand,PutObjectCommand,HeadObjectCommand,CopyObjectCommand}from'@aws-sdk/client-s3';import {NodeHttpHandler}from'@smithy/node-http-handler';import {Readable}from'stream';import {Client}from'basic-ftp';import {zodToJsonSchema}from'zod-to-json-schema';function Qr(d){et=d;}async function Nt(){if(et)try{let d=await et.findOne({collection:"_globals_system",where:{}});if(d){de={appSecret:d.appSecret||null,encryptionKey:d.encryptionKey||null,sessionConfig:d.sessionMaxAge||d.maxSessionsPerUser?{maxAge:(d.sessionMaxAge||7)*24*60*60*1e3,maxSessionsPerUser:d.maxSessionsPerUser||3}:null};return}}catch{}de={appSecret:process.env.APP_SECRET||"development-secret-key",encryptionKey:null,sessionConfig:null};}function gr(){return de?.appSecret?de.appSecret:process.env.APP_SECRET||"development-secret-key"}function es(){if(de?.encryptionKey)return de.encryptionKey;let d=gr();return mr.createHash("sha256").update(d).digest("hex")}function Ot(){return de?.sessionConfig?de.sessionConfig:{maxAge:10080*60*1e3,maxSessionsPerUser:3}}var et,de,tt=a(()=>{et=null,de=null;});var Bt={};b(Bt,{SESSION_CONFIG:()=>ie,clearSessionCookie:()=>it,createSession:()=>ot,deleteSession:()=>ve,getClientIp:()=>st,getCurrentUser:()=>ee,getSession:()=>fe,getSessionIdFromRequest:()=>se,getUserSessions:()=>Ie,invalidateAllUserSessions:()=>Ar,refreshSession:()=>_e,setSessionCookie:()=>at,updateSessionName:()=>lt,validateSession:()=>Le});async function ce(){return $e||($e=createStorage({driver:yr({base:".astro/sessions"})}),$e)}function wr(){return mr.randomUUID()}function Mt(d){let e="Unknown",t="Unknown",s="Unknown";return d.includes("Firefox")?e="Firefox":d.includes("Edg/")?e="Edge":d.includes("Chrome")?e="Chrome":d.includes("Safari")&&!d.includes("Chrome")&&(e="Safari"),d.includes("iPhone")?(t="iPhone",s="iOS"):d.includes("iPad")?(t="iPad",s="iOS"):d.includes("Mac")?(t="MacBook",s="macOS"):d.includes("Windows")?(t="Windows PC",s="Windows"):d.includes("Linux")?(t="Linux PC",s="Linux"):d.includes("Android")&&(t="Android Phone",s="Android"),{browser:e,device:t,platform:s}}function br(d){if(!d?.userAgent)return "Session";let{browser:e,device:t}=Mt(d.userAgent);return `${t} - ${e}`}function se(d){let e=d.headers.get("Cookie");return e&&Object.fromEntries(e.split("; ").map(s=>s.split("=")))[rt]||null}function st(d){let e=d.headers.get("x-forwarded-for");return e?e.split(",")[0].trim():d.headers.get("x-real-ip")||"unknown"}function at(d,e){let s=process.env.NODE_ENV==="production"?"Secure; ":"",n=new Headers(d.headers);return n.append("Set-Cookie",`${rt}=${e}; HttpOnly; Path=/; Max-Age=${ie.absoluteMaxAge/1e3}; SameSite=Strict; ${s}`),new Response(d.body,{status:d.status,statusText:d.statusText,headers:n})}function it(d){let t=process.env.NODE_ENV==="production"?"Secure; ":"",s=new Headers(d.headers);return s.append("Set-Cookie",`${rt}=; HttpOnly; Path=/; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Strict; ${t}`),new Response(d.body,{status:d.status,statusText:d.statusText,headers:s})}async function Ce(d){return await(await ce()).getItem(`user:${d}`)||[]}async function nt(d,e){let t=await ce();e.length>0?await t.setItem(`user:${d}`,e):await t.removeItem(`user:${d}`);}async function ot(d,e){let t=await ce(),s=await Ce(d.id);for(;s.length>=ie.maxSessionsPerUser;){let x=s.shift();x&&await t.removeItem(`session:${x}`);}let n=wr(),c=Date.now(),l=e?.headers.get("user-agent"),u=e?st(e):"unknown",f=l?{userAgent:l,ip:u,...Mt(l)}:{ip:u},y={id:n,userId:d.id,email:d.email,role:d.role,tenantId:d.tenantId,permissions:d.permissions,createdAt:c,expiresAt:c+ie.absoluteMaxAge,lastActivityAt:c,deviceInfo:f,sessionName:br(f)};return await t.setItem(`session:${n}`,y,{ttl:Math.floor(ie.absoluteMaxAge/1e3)}),s.push(n),await nt(d.id,s),n}async function fe(d){return await(await ce()).getItem(`session:${d}`)||null}async function Le(d){let e=await fe(d);return e?e.expiresAt<Date.now()?(await ve(d),{valid:false,reason:"Session expired"}):{valid:true}:{valid:false,reason:"Session not found"}}async function _e(d,e){let t=await ce(),s=await fe(d);if(!s)return null;let n=Date.now(),c=s.expiresAt-n,l=s.deviceInfo;if(e){let y=st(e);y!==s.deviceInfo?.ip&&(l={...s.deviceInfo,ip:y});}let u={...s,lastActivityAt:n,expiresAt:c<ie.refreshThreshold?n+ie.absoluteMaxAge:s.expiresAt,deviceInfo:l},f=c<ie.refreshThreshold?ie.absoluteMaxAge:void 0;return await t.setItem(`session:${d}`,u,f?{ttl:Math.floor(f/1e3)}:void 0),u}async function ve(d){let e=await ce(),t=await fe(d);if(t){let n=(await Ce(t.userId)).filter(c=>c!==d);await nt(t.userId,n);}await e.removeItem(`session:${d}`),await e.removeItem(`activity:${d}`);}async function Ar(d){let e=await Ce(d),t=await ce();for(let s of e)await t.removeItem(`session:${s}`),await t.removeItem(`activity:${s}`);await nt(d,[]);}async function Ie(d,e){let t=await Ce(d),s=[];for(let n of t){let c=await fe(n);c&&s.push({id:c.id,sessionName:c.sessionName||"Session",deviceInfo:c.deviceInfo,createdAt:c.createdAt,lastActivityAt:c.lastActivityAt,currentSession:c.id===e});}return s.sort((n,c)=>c.lastActivityAt-n.lastActivityAt),s}async function lt(d,e){let t=await fe(d);return t?(await(await ce()).setItem(`session:${d}`,{...t,sessionName:e}),true):false}async function ee(d){let e=se(d);if(!e||!(await Le(e)).valid)return null;let s=await fe(e);return s?(await _e(e,d),s):null}var Ft,ie,rt,$e,Ne=a(()=>{tt();Ft=Ot(),ie={absoluteMaxAge:Ft.maxAge,maxSessionsPerUser:Ft.maxSessionsPerUser,refreshThreshold:300*1e3,activityDebounce:30*1e3,pollInterval:30*1e3},rt="kyro-session",$e=null;});function ge(d,e){for(let t of d){if(t.name===e)return t;if(t.type==="group"||t.type==="array"){let s=ge(t.fields||[],e);if(s)return s}if(t.type==="blocks")for(let s of t.blocks||[]){let n=ge(s.fields||[],e);if(n)return n}if(t.type==="tabs")for(let s of t.tabs||[]){let n=ge(s.fields||[],e);if(n)return n}if(t.type==="collapsible"||t.type==="row"){let s=ge(t.fields||[],e);if(s)return s}}return null}Ne();function zt(d){let{db:t,userLookup:s}=d;return async function(c){let l=f(c);if(l&&t){let f=await e$1(l,t,s);if(f.valid&&f.user)return {user:f.user,tenantContext:Kt(f.user),apiKeyContext:g(f),status:200,authType:"apikey"};if(f.error)return {status:401,error:f.error}}let u=se(c);if(u)try{let f=await Le(u);if(!f.valid)return {status:401,error:f.reason||"Session invalid"};let y=await ee(c);if(y){let x=s?await s(y.userId):null;if(x)return {user:x,tenantContext:Kt(x),status:200,authType:"session"}}}catch(f){console.error("Session validation error:",f);}return {status:401,error:"Authentication required"}}}function Kt(d){return {tenantId:d.tenantId||"default",userId:d.id||"anonymous",role:d.role||"guest",roles:[d.role||"guest"],permissions:[],isSuperAdmin:d.role==="super_admin"}}tt();var Oe=class{storage=new Map;userStorage=new Map;limits;userLimits;constructor(e,t){this.limits={...xr,...e},this.userLimits=t||{"user:api":{window:6e4,max:500},"user:write":{window:36e5,max:100}};}getKey(e,t){return `${e}:${t}`}getUserKey(e,t,s){return `user:${e}:${t}:${s}`}cleanupOldEntries(e,t){let n=Date.now()-t;for(;e.length>0&&e[0].timestamp<n;)e.shift();}async check(e,t){let s=this.limits[e]||this.limits["api:general"],n=this.getKey(e,t),c=this.storage.get(n);c||(c=[],this.storage.set(n,c)),this.cleanupOldEntries(c,s.window);let l=Date.now(),u=c.reduce((f,y)=>f+y.count,0);if(c.push({timestamp:l,count:1}),u>=s.max){let y=c.reduce((x,h)=>x.timestamp<h.timestamp?x:h,c[0]).timestamp+s.window;return {allowed:false,remaining:0,resetAt:y,retryAfter:Math.ceil((y-l)/1e3)}}return {allowed:true,remaining:s.max-u-1,resetAt:l+s.window}}async checkUser(e,t,s){let n=this.userLimits[e]||this.userLimits["user:api"],c=this.userStorage.get(t),l=[];c?l=c.get(this.getKey(e,s))||[]:(this.userStorage.has(t)||this.userStorage.set(t,new Map),this.userStorage.get(t).set(this.getKey(e,s),l)),this.cleanupOldEntries(l,n.window);let u=Date.now(),f=l.reduce((y,x)=>y+x.count,0);if(l.push({timestamp:u,count:1}),f>=n.max){let x=l.reduce((h,E)=>h.timestamp<E.timestamp?h:E,l[0]).timestamp+n.window;return {allowed:false,remaining:0,resetAt:x,retryAfter:Math.ceil((x-u)/1e3)}}return {allowed:true,remaining:n.max-f-1,resetAt:u+n.window}}async reset(e,t){let s=this.getKey(e,t);this.storage.delete(s);}async resetUser(e,t,s){let n=this.userStorage.get(t);if(n){let c=this.getKey(e,s);n.delete(c);}}async getStatus(e,t){let s=this.limits[e]||this.limits["api:general"],n=this.getKey(e,t),c=this.storage.get(n);c||(c=[],this.storage.set(n,c)),this.cleanupOldEntries(c,s.window);let l=Date.now(),u=c.reduce((f,y)=>f+y.count,0);return {count:u,limit:s.max,remaining:Math.max(0,s.max-u),resetAt:l+s.window}}setLimit(e,t){this.limits[e]=t;}setUserLimit(e,t){this.userLimits[e]=t;}},xr={"auth:login":{window:9e5,max:5},"auth:register":{window:36e5,max:3},"auth:forgot":{window:36e5,max:3},"auth:reset":{window:36e5,max:5},"auth:verify":{window:36e5,max:5},"api:general":{window:6e4,max:100},"api:authenticated":{window:6e4,max:200}};var dt={retentionDays:30};var Wt=class{redis;prefix;retentionDays;constructor(e,t=30,s="kyro:audit:"){this.redis=e,this.prefix=s,this.retentionDays=t;}async log(e){let t=randomBytes(16).toString("hex"),s=new Date,n={...e,id:t,timestamp:s},c=this.getKeyForDate(s),l=`${this.prefix}log:${t}`;await this.redis.hset(l,this.serializeLog(n)),await this.redis.expire(l,this.retentionDays*24*60*60+3600),await this.redis.zadd(c,s.getTime(),t),await this.redis.expire(c,this.retentionDays*24*60*60+3600);let u=e.userId?`${this.prefix}user:${e.userId}`:null;return u&&(await this.redis.zadd(u,s.getTime(),t),await this.redis.expire(u,this.retentionDays*24*60*60+3600)),t}async get(e){let t=`${this.prefix}log:${e}`,s=await this.redis.hgetall(t);return !s||Object.keys(s).length===0?null:this.deserializeLog(s)}async query(e={}){let{limit:t=50,offset:s=0}=e,n=[];if(e.userId)n.push(`${this.prefix}user:${e.userId}`);else if(e.startDate||e.endDate)n=this.getKeysForDateRange(e.startDate,e.endDate);else {let f=new Date;n=this.getKeysForDateRange(new Date(f.getTime()-this.retentionDays*24*60*60*1e3),f);}let c=[];for(let f of n){let y=await this.redis.zrange(f,0,-1,"WITHSCORES");for(let x=0;x<y.length;x+=2)c.push([y[x],parseInt(y[x+1],10)]);}c.sort((f,y)=>y[1]-f[1]);let l=c.length;c=c.slice(s,s+t);let u=[];for(let[f]of c){let y=await this.get(f);y&&this.matchesFilter(y,e)&&u.push(y);}return {logs:u,total:l}}async getRecent(e=50){let t=[],s=new Date,n=this.getKeysForDateRange(new Date(s.getTime()-10080*60*1e3),s),c=[];for(let l of n){let u=await this.redis.zrange(l,0,-1,"WITHSCORES");for(let f=0;f<u.length;f+=2)c.push([u[f],parseInt(u[f+1],10)]);}c.sort((l,u)=>u[1]-l[1]);for(let[l]of c.slice(0,e)){let u=await this.get(l);u&&t.push(u);}return t}async getUserActivity(e,t=50){let s=`${this.prefix}user:${e}`,n=await this.redis.zrange(s,0,t-1),c=[];for(let l of n){let u=await this.get(l);u&&c.push(u);}return c}async getStats(e,t){let s=this.getKeysForDateRange(e||new Date(Date.now()-2592e6),t||new Date),n={},c=0,l=0,u=0,f=new Set;for(let y of s){let x=await this.redis.zrange(y,0,-1);for(let h of x){let E=await this.get(h);E&&(c++,n[E.action]=(n[E.action]||0)+1,E.success&&u++,E.action==="login_failed"&&l++,E.userId&&f.add(E.userId));}}return {totalEvents:c,byAction:n,successRate:c>0?u/c:1,failedLogins:l,uniqueUsers:f}}async cleanup(){let e=Date.now()-this.retentionDays*24*60*60*1e3,t=await this.redis.keys(`${this.prefix}date:*`),s=0;for(let n of t){let c=await this.redis.zrangebyscore(n,0,e);for(let l of c)await this.redis.del(`${this.prefix}log:${l}`),s++;await this.redis.zremrangebyscore(n,0,e);}return s}getKeyForDate(e){let t=e.getFullYear(),s=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return `${this.prefix}date:${t}-${s}-${n}`}getKeysForDateRange(e,t){let s=[],n=e||new Date(Date.now()-this.retentionDays*24*60*60*1e3),c=t||new Date,l=new Date(n);for(;l<=c;)s.push(this.getKeyForDate(l)),l.setDate(l.getDate()+1);return s}matchesFilter(e,t){return !(t.action&&!(Array.isArray(t.action)?t.action:[t.action]).includes(e.action)||t.resource&&e.resource!==t.resource||t.resourceId&&e.resourceId!==t.resourceId||t.success!==void 0&&e.success!==t.success)}serializeLog(e){let t={id:e.id,timestamp:new Date(e.timestamp).toISOString(),action:e.action,resource:e.resource,success:e.success?"1":"0"};return e.userId&&(t.userId=e.userId),e.userEmail&&(t.userEmail=e.userEmail),e.role&&(t.role=e.role),e.resourceId&&(t.resourceId=e.resourceId),e.ipAddress&&(t.ipAddress=e.ipAddress),e.userAgent&&(t.userAgent=e.userAgent),e.error&&(t.error=e.error),e.changes&&(t.changes=JSON.stringify(e.changes)),e.metadata&&(t.metadata=JSON.stringify(e.metadata)),t}deserializeLog(e){return {id:e.id,timestamp:new Date(e.timestamp),action:e.action,userId:e.userId,userEmail:e.userEmail,role:e.role,resource:e.resource,resourceId:e.resourceId,ipAddress:e.ipAddress,userAgent:e.userAgent,success:e.success==="1",error:e.error,changes:e.changes?JSON.parse(e.changes):void 0,metadata:e.metadata?JSON.parse(e.metadata):void 0}}};function gs(d){return {ipAddress:d.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||d.headers.get("x-real-ip")||"unknown",userAgent:d.headers.get("user-agent")||"unknown"}}var Ht=class{logs=[];retentionDays;constructor(e=dt.retentionDays){this.retentionDays=e;}async log(e){let t=randomBytes(16).toString("hex"),n={...e,id:t,timestamp:new Date};return this.logs.push(n),this.cleanupOldLogs(),t}async get(e){return this.logs.find(t=>t.id===e)||null}async query(e={}){let{limit:t=50,offset:s=0}=e,n=[...this.logs];if(e.userId&&(n=n.filter(y=>y.userId===e.userId)),e.action){let y=Array.isArray(e.action)?e.action:[e.action];n=n.filter(x=>y.includes(x.action));}e.resource&&(n=n.filter(y=>y.resource===e.resource)),e.resourceId&&(n=n.filter(y=>y.resourceId===e.resourceId)),e.success!==void 0&&(n=n.filter(y=>y.success===e.success));let c=e.startDate,l=e.endDate;c!==void 0&&(n=n.filter(y=>y.timestamp>=c)),l!==void 0&&(n=n.filter(y=>y.timestamp<=l)),n.sort((y,x)=>x.timestamp.getTime()-y.timestamp.getTime());let u=n.length;return {logs:n.slice(s,s+t),total:u}}async getRecent(e=50){let t=new Date(Date.now()-6048e5);return this.logs.filter(n=>n.timestamp>=t).sort((n,c)=>c.timestamp.getTime()-n.timestamp.getTime()).slice(0,e)}async getUserActivity(e,t=50){return this.logs.filter(n=>n.userId===e).sort((n,c)=>c.timestamp.getTime()-n.timestamp.getTime()).slice(0,t)}async getStats(e,t){let s=e||new Date(Date.now()-2592e6),n=t||new Date,c=this.logs.filter(h=>h.timestamp>=s&&h.timestamp<=n),l={},u=0,f=0,y=0,x=new Set;for(let h of c){u++;let E=h.action;l[E]=(l[E]||0)+1,h.success&&y++,h.action==="login_failed"&&f++,h.userId&&x.add(h.userId);}return {totalEvents:u,byAction:l,successRate:u>0?y/u:1,failedLogins:f,uniqueUsers:x}}async cleanup(){let e=new Date(Date.now()-this.retentionDays*24*60*60*1e3),t=this.logs.length;return this.logs=this.logs.filter(s=>s.timestamp>=e),t-this.logs.length}cleanupOldLogs(){let e=new Date(Date.now()-this.retentionDays*24*60*60*1e3);this.logs.length;this.logs=this.logs.filter(s=>s.timestamp>=e);}};Ne();var Me=class{authAdapter;email;passwordPolicy;lockout;rateLimiter;auditLogger;baseUrl;emailVerificationRequired;constructor(e){this.authAdapter=e.redis,this.email=e.email,this.passwordPolicy=e.passwordPolicy||new l,this.lockout=e.lockout,this.rateLimiter=e.rateLimiter,this.auditLogger=e.auditLogger,this.baseUrl=e.baseUrl||"http://localhost:4321",this.emailVerificationRequired=e.emailVerificationRequired??true;}getBaseUrl(e){if(e)try{let t=e.headers.get("x-forwarded-proto")||(e.url.startsWith("https")?"https":"http"),s=e.headers.get("x-forwarded-host")||e.headers.get("host");return s?`${t}://${s}`:new URL(e.url).origin}catch{}return process.env.KYRO_BASE_URL||process.env.SERVER_URL||process.env.PUBLIC_URL||process.env.SITE_URL||this.baseUrl||"http://localhost:4321"}async register(e){let{ipAddress:t,userAgent:s}=a$1(e);if(this.rateLimiter){let n=await this.rateLimiter.check("auth:register",t);if(!n.allowed)return this.rateLimitResponse(n)}try{let n=await e.json();if(!n.email||!n.password)return this.errorResponse("Email and password are required",400);if(n.password!==n.confirmPassword)return this.errorResponse("Passwords do not match",400);let c=this.passwordPolicy.validate(n.password);if(!c.valid)return this.errorResponse(c.errors.join(". "),400);let l=await this.authAdapter.findUserByEmail(n.email);if(l){if(!l.emailVerified&&this.emailVerificationRequired&&this.email){let y=(await this.authAdapter.createEmailVerificationToken?.(l.id))?.token||randomBytes(32).toString("hex"),h=`${this.getBaseUrl(e)}/admin/auth/verify-email?token=${y}`,E=this.email.getTemplates().verifyEmail(h,n.email);return await this.email.send({to:n.email,...E}),this.jsonResponse({success:!0,message:"An unverified account already exists with this email. We have resent the confirmation link to your inbox.",requiresVerification:!0},200)}return this.errorResponse("Email already registered",400)}let u=await this.authAdapter.createUser({email:n.email,password:n.password,role:n.role||"customer",tenantId:n.tenantId});if(this.emailVerificationRequired&&this.email){let f=randomBytes(32).toString("hex"),x=`${this.getBaseUrl(e)}/admin/auth/verify-email?token=${f}`;await this.authAdapter.createSession(u.id,{ipAddress:t,userAgent:s});let h=this.email.getTemplates().verifyEmail(x,n.email);await this.email.send({to:n.email,...h});}return this.auditLogger&&await this.auditLogger.log({action:"register",userId:u.id,userEmail:u.email,resource:"auth",ipAddress:t,userAgent:s,success:!0}),this.jsonResponse({success:!0,message:"Registration successful",user:this.sanitizeUser(u),requiresVerification:this.emailVerificationRequired&&!!this.email},201)}catch(n){return console.error("[AuthRoutes.register] Registration error:",n),this.errorResponse("Registration failed",500)}}async login(e){let{ipAddress:t,userAgent:s}=a$1(e);if(this.rateLimiter){let n=await this.rateLimiter.check("auth:login",t);if(!n.allowed)return this.rateLimitResponse(n)}try{let n=await e.json();if(!n.email||!n.password)return this.errorResponse("Email and password are required",400);let c=await this.authAdapter.findUserByEmail(n.email);if(!c)return await this.recordFailedLogin(t,s),this.errorResponse("Invalid credentials",401);if(c.locked)return this.auditLogger&&await this.auditLogger.log({action:"login_failed",userId:c.id,userEmail:c.email,resource:"auth",ipAddress:t,userAgent:s,success:!1,error:"Account locked"}),this.errorResponse("Account locked. Contact an administrator.",403);if(this.lockout){let x=await this.lockout.checkLockout(c.id);if(x.locked)return this.auditLogger&&await this.auditLogger.log({action:"login_failed",userId:c.id,userEmail:c.email,resource:"auth",ipAddress:t,userAgent:s,success:!1,error:"Account locked"}),this.errorResponse(`Account locked. Try again in ${Math.ceil((x.lockedUntil.getTime()-Date.now())/6e4)} minutes`,423)}let l=await this.authAdapter.verifyPassword(n.email,n.password);if(!l)return await this.recordFailedLogin(t,s,c.id,c.email),this.errorResponse("Invalid credentials",401);if(this.emailVerificationRequired&&l.emailVerified===!1){if(this.email){let h=(await this.authAdapter.createEmailVerificationToken?.(l.id))?.token||randomBytes(32).toString("hex"),_=`${this.getBaseUrl(e)}/admin/auth/verify-email?token=${h}`,R=this.email.getTemplates().verifyEmail(_,l.email);await this.email.send({to:l.email,...R});}return this.errorResponse("Your email address is not verified yet. We have sent a new confirmation link to your email inbox.",403)}this.lockout&&await this.lockout.resetAttempts(c.id),this.auditLogger&&await this.auditLogger.log({action:"login",userId:c.id,userEmail:c.email,role:c.role,resource:"auth",ipAddress:t,userAgent:s,success:!0}),await this.authAdapter.updateUser(c.id,{lastLogin:new Date().toISOString()});let u=await ot({id:c.id,email:c.email,role:c.role,tenantId:c.tenantId}),f={success:!0,user:this.sanitizeUser(c)},y=this.jsonResponse(f);return at(y,u)}catch(n){return console.error("[Auth] Login error:",n),this.errorResponse("Login failed",500)}}async logout(e){let t=se(e);if(!t)return this.errorResponse("No session to logout",401);let{ipAddress:s,userAgent:n}=a$1(e);try{let c=await ee(e);c&&(await ve(t),this.auditLogger&&await this.auditLogger.log({action:"logout",userId:c.userId,userEmail:c.email,resource:"auth",ipAddress:s,userAgent:n,success:!0}));let l=this.jsonResponse({success:!0,message:"Logged out successfully"});return it(l)}catch{return this.errorResponse("Logout failed",500)}}async refresh(e){try{let t=se(e);if(!t)return this.errorResponse("Not authenticated",401);let s=await _e(t,e);return s?this.jsonResponse({success:!0,expiresAt:s.expiresAt}):this.errorResponse("Session not found",404)}catch(t){return console.error("[Auth] Session refresh error:",t),this.errorResponse("Session refresh failed",500)}}async me(e){let t=await ee(e);return t?this.jsonResponse({success:true,user:{id:t.userId,email:t.email,role:t.role,tenantId:t.tenantId}}):this.errorResponse("Not authenticated",401)}async changePassword(e){let t=await ee(e);if(!t)return this.errorResponse("Not authenticated",401);let{ipAddress:s,userAgent:n}=a$1(e);try{let c=await e.json(),{currentPassword:l,newPassword:u,confirmPassword:f}=c;if(!l||!u)return this.errorResponse("Current and new password required",400);if(u!==f)return this.errorResponse("Passwords do not match",400);let y=this.passwordPolicy.validate(u);if(!y.valid)return this.errorResponse(y.errors.join(". "),400);let x=await this.authAdapter.findUserById(t.userId);if(!x)return this.errorResponse("User not found",404);if(!(x.passwordHash?await this.authAdapter.verifyPassword(l,x.passwordHash):!1))return this.errorResponse("Current password is incorrect",401);let E=await this.authAdapter.getPasswordHistory?.(x.id,5);if(await this.authAdapter.isPasswordInHistory?.(u,x.id,5))return this.errorResponse("Password was recently used. Please choose a different password",400);let R=await this.authAdapter.hashPassword(u);if(x.passwordHash&&await this.authAdapter.addPasswordToHistory?.(x.id,x.passwordHash),await this.authAdapter.updateUser(x.id,{passwordHash:R}),await this.authAdapter.deleteUserSessions(x.id),this.email&&this.email.getTemplates){let q=this.email.getTemplates().passwordChanged(x.email);await this.email.send({to:x.email,...q});}return this.auditLogger&&await this.auditLogger.log({action:"password_change",userId:x.id,userEmail:x.email,resource:"auth",ipAddress:s,userAgent:n,success:!0}),this.jsonResponse({success:!0,message:"Password changed successfully"})}catch{return this.errorResponse("Password change failed",500)}}async forgotPassword(e){let{ipAddress:t,userAgent:s}=a$1(e);if(this.rateLimiter){let n=await this.rateLimiter.check("auth:forgot",t);if(!n.allowed)return this.rateLimitResponse(n)}try{let n=await e.json(),{email:c}=n;if(!c)return this.errorResponse("Email required",400);let l=await this.authAdapter.findUserByEmail(c);if(!l)return this.jsonResponse({success:!0,message:"If the email exists, a reset link has been sent"});if(this.email){let u=randomBytes(32).toString("hex");if(this.authAdapter.createPasswordResetToken){let h=await this.authAdapter.createPasswordResetToken(l.email);h.token&&(u=h.token);}let y=`${this.getBaseUrl(e)}/admin/auth/reset-password?token=${u}`,x=this.email.getTemplates().resetPassword(y,l.email);await this.email.send({to:l.email,...x});}return this.auditLogger&&await this.auditLogger.log({action:"password_reset",userId:l.id,userEmail:l.email,resource:"auth",ipAddress:t,userAgent:s,success:!0}),this.jsonResponse({success:!0,message:"If the email exists, a reset link has been sent"})}catch{return this.errorResponse("Password reset request failed",500)}}async resetPassword(e){let{ipAddress:t,userAgent:s}=a$1(e);if(this.rateLimiter){let n=await this.rateLimiter.check("auth:reset",t);if(!n.allowed)return this.rateLimitResponse(n)}try{let n=await e.json(),{token:c,newPassword:l,confirmPassword:u}=n;if(!c||!l)return this.errorResponse("Reset token and new password are required",400);if(l!==u)return this.errorResponse("Passwords do not match",400);let f=this.passwordPolicy.validate(l);if(!f.valid)return this.errorResponse(f.errors.join(". "),400);if(this.authAdapter.resetPasswordWithToken){let y=await this.authAdapter.resetPasswordWithToken(c,l);if(!y.success)return this.errorResponse(y.error||"Password reset failed or token expired",400)}return this.jsonResponse({success:!0,message:"Password reset successful. You can now log in with your new password."})}catch(n){return console.error("[AuthRoutes.resetPassword] Error:",n),this.errorResponse("Password reset failed",500)}}async verifyEmail(e){let s=new URL(e.url).searchParams.get("token");if(!s)return this.errorResponse("Verification token required",400);try{if(this.authAdapter.verifyEmailToken){let n=await this.authAdapter.verifyEmailToken(s);if(!n.success)return this.errorResponse(n.error||"Invalid or expired verification token",400);if(n.userId&&this.email){let c=await this.authAdapter.findUserById(n.userId);if(c){let l=this.email.getTemplates().welcome(c.email);await this.email.send({to:c.email,...l});}}}return this.jsonResponse({success:!0,message:"Email address verified successfully"})}catch(n){return console.error("[AuthRoutes.verifyEmail] Error:",n),this.errorResponse("Email verification failed",500)}}async recordFailedLogin(e,t,s,n){this.lockout&&await this.lockout.recordFailedAttempt(s||e),this.auditLogger&&await this.auditLogger.log({action:"login_failed",userId:s,userEmail:n,resource:"auth",ipAddress:e,userAgent:t,success:false,error:"Invalid credentials"});}sanitizeUser(e){let{passwordHash:t,...s}=e;return s}jsonResponse(e,t=200){return new Response(JSON.stringify(e),{status:t,headers:{"Content-Type":"application/json","Cache-Control":"no-store, no-cache, must-revalidate, max-age=0"}})}async listSessions(e){let t=await ee(e);if(!t)return this.errorResponse("Not authenticated",401);try{let s=await Ie(t.userId,se(e)??void 0);return this.jsonResponse({sessions:s})}catch(s){return console.error("[AuthRoutes.listSessions] Error:",s),this.errorResponse("Failed to list sessions",500)}}async revokeSession(e,t){let s=await ee(e);if(!s)return this.errorResponse("Not authenticated",401);try{let c=(await Ie(s.userId)).find(l=>l.id===t);return c?c.currentSession?this.errorResponse("Cannot revoke current session",400):(await ve(t),this.jsonResponse({success:!0,message:"Session revoked"})):this.errorResponse("Session not found",404)}catch(n){return console.error("[AuthRoutes.revokeSession] Error:",n),this.errorResponse("Failed to revoke session",500)}}async revokeOtherSessions(e){let t=await ee(e);if(!t)return this.errorResponse("Not authenticated",401);try{let s=await Ie(t.userId),n=se(e);for(let c of s)c.currentSession||await ve(c.id);return this.jsonResponse({success:!0,message:"Other sessions revoked"})}catch(s){return console.error("[AuthRoutes.revokeOtherSessions] Error:",s),this.errorResponse("Failed to revoke sessions",500)}}async renameSession(e,t){let s=await ee(e);if(!s)return this.errorResponse("Not authenticated",401);try{if(!(await Ie(s.userId)).find(f=>f.id===t))return this.errorResponse("Session not found",404);let l=await e.json(),{name:u}=l;return !u||typeof u!="string"||u.trim().length===0?this.errorResponse("Invalid session name",400):(await lt(t,u.trim()),this.jsonResponse({success:!0,message:"Session renamed"}))}catch(n){return console.error("[AuthRoutes.renameSession] Error:",n),this.errorResponse("Failed to rename session",500)}}async refreshSession(e){let t=se(e);if(!t)return this.errorResponse("No session",401);try{let s=await(Ne(),c(Bt)).refreshSession(t,e);return s?this.jsonResponse({success:!0,expiresAt:s.expiresAt}):this.errorResponse("Session not found",404)}catch(s){return console.error("[AuthRoutes.refreshSession] Error:",s),this.errorResponse("Failed to refresh session",500)}}errorResponse(e,t){return new Response(JSON.stringify({success:false,error:e}),{status:t,headers:{"Content-Type":"application/json"}})}async rateLimitResponse(e){return new Response(JSON.stringify({success:false,error:"Too many requests",retryAfter:e.retryAfter}),{status:429,headers:{"Content-Type":"application/json","Retry-After":String(e.retryAfter||60)}})}};function he(d){let{uploadDir:e=join(Er.cwd(),"public","uploads"),baseUrl:t="/uploads"}=d;async function s(l){existsSync(l)||await mkdir(l,{recursive:true});}function n(l){let u=extname(l).toLowerCase();return {".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".webp":"image/webp",".avif":"image/avif",".svg":"image/svg+xml",".mp4":"video/mp4",".webm":"video/webm",".mov":"video/quicktime",".avi":"video/x-msvideo",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip",".rar":"application/vnd.rar",".7z":"application/x-7z-compressed"}[u]||"application/octet-stream"}async function c(l){try{let u=l.toString("hex",0,8);if(u.startsWith("89504e47")){let f=l.readUInt32BE(16),y=l.readUInt32BE(20);return {width:f,height:y}}if(u.startsWith("ffd8")){let f=2;for(;f<l.length&&l[f]===255;){let y=l[f+1];if(y===192||y===194){let x=l.readUInt16BE(f+5);return {width:l.readUInt16BE(f+7),height:x}}f+=2+l.readUInt16BE(f+2);}}}catch{}return {}}return ue({name:"local",displayName:"Local Storage",supportsDynamicResize:true,async upload(l,u){await s(e);let f=Buffer.from(await l.arrayBuffer()),y=createHash("md5").update(f).digest("hex"),x=extname(l.name),h=u?.filename||`${y}${x}`,E=u?.folder||"",_=E?join(e,E):e;await s(_);let R=join(_,h);await writeFile(R,f);let q=l.type.startsWith("image/")?await c(f):{},W=t||"/uploads",V=E?`/${E}/${h}`:`/${h}`,ne=W+V;return {id:y,filename:h,originalName:l.name,mimeType:l.type||n(l.name),size:f.length,url:ne,thumbnailUrl:l.type.startsWith("image/")?ne:void 0,folder:E||void 0,provider:"local",metadata:{...q,...u?.metadata},createdAt:new Date().toISOString()}},async uploadFromUrl(l,u){let f=await fetch(l);if(!f.ok)throw new Error(`Failed to fetch file: ${f.statusText}`);let y=await f.blob(),x=f.headers.get("content-disposition"),h=u?.filename;if(!h&&x){let _=x.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);_&&(h=_[1].replace(/['"]/g,""));}h||(h=basename(new URL(l).pathname));let E=new File([y],h,{type:y.type||n(h)});return this.upload(E,u)},async delete(l){let u=join(e,l.replace(t+"/",""));try{await unlink(u);}catch{}},async rename(l,u){let f=join(e,l.replace(t+"/","")),y=join(e,u);return await rename(f,y),`${t}/${u}`},async list(l){let u=l?join(e,l):e;if(!existsSync(u))return [];let f=[],y=await readdir(u,{withFileTypes:true});for(let x of y)if(x.isFile()){let h=join(u,x.name),E=await stat(h),_=`${t}${l?`/${l}`:""}/${x.name}`;f.push({id:createHash("md5").update(x.name).digest("hex"),filename:x.name,originalName:x.name,mimeType:n(x.name),size:E.size,url:_,provider:"local",createdAt:E.birthtime.toISOString()});}return f},async exists(l){let u=join(e,l.replace(t+"/",""));return existsSync(u)},async createFolder(l){let u=join(e,l);await mkdir(u,{recursive:true});},async deleteFolder(l){let u=join(e,l);if(existsSync(u)){let{rm:f}=await import('fs/promises');await f(u,{recursive:true,force:true});}}})}function ct(d){let e=(t,s)=>{if(!d.signKey)return t;let n=createHmac("sha256",d.signKey).update(t+s.toString()).digest("hex");return s.set("s",n),t};return {name:"imgix",displayName:"Imgix",supportsDynamicResize:true,async upload(t,s){throw new Error("Imgix is a transformation service. Use another provider for uploads.")},async uploadFromUrl(t,s){let n=s?.filename||t.split("/").pop()||"file",c=await fetch(t);if(!c.ok)throw new Error(`Failed to fetch: ${c.statusText}`);let l=await c.blob();new File([l],n,{type:l.type});return {id:Buffer.from(t).toString("base64").slice(0,20),filename:n,originalName:n,mimeType:l.type,size:l.size,url:this.getImageUrl(t),thumbnailUrl:this.getImageUrl(t,{width:200,height:200,fit:"crop"}),provider:"imgix",createdAt:new Date().toISOString()}},async delete(t){},async rename(t,s){return `https://${d.domain}/${s}`},getImageUrl(t,s){let n=new URL(t),c=new URLSearchParams(n.search);d.defaultParameters&&Object.entries(d.defaultParameters).forEach(([u,f])=>{c.has(u)||c.set(u,f);}),s&&(s.width&&c.set("w",String(s.width)),s.height&&c.set("h",String(s.height)),s.quality&&c.set("q",String(s.quality)),s.format&&c.set("fm",s.format),s.fit&&c.set("fit",s.fit),s.blur&&c.set("blur",String(s.blur)),s.sharpen&&c.set("sharp",String(s.sharpen))),c.set("auto","compress,format");n.pathname+"?"+c.toString();return d.signKey&&(e(n.pathname+c.toString(),c)),`https://${d.domain}${n.pathname}${c.toString()?"?"+c.toString():""}`},async generateThumbnail(t){return this.getImageUrl(t.url,{width:200,height:200,fit:"crop"})},async list(){return []},async exists(t){try{return (await fetch(t,{method:"HEAD"})).ok}catch{return false}},async createFolder(){},async deleteFolder(){}}}function Ke(d,e){return e.cdnUrl?`${e.cdnUrl.replace(/\/$/,"")}/${d}`:`https://${e.storageZone}.b-cdn.net/${d}`}function ut(d){return d.cdnUrl?d.cdnUrl.replace(/\/$/,"")+"/":`https://${d.storageZone}.b-cdn.net/`}function pt(d){let e=`https://storage.bunnycdn.com/${d.storageZone}`,t=s=>`${d.prefix?`${d.prefix}/`:""}${s}`.replace(/\/+/g,"/");return ue({name:"bunny",displayName:"Bunny.net Storage",supportsDynamicResize:true,async upload(s,n){let c=t(`${n?.folder?`${n.folder}/`:""}${n?.filename||s.name}`),l=Buffer.from(await s.arrayBuffer()),u=await fetch(`${e}/${c}`,{method:"PUT",headers:{AccessKey:d.apiKey,"Content-Type":s.type},body:l});if(!u.ok){let f=await u.text();throw new Error(`Bunny.net upload failed: ${u.status} ${f}`)}return {id:Buffer.from(c).toString("base64url"),filename:n?.filename||s.name,originalName:s.name,mimeType:s.type,size:l.length,url:Ke(c,d),thumbnailUrl:s.type.startsWith("image/")?Ke(c,d):void 0,folder:n?.folder,provider:"bunny",metadata:n?.metadata,createdAt:new Date().toISOString()}},async delete(s){let n=s.replace(ut(d),""),c=await fetch(`${e}/${n}`,{method:"DELETE",headers:{AccessKey:d.apiKey}});if(!c.ok&&c.status!==404){let l=await c.text();throw new Error(`Bunny.net delete failed: ${c.status} ${l}`)}},async rename(s,n){let c=s.replace(ut(d),""),l=d.prefix?`${d.prefix}/${n}`:n,u=await fetch(`${e}/${c}`,{method:"GET",headers:{AccessKey:d.apiKey}});if(!u.ok)throw new Error("Bunny.net rename failed: could not read old file");let f=await u.arrayBuffer();return await fetch(`${e}/${l}`,{method:"PUT",headers:{AccessKey:d.apiKey,"Content-Type":u.headers.get("Content-Type")||"application/octet-stream"},body:f}),await this.delete(s),Ke(l,d)},async list(s){let n=t(s||""),c=await fetch(`${e}/${n}`,{method:"GET",headers:{AccessKey:d.apiKey}});if(!c.ok){let u=await c.text();throw new Error(`Bunny.net list failed: ${c.status} ${u}`)}return (await c.json()).map(u=>({id:Buffer.from(u.ObjectName||"").toString("base64url"),filename:u.ObjectName?.split("/").pop()||"",originalName:u.ObjectName?.split("/").pop()||"",mimeType:"application/octet-stream",size:u.Length||0,url:Ke(u.ObjectName||"",d),provider:"bunny",createdAt:u.LastChanged||new Date().toISOString()}))},async exists(s){let n=s.replace(ut(d),"");return (await fetch(`${e}/${n}`,{method:"HEAD",headers:{AccessKey:d.apiKey}})).ok},async createFolder(s){let n=t(`${s}/`);await fetch(`${e}/${n}`,{method:"PUT",headers:{AccessKey:d.apiKey,"Content-Length":"0"},body:""});},async deleteFolder(s){let n=t(`${s}/`);await fetch(`${e}/${n}`,{method:"DELETE",headers:{AccessKey:d.apiKey}});}})}var gt=class{providers=new Map;providerToPlugin=new Map;disabledPlugins=new Set;constructor(){this.registerLocal(),this.registerImgix(),this.registerBunny();}registerLocal(){this.register({type:"local",displayName:"Local Server",configKey:"local",configFields:[{name:"uploadDir",type:"text",label:"Upload Directory",defaultValue:"./public/uploads"},{name:"baseUrl",type:"text",label:"Base URL",defaultValue:"/uploads"}],extractConfig:(e,t)=>e[t]||{},extractRawConfig:e=>{let t=e?.local||e,s=(t?.uploadDir||"").trim(),n;s?ze.isAbsolute(s)?n=s:s.includes("/")||s.includes("\\")?n=ze.resolve(process.cwd(),s):n=ze.join(process.cwd(),"public",s):n=ze.join(process.cwd(),"public","uploads");let c=(t?.baseUrl||"").trim(),l;return c?l=c.startsWith("/")?c:`/${c}`:l="/uploads",{uploadDir:n,baseUrl:l}},factory:e=>he(e)});}registerImgix(){this.register({type:"imgix",displayName:"Imgix",configKey:"imgix",configFields:[{name:"domain",type:"text",label:"Domain",required:true},{name:"signKey",type:"password",label:"Sign Key"}],extractConfig:(e,t)=>e[t]||{},extractRawConfig:e=>e?.imgix||e,factory:e=>ct(e)});}registerBunny(){this.register({type:"bunny",displayName:"Bunny.net",configKey:"bunny",configFields:[{name:"storageZone",type:"text",label:"Storage Zone",required:true},{name:"apiKey",type:"password",label:"API Key",required:true},{name:"cdnUrl",type:"text",label:"CDN URL"},{name:"prefix",type:"text",label:"Path Prefix"}],extractConfig:(e,t)=>e[t]||{},extractRawConfig:e=>e?.bunny||e,factory:e=>pt(e)});}register(e){if(this.providers.has(e.type)){console.warn(`[StorageRegistry] Provider "${e.type}" already registered, skipping`);return}e.pluginName&&this.providerToPlugin.set(e.type,e.pluginName),this.providers.set(e.type,e);}unregister(e){this.providers.delete(e),this.providerToPlugin.delete(e);}get(e){return this.providers.get(e)}getAll(){return Array.from(this.providers.values())}getAllAvailable(e){let t=this.getAll();return e?t.filter(s=>s.pluginName?e(s.pluginName):true):t}has(e){return this.providers.has(e)}async resolve(e,t){let s=this.providers.get(e);if(!s)throw new Error(`Unknown storage provider type: "${e}". Is the plugin that provides it enabled?`);if(s.pluginName&&this.disabledPlugins.has(s.pluginName))throw new Error(`Storage provider "${e}" is not available (plugin "${s.pluginName}" is disabled)`);let n=s.configKey||e,c=s.extractConfig(t,n);return s.factory(c)}async resolveWithConfig(e,t){let s=this.providers.get(e);if(!s)throw new Error(`Unknown storage provider type: "${e}". Is the plugin that provides it enabled?`);if(s.pluginName&&this.disabledPlugins.has(s.pluginName))throw new Error(`Storage provider "${e}" is not available (plugin "${s.pluginName}" is disabled)`);let n=s.extractRawConfig(t);return s.factory(n)}getProviderPluginName(e){return this.providerToPlugin.get(e)}getAllPluginNames(){return Array.from(new Set(this.providerToPlugin.values()))}setPluginEnabled(e,t){t?this.disabledPlugins.delete(e):this.disabledPlugins.add(e);}isPluginEnabled(e){return !this.disabledPlugins.has(e)}},mt=null;function ft(){return mt||(mt=new gt),mt}function Qt(d){if(!d)return "";if(d.startsWith("pub-"))return d;let e=d.match(/pub-[a-zA-Z0-9]+/i);return e?e[0]:""}function Lr(d,e){let t=d.startsWith("/")?d.slice(1):d;if(e.cdnUrl)return `${e.cdnUrl.replace(/\/$/,"")}/${t}`;switch(e.provider){case "r2":{let s=Qt(e.publicDevUrl);return s?`https://${s}.r2.dev/${t}`:`https://${e.bucket}.${e.accountId}.r2.cloudflarestorage.com/${t}`}case "gcs":return `https://storage.googleapis.com/${e.bucket}/${t}`;case "digitalocean":return `https://${e.bucket}.${e.region}.cdn.digitaloceanspaces.com/${t}`;case "backblaze":return `https://${e.bucket}.s3.backblazeb2.com/${t}`;case "wasabi":return `https://${e.bucket}.s3.wasabisys.com/${t}`;default:return `https://${e.bucket}.s3.${e.region}.amazonaws.com/${t}`}}function yt(d){if(d.cdnUrl)return d.cdnUrl.replace(/\/$/,"")+"/";switch(d.provider){case "r2":{let e=Qt(d.publicDevUrl);return e?`https://${e}.r2.dev/`:`https://${d.bucket}.${d.accountId}.r2.cloudflarestorage.com/`}case "gcs":return `https://storage.googleapis.com/${d.bucket}/`;case "digitalocean":return `https://${d.bucket}.${d.region}.cdn.digitaloceanspaces.com/`;case "backblaze":return `https://${d.bucket}.s3.backblazeb2.com/`;case "wasabi":return `https://${d.bucket}.s3.wasabisys.com/`;default:return `https://${d.bucket}.s3.${d.region}.amazonaws.com/`}}function _r(d){switch(d){case "r2":return "Cloudflare R2";case "gcs":return "Google Cloud Storage";case "digitalocean":return "DigitalOcean Spaces";case "backblaze":return "Backblaze B2";case "wasabi":return "Wasabi";default:return "AWS S3"}}function Nr(d){let e=new S3Client({region:d.region||"auto",endpoint:d.endpoint,credentials:{accessKeyId:d.accessKeyId,secretAccessKey:d.secretAccessKey},forcePathStyle:true,tls:true,...d.provider==="r2"&&{requestHandler:new NodeHttpHandler}}),t=n=>`${d.prefix?`${d.prefix}/`:""}${n}`.replace(/\/+/g,"/"),s=n=>Lr(n,d);return ue({name:d.provider,displayName:_r(d.provider),supportsDynamicResize:true,async upload(n,c){let l=t(`${c?.folder?`${c.folder}/`:""}${c?.filename||n.name}`),u=Buffer.from(await n.arrayBuffer());await e.send(new PutObjectCommand({Bucket:d.bucket,Key:l,Body:u,ContentType:n.type,Metadata:c?.metadata}));let f=await e.send(new HeadObjectCommand({Bucket:d.bucket,Key:l}));return {id:Buffer.from(l).toString("base64url"),filename:c?.filename||n.name,originalName:n.name,mimeType:n.type,size:u.length,url:s(l),thumbnailUrl:n.type.startsWith("image/")?s(l):void 0,folder:c?.folder,provider:d.provider,metadata:{...c?.metadata,etag:f.ETag},createdAt:new Date().toISOString()}},async delete(n){let c=n.replace(yt(d),"");await e.send(new DeleteObjectCommand({Bucket:d.bucket,Key:c}));},async rename(n,c){let l=n.replace(yt(d),""),u=d.prefix?`${d.prefix}/${c}`:c;return await e.send(new CopyObjectCommand({Bucket:d.bucket,CopySource:`${d.bucket}/${l}`,Key:u})),await e.send(new DeleteObjectCommand({Bucket:d.bucket,Key:l})),s(u)},async list(n){let c=t(n||"");return ((await e.send(new ListObjectsV2Command({Bucket:d.bucket,Prefix:c}))).Contents||[]).map(u=>({id:Buffer.from(u.Key||"").toString("base64url"),filename:u.Key?.split("/").pop()||"",originalName:u.Key?.split("/").pop()||"",mimeType:"application/octet-stream",size:u.Size||0,url:s(u.Key||""),provider:d.provider,createdAt:u.LastModified?.toISOString()||new Date().toISOString()}))},async exists(n){try{let c=n.replace(yt(d),"");return await e.send(new HeadObjectCommand({Bucket:d.bucket,Key:c})),!0}catch{return false}},async createFolder(n){let c=t(`${n}/`);await e.send(new PutObjectCommand({Bucket:d.bucket,Key:c,Body:""}));},async deleteFolder(n){let c=t(`${n}/`),l;do{let u=await e.send(new ListObjectsV2Command({Bucket:d.bucket,Prefix:c,ContinuationToken:l}));if(u.Contents?.length){let f=u.Contents.map(y=>({Key:y.Key}));await e.send(new DeleteObjectsCommand({Bucket:d.bucket,Delete:{Objects:f}}));}l=u.IsTruncated?u.NextContinuationToken:void 0;}while(l);await e.send(new DeleteObjectCommand({Bucket:d.bucket,Key:c}));}})}function Or(d){let e=()=>`https://api.cloudinary.com/v1_1/${d.cloudName}/upload`,t=async s=>{let n=await import('crypto'),c=Object.keys(s).sort().map(l=>`${l}=${s[l]}`).join("&");return n.createHash("sha256").update(c+d.apiSecret).digest("hex")};return {name:"cloudinary",displayName:"Cloudinary",supportsDynamicResize:true,async upload(s,n){let c=new FormData;if(c.append("file",s),d.uploadPreset)c.append("upload_preset",d.uploadPreset);else {let f=Math.round(Date.now()/1e3),y={timestamp:String(f)};(n?.folder||d.folder)&&(y.folder=n?.folder||d.folder||"");let x=await t(y);c.append("timestamp",String(f)),c.append("signature",x),c.append("api_key",d.apiKey);}(n?.folder||d.folder)&&c.append("folder",n?.folder||d.folder||"");let l=await fetch(e(),{method:"POST",body:c});if(!l.ok){let f=await l.json();throw new Error(`Cloudinary upload failed: ${f.error?.message||l.statusText}`)}let u=await l.json();return {id:u.public_id,filename:`${u.public_id}.${u.format}`,originalName:u.original_filename||s.name,mimeType:s.type||`image/${u.format}`,size:u.bytes,url:u.secure_url,thumbnailUrl:this.getImageUrl(u.secure_url,{width:200,height:200,fit:"crop"}),width:u.width,height:u.height,folder:n?.folder||d.folder,provider:"cloudinary",createdAt:new Date().toISOString()}},async uploadFromUrl(s,n){let c=new FormData;c.append("file",s),c.append("upload_preset","ml_default"),(n?.folder||d.folder)&&c.append("folder",n?.folder||d.folder||"");let l=await fetch(e(),{method:"POST",body:c});if(!l.ok)throw new Error("Cloudinary upload failed");let u=await l.json();return {id:u.public_id,filename:`${u.public_id}.${u.format}`,originalName:u.original_filename||s.split("/").pop()||"file",mimeType:`image/${u.format}`,size:u.bytes,url:u.secure_url,thumbnailUrl:this.getImageUrl(u.secure_url,{width:200,height:200,fit:"crop"}),width:u.width,height:u.height,provider:"cloudinary",createdAt:new Date().toISOString()}},async delete(s){try{let n=s.split("/image/upload/");if(n.length!==2){console.warn("[Cloudinary delete] Could not parse URL:",s);return}let c=n[1].replace(/^v\d+\//,"").replace(/\.[^.]+$/,""),l=Math.round(Date.now()/1e3),u={timestamp:String(l),public_id:c},f=Object.keys(u).sort().map(R=>`${R}=${u[R]}`).join("&"),x=(await import('crypto')).createHash("sha256").update(f+d.apiSecret).digest("hex"),h=`https://api.cloudinary.com/v1_1/${d.cloudName}/image/destroy`,E=new FormData;E.append("public_id",c),E.append("timestamp",String(l)),E.append("signature",x),E.append("api_key",d.apiKey);let _=await fetch(h,{method:"POST",body:E});if(!_.ok){let R=await _.json();console.warn("[Cloudinary delete] Failed:",R);}}catch(n){console.warn("[Cloudinary delete] Error:",n.message);}},async rename(s,n){let c="",l=n.replace(/\.[^.]+$/,""),u="";try{let f=s.split("/image/upload/");if(f.length!==2)return console.warn("[Cloudinary rename] Could not parse old URL:",s),s;let y=f[1],x=y.match(/^(v\d+)\//);c=x?x[1]:"";let h=y.replace(/^v\d+\//,"").replace(/\.[^.]+$/,""),E=h.split("/");u=E.length>1?E.slice(0,-1).join("/"):"";let _=n.replace(/\.[^.]+$/,"");l=u?`${u}/${_}`:_;let R=Math.round(Date.now()/1e3),q={from_public_id:h,to_public_id:l,timestamp:String(R)},W=Object.keys(q).sort().map(Z=>`${Z}=${q[Z]}`).join("&"),ne=(await import('crypto')).createHash("sha256").update(W+d.apiSecret).digest("hex"),$=new FormData;$.append("from_public_id",h),$.append("to_public_id",l),$.append("timestamp",String(R)),$.append("signature",ne),$.append("api_key",d.apiKey);let pe=await fetch(`https://api.cloudinary.com/v1_1/${d.cloudName}/image/rename`,{method:"POST",body:$});if(pe.ok)return (await pe.json()).secure_url;{let Z=await pe.json();console.warn("[Cloudinary rename] Failed:",Z);let k=c?`/${c}/`:"/";return `https://res.cloudinary.com/${d.cloudName}/image/upload${k}${l}.${n.split(".").pop()}`}}catch(f){console.warn("[Cloudinary rename] Error:",f.message);let y=c?`/${c}/`:"/";return `https://res.cloudinary.com/${d.cloudName}/image/upload${y}${l}.${n.split(".").pop()}`}},getImageUrl(s,n){if(!n)return s;let c=s.split("/upload/");if(c.length!==2)return s;let l=[];if(n.width&&l.push(`w_${n.width}`),n.height&&l.push(`h_${n.height}`),n.fit){let f={crop:"c_fill",clip:"c_fit",scale:"c_scale",fill:"c_fill"};l.push(f[n.fit]||"c_limit");}n.quality&&l.push(`q_${n.quality}`),n.format&&l.push(`f_${n.format}`);let u=l.join(",");return `${c[0]}/upload/${u}/${c[1]}`},async generateThumbnail(s){return this.getImageUrl(s.url,{width:200,height:200,fit:"crop"})},async list(){return []},async exists(s){return (await fetch(s,{method:"HEAD"})).ok},async createFolder(){},async deleteFolder(){}}}function Br(d){let e=null;async function t(){return e||(e=new Client(6e4,{allowSeparateTransferHost:true}),e.ftp.verbose=false,await e.access({host:d.host,port:d.port||21,user:d.user,password:d.password,secure:d.secure,secureOptions:{}})),e}let s=l=>`${d.prefix?`${d.prefix}/`:""}${l}`.replace(/\/+/g,"/"),n=l=>`${d.baseUrl.replace(/\/$/,"")}/${l}`,c=()=>d.baseUrl.replace(/\/$/,"")+"/";return ue({name:d.type,displayName:d.type==="sftp"?"SFTP Storage":"FTP Storage",supportsDynamicResize:false,async upload(l,u){let f=await t(),y=s(`${u?.folder?`${u.folder}/`:""}${u?.filename||l.name}`),x=Buffer.from(await l.arrayBuffer()),h=y.split("/").slice(0,-1),E="";for(let R of h){E=E?`${E}/${R}`:R;try{await f.ensureDir(E);}catch{}}let _=Readable.from(x);return await f.uploadFrom(_,y),{id:Buffer.from(y).toString("base64url"),filename:u?.filename||l.name,originalName:l.name,mimeType:l.type,size:x.length,url:n(y),thumbnailUrl:l.type.startsWith("image/")?n(y):void 0,folder:u?.folder,provider:d.type,metadata:u?.metadata,createdAt:new Date().toISOString()}},async delete(l){let u=await t(),f=l.replace(c(),"");await u.remove(f);},async rename(l,u){let f=await t(),y=l.replace(c(),""),x=d.prefix?`${d.prefix}/${u}`:u;return await f.rename(y,x),n(x)},async list(l){let u=await t(),f=s(l||""),y;try{y=await u.list(f);}catch{return []}return y.filter(x=>x.type===0).map(x=>({id:Buffer.from(`${f}/${x.name}`).toString("base64url"),filename:x.name,originalName:x.name,mimeType:"application/octet-stream",size:Number(x.size)||0,url:n(`${f}/${x.name}`.replace(/\/+/g,"/")),provider:d.type,createdAt:x.modifiedAt?x.modifiedAt.toISOString():new Date().toISOString()}))},async exists(l){let u=await t(),f=l.replace(c(),"");try{return await u.size(f),!0}catch{return false}},async createFolder(l){let u=await t(),f=s(l);await u.ensureDir(f);},async deleteFolder(l){let u=await t(),f=s(l);await u.removeDir(f);}})}async function er(d){let e=d.getStorageConfig(),t=ft();try{return await t.resolve(e.type,e)}catch(s){return console.warn(`[resolveProvider] ${s.message} \u2014 falling back to local storage`),he({uploadDir:ze.join(process.cwd(),"public","uploads"),baseUrl:"/uploads"})}}function ue(d){return {async uploadFromUrl(e,t){let s=await fetch(e);if(!s.ok)throw new Error(`Failed to fetch: ${s.statusText}`);let n=await s.blob(),c=e.split("/").pop()||"file",l=new File([n],c,{type:n.type});return this.upload(l,t)},getImageUrl(e,t){if(!t||Object.keys(t).length===0)return e;let s=new URLSearchParams({url:e});return t.width&&s.set("w",String(t.width)),t.height&&s.set("h",String(t.height)),t.quality&&s.set("q",String(t.quality)),t.format&&s.set("f",t.format),t.cropWidth&&t.cropHeight&&(s.set("cx",String(t.cropX??0)),s.set("cy",String(t.cropY??0)),s.set("cw",String(t.cropWidth)),s.set("ch",String(t.cropHeight))),`/api/media/resize?${s.toString()}`},async generateThumbnail(e){return this.getImageUrl(e.url,{width:400,height:400})},...d}}async function tr(d){if(!d)return console.warn("[resolveProviderWithConfig] No config, using local"),he({uploadDir:ze.join(process.cwd(),"public","uploads"),baseUrl:"/uploads"});let e=d.type||"local",t=ft();try{return await t.resolveWithConfig(e,d)}catch(s){return console.warn(`[resolveProviderWithConfig] ${s.message} \u2014 falling back to local storage`),he({uploadDir:ze.join(process.cwd(),"public","uploads"),baseUrl:"/uploads"})}}function rr(){return typeof globalThis>"u"?false:typeof globalThis.EdgeRuntime=="string"||typeof globalThis.WebSocketPair<"u"||typeof globalThis.Deno<"u"||typeof process<"u"&&process.env?.NEXT_RUNTIME==="edge"}async function sr(d){if(!rr())try{let{default:e}=await import('sharp'),t=await e(d).metadata(),s=e(d).webp({quality:85}),n=e(d).resize({width:500,withoutEnlargement:!0}).webp({quality:80});return {buffer:await s.toBuffer(),thumbnailBuffer:await n.toBuffer(),width:t.width,height:t.height,format:"webp"}}catch{}return {buffer:d,thumbnailBuffer:d,format:"passthrough"}}var bt=false;function ke(d){if(typeof d!="string")return d;let e=d.replace(/-/g,"").toLowerCase();return e.length===32?`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`:d}var We=class d{db;storage;dialect;genId;mediaTable="media";foldersTable="media_folders";constructor(e$1,t,s){this.db=e$1,this.storage=t,this.dialect=s?.dialect||"sqlite",this.genId=s?.genId||e;}static async init(e,t){let s;if(t?.storageConfig)s=await tr(t.storageConfig);else {let c=new j(e);await c.load(),s=await er(c);}let n=new d(e,s,t);return await n.ensureTables(),n}async ensureTables(){if(this.dialect==="mongodb"){let e=this.db.db;await e.collection(this.mediaTable).createIndex({filename:1},{unique:true}),await e.collection(this.foldersTable).createIndex({path:1},{unique:true}),bt=true;return}if(this.dialect==="sqlite"){this.db.exec(`
2
2
  CREATE TABLE IF NOT EXISTS media (
3
3
  id TEXT PRIMARY KEY,
4
4
  filename TEXT NOT NULL UNIQUE,