modelence 0.21.0-ml.dev.5 → 0.22.0-mt.dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/chunk-5DFWJU3M.js +3 -0
  2. package/dist/chunk-5DFWJU3M.js.map +1 -0
  3. package/dist/chunk-6BB456MV.js +4 -0
  4. package/dist/chunk-6BB456MV.js.map +1 -0
  5. package/dist/chunk-BJWGBMNX.js +3 -0
  6. package/dist/chunk-BJWGBMNX.js.map +1 -0
  7. package/dist/chunk-KYQ6UVLY.js +37 -0
  8. package/dist/chunk-KYQ6UVLY.js.map +1 -0
  9. package/dist/{chunk-WN6LHVUX.js → chunk-MQQLQMPM.js} +2 -2
  10. package/dist/{chunk-WN6LHVUX.js.map → chunk-MQQLQMPM.js.map} +1 -1
  11. package/dist/{chunk-ENHGU3X4.js → chunk-VF4RU7MF.js} +2 -2
  12. package/dist/chunk-VF4RU7MF.js.map +1 -0
  13. package/dist/chunk-VYR7VQMQ.js +2 -0
  14. package/dist/chunk-VYR7VQMQ.js.map +1 -0
  15. package/dist/chunk-YM6DVNYH.js +2 -0
  16. package/dist/{chunk-FETZWGRY.js.map → chunk-YM6DVNYH.js.map} +1 -1
  17. package/dist/chunk-ZEXT732Q.js +2 -0
  18. package/dist/chunk-ZEXT732Q.js.map +1 -0
  19. package/dist/client.d.ts +64 -1
  20. package/dist/client.js +1 -1
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.js +1 -1
  23. package/dist/{package-DR33NPA4.js → package-Y67IHT4E.js} +2 -2
  24. package/dist/{package-DR33NPA4.js.map → package-Y67IHT4E.js.map} +1 -1
  25. package/dist/render-G33LE5AY.js +2 -0
  26. package/dist/render-G33LE5AY.js.map +1 -0
  27. package/dist/renderApp-F7NZT5JC.js +2 -0
  28. package/dist/{renderApp-MUFL3XZS.js.map → renderApp-F7NZT5JC.js.map} +1 -1
  29. package/dist/server-BEYRNZY5.js +2 -0
  30. package/dist/{server-MX562GVR.js.map → server-BEYRNZY5.js.map} +1 -1
  31. package/dist/server.d.ts +33 -2
  32. package/dist/server.js +1 -1
  33. package/dist/telemetry.js +1 -1
  34. package/dist/transport-TR3OYHQR.js +2 -0
  35. package/dist/{transport-ESHFT6E2.js.map → transport-TR3OYHQR.js.map} +1 -1
  36. package/dist/{types-XQVUUWNK.d.ts → types-D_70a365.d.ts} +46 -1
  37. package/dist/types.d.ts +1 -1
  38. package/package.json +4 -6
  39. package/dist/chunk-AMJHJA2V.js +0 -2
  40. package/dist/chunk-AMJHJA2V.js.map +0 -1
  41. package/dist/chunk-ENHGU3X4.js.map +0 -1
  42. package/dist/chunk-FETZWGRY.js +0 -2
  43. package/dist/chunk-FPJ4JADS.js +0 -2
  44. package/dist/chunk-FPJ4JADS.js.map +0 -1
  45. package/dist/chunk-GSNESHYT.js +0 -37
  46. package/dist/chunk-GSNESHYT.js.map +0 -1
  47. package/dist/chunk-MIRF7FP3.js +0 -2
  48. package/dist/chunk-MIRF7FP3.js.map +0 -1
  49. package/dist/chunk-POLHYJF6.js +0 -3
  50. package/dist/chunk-POLHYJF6.js.map +0 -1
  51. package/dist/chunk-UP2DHNXI.js +0 -4
  52. package/dist/chunk-UP2DHNXI.js.map +0 -1
  53. package/dist/render-F724NVRL.js +0 -2
  54. package/dist/render-F724NVRL.js.map +0 -1
  55. package/dist/renderApp-MUFL3XZS.js +0 -2
  56. package/dist/server-MX562GVR.js +0 -2
  57. package/dist/transport-ESHFT6E2.js +0 -2
@@ -0,0 +1,37 @@
1
+ import {s as s$1}from'./chunk-5DFWJU3M.js';import {a,b as b$1,c,r,s,t,u,v,n,o,h,k,d,A,m,l,p,q,w,B as B$1,C as C$1,D,E as E$1,e as e$1,F as F$1,y as y$1,x,f as f$1,g as g$1,I,G as G$1,H}from'./chunk-6BB456MV.js';import {c as c$1,b as b$2,d as d$1,a as a$4}from'./chunk-VYR7VQMQ.js';import {a as a$2,f,e,g,c as c$2,h as h$1,l as l$1,k as k$1,d as d$2,j,m as m$1,i,n as n$1}from'./chunk-VF4RU7MF.js';import {a as a$3,b as b$3}from'./chunk-5M6FUMUK.js';import {a as a$1}from'./chunk-DO5TZLF5.js';import ho from'dotenv';import Fi from'fs/promises';import li from'os';import Z from'path';import {Server}from'socket.io';import {createAdapter}from'@socket.io/mongo-adapter';import {ObjectId,MongoServerError,MongoClient,MongoError}from'mongodb';export{ObjectId as m}from'mongodb';import jo from'bcrypt';import G,{z}from'zod';import {randomBytes,randomInt,randomUUID}from'crypto';import {createServer,defineConfig,loadConfigFromFile,mergeConfig}from'vite';import xi from'@vitejs/plugin-react';import Le from'fs';import q$1,{Router}from'express';import Ln from'cookie-parser';import Un from'http';var le=new a("_system",{configSchema:{mongodbUri:{type:"secret",isPublic:false,default:""},mongodbPoolSize:{type:"number",isPublic:false,default:10},"env.type":{type:"string",isPublic:true,default:""},"site.url":{type:"string",isPublic:true,default:""},multiInstance:{type:"boolean",isPublic:false,default:false}}});var B=null;async function Qt(){if(B)return B;let e=N();if(!e)throw new Error("MongoDB URI is not set");let t=le.getConfig("mongodbPoolSize");B=new MongoClient(e,{driverInfo:{name:"Modelence",version:s$1.version},ignoreUndefined:true,maxPoolSize:t});try{return await B.connect(),await B.db("admin").command({ping:1}),console.log("Pinged your deployment. You successfully connected to MongoDB!"),B}catch(r){throw console.error(r),B=null,r}}function N(){return le.getConfig("mongodbUri")||void 0}function ve(){return B}var de=null,To="_modelenceSocketio",Xt=60;async function Mo({httpServer:e,channels:t}){let r=ve(),o=!!a$2("_system.multiInstance");console.log("Initializing Socket.IO server...");let i=null;if(o&&r){i=r.db().collection(To);try{await i.createIndex({createdAt:1},{expireAfterSeconds:Xt,background:!0});}catch(n){if(n instanceof Error&&"code"in n&&n.code===85)try{await i.dropIndex("createdAt_1"),await i.createIndex({createdAt:1},{expireAfterSeconds:Xt,background:!0});}catch(s){console.error("Failed to recreate index on MongoDB collection for Socket.IO:",s);}else console.error("Failed to create index on MongoDB collection for Socket.IO:",n);}}de=new Server(e,{cors:{origin:"*",methods:["GET","POST"]},adapter:i?createAdapter(i):void 0,transports:["websocket"],perMessageDeflate:false}),de.on("error",n=>{console.error("Socket.IO error:",n);}),de.use(async(n,s)=>{let a=n.handshake.auth.token;try{n.data=await y$1(a),s();}catch(c){s(c instanceof Error?c:new Error(String(c)));}}),de.on("connection",n=>{n.on("disconnect",()=>{I(n);}),n.on("joinChannel",async s=>{let[a]=s.split(":"),c=false;for(let l of t)if(l.category===a){(!l.canAccessChannel||await l.canAccessChannel(n.data))&&(n.join(s),c=true,n.emit("joinedChannel",s));break}c||n.emit("joinError",{channel:s,error:"Access denied"});}),n.on("leaveChannel",s=>{n.leave(s),console.log(`User ${n.id} left channel ${s}`),n.emit("leftChannel",s);}),n.on("subscribeLiveQuery",s=>G$1(n,s)),n.on("unsubscribeLiveQuery",s=>H(n,s));}),console.log("Socket.IO server initialized");}function Io({category:e,id:t,data:r}){de?.to(`${e}:${t}`).emit(e,r);}var Zt={init:Mo,broadcast:Io};async function ke(e){let t=e.toLowerCase().trim().split("@");if(t.length!==2)return false;let r=t[1];return !!await s.findOne({domain:r})}var er={interval:a$1.days(1),async handler(){let e=await fetch("https://disposable.github.io/disposable-email-domains/domains.txt");if(!e.ok)throw new Error(`HTTP ${e.status}: ${e.statusText}`);let r=(await e.text()).split(`
2
+ `).map(n=>n.trim().toLowerCase()).filter(n=>n.length>0),o=new Date,i=500;for(let n=0;n<r.length;n+=i){let s$1=r.slice(n,n+i);try{await s.insertMany(s$1.map(a=>({domain:a,addedAt:o})));}catch(a){a&&typeof a=="object"&&"name"in a&&a.name;}}}};var Ce=3,J=50,tr=8,rr=128,or=254,ir=e=>z.string().trim().min(e.min??1,{message:`must be at least ${e.min??1} characters`}).max(e.max,{message:`must be at most ${e.max} characters`}),ze=e=>z.string().trim().max(e.max,{message:`must be at most ${e.max} characters`}).transform(t=>t===""?void 0:t).optional(),No=z.object({firstName:ze({max:50}),lastName:ze({max:50}),avatarUrl:ze({max:400}),handle:ir({min:Ce,max:J})}).strict();function Se(e){let t=No.partial().safeParse(e);if(!t.success){let r=t.error.issues[0],o=r.path.join("."),i=o?`${o}: ${r.message}`:r.message;throw new Error(i)}return t.data}function Ae(e){return z.string().min(tr,{message:`Password must contain at least ${tr} characters`}).max(rr,{message:`Password must be at most ${rr} characters`}).parse(e)}function _(e){return z.string().max(or,{message:`Email must be at most ${or} characters`}).email({message:"Invalid email address"}).parse(e).toLowerCase()}function nr(e){return ir({min:Ce,max:J}).parse(e)}function Re(e){return e instanceof MongoServerError&&e.code===11e3&&typeof e.keyPattern=="object"&&e.keyPattern!==null&&"emails.address"in e.keyPattern}function Oe(e,t){return t?t.startsWith("http://")||t.startsWith("https://")?t:`${e}${t.startsWith("/")?"":"/"}${t}`:e}function F(e){return {id:e._id,handle:e.handle,roles:e.roles||[],firstName:e.firstName??void 0,lastName:e.lastName??void 0,avatarUrl:e.avatarUrl??void 0}}async function sr(e){let t=e.slice(0,J);try{if(!await r.findOne({handle:t},{collation:{locale:"en",strength:2}}))return t}catch(i){throw new Error(`Database error while checking handle availability: ${i}`)}let r$1=51;for(let i=2;i<=r$1;i++){let n=`_${i}`,s=`${t.slice(0,J-n.length)}${n}`;try{if(!await r.findOne({handle:s},{collation:{locale:"en",strength:2}}))return s}catch(a){throw new Error(`Database error while checking handle "${s}": ${a}`)}}let o=10;for(let i=0;i<o;i++){let n=`_${randomBytes(3).toString("hex")}`,s=`${t.slice(0,J-n.length)}${n}`;try{if(!await r.findOne({handle:s},{collation:{locale:"en",strength:2}}))return s}catch(a){throw new Error(`Database error while checking handle "${s}": ${a}`)}}throw new Error(`Could not generate a unique handle for base "${e}" after exhausting all attempts.`)}async function U(e,t,{throwOnConflict:r$1=true}={}){if(e!=null&&String(e).trim()!==""){let i=nr(String(e).trim());if(r$1){if(await r.findOne({handle:i},{collation:{locale:"en",strength:2}}))throw new Error("Handle already taken.");return i}return sr(i)}let o=t.split("@")[0].padEnd(Ce,"_").slice(0,J);return sr(o)}var We=Object.freeze({});function Je(e){We=Object.freeze(Object.assign({},We,e));}function E(){return We}var Ke=Object.freeze({});function ar(e){Ke=Object.freeze(Object.assign({},Ke,e));}function y(){return Ke}function Vo(){return E()?.provider?!!a$2("_system.user.auth.email.verification"):false}async function lr(e,{user:t,session:r$1,connectionInfo:o$1,res:i}){try{if(!r$1)throw new Error("Session is not initialized");if(t)throw new c$1("User is already authenticated","ALREADY_AUTHENTICATED");let n=o$1?.ip;n&&await C({bucket:"signin",type:"ip",value:n});let s=_(e.email),a=z.string().parse(e.password),c=await r.findOne({"emails.address":s,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}}),l=c?.authMethods?.password?.hash;if(!l)throw cr();if(!c.emails?.find(f=>f.address.toLowerCase()===s)?.verified&&Vo())throw new b$2("Your email address hasn't been verified yet. Please check your inbox for the verification email.","EMAIL_NOT_VERIFIED");if(!await jo.compare(a,l))throw cr();return await k(r$1.authToken,c._id),i&&o(i,r$1.authToken),y().onAfterLogin?.({provider:"email",user:c,session:r$1,connectionInfo:o$1}),y().login?.onSuccess?.(c),{user:F(c),session:{authToken:r$1.authToken}}}catch(n){throw n instanceof Error&&(y().onLoginError?.({provider:"email",error:n,session:r$1,connectionInfo:o$1}),y().login?.onError?.(n)),n}}async function dr(e,{session:t,res:r}){if(!t)throw new Error("Session is not initialized");await l(t.authToken),r&&p(r);}function cr(){return new Error("Incorrect email/password combination")}async function ur(e,{user:t}){if(!t)throw new Error("Not authenticated");let r$1=await r.requireById(t.id);return {handle:r$1.handle,emails:r$1.emails,authMethods:Object.keys(r$1.authMethods||{}),firstName:r$1.firstName??void 0,lastName:r$1.lastName??void 0,avatarUrl:r$1.avatarUrl??void 0}}async function mr(e,{user:t}){if(!t)throw new Error("Not authenticated");let r$1=await r.requireById(t.id),o=Se(e);if(await y().validateProfileUpdate?.(o),"handle"in o&&o.handle!==void 0&&await r.findOne({handle:o.handle,_id:{$ne:r$1._id}},{collation:{locale:"en",strength:2}}))throw new Error("Handle already taken.");if(Object.keys(o).length>0){let i={},n={};for(let[a,c]of Object.entries(o))c===void 0?n[a]="":i[a]=c;let s={};Object.keys(i).length>0&&(s.$set=i),Object.keys(n).length>0&&(s.$unset=n);try{await r.updateOne({_id:r$1._id},s);let a=Object.fromEntries(Object.keys(n).map(c=>[c,void 0]));r$1={...r$1,...i,...a};}catch(a){throw a instanceof Error&&"code"in a&&a.code===11e3?new Error("Handle already taken."):a}}return {user:F(r$1)}}var Ye=["google","github"];async function pr({provider:e},{user:t}){if(!t)throw new Error("You must be signed in to unlink a provider.");if(typeof e!="string"||!Ye.includes(e))throw new Error(`Invalid provider. Supported providers are: ${Ye.join(", ")}.`);let r$1=await r.requireById(t.id),o=r$1.authMethods??{};if(!o[e])throw new Error(`${e} is not linked to your account.`);if(Object.values(o).filter(Boolean).length<=1)throw new Error("Cannot unlink your only authentication method. Please add another method first.");let s=Object.keys(o).filter(l=>l!==e&&o[l]),a=s.length>0?{$or:s.map(l=>({[`authMethods.${l}`]:{$exists:true}}))}:{};if((await r.updateOne({_id:r$1._id,...a},{$unset:{[`authMethods.${e}`]:""}})).matchedCount===0)throw new Error("Cannot unlink your only authentication method. Please add another method first.")}var me=new b$1("_modelenceRateLimits",{schema:{bucket:c.string(),type:c.enum(["ip","user","email"]),value:c.string(),windowMs:c.number(),windowStart:c.date(),windowCount:c.number(),prevWindowCount:c.number(),expiresAt:c.date()},indexes:[{key:{bucket:1,type:1,value:1,windowMs:1},unique:true},{key:{expiresAt:1},expireAfterSeconds:0}]});var Qe=[];function fr(e){if(Qe.length>0)throw new Error("Duplicate call to initRateLimits - already initialized");Qe=e;}async function C(e){let{bucket:t,type:r,value:o,message:i}=e,n=Qe.filter(a=>a.bucket===t&&a.type===r),s=i?()=>new d$1(i):void 0;for(let a of n)await Bo(a,o,s);}async function Bo(e,t,r){let o=()=>r?r():new d$1(`Rate limit exceeded for ${e.bucket}`),i=await me.findOne({bucket:e.bucket,type:e.type,value:t,windowMs:e.window}),n=Date.now(),s=Math.floor(n/e.window)*e.window,{count:a,modifier:c}=i?Fo(i,s,n):{count:0,modifier:{$setOnInsert:{windowStart:new Date(s),windowCount:1,prevWindowCount:0,expiresAt:new Date(s+e.window+e.window)}}};if(a>=e.limit)throw o();await me.upsertOne({bucket:e.bucket,type:e.type,value:t,windowMs:e.window},c);}function Fo(e,t,r){let o=t-e.windowMs;if(e.windowStart.getTime()===t){let i=e.windowCount,n=e.prevWindowCount,s=1-(r-t)/e.windowMs;return {count:Math.round(i+n*s),modifier:{$inc:{windowCount:1},$setOnInsert:{windowStart:new Date(t),prevWindowCount:0,expiresAt:new Date(t+e.windowMs+e.windowMs)}}}}if(e.windowStart.getTime()===o){let i=1-(r-t)/e.windowMs;return {count:Math.round(e.windowCount*i),modifier:{$set:{windowStart:new Date(t),windowCount:1,prevWindowCount:e.windowCount,expiresAt:new Date(t+e.windowMs+e.windowMs)}}}}return {count:0,modifier:{$set:{windowStart:new Date(t),windowCount:1,prevWindowCount:0,expiresAt:new Date(t+e.windowMs+e.windowMs)}}}}function gr({name:e,email:t,verificationUrl:r}){return `
3
+ <p>Hi${e?` ${e}`:""},</p>
4
+ <p>Please verify your email address ${t} by clicking the link below:</p>
5
+ <p><a href="${r}">${r}</a></p>
6
+ <p>If you did not request this, please ignore this email.</p>
7
+ `}async function zo(e){let t$1=await t.findOne({token:e,expiresAt:{$gt:new Date}});if(!t$1)throw new Error("Invalid or expired verification token");if(!await r.findOne({_id:t$1.userId,status:{$nin:["deleted","disabled"]}}))throw new Error("User not found");let o=t$1.email;if(!o)throw new Error("Email not found in token");let i=await r.findOneAndUpdate({_id:t$1.userId,status:{$nin:["deleted","disabled"]},"emails.address":o,"emails.verified":{$ne:true}},{$set:{"emails.$.verified":true}},{returnDocument:"after"});if(!i)throw await r.findOne({_id:t$1.userId,"emails.address":o})?new Error("Email is already verified"):new Error("Email address not found for this user");return await t.deleteOne({_id:t$1._id}),{userDoc:i,email:o}}async function hr(e){let t=a$2("_system.site.url"),r=E().verification?.redirectUrl||E().emailVerifiedRedirectUrl||t||"/";try{let o$1=z.string().parse(e.query.token),{userDoc:i}=await zo(o$1);y().onAfterEmailVerification?.({provider:"email",user:i,session:null,connectionInfo:{baseUrl:t,ip:e.req.ip||e.req.socket.remoteAddress,userAgent:e.headers["user-agent"],acceptLanguage:e.headers["accept-language"],referrer:e.headers.referer}});let{authToken:s}=await n(i._id);return o(e.res,s),{status:301,headers:{"Referrer-Policy":"no-referrer"},redirect:`${r}?status=verified`}}catch(o){let i=o instanceof Error?o.message:"An unexpected error occurred";return o instanceof Error&&(y().onEmailVerificationError?.({provider:"email",error:o,session:null,connectionInfo:{baseUrl:t,ip:e.req.ip||e.req.socket.remoteAddress,userAgent:e.headers["user-agent"],acceptLanguage:e.headers["accept-language"],referrer:e.headers.referer}}),console.error("Error verifying email:",o)),{status:301,headers:{"Referrer-Policy":"no-referrer"},redirect:`${r}?status=error&message=${encodeURIComponent(i)}`}}}async function Ze({userId:e,email:t$1,baseUrl:r}){let o=a$2("_system.site.url")||r;if(E().provider){let i=E().provider,n=randomBytes(32).toString("hex"),s=new Date(Date.now()+a$1.hours(24));await t.insertOne({userId:e,email:t$1,token:n,createdAt:new Date,expiresAt:s});let a=`${o}/api/_internal/auth/verify-email?token=${n}`,l=(E()?.verification?.template||gr)({name:"",email:t$1,verificationUrl:a}),d=A(l);await i?.sendEmail({to:t$1,from:E()?.from||"noreply@modelence.com",subject:E()?.verification?.subject||"Verify your email address",text:d,html:l});}}var Xe={success:true,message:"If that email is registered and not yet verified, a verification email has been sent"};async function wr(e,{connectionInfo:t}){let r$1=_(e.email),o=await r.findOne({"emails.address":r$1,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}});if(!o)return Xe;let i=o.emails?.find(n=>n.address.toLowerCase()===r$1);if(!i||i.verified)return Xe;if(!E().provider)throw new Error("Email provider is not configured");return await C({bucket:"verification",type:"user",value:o._id.toString(),message:"Please wait at least 60 seconds before requesting another verification email"}),await Ze({userId:o._id,email:r$1,baseUrl:t?.baseUrl}),Xe}async function yr(e,{user:t,session:r$1,connectionInfo:o}){let i=y();try{if(t)throw new c$1("User is already authenticated","ALREADY_AUTHENTICATED");let n=e,{firstName:s,lastName:a,avatarUrl:c,handle:l}=n,d=_(n.email),u=Ae(n.password),f=o?.ip;if(f&&await C({bucket:"signupAttempt",type:"ip",value:f}),!i.allowDisposableEmails&&await ke(d))throw new Error("Please use a permanent email address");let h=await r.findOne({"emails.address":d},{collation:{locale:"en",strength:2}});if(h){let L=h.emails?.find(D=>D.address.toLowerCase()===d);throw h.status==="disabled"?new Error("User is marked for deletion, please contact support if you want to restore the account."):new Error(`User with email already exists: ${L?.address}`)}await i.onBeforeSignup?.({email:d,firstName:s,lastName:a,handle:l,provider:"email",connectionInfo:o}),f&&await C({bucket:"signup",type:"ip",value:f});let w=Se({firstName:s,lastName:a,avatarUrl:c,handle:l});await i.validateSignup?.({email:d,password:u,...w});let k;if(w.handle)k=await U(w.handle,d);else if(i.generateHandle){let L=await i.generateHandle({email:d,firstName:w.firstName,lastName:w.lastName});k=await U(L,d,{throwOnConflict:!1});}else k=await U(void 0,d);let x=await jo.hash(u,10),T;try{T=await r.insertOne({handle:k,status:"active",emails:[{address:d,verified:!1}],createdAt:new Date,authMethods:{password:{hash:x}},...w.firstName!==void 0&&{firstName:w.firstName},...w.lastName!==void 0&&{lastName:w.lastName},...w.avatarUrl!==void 0&&{avatarUrl:w.avatarUrl}});}catch(L){throw Re(L)?new Error(`User with email already exists: ${d}`):L}let S=await r.findOne({_id:T.insertedId},{readPreference:"primary"});if(!S)throw new Error("User not found");return await Ze({userId:T?.insertedId,email:d,baseUrl:o?.baseUrl}),i.onAfterSignup?.({provider:"email",user:S,session:r$1,connectionInfo:o}),i.signup?.onSuccess?.(S),T.insertedId}catch(n){throw n instanceof Error&&(i.onSignupError?.({provider:"email",error:n,session:r$1,connectionInfo:o}),i.signup?.onError?.(n)),n}}var et="resetPasswordToken",Yo="/api/_internal/",kr={httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:Yo};async function Cr(e){return u.findOne({token:d(e)})}async function br(e){return u.findOneAndDelete({_id:e})}function Qo({email:e,resetUrl:t}){return `
8
+ <p>Hi,</p>
9
+ <p>We received a request to reset your password for ${e}.</p>
10
+ <p>Click the link below to reset your password:</p>
11
+ <p><a href="${t}">${t}</a></p>
12
+ <p>This link will expire in 1 hour.</p>
13
+ <p>If you did not request this password reset, please ignore this email.</p>
14
+ `}var Er={success:true,message:"If an account with that email exists, a password reset link has been sent"};async function Sr(e,{connectionInfo:t}){let r$1=_(e.email),o=t?.ip;o&&await C({bucket:"passwordReset",type:"ip",value:o}),await C({bucket:"passwordReset",type:"email",value:r$1});let i=await r.findOne({"emails.address":r$1,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}});if(!i)return Er;let n=E().provider;if(!n)throw new Error("Email provider is not configured");let s=randomBytes(32).toString("hex"),a=Date.now(),c=new Date(a),l=new Date(a+a$1.hours(1));await u.insertOne({userId:i._id,email:r$1,token:d(s),createdAt:c,expiresAt:l});let d$1=a$2("_system.site.url")||t?.baseUrl;if(!d$1)throw new Error("Unable to build password reset link: set _system.site.url (MODELENCE_SITE_URL)");let u$1=`${d$1}/api/_internal/auth/reset-password?token=${s}`,h=(E()?.passwordReset?.template||Qo)({email:r$1,resetUrl:u$1,name:""}),w=A(h);return await n.sendEmail({to:r$1,from:E()?.from||"noreply@modelence.com",subject:E()?.passwordReset?.subject||"Reset your password",text:w,html:h}),Er}async function Ar(e){let t=a$2("_system.site.url")||`${e.req.protocol}://${e.req.get("host")}`,r=Oe(t,E().passwordReset?.redirectUrl);try{let o=z.string().parse(e.query.token),i=await Cr(o);if(!i||i.expiresAt<new Date)throw new Error("This password reset link is invalid or has expired.");return e.res.cookie(et,o,{...kr,maxAge:a$1.hours(1)}),{status:302,headers:{"Referrer-Policy":"no-referrer"},redirect:r}}catch(o){return console.error("Error handling password reset landing:",o),{status:302,headers:{"Referrer-Policy":"no-referrer"},redirect:`${r}?status=error&message=${encodeURIComponent("This password reset link is invalid or has expired.")}`}}}async function Rr(e,t){let r$1=t.req?.cookies?.[et];!r$1&&e.token&&console.warn("[modelence] resetPassword received a token via request args instead of the httpOnly cookie. This path is deprecated and will be removed; ensure password reset emails link to /api/_internal/auth/reset-password so the token is exchanged server-side.");let o=z.string().parse(r$1??e.token),i=Ae(e.password),n=()=>{t.res?.clearCookie(et,kr);},s=await Cr(o);if(!s)throw n(),new Error("Invalid or expired reset token");if(s.expiresAt<new Date)throw await br(s._id),n(),new Error("Reset token has expired");let a=await r.findOne({_id:s.userId});if(!a)throw new Error("User not found");let c=await jo.hash(i,10);if(!await br(s._id))throw n(),new Error("Invalid or expired reset token");await r.updateOne({_id:a._id},{$set:{"authMethods.password.hash":c}}),s.email&&await r.updateOne({_id:a._id,"emails.address":s.email},{$set:{"emails.$.verified":true}},{collation:{locale:"en",strength:2}}),await m(a._id);let d=Array.from(new Set((a.emails??[]).map(u=>u.address?.toLowerCase()).filter(u=>!!u)));return d.length>0&&await v.deleteMany({email:{$in:d}}),n(),{success:true,message:"Password has been reset successfully"}}function Or({name:e,email:t,magicLinkUrl:r,code:o}){return `
15
+ <p>Hi${e?` ${e}`:""},</p>
16
+ <p>Click the link below to sign in as ${t}:</p>
17
+ <p><a href="${r}">${r}</a></p>
18
+ <p>Or enter this one-time code in the app:</p>
19
+ <p><strong style="font-size: 24px; letter-spacing: 4px;">${o}</strong></p>
20
+ <p>The link and code can only be used once and will expire in 15 minutes.</p>
21
+ <p>If you did not request this, please ignore this email.</p>
22
+ `}var ot="magicLinkToken",ei="/api/_internal/",_r={httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:ei},Lr=15,xr=6,ti=5;function xe(e,t){try{Promise.resolve(t?.()).catch(r=>{console.error(`Error in ${e} hook:`,r);});}catch(r){console.error(`Error in ${e} hook:`,r);}}function st(){return !!y().magicLink?.enabled}function Ur(){return !!y().magicLink?.allowSignup}async function Pr(e){return v.findOne({token:d(e)})}async function at(e){return v.findOneAndDelete({_id:e})}async function tt(e){try{await v.insertOne(e);}catch(t){console.error("Failed to restore a magic link token after a failed signup:",t);}}var rt={success:true,message:"If this email can be used to sign in, a link has been sent"};async function Tr(e,{connectionInfo:t}){if(!st())throw new Error("Magic link authentication is not enabled");let r$1=_(e.email),o=t?.ip;o&&await C({bucket:"magicLink",type:"ip",value:o}),await C({bucket:"magicLink",type:"email",value:r$1});let i=E().provider;if(!i)throw new Error("Email provider is not configured");let n=E().from;if(!n)throw new Error("Email `from` address is not configured");let s=a$2("_system.site.url");if(!s)throw new Error("Unable to build magic link: set _system.site.url (MODELENCE_SITE_URL)");if(!y().allowDisposableEmails&&await ke(r$1))throw new Error("Please use a permanent email address");let a=await r.findOne({"emails.address":r$1},{collation:{locale:"en",strength:2}});if(a&&(a.status==="disabled"||a.status==="deleted")||!a&&!Ur())return rt;let c=randomBytes(32).toString("hex"),l=randomInt(0,10**xr).toString().padStart(xr,"0"),d$1=Date.now(),u=new Date(d$1),f=new Date(d$1+a$1.minutes(Lr));await v.insertOne({email:r$1,token:d(c),code:d(l),attempts:0,createdAt:u,expiresAt:f});let h=`${s}/api/_internal/auth/magic-link?token=${c}`,k=(E()?.magicLink?.template||Or)({email:r$1,magicLinkUrl:h,code:l,name:""}),x=A(k);return await i.sendEmail({to:r$1,from:n,subject:E()?.magicLink?.subject||"Your sign-in link",text:x,html:k}),rt}async function Mr(e){let t=a$2("_system.site.url")||"",r=Oe(t,E().magicLink?.redirectUrl)||"/";try{let o=z.string().parse(e.query.token),i=await Pr(o);if(!i||i.expiresAt<new Date)throw new Error("This sign-in link is invalid or has expired.");return e.res.cookie(ot,o,{..._r,maxAge:a$1.minutes(Lr)}),{status:302,headers:{"Referrer-Policy":"no-referrer"},redirect:r}}catch(o){return console.error("Error handling magic link landing:",o),{status:302,headers:{"Referrer-Policy":"no-referrer"},redirect:`${r}?status=error&message=${encodeURIComponent("This sign-in link is invalid or has expired.")}`}}}var it={locale:"en",strength:2};async function Ir(e){let{tokenDoc:t,session:r$1,connectionInfo:o$1,res:i,clearCookie:n}=e,s=t.email,a=y(),c=Ur(),l=false;try{let d=await at(t._id);if(!d)throw n(),new Error("Invalid or expired code or magic link");let u;if(c)try{if(!await r.findOne({"emails.address":s},{collation:it})){l=!0,await a.onBeforeSignup?.({email:s,provider:"magicLink",connectionInfo:o$1});let L=o$1?.ip;L&&await C({bucket:"signup",type:"ip",value:L}),u=a.generateHandle?await U(await a.generateHandle({email:s}),s,{throwOnConflict:!1}):await U(void 0,s);}}catch(S){throw await tt(d),S}let f;try{f=await ri(s,u,c);}catch(S){throw await tt(d),S}let{userDoc:h,isNew:w}=f;if(!h)throw await tt(d),n(),c&&!l?new Error("User account is not active"):(l=!0,new Error("Sign up with magic link is not enabled"));if(l=w,h.status==="disabled"||h.status==="deleted")throw n(),new Error("User account is not active");let k$1=h,x=h.emails?.find(S=>S.address.toLowerCase()===s),T=!w&&!x?.verified;return T&&(k$1=await r.findOneAndUpdate({_id:h._id,"emails.address":s},{$set:{"emails.$.verified":!0}},{collation:it,returnDocument:"after"})??h),await k(r$1.authToken,k$1._id),i&&o(i,r$1.authToken),w?xe("onAfterSignup",()=>a.onAfterSignup?.({provider:"magicLink",user:k$1,session:r$1,connectionInfo:o$1})):(T&&xe("onAfterEmailVerification",()=>a.onAfterEmailVerification?.({provider:"magicLink",user:k$1,session:r$1,connectionInfo:o$1})),xe("onAfterLogin",()=>a.onAfterLogin?.({provider:"magicLink",user:k$1,session:r$1,connectionInfo:o$1}))),n(),{user:F(k$1),session:{authToken:r$1.authToken}}}catch(d){if(d instanceof Error){let u=l?"onSignupError":"onLoginError",f=l?a.onSignupError:a.onLoginError;xe(u,()=>f?.({provider:"magicLink",error:d,session:r$1,connectionInfo:o$1}));}throw d}}async function ri(e,t,r$1){let o=r$1&&t!==void 0,i=()=>r.findOneAndUpsert({emails:{$elemMatch:{address:e}}},{$setOnInsert:{handle:t,status:"active",emails:[{address:e,verified:true}],createdAt:new Date,authMethods:{}}},{upsert:o,collation:it});try{let{doc:n,isNew:s}=await i();return {userDoc:n,isNew:s}}catch(n){if(!Re(n))throw n;let{doc:s}=await i();return {userDoc:s,isNew:false}}}async function Nr(e,t){let{session:r,connectionInfo:o,res:i,req:n}=t;if(!r)throw new Error("Session is not initialized");if(!st())throw new Error("Magic link authentication is not enabled");let s=z.string().parse(n?.cookies?.[ot]),a=()=>{i?.clearCookie(ot,_r);},c=await Pr(s);if(!c)throw a(),new Error("Invalid or expired code or magic link");if(c.expiresAt<new Date)throw await at(c._id),a(),new Error("Code or magic link has expired");return Ir({tokenDoc:{_id:c._id,email:c.email},session:r,connectionInfo:o,res:i,clearCookie:a})}async function Dr(e,t){let{session:r,connectionInfo:o,res:i}=t;if(!r)throw new Error("Session is not initialized");if(!st())throw new Error("Magic link authentication is not enabled");let n=_(e.email),s=z.string().parse(e.code).replace(/[\s-]/g,""),a=o?.ip;a&&await C({bucket:"oneTimeCode",type:"ip",value:a}),await C({bucket:"oneTimeCode",type:"email",value:n});let c=await v.findOne({email:n,code:d(s),attempts:{$lt:ti}});if(!c)throw await v.updateMany({email:n},{$inc:{attempts:1}}),new Error("Invalid or expired code or magic link");if(c.expiresAt<new Date)throw await at(c._id),new Error("Code or magic link has expired");return Ir({tokenDoc:{_id:c._id,email:c.email},session:r,connectionInfo:o,res:i,clearCookie:()=>{}})}function jr(){return new b$2("Invalid or expired sign-in code","INVALID_OAUTH_CODE")}async function Hr(e,{session:t,connectionInfo:r$1}){let o;try{if(!t)throw new Error("Session is not initialized");let i=r$1?.ip;i&&await C({bucket:"oauthExchange",type:"ip",value:i});let n=z.string().min(1).parse(e.code),s=await h(n);if(!s||!ObjectId.isValid(s.userId))throw jr();o=s.provider;let a=await r.findOne({_id:new ObjectId(s.userId),status:{$nin:["deleted","disabled"]}});if(!a)throw jr();return await k(t.authToken,a._id),y().onAfterLogin?.({provider:o,user:a,session:t,connectionInfo:r$1}),y().login?.onSuccess?.(a),{user:F(a),session:{authToken:t.authToken}}}catch(i){throw i instanceof Error&&o&&(y().onLoginError?.({provider:o,error:i,session:t,connectionInfo:r$1}),y().login?.onError?.(i)),i}}function Vr(e){return `${e.bucket}
23
+ ${e.type}
24
+ ${e.window}`}function ii(){return [{bucket:"signup",type:"ip",window:a$1.minutes(15),limit:20},{bucket:"signup",type:"ip",window:a$1.days(1),limit:200},{bucket:"signupAttempt",type:"ip",window:a$1.minutes(15),limit:50},{bucket:"signupAttempt",type:"ip",window:a$1.days(1),limit:500},{bucket:"signin",type:"ip",window:a$1.minutes(15),limit:50},{bucket:"signin",type:"ip",window:a$1.days(1),limit:500},{bucket:"verification",type:"user",window:a$1.seconds(60),limit:1},{bucket:"verification",type:"user",window:a$1.days(1),limit:10},{bucket:"passwordReset",type:"ip",window:a$1.minutes(15),limit:10},{bucket:"passwordReset",type:"ip",window:a$1.days(1),limit:100},{bucket:"passwordReset",type:"email",window:a$1.hours(1),limit:5},{bucket:"passwordReset",type:"email",window:a$1.days(1),limit:10},{bucket:"magicLink",type:"ip",window:a$1.minutes(15),limit:10},{bucket:"magicLink",type:"ip",window:a$1.days(1),limit:100},{bucket:"magicLink",type:"email",window:a$1.hours(1),limit:5},{bucket:"magicLink",type:"email",window:a$1.days(1),limit:10},{bucket:"oneTimeCode",type:"ip",window:a$1.minutes(15),limit:20},{bucket:"oneTimeCode",type:"ip",window:a$1.days(1),limit:100},{bucket:"oneTimeCode",type:"email",window:a$1.hours(1),limit:10},{bucket:"oneTimeCode",type:"email",window:a$1.days(1),limit:20},{bucket:"oauthExchange",type:"ip",window:a$1.minutes(15),limit:30},{bucket:"oauthExchange",type:"ip",window:a$1.days(1),limit:300}]}function ni(e){let t=[],r=["signup","signupAttempt","signin","verification","passwordReset","magicLink","oneTimeCode","oauthExchange"];for(let o of r){let i=e[o];if(i!==void 0)for(let n of i)t.push({bucket:o,...n});}return t}function ct(e={}){let t=ii(),r=ni(e),o=new Map;for(let s of r)o.set(Vr(s),s);let i=[],n=new Set;for(let s of t){let a=Vr(s),c=o.get(a);c!==void 0?(i.push(c),n.add(a)):i.push(s);}for(let[s,a]of o)n.has(s)||i.push(a);return i}var lt=new a("_system.user",{stores:[r,s,t,u,v],queries:{getOwnProfile:ur},mutations:{signupWithPassword:yr,loginWithPassword:lr,logout:dr,resendEmailVerification:wr,sendResetPasswordToken:Sr,resetPassword:Rr,sendMagicLink:Tr,loginWithMagicLink:Nr,loginWithOneTimeCode:Dr,loginWithOAuth:Hr,updateProfile:mr,unlinkOAuthProvider:pr},cronJobs:{updateDisposableEmailList:er},rateLimits:ct(),configSchema:{"auth.email.enabled":{type:"boolean",isPublic:true,default:true},"auth.email.from":{type:"string",isPublic:false,default:""},"auth.email.verification":{type:"boolean",isPublic:true,default:true},"auth.google.enabled":{type:"boolean",isPublic:true,default:false},"auth.google.clientId":{type:"string",isPublic:false,default:""},"auth.google.clientSecret":{type:"secret",isPublic:false,default:""},"auth.github.enabled":{type:"boolean",isPublic:true,default:false},"auth.github.clientId":{type:"string",isPublic:false,default:""},"auth.github.clientSecret":{type:"secret",isPublic:false,default:""},"auth.mobile.redirectUrls":{type:"text",isPublic:false,default:""}},routes:[{path:"/api/_internal/auth/verify-email",handlers:{get:hr}},{path:"/api/_internal/auth/reset-password",handlers:{get:Ar}},{path:"/api/_internal/auth/magic-link",handlers:{get:Mr}}]});var si={withoutRemoteServer:{MONGODB_URI:"_system.mongodbUri",MONGODB_POOL_SIZE:"_system.mongodbPoolSize",MODELENCE_AUTH_GOOGLE_ENABLED:"_system.user.auth.google.enabled",MODELENCE_AUTH_GOOGLE_CLIENT_ID:"_system.user.auth.google.clientId",MODELENCE_AUTH_GOOGLE_CLIENT_SECRET:"_system.user.auth.google.clientSecret",MODELENCE_AUTH_GITHUB_ENABLED:"_system.user.auth.github.enabled",MODELENCE_AUTH_GITHUB_CLIENT_ID:"_system.user.auth.github.clientId",MODELENCE_AUTH_GITHUB_CLIENT_SECRET:"_system.user.auth.github.clientSecret",MODELENCE_AUTH_GITHUB_CLIENT_SCOPES:"_system.user.auth.github.scopes",MODELENCE_AUTH_MOBILE_REDIRECT_URLS:"_system.user.auth.mobile.redirectUrls",MODELENCE_EMAIL_RESEND_API_KEY:"_system.email.resend.apiKey",MODELENCE_EMAIL_AWS_SES_REGION:"_system.email.awsSes.region",MODELENCE_EMAIL_AWS_SES_ACCESS_KEY_ID:"_system.email.awsSes.accessKeyId",MODELENCE_EMAIL_AWS_SES_SECRET_ACCESS_KEY:"_system.email.awsSes.secretAccessKey",MODELENCE_EMAIL_SMTP_HOST:"_system.email.smtp.host",MODELENCE_EMAIL_SMTP_PORT:"_system.email.smtp.port",MODELENCE_EMAIL_SMTP_USER:"_system.email.smtp.user",MODELENCE_EMAIL_SMTP_PASS:"_system.email.smtp.pass",MODELENCE_SITE_URL:"_system.site.url",MODELENCE_ENV_TYPE:"_system.env.type",MODELENCE_MULTI_INSTANCE:"_system.multiInstance",MODELENCE_ENV:"_system.env",GOOGLE_AUTH_ENABLED:"_system.user.auth.google.enabled",GOOGLE_AUTH_CLIENT_ID:"_system.user.auth.google.clientId",GOOGLE_AUTH_CLIENT_SECRET:"_system.user.auth.google.clientSecret"},withRemoteServer:{MODELENCE_SITE_URL:"_system.site.url"}};function ai(e,t){if(t==="number"){let r=Number(e);if(isNaN(r))throw new Error(`Invalid number value for config: ${e}`);return r}if(t==="boolean"){if(e.toLowerCase()==="true")return true;if(e.toLowerCase()==="false")return false;throw new Error(`Invalid boolean value for config: ${e}`)}return e}function ci(e,t){let r=[];for(let[o,i]of Object.entries(e)){let n=process.env[o],s=t[i];if(n){let a=s?.type??"string";r.push({key:i,type:a,value:ai(n,a)});}}return r}function _e(e,t="withoutRemoteServer"){let r=si[t];return ci(r,e)}async function Br({configSchema:e,cronJobsMetadata:t,stores:r,roles:o}){let i=process.env.MODELENCE_CONTAINER_ID;if(!i)throw new Error("Unable to connect to Modelence Cloud: MODELENCE_CONTAINER_ID is not set");try{let n=(r??[]).map(a=>({name:a.getName(),schema:a.getSerializedSchema(),collections:[a.getName()],version:2,indexes:a.getIndexes(),searchIndexes:a.getSearchIndexes(),indexCreationMode:a.getIndexCreationMode()})),s=await P("/api/connect","POST",{hostname:li.hostname(),containerId:i,dataModels:n,configSchema:e,cronJobsMetadata:t,roles:o});if(s.status==="error")throw new Error(s.error);return console.log("Successfully connected to Modelence Cloud"),s}catch(n){throw console.error("Unable to connect to Modelence Cloud:",n),n}}async function Fr(){return P("/api/configs","GET")}async function Gr(){return await P("/api/sync","POST",{containerId:process.env.MODELENCE_CONTAINER_ID})}async function P(e,t,r){let{MODELENCE_SERVICE_ENDPOINT:o,MODELENCE_SERVICE_TOKEN:i}=process.env;if(!o)throw new Error("Unable to connect to Modelence Cloud: MODELENCE_SERVICE_ENDPOINT is not set");let n=await fetch(`${o}${e}`,{method:t,headers:{Authorization:`Bearer ${i}`,...r?{"Content-Type":"application/json"}:{}},body:r?JSON.stringify(r):void 0});if(!n.ok){let s=await n.text(),a,c=s;try{a=JSON.parse(s);let d=a.error;if(typeof d=="string")c=d;else if(d&&typeof d=="object"){let u=d.message;typeof u=="string"&&(c=u);}}catch{}let l=new Error(`Unable to connect to Modelence Cloud: HTTP status: ${n.status}, ${c}`);throw a!==void 0&&(l.responseBody=a),l.status=n.status,l}if(!(n.status===204||n.headers?.get("content-length")==="0"))return await n.json()}var dt=false,di=a$1.seconds(10);function qr(){setInterval(async()=>{if(!dt){dt=true;try{await Gr();}catch(e){console.error("Error syncing status",e);}try{await ui();}catch(e){console.error("Error syncing config",e);}dt=false;}},di);}function ut(e){c$2(e),c$2(_e(d$2(),"withRemoteServer"));}async function ui(){let{configs:e}=await Fr();ut(e);}var K=new b$1("_modelenceLocks",{schema:{_id:c.string(),instanceId:c.string(),acquiredAt:c.date(),resource:c.string()},indexes:[{key:{resource:1},unique:true},{key:{resource:1,instanceId:1}},{key:{resource:1,acquiredAt:1}}],indexCreationMode:"blocking"});var Y={},zr=a$1.seconds(10),Yr=randomBytes(32).toString("base64url"),fi=a$1.seconds(30),re=new Map,mt=e=>e instanceof MongoError&&e.code===11e3,Wr=(e,t)=>typeof e.keyPattern=="object"&&e.keyPattern!==null&&Object.prototype.hasOwnProperty.call(e.keyPattern,t),gi=async({error:e,resource:t})=>{if(Wr(e,"resource"))return true;if(Wr(e,"_id"))return false;let r=await K.findOne({resource:t});return !!r&&r._id!==t},Jr=async({resource:e,staleThresholdDate:t,instanceId:r})=>{let o=await K.upsertOne({_id:e,$or:[{instanceId:r},{acquiredAt:{$lt:t}}]},{$set:{resource:e,instanceId:r,acquiredAt:new Date},$setOnInsert:{_id:e}});return o.upsertedCount>0||o.modifiedCount>0},Qr=async({resource:e,instanceId:t,staleThresholdDate:r})=>{let o=r?{resource:e,_id:{$ne:e},$or:[{instanceId:t},{acquiredAt:{$lt:r}}]}:{resource:e,instanceId:t};return (await K.deleteOne(o)).deletedCount>0},hi=e=>{let t=e,r=re.get(t);r&&(r.stopRequested=true,r.timer&&(clearTimeout(r.timer),r.timer=null),re.delete(t));},Kr=({resource:e,lockDuration:t,instanceId:r})=>{let o=Math.floor(t/3),i=e,n=re.get(i);if(n&&!n.stopRequested&&n.heartbeatInterval===o&&n.lockDuration===t)return;n&&(n.stopRequested=true,n.timer&&(clearTimeout(n.timer),n.timer=null),re.delete(i));let s={timer:null,stopRequested:false,lockDuration:t,heartbeatInterval:o},a=()=>{s.timer=setTimeout(()=>{Q(e,{lockDuration:t,bypassCache:true,instanceId:r}).then(c=>{c||(s.stopRequested=true,j(`Lost lock while refreshing heartbeat: ${e}`,{source:"lock",resource:e,instanceId:r}));}).finally(()=>{if(s.stopRequested){re.delete(i);return}a();});},o);};re.set(i,s),a();};async function Q(e,{lockDuration:t=fi,successfulLockCacheDuration:r=zr,failedLockCacheDuration:o=zr,heartbeat:i,bypassCache:n,instanceId:s=Yr}={}){let a=Date.now();if(!n&&Y[e]&&a<Y[e].expiresAt)return Y[e].value&&i&&Kr({resource:e,lockDuration:t,instanceId:s}),Y[e].value;let c=new Date(a-t);j(`Attempting to acquire lock: ${e}`,{source:"lock",resource:e,instanceId:s});try{let l=await wi({resource:e,staleThresholdDate:c,instanceId:s});return Y[e]={value:l,expiresAt:a+(l?r:o)},l?(i&&Kr({resource:e,lockDuration:t,instanceId:s}),j(`Lock acquired: ${e}`,{source:"lock",resource:e,instanceId:s})):j(`Failed to acquire lock (already held): ${e}`,{source:"lock",resource:e,instanceId:s}),l}catch{return Y[e]={value:false,expiresAt:a+o},j(`Failed to acquire lock (already held): ${e}`,{source:"lock",resource:e,instanceId:s}),false}}var wi=async({resource:e,staleThresholdDate:t,instanceId:r})=>{try{return await Jr({resource:e,staleThresholdDate:t,instanceId:r})}catch(o){if(mt(o)&&await gi({error:o,resource:e})){if(!await Qr({resource:e,staleThresholdDate:t,instanceId:r}))return false;try{return await Jr({resource:e,staleThresholdDate:t,instanceId:r})}catch(n){if(mt(n))return false;throw n}}if(mt(o))return false;throw o}};async function pe(e,{instanceId:t=Yr}={}){hi(e);try{let r=await K.deleteOne({_id:e,instanceId:t});return r.deletedCount===0?await Qr({resource:e,instanceId:t}):r.deletedCount>0}catch{return false}finally{delete Y[e];}}var X={},pt=null,ft=new b$1("_modelenceCronJobs",{schema:{alias:c.string(),lastStartDate:c.date().optional()},indexes:[{key:{alias:1},unique:true,background:true}]});function Zr(e,{description:t="",interval:r,timeout:o=Math.min(Math.max(r,a$1.minutes(1)),a$1.days(1)),handler:i}){if(X[e])throw new Error(`Duplicate cron job declaration: '${e}' already exists`);if(pt)throw new Error(`Unable to add a cron job - cron jobs have already been initialized: [${e}]`);if(r<a$1.seconds(5))throw new Error(`Cron job interval should not be less than 5 second [${e}]`);if(o>a$1.days(1))throw new Error(`Cron job timeout should not be longer than 1 day [${e}]`);X[e]={alias:e,params:{description:t,interval:r,timeout:o},handler:i,state:{isRunning:false}};}async function eo(){if(pt)throw new Error("Cron jobs already started");let e=Object.keys(X);if(e.length>0){if(!N()){console.log("MongoDB URI is not configured. Skipping cron jobs.");return}let t={alias:{$in:e}},r=await ft.fetch(t),o=Date.now();r.forEach(i=>{let n=X[i.alias];n&&(n.state.scheduledRunTs=i.lastStartDate?i.lastStartDate.getTime()+n.params.interval:o);}),Object.values(X).forEach(i=>{i.state.scheduledRunTs||(i.state.scheduledRunTs=o);}),pt=setInterval(yi,a$1.seconds(1));}}async function yi(){let e=Date.now();await Q("cron",{successfulLockCacheDuration:a$1.seconds(10),failedLockCacheDuration:a$1.seconds(30)})&&Object.values(X).forEach(async r=>{let{params:o,state:i}=r;if(i.isRunning){i.startTs&&i.startTs+o.timeout<e&&(i.isRunning=false);return}i.scheduledRunTs&&i.scheduledRunTs<=e&&await bi(r);});}async function bi(e){let{alias:t,params:r,handler:o,state:i}=e;i.isRunning=true,i.startTs=Date.now(),await ft.upsertOne({alias:t},{$set:{lastStartDate:new Date(i.startTs)},$setOnInsert:{alias:t}});let n=m$1("cron",`cron:${t}`);try{await o(),Xr(i,r),n.end("success");}catch(s){Xr(i,r);let a=s instanceof Error?s:new Error(String(s));n$1(a),n.end("error"),console.error(`Error in cron job '${t}':`,s);}}function Xr(e,t){e.scheduledRunTs=e.startTs?e.startTs+t.interval:Date.now(),e.startTs=void 0,e.isRunning=false;}function to(){return Object.values(X).map(({alias:e,params:t})=>({alias:e,description:t.description,interval:t.interval,timeout:t.timeout}))}var ro=new a("_system.cron",{stores:[ft]});function oo(e){let t=[...new Set(e)],r=new Map;for(let n of t){let s=n.getChainRoot();r.set(s,s.getChainTail());}let o=[...new Set(r.values())],i=new Map;for(let[n,s]of r){let a=s.getName(),c=i.get(a);if(c!==void 0&&c!==n)throw new Error(`Store collision: multiple unrelated stores use collection name '${a}'. Use .extend() to create a single extension chain instead of independent stores.`);i.set(a,n);}return {storesToInit:t,effectiveStores:o}}var gt=new a("_system.lock",{stores:[K]});var fe=new b$1("_modelenceMigrations",{schema:{version:c.number(),status:c.enum(["completed","failed"]),description:c.string().optional(),output:c.string().optional(),appliedAt:c.date()},indexes:[{key:{version:1},unique:true},{key:{version:1,status:1}}]});async function ht(e,{lockMode:t="acquire"}={}){if(e.length!==0){if(t==="acquire"&&!await Q("migrations")){k$1("Another instance is running migrations. Skipping migration run.",{source:"migrations"});return}try{let r=e.map(({version:s})=>s),o=await fe.fetch({version:{$in:r}}),i=new Set(o.map(({version:s})=>s)),n=e.filter(({version:s})=>!i.has(s));if(n.length===0)return;k$1(`Running migrations (${n.length})...`,{source:"migrations"});for(let{version:s,description:a,handler:c}of n){k$1(`Running migration v${s}: ${a}`,{source:"migrations"});try{let d=(await c()||"").toString().trim(),u=15*1024*1024,f=d.length>u?d.slice(0,u)+`
25
+ [Output truncated - exceeded size limit]`:d;await fe.upsertOne({version:s},{$set:{version:s,status:"completed",description:a,output:f,appliedAt:new Date}}),k$1(`Migration v${s} complete`,{source:"migrations"});}catch(l){l instanceof Error&&(await fe.upsertOne({version:s},{$set:{version:s,status:"failed",description:a,output:l.message||"",appliedAt:new Date}}),k$1(`Migration v${s} is failed: ${l.message}`,{source:"migrations"}));}}}finally{t==="acquire"&&await pe("migrations");}}}function io(e){setTimeout(()=>{ht(e).catch(t=>{console.error("Error running migrations:",t);});},0);}var no=new a("_system.migration",{stores:[fe]});var so=new a("_system.rateLimit",{stores:[me]});async function Ei({filePath:e,contentType:t,visibility:r}){return await P("/api/files/upload","POST",{filePath:e,contentType:t,visibility:r})}async function vi(e){await P("/api/files/delete","POST",{filePath:e});}async function ki(e){return await P("/api/files/download","POST",{filePath:e})}async function Ci(e){return await P("/api/files/url","POST",{filePath:e})}var ao=new a("_system.files",{});function wt(e){return e.replace(/[<>&\u2028\u2029]/g,t=>`\\u${t.charCodeAt(0).toString(16).padStart(4,"0")}`)}var ge="./.modelence/build/client".replace(/\\/g,"/"),lo="./.modelence/build/ssr".replace(/\\/g,"/"),uo="/index.tsx",_i=/(<div\b[^>]*\bid\s*=\s*["']root["'][^>]*>)\s*<\/div>/i,Li="</head>",yt=class{constructor(){this.ssrEnabled=false;this.ssrTransportInstalled=false;this.prodEntryLoaded=false;}enableSsr(){this.ssrEnabled=true;}async init({httpServer:t}){if(this.config=await Di(this.isDev()?t:void 0,{ssr:this.ssrEnabled}),this.isDev())console.log("Starting Vite dev server..."),this.viteServer=await createServer(this.config);else if(this.ssrEnabled){let r=Z.resolve(process.cwd(),lo,"index.mjs");if(!Le.existsSync(r))throw new Error(`Modelence: SSR is enabled (startApp({ ssr: true })) but the SSR bundle is missing at ${r}.
26
+
27
+ This usually means \`postBuildCommand\` is set in modelence.config.ts, which replaces the default Vite client build (and the SSR build along with it). Either:
28
+ \u2022 remove \`postBuildCommand\` so Modelence builds the SSR bundle, or
29
+ \u2022 remove \`ssr: true\` from startApp() if your custom toolchain handles SSR itself.`)}if(this.ssrEnabled&&!this.ssrTransportInstalled){let{installSsrCallMethodTransport:r}=await import('./transport-TR3OYHQR.js');r(),this.ssrTransportInstalled=true;}}middlewares(){if(this.isDev())return this.viteServer?.middlewares??[];let t=this.ssrEnabled?{index:false}:void 0,r=[q$1.static(ge,t)];return this.config?.publicDir&&r.push(q$1.static(this.config.publicDir,t)),r}async handler(t,r){if(this.ssrEnabled&&Ui(t)){if(t.method==="HEAD"){r.setHeader("Content-Type","text/html; charset=utf-8"),r.setHeader("Cache-Control","no-store"),r.status(200).end();return}try{await this.handleSsr(t,r);}catch(o){if(this.isDev()&&this.viteServer&&o instanceof Error&&this.viteServer.ssrFixStacktrace(o),console.error("SSR render error:",{url:t.originalUrl,method:t.method,userAgent:t.get("user-agent"),error:o}),r.headersSent){r.end();return}this.serveStaticShell(r);}return}if(this.ssrEnabled){r.status(404).end();return}this.serveStaticShell(r);}async handleSsr(t,r){let o=await this.getTemplate(t.originalUrl),i=await this.captureSsrSnapshot();if(!i)throw new Error("Modelence SSR is enabled but no SSR snapshot was captured. Make sure 'src/client/index.tsx' calls renderApp(...) from 'modelence/client'.");let[{renderSsrTreeStream:n},{getCallContext:s},a]=await Promise.all([import('./render-G33LE5AY.js'),import('./server-BEYRNZY5.js'),import('./collectCss-4YETFI7P.js')]),c=await s(t,r),l=this.collectCssAssets(a);Mi(r,a.buildEarlyHintsLink(l));let{sessionState:d,pipe:u,getQueryState:f}=await n({callContext:c,loadingElement:i.loadingElement,routesElement:i.routesElement,router:i.router,location:t.originalUrl}),{prelude:h,rootOpenTag:w,epilogue:k}=Pi(o),x=Ti(h,a.renderStylesheetLinks(l));r.setHeader("Content-Type","text/html; charset=utf-8"),r.setHeader("Cache-Control","no-store"),r.status(200),r.write(x),r.write(`<script id="__MODELENCE_STATE__" type="application/json">${wt(d)}</script>`),r.write(w),await u(r),r.write("</div>"),r.write(`<script id="__MODELENCE_QUERY_STATE__" type="application/json">${wt(f())}</script>`),r.end(k);}collectCssAssets(t){return this.isDev()?this.viteServer?t.collectDevCssAssets(this.viteServer,uo):{hrefs:[],source:"dev"}:(this.prodCssAssetsCache||(this.prodCssAssetsCache=t.loadProdCssAssets(ge)),this.prodCssAssetsCache)}async getTemplate(t){if(this.isDev()){let r=Z.resolve(process.cwd(),"src/client/index.html"),o=Le.readFileSync(r,"utf-8");return this.viteServer&&(o=await this.viteServer.transformIndexHtml(t,o)),o}if(!this.prodTemplateCache){let r=Z.resolve(process.cwd(),ge,"index.html");this.prodTemplateCache=Le.readFileSync(r,"utf-8");}return this.prodTemplateCache}async captureSsrSnapshot(){let{_getSsrSnapshot:t}=await import('./renderApp-F7NZT5JC.js');if(this.isDev()){if(!this.viteServer)throw new Error("Vite dev server not initialized");return await this.viteServer.ssrLoadModule(uo),t()}return this.prodEntryLoaded||(await import(Z.resolve(process.cwd(),lo,"index.mjs")),this.prodEntryLoaded=true),t()}serveStaticShell(t){if(this.isDev())try{t.setHeader("Cache-Control","no-store"),t.sendFile("index.html",{root:"./src/client"});}catch(r){console.error("Error serving index.html:",r),t.status(500).send("Internal Server Error");}else t.sendFile("index.html",{root:ge});}isDev(){return process.env.NODE_ENV!=="production"}};function Ui(e){if(e.method!=="GET"&&e.method!=="HEAD")return false;let t=e.get("accept")??"";if(t&&!t.includes("text/html")&&!t.includes("*/*"))return false;let r=(e.path??e.url??"").split("?")[0];if(r.startsWith("/api/"))return false;let o=r.split("/").pop()??"",i=o.lastIndexOf(".");if(i>0){let n=o.slice(i).toLowerCase();if(n!==".html"&&n!==".htm")return false}return true}function Pi(e){let t=e.match(_i);if(!t||t.index===void 0)throw new Error('SSR template is missing the expected `<div id="root"></div>` placeholder.');let r=e.slice(0,t.index),o=e.slice(t.index+t[0].length);return {prelude:r,rootOpenTag:t[1],epilogue:o}}function Ti(e,t){if(!t)return e;let r=e.lastIndexOf(Li);return r===-1?t+e:e.slice(0,r)+t+e.slice(r)}function Mi(e,t){if(t.length===0)return;let r=e;if(typeof r.writeEarlyHints=="function")try{r.writeEarlyHints({link:t});}catch(o){process.env.NODE_ENV!=="production"&&console.warn("Modelence SSR: writeEarlyHints failed",o);}}async function Ii(){let e=process.cwd();try{return (await loadConfigFromFile({command:"serve",mode:"development"},void 0,e))?.config||{}}catch(t){return console.warn("Could not load vite config:",t),{}}}function Ni(e,t){let r=mergeConfig(e,t);if(r.plugins&&Array.isArray(r.plugins)){let o=new Set;r.plugins=r.plugins.flat().filter(i=>{if(!i||typeof i!="object"||Array.isArray(i))return true;let n=i.name;return !n||o.has(n)?false:(o.add(n),true)}).reverse(),r.plugins.reverse();}return r}async function Di(e,t={}){let r=process.cwd(),o=await Ii(),i=[".eslintrc.js",".eslintrc.json",".eslintrc","eslint.config.js",".eslintrc.yml",".eslintrc.yaml"].find(a=>Le.existsSync(Z.join(r,a))),n=[xi(),$i()];if(i){let a=(await import('vite-plugin-eslint')).default;n.push(a({failOnError:false,include:["src/**/*.js","src/**/*.jsx","src/**/*.ts","src/**/*.tsx"],cwd:r,overrideConfigFile:Z.resolve(r,i)}));}let s=defineConfig({plugins:n,build:{outDir:ge,emptyOutDir:true},server:{middlewareMode:true,hmr:e?{server:e}:void 0},appType:t.ssr?"custom":"spa",root:"./src/client",resolve:{alias:{"@":Z.resolve(r,"src").replace(/\\/g,"/")}}});return Ni(s,o)}function $i(){return {name:"modelence-asset-handler",async transform(e,t){if(/\.(png|jpe?g|gif|svg|mpwebm|ogg|mp3|wav|flac|aac)$/.test(t))return process.env.NODE_ENV==="development",e}}}var Ue=new yt;function ji(e){return e?e.match(/^\s*"?([^"<]+?)"?\s*<[^>]+>\s*$/)?.[1]?.trim():void 0}function Hi(e){if(e)return Array.isArray(e)?e:[e]}function Vi(e){return {to:Array.isArray(e.to)?e.to:[e.to],subject:e.subject,html:e.html,text:e.text,fromName:ji(e.from),replyTo:Hi(e.replyTo)}}function Bi(e){if(!(e instanceof Error))return new Error("Managed email send failed");let t=e.responseBody,r=t?.error?.code,o=t?.error?.message;return r&&o?new Error(`Managed email rejected (${r}): ${o}`):e}var mo={async sendEmail(e){if(e.cc||e.bcc||e.attachments||e.headers)throw new Error("Modelence managed email does not support cc, bcc, attachments, or custom headers in v1. Configure your own provider (Resend, SES, SMTP) to use these features. See https://docs.modelence.com/email/managed.");try{await P("/api/email/send","POST",Vi(e));}catch(t){throw Bi(t)}}};var bt=Object.freeze({});function po(e){bt=Object.freeze(Object.assign({},bt,e));}function fo(){return bt}var Et=Object.freeze({});function go(e){Et=Object.freeze(Object.assign({},Et,e));}function Pe(){return Et}async function zi({modules:e$1=[],roles:t={},defaultRoles:r={},server:o=Ue,migrations:i=[],email:n={},auth:s={},security:a={},websocket:c={},ssr:l=false}){l&&o===Ue&&Ue.enableSsr(),ho.config(),ho.config({path:".modelence.env"});let d=!!process.env.MODELENCE_SERVICE_ENDPOINT;on().then(()=>{}).catch(()=>{});for(let D of e$1)if(D.name.toLowerCase().startsWith("_system."))throw new Error(`Invalid module name: '${D.name}'
30
+
31
+ The '_system.' prefix is reserved for internal use and cannot be used in user-defined modules.
32
+
33
+ Rename your module to something that does not start with '_system.'`);let u=[lt,q,ro,no,so,le,gt,ao],f$1=[...u,...e$1];f(),Ji(u),Wi(e$1),w(t,r);let h=en(f$1);e(h);let w$1=Ki(f$1),k=Yi(f$1);tn(f$1),lt.rateLimits=ct(s.rateLimits);let x=Qi(f$1);fr(x);let{storesToInit:T,effectiveStores:S}=oo(w$1);if(d){let{configs:D,environmentId:Ro,appAlias:Oo,environmentAlias:xo,telemetry:_o}=await Br({configSchema:h,cronJobsMetadata:to(),stores:S,roles:t});ut(D),g({environmentId:Ro,appAlias:Oo,environmentAlias:xo,telemetry:_o});}else c$2(_e(h));if(d&&!n.provider?Je({...n,provider:mo}):Je(n),ar(s),po(a),go({...c,provider:c.provider||Zt}),N()){await Qt();let D=[...new Set([...T,...S])];rn(D),await Zi(S,i);}else io(i);d&&(await h$1(),qr()),eo().catch(console.error),await wo(o,{combinedModules:f$1,channels:k});}function Wi(e){for(let t of e){for(let[r,o]of Object.entries(t.queries))B$1(`${t.name}.${r}`,o);for(let[r,o]of Object.entries(t.mutations))C$1(`${t.name}.${r}`,o);}}function Ji(e){for(let t of e){for(let[r,o]of Object.entries(t.queries))D(`${t.name}.${r}`,o);for(let[r,o]of Object.entries(t.mutations))E$1(`${t.name}.${r}`,o);}}function Ki(e){return e.flatMap(t=>t.stores)}function Yi(e){return e.flatMap(t=>t.channels)}function Qi(e){return e.flatMap(t=>t.rateLimits)}function Xi(e,t){console.warn(`Failed to create indexes for store '${e}'. Continuing startup.`,t);}var vt="migrations";async function Zi(e,t){if(!await Q(vt,{lockDuration:a$1.seconds(30),heartbeat:true}))return;let o,i;try{o=e.filter(a=>a.getIndexCreationMode()==="blocking"),i=e.filter(a=>a.getIndexCreationMode()==="background");for(let a of o)await kt(a,"full");for(let a of i)await kt(a,"drop-only");}catch(a){throw await pe(vt),a}let n=(async()=>{for(let a of i)await kt(a,"create-only");})(),s=ht(t,{lockMode:"skip"});Promise.allSettled([n,s]).then(([a,c])=>{a.status==="rejected"&&console.error("Error creating background indexes:",a.reason),c.status==="rejected"&&console.error("Error running migrations:",c.reason);}).finally(async()=>{await pe(vt);});}async function kt(e,t="full"){let r=e.getName();try{await e.createIndexes(t);}catch(o){Xi(r,o);}}function en(e){let t={};for(let r of e)for(let[o,i]of Object.entries(r.configSchema)){let n=`${r.name}.${o}`;if(n in t)throw new Error(`Duplicate config schema key: ${n} (${r.name})`);t[n]=i;}return t}function tn(e){for(let t of e)for(let[r,o]of Object.entries(t.cronJobs))Zr(`${t.name}.${r}`,o);}function rn(e){let t=ve();if(!t)throw new Error("Failed to initialize stores: MongoDB client not initialized");for(let r of e)r.init(t);}async function on(){if(process.env.MODELENCE_TRACKING_ENABLED!=="false"){let t=process.env.MODELENCE_SERVICE_ENDPOINT??"https://cloud.modelence.com",r=process.env.MODELENCE_ENVIRONMENT_ID,o=await nn(),i=await import('./package-Y67IHT4E.js');await fetch(`${t}/api/track/app-start`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({projectName:o.name,version:i.default.version,localHostname:li.hostname(),environmentId:r})});}}async function nn(){try{let e=Z.join(process.cwd(),"package.json"),t=await Fi.readFile(e,"utf-8");return {name:JSON.parse(t).name||"unknown"}}catch{return {name:"unknown"}}}async function yo(e){await t.deleteMany({userId:e}),await u.deleteMany({userId:e});let t$1=await r.findOne({_id:e}),r$1=Array.from(new Set((t$1?.emails??[]).map(o=>o.address?.toLowerCase()).filter(o=>!!o)));r$1.length>0&&await v.deleteMany({email:{$in:r$1}});}async function an(e){await yo(e),await r.updateOne(e,{$set:{status:"disabled",disabledAt:new Date}});}async function cn(e){await yo(e),await r.updateOne({_id:e},{$set:{handle:`deleted-${e}-${randomUUID()}`,status:"deleted",deletedAt:new Date,authMethods:{},emails:[]}});}var Ct=class{constructor(t,r){this.category=t,this.canAccessChannel=r||null;}broadcast(t,r){let o=Pe().provider;if(!o){l$1("Websockets provider should be added to startApp",{});return}o.broadcast({category:this.category,id:t,data:r});}};function ln(e){if(!E().provider)throw new Error("Email provider is not configured, see https://docs.modelence.com/email for more details.");return E().provider?.sendEmail(e)}var bo=new Set(["javascript:","data:","file:","vbscript:","blob:"]);function Eo(e){try{return new URL(e)}catch{return null}}function dn(){let e=String(a$2("_system.user.auth.mobile.redirectUrls")??"").split(",").map(r=>r.trim()).filter(Boolean),t=(y().mobile?.redirectUrls??[]).map(r=>String(r).trim()).filter(Boolean);return [...new Set([...e,...t])]}function St(e){if(!e||typeof e!="string")return false;let t=Eo(e);return !t||bo.has(t.protocol.toLowerCase())?false:dn().some(r=>{let o=Eo(r);return !o||bo.has(o.protocol.toLowerCase())?false:t.protocol.toLowerCase()===o.protocol.toLowerCase()&&t.host.toLowerCase()===o.host.toLowerCase()&&vo(t.pathname)===vo(o.pathname)})}function vo(e){let t=e.replace(/\/+$/,"");return t===""?"/":t}function Te(e,t){let r=new URL(e);for(let[o,i]of Object.entries(t))r.searchParams.set(o,i);return r.toString()}function Me(e){return e.platform==="mobile"&&e.redirectUri?{platform:"mobile",redirectUri:e.redirectUri}:{platform:"web"}}async function Ie(e){return !e||typeof e!="string"?null:f$1(e)}function b(e,t,r,o={platform:"web"}){if(o.platform==="mobile")return e.status(302),e.set("Referrer-Policy","no-referrer"),e.redirect(Te(o.redirectUri,{error:r}));let i=y(),n=e.status(t);if(i.errorComponent)try{let s=i.errorComponent({error:r,statusCode:t});if(s)return n.send(s)}catch(s){console.error("Unhandled error in authConfig.errorComponent:",s);}return n.json({error:r})}async function At(e,t,r={platform:"web"},o$1){if(r.platform==="mobile"){if(!o$1)throw new Error("An OAuth provider is required to complete a mobile sign-in.");let n=await g$1(t.toString(),o$1);e.status(302),e.set("Referrer-Policy","no-referrer"),e.redirect(Te(r.redirectUri,{code:n}));return}let{authToken:i}=await n(t);o(e,i),e.status(302),e.redirect("/");}async function mn(e,t,r$1,o,i,n){let s=y();try{if(r$1.status==="disabled"||r$1.status==="deleted"){b(e,400,"User account is not active.",n);return}let a={};r$1.firstName===void 0&&t.firstName&&(a.firstName=t.firstName),r$1.lastName===void 0&&t.lastName&&(a.lastName=t.lastName),r$1.avatarUrl===void 0&&t.avatarUrl&&(a.avatarUrl=t.avatarUrl);let c=r$1;Object.keys(a).length>0&&(await r.updateOne({_id:r$1._id},{$set:a}),c={...r$1,...a}),await At(e,r$1._id,n,t.providerName),s.onAfterLogin?.({provider:t.providerName,user:c,session:o,connectionInfo:i}),s.login?.onSuccess?.(c);}catch(a){throw a instanceof Error&&(s.login?.onError?.(a),s.onLoginError?.({provider:t.providerName,error:a,session:o,connectionInfo:i})),a}}async function pn(e,t,r$1,o,i,n){let s=y();if((s.oauthAccountLinking??"manual")==="auto"&&t.emailVerified){if(r$1.status==="disabled"||r$1.status==="deleted"){b(e,400,"User account is not active.",n);return}if(!r$1.emails?.find(l=>l.address.toLowerCase()===t.email.toLowerCase())?.verified){b(e,400,"User with this email already exists. Please log in instead.",n);return}try{let l={...r$1.firstName===void 0&&t.firstName&&{firstName:t.firstName},...r$1.lastName===void 0&&t.lastName&&{lastName:t.lastName},...r$1.avatarUrl===void 0&&t.avatarUrl&&{avatarUrl:t.avatarUrl}};if(!((await r.updateOne({_id:r$1._id,status:{$nin:["deleted","disabled"]},$or:[{[`authMethods.${t.providerName}.id`]:{$exists:!1}},{[`authMethods.${t.providerName}.id`]:t.id}]},{$set:{[`authMethods.${t.providerName}.id`]:t.id,...l}})).matchedCount>0)){b(e,400,"User with this email already exists. Please log in instead.",n);return}await At(e,r$1._id,n,t.providerName);let f={...r$1,...l,authMethods:{...r$1.authMethods,[t.providerName]:{id:t.id}}};s.onAfterLogin?.({provider:t.providerName,user:f,session:o,connectionInfo:i}),s.login?.onSuccess?.(f);return}catch(l){throw l instanceof Error&&(s.login?.onError?.(l),s.onLoginError?.({provider:t.providerName,error:l,session:o,connectionInfo:i})),l}}b(e,400,"User with this email already exists. Please log in instead.",n);}async function fn(e,t,r$1,o,i){let n=y();try{let s;if(n.generateHandle){let d=await n.generateHandle({email:t.email,firstName:t.firstName,lastName:t.lastName});s=await U(d,t.email,{throwOnConflict:!1});}else s=await U(void 0,t.email);let a={handle:s,status:"active",emails:[{address:t.email,verified:t.emailVerified}],createdAt:new Date,authMethods:{[t.providerName]:{id:t.id}},...t.firstName!==void 0&&{firstName:t.firstName},...t.lastName!==void 0&&{lastName:t.lastName},...t.avatarUrl!==void 0&&{avatarUrl:t.avatarUrl}},c=await r.insertOne(a);await At(e,c.insertedId,i,t.providerName);let l=await r.findOne({_id:c.insertedId},{readPreference:"primary"});l&&(n.onAfterSignup?.({provider:t.providerName,user:l,session:r$1,connectionInfo:o}),n.signup?.onSuccess?.(l));}catch(s){throw s instanceof Error&&(n.onSignupError?.({provider:t.providerName,error:s,session:r$1,connectionInfo:o}),n.signup?.onError?.(s)),s}}function ie(e){return `${a$2("_system.site.url")}/api/_internal/auth/${e}/callback`}async function Ne(e,t,r$1,o={platform:"web"}){let i=await r.findOne({[`authMethods.${r$1.providerName}.id`]:r$1.id}),{session:n,connectionInfo:s}=await ne(e,t);if(i)return mn(t,r$1,i,n,s,o);if(!r$1.email){b(t,400,`Email address is required for ${r$1.providerName} authentication.`,o);return}let a;try{a=await r.findOne({"emails.address":r$1.email,status:{$ne:"deleted"}},{collation:{locale:"en",strength:2}});}catch(c){if(c instanceof Error){let l=y();l.onSignupError?.({provider:r$1.providerName,error:c,session:n,connectionInfo:s}),l.signup?.onError?.(c);}throw c}return a?pn(t,r$1,a,n,s,o):fn(t,r$1,n,s,o)}function O(e){e.cookie("oauthLinkToken","",{httpOnly:true,maxAge:0,path:"/api/_internal/auth/",sameSite:"lax",secure:process.env.NODE_ENV==="production"});}function oe(e){if(e)try{e();}catch(t){console.error("Error executing OAuth hook:",t);}}function De(e){let{state:t,mode:r,linkedUserId:o,platform:i="web",redirectUri:n}=e,s=[t,r,o??""];return (i!=="web"||n)&&(s.push(i),s.push(n?Buffer.from(n,"utf8").toString("base64url"):"")),s.join(":")}function gn(e){let[t,r,o,i,n]=(e||"").split(":"),s;if(n)try{s=Buffer.from(n,"base64url").toString("utf8")||void 0;}catch{s=void 0;}return {stateValue:t,mode:r||"login",...o?{linkedUserId:o}:{},platform:i==="mobile"?"mobile":"web",...s?{redirectUri:s}:{}}}function $e(e,t,r){let o=e.query.state,i=e.cookies[r],n=gn(i||"");return !o||!i||o!==n.stateValue?(b(t,400,"Invalid OAuth state - possible CSRF attack"),null):(t.clearCookie(r),n.platform==="mobile"&&(!n.redirectUri||!St(n.redirectUri))?(b(t,400,"Invalid OAuth redirect target."),null):{mode:n.mode,...n.linkedUserId?{linkedUserId:n.linkedUserId}:{},platform:n.platform,...n.redirectUri?{redirectUri:n.redirectUri}:{}})}function je(e,t){if(e.query.platform!=="mobile")return {ok:true,redirectUri:null};let r=typeof e.query.redirectUri=="string"?e.query.redirectUri:"";return r?St(r)?{ok:true,redirectUri:r}:(b(t,400,"This redirectUri is not allowed. Add it to auth.mobile.redirectUrls to enable mobile sign-in."),{ok:false}):(b(t,400,"A redirectUri is required for mobile authentication."),{ok:false})}async function He(e,t,r$1,o,i={platform:"web"}){let n=y(),{session:s,connectionInfo:a}=await ne(e,t),c=null;if(o){if(!ObjectId.isValid(o)){O(t),b(t,400,"Invalid OAuth linking state.",i);return}c=new ObjectId(o);}else c=s?.userId??null;if(!c){O(t),b(t,401,"You must be signed in to link a provider.",i);return}let l=c;try{let d=`authMethods.${r$1.providerName}.id`;if((await r.updateOne({_id:l,status:{$nin:["deleted","disabled"]},$or:[{[d]:{$exists:!1}},{[d]:r$1.id}]},{$set:{[d]:r$1.id}})).matchedCount===0){let h=await r.findOne({_id:l});if(!h||h.status==="deleted"||h.status==="disabled"){oe(()=>n.onOAuthLinkError?.({provider:r$1.providerName,error:new Error("User account not found or not active"),session:s,connectionInfo:a})),O(t),b(t,400,"User account is not active.",i);return}let w=h?.authMethods?.[r$1.providerName]?.id;if(w&&w!==r$1.id){oe(()=>n.onOAuthLinkError?.({provider:r$1.providerName,error:new Error(`User already has a different ${r$1.providerName} account linked`),session:s,connectionInfo:a})),O(t),b(t,400,`You have already linked a different ${r$1.providerName} account.`,i);return}oe(()=>n.onOAuthLinkError?.({provider:r$1.providerName,error:new Error(`Unexpected OAuth linking state for ${r$1.providerName}`),session:s,connectionInfo:a})),O(t),b(t,400,`Unable to link ${r$1.providerName} account.`,i);return}let f=await r.findOne({_id:l},{readPreference:"primary"});if(f&&oe(()=>n.onAfterOAuthLink?.({provider:r$1.providerName,user:f,session:s,connectionInfo:a})),O(t),i.platform==="mobile"){t.status(302),t.set("Referrer-Policy","no-referrer"),t.redirect(Te(i.redirectUri,{linked:r$1.providerName}));return}t.status(302).redirect("/");}catch(d){if(d instanceof MongoServerError&&d.code===11e3){oe(()=>n.onOAuthLinkError?.({provider:r$1.providerName,error:d,session:s,connectionInfo:a})),O(t),b(t,400,`This ${r$1.providerName} account is already linked to a different user.`,i);return}if(d instanceof Error&&oe(()=>n.onOAuthLinkError?.({provider:r$1.providerName,error:d,session:s,connectionInfo:a})),O(t),!t.headersSent)throw d}}function Ve(e){return !e||typeof e!="string"?null:e}async function yn(e,t,r,o){let i=await fetch("https://oauth2.googleapis.com/token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({code:e,client_id:t,client_secret:r,redirect_uri:o,grant_type:"authorization_code"})});if(!i.ok)throw new Error(`Failed to exchange code for token: ${i.statusText}`);return i.json()}async function bn(e){let t=await fetch("https://www.googleapis.com/oauth2/v2/userinfo",{headers:{Authorization:`Bearer ${e}`}});if(!t.ok)throw new Error(`Failed to fetch user info: ${t.statusText}`);return t.json()}async function En(e,t){let r=Ve(e.query.code);if(!r){b(t,400,"Missing authorization code");return}let o=$e(e,t,"authStateGoogle");if(!o)return;let{mode:i,linkedUserId:n}=o,s=Me(o),a=String(a$2("_system.user.auth.google.clientId")),c=String(a$2("_system.user.auth.google.clientSecret")),l=ie("google");try{let d=await yn(r,a,c,l),u=await bn(d.access_token),f={id:u.id,email:u.email,emailVerified:u.verified_email,providerName:"google",firstName:u.given_name||void 0,lastName:u.family_name||void 0,avatarUrl:u.picture||void 0};i==="link"?await He(e,t,f,n,s):await Ne(e,t,f,s);}catch(d){console.error("Google OAuth error:",d),i==="link"&&O(t),b(t,500,"Authentication failed",s);}}function vn(){let e=Router(),t=(r,o,i)=>{let n=!!a$2("_system.user.auth.google.enabled"),s=String(a$2("_system.user.auth.google.clientId")),a=String(a$2("_system.user.auth.google.clientSecret"));if(!n||!s||!a){b(o,503,"Google authentication is not configured");return}i();};return e.get("/api/_internal/auth/google",t,async(r,o)=>{let i=String(a$2("_system.user.auth.google.clientId")),n=ie("google"),s=randomBytes(32).toString("hex"),a=r.query.mode==="link"?"link":"login",c=je(r,o);if(!c.ok)return;let l=c.redirectUri,d=null;if(a==="link"&&r.query.linkNonce&&(d=await Ie(r.query.linkNonce),!d)){b(o,401,"Invalid or expired link nonce for OAuth linking.");return}let u=De({state:s,mode:a,linkedUserId:d,platform:l?"mobile":"web",redirectUri:l});o.cookie("authStateGoogle",u,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",maxAge:a$1.minutes(10)});let f=new URL("https://accounts.google.com/o/oauth2/v2/auth");f.searchParams.append("client_id",i),f.searchParams.append("redirect_uri",n),f.searchParams.append("response_type","code"),f.searchParams.append("scope","profile email"),f.searchParams.append("access_type","online"),f.searchParams.append("state",s),o.redirect(f.toString());}),e.get("/api/_internal/auth/google/callback",t,En),e}var Co=vn;async function Sn(e,t,r,o){let i=await fetch("https://github.com/login/oauth/access_token",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({client_id:t,client_secret:r,code:e,redirect_uri:o})});if(!i.ok)throw new Error(`Failed to exchange code for token: ${i.statusText}`);return i.json()}async function An(e){let t=await fetch("https://api.github.com/user",{headers:{Authorization:`Bearer ${e}`,Accept:"application/vnd.github.v3+json"}});if(!t.ok)throw new Error(`Failed to fetch user info: ${t.statusText}`);return t.json()}async function Rn(e){let t=await fetch("https://api.github.com/user/emails",{headers:{Authorization:`Bearer ${e}`,Accept:"application/vnd.github.v3+json"}});if(!t.ok)throw new Error(`Failed to fetch user emails: ${t.statusText}`);return t.json()}async function On(e,t){return e.email?e.email:(await Rn(t)).find(o=>o.primary&&o.verified)?.email??null}async function xn(e,t){let r=Ve(e.query.code);if(!r){b(t,400,"Missing authorization code");return}let o=$e(e,t,"authStateGithub");if(!o)return;let{mode:i,linkedUserId:n}=o,s=Me(o),a=String(a$2("_system.user.auth.github.clientId")),c=String(a$2("_system.user.auth.github.clientSecret")),l=ie("github");try{let d=await Sn(r,a,c,l),u=await An(d.access_token),f=await On(u,d.access_token);if(!f){i==="link"&&O(t),b(t,400,"Unable to retrieve a primary verified email from GitHub. Please ensure your GitHub account has a verified email set as primary.",s);return}let h=u.name?u.name.trim().split(/\s+/):[],w=h[0]||void 0,k=h.length>1?h.slice(1).join(" "):void 0,x={id:String(u.id),email:f,emailVerified:!0,providerName:"github",firstName:w,lastName:k,avatarUrl:u.avatar_url||void 0};i==="link"?await He(e,t,x,n,s):await Ne(e,t,x,s);}catch(d){console.error("GitHub OAuth error:",d),i==="link"&&O(t),b(t,500,"Authentication failed",s);}}function _n(){let e=Router(),t=(r,o,i)=>{let n=!!a$2("_system.user.auth.github.enabled"),s=String(a$2("_system.user.auth.github.clientId")),a=String(a$2("_system.user.auth.github.clientSecret"));if(!n||!s||!a){b(o,503,"GitHub authentication is not configured");return}i();};return e.get("/api/_internal/auth/github",t,async(r,o)=>{let i=String(a$2("_system.user.auth.github.clientId")),n=ie("github"),s=a$2("_system.user.auth.github.scopes"),a=s?String(s).split(",").map(k=>k.trim()).join(" "):"user:email",c=randomBytes(32).toString("hex"),l=r.query.mode==="link"?"link":"login",d=je(r,o);if(!d.ok)return;let u=d.redirectUri,f=null;if(l==="link"&&r.query.linkNonce&&(f=await Ie(r.query.linkNonce),!f)){b(o,401,"Invalid or expired link nonce for OAuth linking.");return}let h=De({state:c,mode:l,linkedUserId:f,platform:u?"mobile":"web",redirectUri:u});o.cookie("authStateGithub",h,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",maxAge:a$1.minutes(10)});let w=new URL("https://github.com/login/oauth/authorize");w.searchParams.append("client_id",i),w.searchParams.append("redirect_uri",n),w.searchParams.append("scope",a),w.searchParams.append("state",c),o.redirect(w.toString());}),e.get("/api/_internal/auth/github/callback",t,xn),e}var So=_n;function Ao(e,t,r){return async(o,i$1,n)=>{let s=o.headers["x-modelence-auth-token"],a={session:null,user:null};if(typeof s=="string"&&N())try{let{session:l,user:d}=await y$1(s);a={session:l,user:d};}catch{}let c=m$1("route",`route:${e.toLowerCase()}:${t}`,{method:e,path:t,query:i(o.query),body:i(o.body),params:i(o.params)});try{let l=await r({query:o.query,body:o.body,params:o.params,headers:o.headers,cookies:o.cookies,rawBody:Buffer.isBuffer(o.body)?o.body:void 0,req:o,res:i$1,next:n},a);c.end(),l&&(i$1.status(l.status||200),l.contentType&&i$1.setHeader("Content-Type",l.contentType),l.headers&&Object.entries(l.headers).forEach(([d,u])=>{i$1.setHeader(d,u);}),l.redirect?i$1.redirect(l.redirect):i$1.send(l.data));}catch(l){c.end("error"),l instanceof a$4?i$1.status(l.status).send(l.message):(console.error(`Error in route handler: ${o.path}`),console.error(l),i$1.status(500).send(String(l)));}}}function Pn(e){let t=[];if(!e)return t.push(q$1.json({limit:"16mb"})),t.push(q$1.urlencoded({extended:true,limit:"16mb"})),t;if(e.json!==false){let r=typeof e.json=="object"?e.json:{limit:"16mb"};t.push(q$1.json(r));}if(e.urlencoded!==false){let r=typeof e.urlencoded=="object"?e.urlencoded:{extended:true,limit:"16mb"};t.push(q$1.urlencoded(r));}if(e.raw){let r=typeof e.raw=="object"?e.raw:{},o={limit:r.limit||"16mb",type:r.type||"*/*"};t.push(q$1.raw(o));}return t}function Tn(e,t){for(let r of t)for(let o of r.routes){let{path:i,handlers:n,body:s}=o,a=Pn(s);Object.entries(n).forEach(([c,l])=>{e[c](i,...a,Ao(c,i,l));});}}async function wo(e,{combinedModules:t,channels:r}){let o=q$1();o.use(Ln()),o.use(Nn()),Tn(o,t),o.use(q$1.json({limit:"16mb"})),o.use(q$1.urlencoded({extended:true,limit:"16mb"})),o.use(Co()),o.use(So()),o.post("/api/_internal/auth/set-link-cookie",async(a,c)=>{let{session:l}=await ne(a,c);if(!l?.userId){c.status(401).json({error:"Not authenticated"});return}c.cookie("oauthLinkToken",l.authToken,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:"/api/_internal/auth/",maxAge:10*60*1e3}),c.json({ok:true});}),o.post("/api/_internal/auth/issue-link-nonce",async(a,c)=>{let{session:l}=await ne(a,c);if(!l?.userId){c.status(401).json({error:"Not authenticated"});return}let d=await e$1(String(l.userId));c.json({nonce:d});}),o.post("/api/_internal/method/:methodName(*)",async(a,c)=>{let l=a.params.methodName,d=await ne(a,c);try{let u=a$3(await F$1(l,a.body.args,d));c.json({data:u,typeMap:b$3(u)});}catch(u){Mn(c,l,u);}});let i=Un.createServer(o);await e.init({httpServer:i}),e.middlewares&&o.use(e.middlewares()),o.all("*",(a,c,l)=>{Promise.resolve(e.handler(a,c)).catch(l);}),process.on("unhandledRejection",(a,c)=>{console.error("Unhandled Promise Rejection:"),console.error(a instanceof Error?a.stack:a),console.error("Promise:",c);}),process.on("uncaughtException",a=>{console.error("Uncaught Exception:"),console.error(a.stack),console.trace("Full application stack:");});let n=Pe()?.provider;n&&n.init({httpServer:i,channels:r});let s=process.env.MODELENCE_PORT||process.env.PORT||3e3;i.listen(s,()=>{k$1("Application started",{source:"app"});let a=a$2("_system.site.url")||`http://localhost:${s}`;console.log(`
34
+ Application started on ${a}
35
+ `);});}async function ne(e,t=null){let r=(e.path??e.url??"").split("?")[0],o=r.startsWith("/api/_internal/auth/")&&r.endsWith("/callback"),i=e.body??{},n=G.string().nullish().transform(l=>l??null).parse(e.cookies.authToken||(o?e.cookies.oauthLinkToken:null)||i.authToken),s=G.object({screenWidth:G.number(),screenHeight:G.number(),windowWidth:G.number(),windowHeight:G.number(),pixelRatio:G.number(),orientation:G.string().nullable()}).nullish().parse(i.clientInfo)??{screenWidth:0,screenHeight:0,windowWidth:0,windowHeight:0,pixelRatio:1,orientation:null},a={ip:$n(e),userAgent:e.get("user-agent"),acceptLanguage:e.get("accept-language"),referrer:e.get("referrer"),baseUrl:Dn(e)};if(!!N()){let{session:l,user:d,roles:u}=await y$1(n);return {clientInfo:s,connectionInfo:a,session:l,user:d,roles:u,req:e,res:t}}return {clientInfo:s,connectionInfo:a,session:null,user:null,roles:x(),req:e,res:t}}function Mn(e,t,r){if(r instanceof a$4){r.status>=500&&r.status<600&&console.error(`Error calling ${t}:`,r),r.code&&e.setHeader("X-Modelence-Error-Code",r.code),e.status(r.status).send(r.message);return}if(r instanceof Error&&r?.constructor?.name==="ZodError"&&"errors"in r){let o="";try{o=In(r);}catch(i){console.error(`Error parsing Zod error in ${t}:`,i),o="Validation failed";}e.status(400).send(o);return}console.error(`Error calling ${t}:`,r),e.status(500).send(r instanceof Error?r.message:String(r));}function In(e){let t=e.flatten(),r=Object.entries(t.fieldErrors).map(([n,s])=>`${n}: ${(s??[]).join(", ")}`),o=t.formErrors;return [...r,...o].filter(Boolean).join("; ")}function Nn(){let{frameAncestors:e}=fo(),t=e&&e.length>0,r=t?["'self'",...e].join(" "):"'self'";return (o,i,n)=>{i.setHeader("Content-Security-Policy",`frame-ancestors ${r}`),t||i.setHeader("X-Frame-Options","SAMEORIGIN"),n();}}function Dn(e){let t=e.headers["x-forwarded-host"],r=(Array.isArray(t)?t[0]:t?.split(",")[0])?.trim()||e.get("host"),o=e.headers["x-forwarded-proto"];return `${(Array.isArray(o)?o[0]:o?.split(",")[0])?.trim()||e.protocol}://${r}`}function $n(e){let t=e.headers["x-forwarded-for"];if(t)return (Array.isArray(t)?t[0]:t.split(",")[0]).trim();let r=e.ip||e.socket?.remoteAddress;if(r)return r.startsWith("::ffff:")?r.substring(7):r}
36
+ export{C as a,Ei as b,vi as c,ki as d,Ci as e,wo as f,ne as g,zi as h,an as i,cn as j,Ct as k,ln as l};//# sourceMappingURL=chunk-KYQ6UVLY.js.map
37
+ //# sourceMappingURL=chunk-KYQ6UVLY.js.map