modelence 0.25.0 → 0.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/bin/modelence.js +1 -1
- package/dist/bin/modelence.js.map +1 -1
- package/dist/{chunk-BVJJCQ6Y.js → chunk-6CIFSSQP.js} +4 -4
- package/dist/chunk-6CIFSSQP.js.map +1 -0
- package/dist/{chunk-FXPFIA66.js → chunk-DAV46WE7.js} +3 -3
- package/dist/{chunk-FXPFIA66.js.map → chunk-DAV46WE7.js.map} +1 -1
- package/dist/{chunk-7JUFVY6Q.js → chunk-FF6FEX7U.js} +2 -2
- package/dist/{chunk-7JUFVY6Q.js.map → chunk-FF6FEX7U.js.map} +1 -1
- package/dist/{chunk-J3ZZEZIV.js → chunk-IKIOVFVD.js} +13 -13
- package/dist/chunk-IKIOVFVD.js.map +1 -0
- package/dist/chunk-K4PI6L5V.js +2 -0
- package/dist/chunk-K4PI6L5V.js.map +1 -0
- package/dist/{chunk-VKGZ35WJ.js → chunk-KJBMQRY6.js} +2 -2
- package/dist/{chunk-VKGZ35WJ.js.map → chunk-KJBMQRY6.js.map} +1 -1
- package/dist/{chunk-7MIBHVZS.js → chunk-NAWQYPGM.js} +3 -3
- package/dist/{chunk-7MIBHVZS.js.map → chunk-NAWQYPGM.js.map} +1 -1
- package/dist/{chunk-CAN2CWEI.js → chunk-S5OQYKNR.js} +2 -2
- package/dist/{chunk-CAN2CWEI.js.map → chunk-S5OQYKNR.js.map} +1 -1
- package/dist/client.js +1 -1
- package/dist/{package-PKGSNHLQ.js → package-GGPYIET6.js} +2 -2
- package/dist/{package-PKGSNHLQ.js.map → package-GGPYIET6.js.map} +1 -1
- package/dist/{render-GH7MWT27.js → render-WY23X5RN.js} +2 -2
- package/dist/{render-GH7MWT27.js.map → render-WY23X5RN.js.map} +1 -1
- package/dist/renderApp-FRZBJICP.js +2 -0
- package/dist/{renderApp-5P62J4NO.js.map → renderApp-FRZBJICP.js.map} +1 -1
- package/dist/server-J75POKU5.js +2 -0
- package/dist/{server-LBKWH4I3.js.map → server-J75POKU5.js.map} +1 -1
- package/dist/server.d.ts +3 -1
- package/dist/server.js +1 -1
- package/dist/transport-RJFMTIDK.js +2 -0
- package/dist/{transport-QMFZ67HR.js.map → transport-RJFMTIDK.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-5M6FUMUK.js +0 -2
- package/dist/chunk-5M6FUMUK.js.map +0 -1
- package/dist/chunk-BVJJCQ6Y.js.map +0 -1
- package/dist/chunk-J3ZZEZIV.js.map +0 -1
- package/dist/renderApp-5P62J4NO.js +0 -2
- package/dist/server-LBKWH4I3.js +0 -2
- package/dist/transport-QMFZ67HR.js +0 -2
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {t as t$1}from'./chunk-
|
|
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=r.slice(n,n+i);try{await t.insertMany(s.map(a=>({domain:a,addedAt:o})));}catch(a){a&&typeof a=="object"&&"name"in a&&a.name;}}}};var Qe=3,ne=50,en=/^[a-zA-Z0-9_-]+$/,lr=8,dr=128,ur=254,tn=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`}),Xe=e=>z.string().trim().max(e.max,{message:`must be at most ${e.max} characters`}).transform(t=>t===""?void 0:t).optional(),mr=tn({min:Qe,max:ne}).regex(en,{message:"must contain only letters, numbers, underscores, and hyphens"}),rn=z.object({firstName:Xe({max:50}),lastName:Xe({max:50}),avatarUrl:Xe({max:400}),handle:mr}).strict();function
|
|
1
|
+
import {t as t$1}from'./chunk-NAWQYPGM.js';import {a,b as b$1,c,d,s,t,u,v,w,o,p,i,l,e,B,n,m,q,r,x as x$1,C,D,E as E$1,F,f as f$1,G as G$1,z as z$1,y as y$1,g as g$1,h,J,H,I}from'./chunk-6CIFSSQP.js';import {b as b$2,c as c$1,d as d$1,a as a$4}from'./chunk-VYR7VQMQ.js';import {a as a$2,f,e as e$1,g,c as c$2,i as i$1,m as m$1,l as l$1,d as d$2,k as k$1,o as o$1,n as n$1,j}from'./chunk-UW37F3GV.js';import {a as a$3,b as b$3}from'./chunk-K4PI6L5V.js';import {a as a$1}from'./chunk-DO5TZLF5.js';import Oo from'dotenv';import Ei from'fs/promises';import Xr from'os';import ee 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 {randomBytes,randomInt,randomUUID,createHash}from'crypto';import hr from'bcrypt';import F$1,{z}from'zod';import Ie from'fs';import {createServer,defineConfig,loadConfigFromFile,mergeConfig}from'vite';import ri from'@vitejs/plugin-react';import q$1,{Router}from'express';import ls from'cookie-parser';import ds from'http';var fe=new a("_system",{queries:{setupStatus:async()=>({setupRequired:b$1()})},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 V=null;async function ir(){if(V)return V;let e=N();if(!e)throw new Error("MongoDB URI is not set");let t=fe.getConfig("mongodbPoolSize");V=new MongoClient(e,{driverInfo:{name:"Modelence",version:t$1.version},ignoreUndefined:true,maxPoolSize:t});try{return await V.connect(),await V.db("admin").command({ping:1}),console.log("Pinged your deployment. You successfully connected to MongoDB!"),V}catch(r){throw console.error(r),V=null,r}}function N(){return fe.getConfig("mongodbUri")||void 0}function Oe(){return V}var ge=null,Xo="_modelenceSocketio",sr=60;async function Qo({httpServer:e,channels:t}){let r=Oe(),o=!!a$2("_system.multiInstance");console.log("Initializing Socket.IO server...");let i=null;if(o&&r){i=r.db().collection(Xo);try{await i.createIndex({createdAt:1},{expireAfterSeconds:sr,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:sr,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);}}ge=new Server(e,{cors:{origin:"*",methods:["GET","POST"]},adapter:i?createAdapter(i):void 0,transports:["websocket"],perMessageDeflate:false}),ge.on("error",n=>{console.error("Socket.IO error:",n);}),ge.use(async(n,s)=>{let a=n.handshake.auth.token;try{n.data=await z$1(a),s();}catch(c){s(c instanceof Error?c:new Error(String(c)));}}),ge.on("connection",n=>{n.on("disconnect",()=>{J(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=>H(n,s)),n.on("unsubscribeLiveQuery",s=>I(n,s));}),console.log("Socket.IO server initialized");}function Zo({category:e,id:t,data:r}){ge?.to(`${e}:${t}`).emit(e,r);}var ar={init:Qo,broadcast:Zo};async function Re(e){let t$1=e.toLowerCase().trim().split("@");if(t$1.length!==2)return false;let r=t$1[1];return !!await t.findOne({domain:r})}var cr={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=r.slice(n,n+i);try{await t.insertMany(s.map(a=>({domain:a,addedAt:o})));}catch(a){a&&typeof a=="object"&&"name"in a&&a.name;}}}};var Qe=3,ne=50,en=/^[a-zA-Z0-9_-]+$/,lr=8,dr=128,ur=254,tn=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`}),Xe=e=>z.string().trim().max(e.max,{message:`must be at most ${e.max} characters`}).transform(t=>t===""?void 0:t).optional(),mr=tn({min:Qe,max:ne}).regex(en,{message:"must contain only letters, numbers, underscores, and hyphens"}),rn=z.object({firstName:Xe({max:50}),lastName:Xe({max:50}),avatarUrl:Xe({max:400}),handle:mr}).strict();function xe(e){let t=rn.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 c$1(i)}return t.data}function _e(e){return z.string().min(lr,{message:`Password must contain at least ${lr} characters`}).max(dr,{message:`Password must be at most ${dr} characters`}).parse(e)}function L(e){return z.string().max(ur,{message:`Email must be at most ${ur} characters`}).email({message:"Invalid email address"}).parse(e).toLowerCase()}function pr(e){return mr.parse(e)}function Le(e){return e instanceof MongoServerError&&e.code===11e3&&typeof e.keyPattern=="object"&&e.keyPattern!==null&&"emails.address"in e.keyPattern}function Ue(e,t){return t?t.startsWith("http://")||t.startsWith("https://")?t:`${e}${t.startsWith("/")?"":"/"}${t}`:e}function G(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 fr(e){let t=e.slice(0,ne);try{if(!await s.findOne({handle:t},{collation:{locale:"en",strength:2}}))return t}catch(i){throw new Error(`Database error while checking handle availability: ${i}`)}let r=51;for(let i=2;i<=r;i++){let n=`_${i}`,s$1=`${t.slice(0,ne-n.length)}${n}`;try{if(!await s.findOne({handle:s$1},{collation:{locale:"en",strength:2}}))return s$1}catch(a){throw new Error(`Database error while checking handle "${s$1}": ${a}`)}}let o=10;for(let i=0;i<o;i++){let n=`_${randomBytes(3).toString("hex")}`,s$1=`${t.slice(0,ne-n.length)}${n}`;try{if(!await s.findOne({handle:s$1},{collation:{locale:"en",strength:2}}))return s$1}catch(a){throw new Error(`Database error while checking handle "${s$1}": ${a}`)}}throw new Error(`Could not generate a unique handle for base "${e}" after exhausting all attempts.`)}async function U(e,t,{throwOnConflict:r=true}={}){if(e!=null&&String(e).trim()!==""){let n=pr(String(e).trim());if(r){if(await s.findOne({handle:n},{collation:{locale:"en",strength:2}}))throw new Error("Handle already taken.");return n}return fr(n)}let i=t.split("@")[0].replace(/[^a-zA-Z0-9_-]/g,"_").padEnd(Qe,"_").slice(0,ne);return fr(i)}var Ze=Object.freeze({});function et(e){Ze=Object.freeze(Object.assign({},Ze,e));}function b(){return Ze}var tt=Object.freeze({});function gr(e){tt=Object.freeze(Object.assign({},tt,e));}function y(){return tt}function cn(){return b()?.provider?!!a$2("_system.user.auth.email.verification"):false}var ln=10,dn=hr.hashSync(randomBytes(32).toString("hex"),ln);async function wr(e,{user:t,session:r,connectionInfo:o,res:i}){try{if(!r)throw new Error("Session is not initialized");if(t)throw new c$1("User is already authenticated","ALREADY_AUTHENTICATED");let n=o?.ip;n&&await k({bucket:"signin",type:"ip",value:n});let s$1=L(e.email),a=z.string().parse(e.password),c=await s.findOne({"emails.address":s$1,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}}),l$1=c?.authMethods?.password?.hash,d=l$1||dn,u=await hr.compare(a,d);if(!l$1||!u)throw un();if(!c.emails?.find(g=>g.address.toLowerCase()===s$1)?.verified&&cn())throw new b$2("Your email address hasn't been verified yet. Please check your inbox for the verification email.","EMAIL_NOT_VERIFIED");return await l(r.authToken,c._id),i&&p(i,r.authToken),y().onAfterLogin?.({provider:"email",user:c,session:r,connectionInfo:o}),y().login?.onSuccess?.(c),{user:G(c),session:{authToken:r.authToken}}}catch(n){throw n instanceof Error&&(y().onLoginError?.({provider:"email",error:n,session:r,connectionInfo:o}),y().login?.onError?.(n)),n}}async function yr(e,{session:t,res:r}){if(!t)throw new Error("Session is not initialized");await m(t.authToken),r&&q(r);}function un(){return new Error("Incorrect email/password combination")}var we=new c("_modelenceRateLimits",{schema:{bucket:d.string(),type:d.enum(["ip","user","email"]),value:d.string(),windowMs:d.number(),windowStart:d.date(),windowCount:d.number(),prevWindowCount:d.number(),expiresAt:d.date()},indexes:[{key:{bucket:1,type:1,value:1,windowMs:1},unique:true},{key:{expiresAt:1},expireAfterSeconds:0}]});var rt=[];function Er(e){if(rt.length>0)throw new Error("Duplicate call to initRateLimits - already initialized");rt=e;}async function k(e){let{bucket:t,type:r,value:o,message:i}=e,n=rt.filter(a=>a.bucket===t&&a.type===r),s=i?()=>new d$1(i):void 0;for(let a of n)await mn(a,o,s);}async function mn(e,t,r){let o=()=>r?r():new d$1(`Rate limit exceeded for ${e.bucket}`),i={bucket:e.bucket,type:e.type,value:t,windowMs:e.window},n=await we.findOne(i),s=Date.now(),a=Math.floor(s/e.window)*e.window,{count:c,modifier:l}=n?pn(n,a,s):{count:0,modifier:{$setOnInsert:{windowStart:new Date(a),windowCount:1,prevWindowCount:0,expiresAt:new Date(a+e.window+e.window)}}};if(c>=e.limit)throw o();await we.upsertOne(i,l);}function pn(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)}}}}async function br(e,{user:t}){if(!t)throw new b$2("Not authenticated");let r=await s.requireById(t.id);return {handle:r.handle,emails:r.emails,authMethods:Object.keys(r.authMethods||{}),firstName:r.firstName??void 0,lastName:r.lastName??void 0,avatarUrl:r.avatarUrl??void 0}}async function vr(e,{user:t}){if(!t)throw new b$2("Not authenticated");let r=await s.requireById(t.id),o=e,i=typeof o.handle=="string"&&o.handle.trim()===r.handle,{handle:n,...s$1}=o,a=xe(i?s$1:o);if(await y().validateProfileUpdate?.(a),"handle"in a&&a.handle!==void 0&&await s.findOne({handle:a.handle,_id:{$ne:r._id}},{collation:{locale:"en",strength:2}}))throw new c$1("Handle already taken.");if(Object.keys(a).length>0){await k({bucket:"updateProfile",type:"user",value:t.id});let c={},l={};for(let[u,m]of Object.entries(a))m===void 0?l[u]="":c[u]=m;let d={};Object.keys(c).length>0&&(d.$set=c),Object.keys(l).length>0&&(d.$unset=l);try{await s.updateOne({_id:r._id},d);let u=Object.fromEntries(Object.keys(l).map(m=>[m,void 0]));r={...r,...c,...u};}catch(u){throw u instanceof Error&&"code"in u&&u.code===11e3?new c$1("Handle already taken."):u}}return {user:G(r)}}var ot=["google","github"];async function Cr({provider:e},{user:t}){if(!t)throw new Error("You must be signed in to unlink a provider.");if(typeof e!="string"||!ot.includes(e))throw new Error(`Invalid provider. Supported providers are: ${ot.join(", ")}.`);let r=await s.requireById(t.id),o=r.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$1=Object.keys(o).filter(l=>l!==e&&o[l]),a=s$1.length>0?{$or:s$1.map(l=>({[`authMethods.${l}`]:{$exists:true}}))}:{};if((await s.updateOne({_id:r._id,...a},{$unset:{[`authMethods.${e}`]:""}})).matchedCount===0)throw new Error("Cannot unlink your only authentication method. Please add another method first.")}function kr({name:e,email:t,verificationUrl:r}){return `
|
|
3
3
|
<p>Hi${e?` ${e}`:""},</p>
|
|
4
4
|
<p>Please verify your email address ${t} by clicking the link below:</p>
|
|
5
5
|
<p><a href="${r}">${r}</a></p>
|
|
6
6
|
<p>If you did not request this, please ignore this email.</p>
|
|
7
|
-
`}var hn={locale:"en",strength:2};async function wn(e){let t=await u.findOne({token:e,expiresAt:{$gt:new Date}});if(!t)throw new Error("Invalid or expired verification token");let r=await s.findOne({_id:t.userId,status:{$nin:["deleted","disabled"]}});if(!r)throw new Error("User not found");let o=t.email;if(!o)throw new Error("Email not found in token");let i=await s.findOneAndUpdate({_id:t.userId,status:{$nin:["deleted","disabled"]},emails:{$elemMatch:{address:o,verified:{$ne:true}}}},{$set:{"emails.$.verified":true}},{collation:hn,returnDocument:"after"});if(await u.deleteOne({_id:t._id}),!i){let n=r.emails?.find(s=>s.address.toLowerCase()===o);throw n?n.verified?new Error("Email is already verified"):new Error("Unable to verify email address"):new Error("Email address not found for this user")}return {userDoc:i,email:o}}async function Sr(e){let t=a$2("_system.site.url"),r=b().verification?.redirectUrl||b().emailVerifiedRedirectUrl||t||"/";try{let o$1=z.string().parse(e.query.token),{userDoc:i}=await wn(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 o(i._id);return p(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 it({userId:e,email:t,baseUrl:r}){let o=a$2("_system.site.url")||r;if(b().provider){let i=b().provider,n=randomBytes(32).toString("hex"),s=new Date(Date.now()+a$1.hours(24));await u.insertOne({userId:e,email:t,token:n,createdAt:new Date,expiresAt:s});let a=`${o}/api/_internal/auth/verify-email?token=${n}`,l=(b()?.verification?.template||kr)({name:"",email:t,verificationUrl:a}),d=B(l);await i?.sendEmail({to:t,from:b()?.from||"noreply@modelence.com",subject:b()?.verification?.subject||"Verify your email address",text:d,html:l});}}var nt={success:true,message:"If that email is registered and not yet verified, a verification email has been sent"};async function Ar(e,{connectionInfo:t}){let r=L(e.email),o=await s.findOne({"emails.address":r,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}});if(!o)return nt;let i=o.emails?.find(n=>n.address.toLowerCase()===r);if(!i||i.verified)return nt;if(!b().provider)throw new Error("Email provider is not configured");return await k({bucket:"verification",type:"user",value:o._id.toString(),message:"Please wait at least 60 seconds before requesting another verification email"}),await it({userId:o._id,email:r,baseUrl:t?.baseUrl}),nt}async function Or(e,{user:t,session:r,connectionInfo:o}){let i=y();try{if(t)throw new c$1("User is already authenticated","ALREADY_AUTHENTICATED");let n=e,{firstName:s$1,lastName:a,avatarUrl:c,handle:l}=n,d=L(n.email),u=
|
|
7
|
+
`}var hn={locale:"en",strength:2};async function wn(e){let t=await u.findOne({token:e,expiresAt:{$gt:new Date}});if(!t)throw new Error("Invalid or expired verification token");let r=await s.findOne({_id:t.userId,status:{$nin:["deleted","disabled"]}});if(!r)throw new Error("User not found");let o=t.email;if(!o)throw new Error("Email not found in token");let i=await s.findOneAndUpdate({_id:t.userId,status:{$nin:["deleted","disabled"]},emails:{$elemMatch:{address:o,verified:{$ne:true}}}},{$set:{"emails.$.verified":true}},{collation:hn,returnDocument:"after"});if(await u.deleteOne({_id:t._id}),!i){let n=r.emails?.find(s=>s.address.toLowerCase()===o);throw n?n.verified?new Error("Email is already verified"):new Error("Unable to verify email address"):new Error("Email address not found for this user")}return {userDoc:i,email:o}}async function Sr(e){let t=a$2("_system.site.url"),r=b().verification?.redirectUrl||b().emailVerifiedRedirectUrl||t||"/";try{let o$1=z.string().parse(e.query.token),{userDoc:i}=await wn(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 o(i._id);return p(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 it({userId:e,email:t,baseUrl:r}){let o=a$2("_system.site.url")||r;if(b().provider){let i=b().provider,n=randomBytes(32).toString("hex"),s=new Date(Date.now()+a$1.hours(24));await u.insertOne({userId:e,email:t,token:n,createdAt:new Date,expiresAt:s});let a=`${o}/api/_internal/auth/verify-email?token=${n}`,l=(b()?.verification?.template||kr)({name:"",email:t,verificationUrl:a}),d=B(l);await i?.sendEmail({to:t,from:b()?.from||"noreply@modelence.com",subject:b()?.verification?.subject||"Verify your email address",text:d,html:l});}}var nt={success:true,message:"If that email is registered and not yet verified, a verification email has been sent"};async function Ar(e,{connectionInfo:t}){let r=L(e.email),o=await s.findOne({"emails.address":r,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}});if(!o)return nt;let i=o.emails?.find(n=>n.address.toLowerCase()===r);if(!i||i.verified)return nt;if(!b().provider)throw new Error("Email provider is not configured");return await k({bucket:"verification",type:"user",value:o._id.toString(),message:"Please wait at least 60 seconds before requesting another verification email"}),await it({userId:o._id,email:r,baseUrl:t?.baseUrl}),nt}async function Or(e,{user:t,session:r,connectionInfo:o}){let i=y();try{if(t)throw new c$1("User is already authenticated","ALREADY_AUTHENTICATED");let n=e,{firstName:s$1,lastName:a,avatarUrl:c,handle:l}=n,d=L(n.email),u=_e(n.password),m=o?.ip;if(m&&await k({bucket:"signupAttempt",type:"ip",value:m}),!i.allowDisposableEmails&&await Re(d))throw new Error("Please use a permanent email address");if(await s.findOne({"emails.address":d},{collation:{locale:"en",strength:2}}))throw new Error("Unable to create account");await i.onBeforeSignup?.({email:d,firstName:s$1,lastName:a,handle:l,provider:"email",connectionInfo:o}),m&&await k({bucket:"signup",type:"ip",value:m});let h=xe({firstName:s$1,lastName:a,avatarUrl:c,handle:l});await i.validateSignup?.({email:d,password:u,...h}),await i.validatePassword?.({password:u,email:d,context:"signup"});let v;if(h.handle)v=await U(h.handle,d);else if(i.generateHandle){let D=await i.generateHandle({email:d,firstName:h.firstName,lastName:h.lastName});v=await U(D,d,{throwOnConflict:!1});}else v=await U(void 0,d);let S=await hr.hash(u,10),T;try{T=await s.insertOne({handle:v,status:"active",emails:[{address:d,verified:!1}],createdAt:new Date,authMethods:{password:{hash:S}},...h.firstName!==void 0&&{firstName:h.firstName},...h.lastName!==void 0&&{lastName:h.lastName},...h.avatarUrl!==void 0&&{avatarUrl:h.avatarUrl}});}catch(D){throw Le(D)?new Error("Unable to create account"):D}let A=await s.findOne({_id:T.insertedId},{readPreference:"primary"});if(!A)throw new Error("User not found");return await it({userId:T?.insertedId,email:d,baseUrl:o?.baseUrl}),i.onAfterSignup?.({provider:"email",user:A,session:r,connectionInfo:o}),i.signup?.onSuccess?.(A),T.insertedId}catch(n){throw n instanceof Error&&(i.onSignupError?.({provider:"email",error:n,session:r,connectionInfo:o}),i.signup?.onError?.(n)),n}}var st="resetPasswordToken",vn="/api/_internal/",Lr={httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:vn};async function Ur(e$1){return v.findOne({token:e(e$1)})}async function Rr(e){return v.findOneAndDelete({_id:e})}function Cn({email:e,resetUrl:t}){return `
|
|
8
8
|
<p>Hi,</p>
|
|
9
9
|
<p>We received a request to reset your password for ${e}.</p>
|
|
10
10
|
<p>Click the link below to reset your password:</p>
|
|
11
11
|
<p><a href="${t}">${t}</a></p>
|
|
12
12
|
<p>This link will expire in 1 hour.</p>
|
|
13
13
|
<p>If you did not request this password reset, please ignore this email.</p>
|
|
14
|
-
`}var xr={success:true,message:"If an account with that email exists, a password reset link has been sent"};async function Pr(e$1,{connectionInfo:t}){let r=L(e$1.email),o=t?.ip;o&&await k({bucket:"passwordReset",type:"ip",value:o}),await k({bucket:"passwordReset",type:"email",value:r});let i=await s.findOne({"emails.address":r,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}});if(!i)return xr;let n=b().provider;if(!n)throw new Error("Email provider is not configured");let s$1=randomBytes(32).toString("hex"),a=Date.now(),c=new Date(a),l=new Date(a+a$1.hours(1));await v.insertOne({userId:i._id,email:r,token:e(s$1),createdAt:c,expiresAt:l});let d=a$2("_system.site.url")||t?.baseUrl;if(!d)throw new Error("Unable to build password reset link: set _system.site.url (MODELENCE_SITE_URL)");let u=`${d}/api/_internal/auth/reset-password?token=${s$1}`,g=(b()?.passwordReset?.template||Cn)({email:r,resetUrl:u,name:""}),h=B(g);return await n.sendEmail({to:r,from:b()?.from||"noreply@modelence.com",subject:b()?.passwordReset?.subject||"Reset your password",text:h,html:g}),xr}async function Tr(e){let t=a$2("_system.site.url")||`${e.req.protocol}://${e.req.get("host")}`,r=
|
|
14
|
+
`}var xr={success:true,message:"If an account with that email exists, a password reset link has been sent"};async function Pr(e$1,{connectionInfo:t}){let r=L(e$1.email),o=t?.ip;o&&await k({bucket:"passwordReset",type:"ip",value:o}),await k({bucket:"passwordReset",type:"email",value:r});let i=await s.findOne({"emails.address":r,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}});if(!i)return xr;let n=b().provider;if(!n)throw new Error("Email provider is not configured");let s$1=randomBytes(32).toString("hex"),a=Date.now(),c=new Date(a),l=new Date(a+a$1.hours(1));await v.insertOne({userId:i._id,email:r,token:e(s$1),createdAt:c,expiresAt:l});let d=a$2("_system.site.url")||t?.baseUrl;if(!d)throw new Error("Unable to build password reset link: set _system.site.url (MODELENCE_SITE_URL)");let u=`${d}/api/_internal/auth/reset-password?token=${s$1}`,g=(b()?.passwordReset?.template||Cn)({email:r,resetUrl:u,name:""}),h=B(g);return await n.sendEmail({to:r,from:b()?.from||"noreply@modelence.com",subject:b()?.passwordReset?.subject||"Reset your password",text:h,html:g}),xr}async function Tr(e){let t=a$2("_system.site.url")||`${e.req.protocol}://${e.req.get("host")}`,r=Ue(t,b().passwordReset?.redirectUrl);try{let o=z.string().parse(e.query.token),i=await Ur(o);if(!i||i.expiresAt<new Date)throw new Error("This password reset link is invalid or has expired.");return e.res.cookie(st,o,{...Lr,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 Mr(e,t){let r=t.req?.cookies?.[st];!r&&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??e.token),i=_e(e.password),n$1=()=>{t.res?.clearCookie(st,Lr);},s$1=await Ur(o);if(!s$1)throw n$1(),new Error("Invalid or expired reset token");if(s$1.expiresAt<new Date)throw await Rr(s$1._id),n$1(),new Error("Reset token has expired");let a=await s.findOne({_id:s$1.userId});if(!a)throw new Error("User not found");await y().validatePassword?.({password:i,email:s$1.email??a.emails?.[0]?.address?.toLowerCase()??"",context:"reset"});let c=await hr.hash(i,10);if(!await Rr(s$1._id))throw n$1(),new Error("Invalid or expired reset token");await s.updateOne({_id:a._id},{$set:{"authMethods.password.hash":c}}),s$1.email&&await s.updateOne({_id:a._id,"emails.address":s$1.email},{$set:{"emails.$.verified":true}},{collation:{locale:"en",strength:2}}),await n(a._id);let d=Array.from(new Set((a.emails??[]).map(u=>u.address?.toLowerCase()).filter(u=>!!u)));return d.length>0&&await w.deleteMany({email:{$in:d}}),n$1(),{success:true,message:"Password has been reset successfully"}}function Ir({name:e,email:t,magicLinkUrl:r,code:o}){return `
|
|
15
15
|
<p>Hi${e?` ${e}`:""},</p>
|
|
16
16
|
<p>Click the link below to sign in as ${t}:</p>
|
|
17
17
|
<p><a href="${r}">${r}</a></p>
|
|
@@ -19,23 +19,23 @@ import {t as t$1}from'./chunk-7MIBHVZS.js';import {a,b as b$1,c,d,s,t,u,v,w,o,p,
|
|
|
19
19
|
<p><strong style="font-size: 24px; letter-spacing: 4px;">${o}</strong></p>
|
|
20
20
|
<p>The link and code can only be used once and will expire in 15 minutes.</p>
|
|
21
21
|
<p>If you did not request this, please ignore this email.</p>
|
|
22
|
-
`}var lt="magicLinkToken",An="/api/_internal/",Dr={httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:An},$r=15,Nr=6,On=5;function
|
|
22
|
+
`}var lt="magicLinkToken",An="/api/_internal/",Dr={httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:An},$r=15,Nr=6,On=5;function Pe(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 mt(){return !!y().magicLink?.enabled}function jr(){return !!y().magicLink?.allowSignup}async function Hr(e$1){return w.findOne({token:e(e$1)})}async function pt(e){return w.findOneAndDelete({_id:e})}async function at(e){try{await w.insertOne(e);}catch(t){console.error("Failed to restore a magic link token after a failed signup:",t);}}var ct={success:true,message:"If this email can be used to sign in, a link has been sent"};async function Br(e$1,{connectionInfo:t}){if(!mt())throw new Error("Magic link authentication is not enabled");let r=L(e$1.email),o=t?.ip;o&&await k({bucket:"magicLink",type:"ip",value:o}),await k({bucket:"magicLink",type:"email",value:r});let i=b().provider;if(!i)throw new Error("Email provider is not configured");let n=b().from;if(!n)throw new Error("Email `from` address is not configured");let s$1=a$2("_system.site.url");if(!s$1)throw new Error("Unable to build magic link: set _system.site.url (MODELENCE_SITE_URL)");if(!y().allowDisposableEmails&&await Re(r))throw new Error("Please use a permanent email address");let a=await s.findOne({"emails.address":r},{collation:{locale:"en",strength:2}});if(a&&(a.status==="disabled"||a.status==="deleted")||!a&&!jr())return ct;let c=randomBytes(32).toString("hex"),l=randomInt(0,10**Nr).toString().padStart(Nr,"0"),d=Date.now(),u=new Date(d),m=new Date(d+a$1.minutes($r));await w.insertOne({email:r,token:e(c),code:e(l),attempts:0,createdAt:u,expiresAt:m});let g=`${s$1}/api/_internal/auth/magic-link?token=${c}`,v=(b()?.magicLink?.template||Ir)({email:r,magicLinkUrl:g,code:l,name:""}),S=B(v);return await i.sendEmail({to:r,from:n,subject:b()?.magicLink?.subject||"Your sign-in link",text:S,html:v}),ct}async function Vr(e){let t=a$2("_system.site.url")||"",r=Ue(t,b().magicLink?.redirectUrl)||"/";try{let o=z.string().parse(e.query.token),i=await Hr(o);if(!i||i.expiresAt<new Date)throw new Error("This sign-in link is invalid or has expired.");return e.res.cookie(lt,o,{...Dr,maxAge:a$1.minutes($r)}),{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 dt={locale:"en",strength:2};async function Gr(e){let{tokenDoc:t,session:r,connectionInfo:o,res:i,clearCookie:n}=e,s$1=t.email,a=y(),c=jr(),l$1=false;try{let d=await pt(t._id);if(!d)throw n(),new Error("Invalid or expired code or magic link");let u;if(c)try{if(!await s.findOne({"emails.address":s$1},{collation:dt})){l$1=!0,await a.onBeforeSignup?.({email:s$1,provider:"magicLink",connectionInfo:o});let D=o?.ip;D&&await k({bucket:"signup",type:"ip",value:D}),u=a.generateHandle?await U(await a.generateHandle({email:s$1}),s$1,{throwOnConflict:!1}):await U(void 0,s$1);}}catch(A){throw await at(d),A}let m;try{m=await Rn(s$1,u,c);}catch(A){throw await at(d),A}let{userDoc:g,isNew:h}=m;if(!g)throw await at(d),n(),c&&!l$1?new Error("User account is not active"):(l$1=!0,new Error("Sign up with magic link is not enabled"));if(l$1=h,g.status==="disabled"||g.status==="deleted")throw n(),new Error("User account is not active");let v=g,S=g.emails?.find(A=>A.address.toLowerCase()===s$1),T=!h&&!S?.verified;return T&&(v=await s.findOneAndUpdate({_id:g._id,"emails.address":s$1},{$set:{"emails.$.verified":!0}},{collation:dt,returnDocument:"after"})??g),await l(r.authToken,v._id),i&&p(i,r.authToken),h?Pe("onAfterSignup",()=>a.onAfterSignup?.({provider:"magicLink",user:v,session:r,connectionInfo:o})):(T&&Pe("onAfterEmailVerification",()=>a.onAfterEmailVerification?.({provider:"magicLink",user:v,session:r,connectionInfo:o})),Pe("onAfterLogin",()=>a.onAfterLogin?.({provider:"magicLink",user:v,session:r,connectionInfo:o}))),n(),{user:G(v),session:{authToken:r.authToken}}}catch(d){if(d instanceof Error){let u=l$1?"onSignupError":"onLoginError",m=l$1?a.onSignupError:a.onLoginError;Pe(u,()=>m?.({provider:"magicLink",error:d,session:r,connectionInfo:o}));}throw d}}async function Rn(e,t,r){let o=r&&t!==void 0,i=()=>s.findOneAndUpsert({emails:{$elemMatch:{address:e}}},{$setOnInsert:{handle:t,status:"active",emails:[{address:e,verified:true}],createdAt:new Date,authMethods:{}}},{upsert:o,collation:dt});try{let{doc:n,isNew:s}=await i();return {userDoc:n,isNew:s}}catch(n){if(!Le(n))throw n;let{doc:s}=await i();return {userDoc:s,isNew:false}}}async function Fr(e,t){let{session:r,connectionInfo:o,res:i,req:n}=t;if(!r)throw new Error("Session is not initialized");if(!mt())throw new Error("Magic link authentication is not enabled");let s=z.string().parse(n?.cookies?.[lt]),a=()=>{i?.clearCookie(lt,Dr);},c=await Hr(s);if(!c)throw a(),new Error("Invalid or expired code or magic link");if(c.expiresAt<new Date)throw await pt(c._id),a(),new Error("Code or magic link has expired");return Gr({tokenDoc:{_id:c._id,email:c.email},session:r,connectionInfo:o,res:i,clearCookie:a})}async function qr(e$1,t){let{session:r,connectionInfo:o,res:i}=t;if(!r)throw new Error("Session is not initialized");if(!mt())throw new Error("Magic link authentication is not enabled");let n=L(e$1.email),s=z.string().parse(e$1.code).replace(/[\s-]/g,""),a=o?.ip;a&&await k({bucket:"oneTimeCode",type:"ip",value:a}),await k({bucket:"oneTimeCode",type:"email",value:n});let c=await w.findOne({email:n,code:e(s),attempts:{$lt:On}});if(!c)throw await w.updateMany({email:n},{$inc:{attempts:1}}),new Error("Invalid or expired code or magic link");if(c.expiresAt<new Date)throw await pt(c._id),new Error("Code or magic link has expired");return Gr({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 Kr(e,{user:t,session:r,connectionInfo:o}){let i$1;try{if(!r)throw new Error("Session is not initialized");if(t)throw new c$1("User is already authenticated","ALREADY_AUTHENTICATED");let n=o?.ip;n&&await k({bucket:"oauthExchange",type:"ip",value:n});let s$1=z.string().min(1).parse(e.code),a=z.string().min(1).optional().parse(e.codeVerifier??void 0),c=await i(s$1,a);if(!c||!ObjectId.isValid(c.userId))throw Jr();i$1=c.provider;let l$1=await s.findOne({_id:new ObjectId(c.userId),status:{$nin:["deleted","disabled"]}});if(!l$1)throw Jr();return await l(r.authToken,l$1._id),y().onAfterLogin?.({provider:i$1,user:l$1,session:r,connectionInfo:o}),y().login?.onSuccess?.(l$1),{user:G(l$1),session:{authToken:r.authToken}}}catch(n){throw n instanceof Error&&i$1&&(y().onLoginError?.({provider:i$1,error:n,session:r,connectionInfo:o}),y().login?.onError?.(n)),n}}function Yr(e){return `${e.bucket}
|
|
23
23
|
${e.type}
|
|
24
|
-
${e.window}`}function xn(){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},{bucket:"updateProfile",type:"user",window:a$1.minutes(15),limit:30},{bucket:"updateProfile",type:"user",window:a$1.days(1),limit:200}]}function _n(e){let t=[],r=["signup","signupAttempt","signin","verification","passwordReset","magicLink","oneTimeCode","oauthExchange","updateProfile"];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 ft(e={}){let t=xn(),r=_n(e),o=new Map;for(let s of r)o.set(Yr(s),s);let i=[],n=new Set;for(let s of t){let a=Yr(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 gt=new a("_system.user",{stores:[s,t,u,v,w],queries:{getOwnProfile:br},mutations:{signupWithPassword:Or,loginWithPassword:wr,logout:yr,resendEmailVerification:Ar,sendResetPasswordToken:Pr,resetPassword:Mr,sendMagicLink:Br,loginWithMagicLink:Fr,loginWithOneTimeCode:qr,loginWithOAuth:Kr,updateProfile:vr,unlinkOAuthProvider:Cr},cronJobs:{updateDisposableEmailList:cr},rateLimits:ft(),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:Sr}},{path:"/api/_internal/auth/reset-password",handlers:{get:Tr}},{path:"/api/_internal/auth/magic-link",handlers:{get:Vr}}]});var Ln={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 Un(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 Pn(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:Un(n,a)});}}return r}function K(){let e=process.env.MODELENCE_PORT||process.env.PORT||3e3;return process.env.MODELENCE_SITE_URL||`http://localhost:${e}`}function
|
|
24
|
+
${e.window}`}function xn(){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},{bucket:"updateProfile",type:"user",window:a$1.minutes(15),limit:30},{bucket:"updateProfile",type:"user",window:a$1.days(1),limit:200}]}function _n(e){let t=[],r=["signup","signupAttempt","signin","verification","passwordReset","magicLink","oneTimeCode","oauthExchange","updateProfile"];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 ft(e={}){let t=xn(),r=_n(e),o=new Map;for(let s of r)o.set(Yr(s),s);let i=[],n=new Set;for(let s of t){let a=Yr(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 gt=new a("_system.user",{stores:[s,t,u,v,w],queries:{getOwnProfile:br},mutations:{signupWithPassword:Or,loginWithPassword:wr,logout:yr,resendEmailVerification:Ar,sendResetPasswordToken:Pr,resetPassword:Mr,sendMagicLink:Br,loginWithMagicLink:Fr,loginWithOneTimeCode:qr,loginWithOAuth:Kr,updateProfile:vr,unlinkOAuthProvider:Cr},cronJobs:{updateDisposableEmailList:cr},rateLimits:ft(),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:Sr}},{path:"/api/_internal/auth/reset-password",handlers:{get:Tr}},{path:"/api/_internal/auth/magic-link",handlers:{get:Vr}}]});var Ln={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 Un(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 Pn(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:Un(n,a)});}}return r}function K(){let e=process.env.MODELENCE_PORT||process.env.PORT||3e3;return process.env.MODELENCE_SITE_URL||`http://localhost:${e}`}function Te(e,t="withoutRemoteServer"){let r=Ln[t],o=Pn(r,e);return t==="withRemoteServer"&&process.env.MODELENCE_RUNTIME==="local"&&!o.some(({key:i})=>i==="_system.site.url")&&o.push({key:"_system.site.url",type:"string",value:K()}),o}var wt;function In(){try{let e=ee.join(Xr.homedir(),".modelence"),t=ee.join(e,"machine-id");try{let o=Ie.readFileSync(t,"utf8").trim();if(o)return o}catch{}let r=randomUUID();return Ie.mkdirSync(e,{recursive:!0}),Ie.writeFileSync(t,r+`
|
|
25
25
|
`),r}catch{return Xr.hostname()}}function Nn(){return wt||(wt=createHash("sha256").update(`${In()}
|
|
26
26
|
${process.cwd()}
|
|
27
|
-
${process.env.MODELENCE_ENVIRONMENT_ID||""}`).digest("hex").slice(0,32)),wt}function
|
|
28
|
-
Re-run with the --takeover flag (e.g. npm run dev -- --takeover) to disconnect it and connect this instance instead.`),process.exit(1);}throw
|
|
29
|
-
[Output truncated - exceeded size limit]`:d;await
|
|
27
|
+
${process.env.MODELENCE_ENVIRONMENT_ID||""}`).digest("hex").slice(0,32)),wt}function ye(){let e=process.env.MODELENCE_RUNTIME;return e==="local"||e==="sandbox"}function Me(){return process.env.MODELENCE_RUNTIME==="local"}function yt(){return ye()?Nn():process.env.MODELENCE_CONTAINER_ID}async function Zr({configSchema:e,cronJobsMetadata:t,stores:r,roles:o}){let i=yt();if(!i)throw new Error("Unable to connect to Modelence Cloud: MODELENCE_CONTAINER_ID is not set");let n=Me()&&process.env.MODELENCE_TAKEOVER==="1";try{let s=(r??[]).map(c=>({name:c.getName(),schema:c.getSerializedSchema(),collections:[c.getName()],version:2,indexes:c.getIndexes(),searchIndexes:c.getSearchIndexes(),indexCreationMode:c.getIndexCreationMode()})),a=await P("/api/connect","POST",{hostname:Xr.hostname(),runtime:process.env.MODELENCE_RUNTIME,containerId:i,...Me()?{localSiteUrl:K()}:{},...n?{force:!0}:{},dataModels:s,configSchema:e,cronJobsMetadata:t,roles:o});if(a.status==="error")throw Object.assign(new Error(`Unable to connect to Modelence Cloud: ${a.error}`),{responseBody:a});return console.log("Successfully connected to Modelence Cloud"),a}catch(s){let a=s;if(Me()&&a?.status===409&&!n){let c=a.responseBody?.error??a.message;console.error(`${c}
|
|
28
|
+
Re-run with the --takeover flag (e.g. npm run dev -- --takeover) to disconnect it and connect this instance instead.`),process.exit(1);}throw ye()&&(a?.status??a?.responseBody)!==void 0&&(console.error(a.message),process.exit(1)),console.error("Unable to connect to Modelence Cloud:",s),s}}async function eo(){return P("/api/configs","GET")}async function to(){return await P("/api/sync","POST",{containerId:yt()})}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 Et=false,$n=a$1.seconds(10);function ro(){setInterval(async()=>{if(!Et){Et=true;try{let e=await to();e?.status==="detached"&&ye()&&(console.error(`Detached from Modelence Cloud: ${e.message??"this environment is now connected from another instance."}`),process.exit(1));}catch(e){console.error("Error syncing status",e);}try{await jn();}catch(e){console.error("Error syncing config",e);}Et=false;}},$n);}function bt(e){c$2(e),c$2(Te(d$2(),"withRemoteServer"));}async function jn(){let{configs:e}=await eo();bt(e);}var Y=new c("_modelenceLocks",{schema:{_id:d.string(),instanceId:d.string(),acquiredAt:d.date(),resource:d.string()},indexes:[{key:{resource:1},unique:true},{key:{resource:1,instanceId:1}},{key:{resource:1,acquiredAt:1}}],indexCreationMode:"blocking"});var X={},oo=a$1.seconds(10),ao=randomBytes(32).toString("base64url"),Vn=a$1.seconds(30),ie=new Map,vt=e=>e instanceof MongoError&&e.code===11e3,no=(e,t)=>typeof e.keyPattern=="object"&&e.keyPattern!==null&&Object.prototype.hasOwnProperty.call(e.keyPattern,t),Gn=async({error:e,resource:t})=>{if(no(e,"resource"))return true;if(no(e,"_id"))return false;let r=await Y.findOne({resource:t});return !!r&&r._id!==t},io=async({resource:e,staleThresholdDate:t,instanceId:r})=>{let o=await Y.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},co=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 Y.deleteOne(o)).deletedCount>0},Fn=e=>{let t=e,r=ie.get(t);r&&(r.stopRequested=true,r.timer&&(clearTimeout(r.timer),r.timer=null),ie.delete(t));},so=({resource:e,lockDuration:t,instanceId:r})=>{let o=Math.floor(t/3),i=e,n=ie.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),ie.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,k$1(`Lost lock while refreshing heartbeat: ${e}`,{source:"lock",resource:e,instanceId:r}));}).finally(()=>{if(s.stopRequested){ie.delete(i);return}a();});},o);};ie.set(i,s),a();};async function Q(e,{lockDuration:t=Vn,successfulLockCacheDuration:r=oo,failedLockCacheDuration:o=oo,heartbeat:i,bypassCache:n,instanceId:s=ao}={}){let a=Date.now();if(!n&&X[e]&&a<X[e].expiresAt)return X[e].value&&i&&so({resource:e,lockDuration:t,instanceId:s}),X[e].value;let c=new Date(a-t);k$1(`Attempting to acquire lock: ${e}`,{source:"lock",resource:e,instanceId:s});try{let l=await qn({resource:e,staleThresholdDate:c,instanceId:s});return X[e]={value:l,expiresAt:a+(l?r:o)},l?(i&&so({resource:e,lockDuration:t,instanceId:s}),k$1(`Lock acquired: ${e}`,{source:"lock",resource:e,instanceId:s})):k$1(`Failed to acquire lock (already held): ${e}`,{source:"lock",resource:e,instanceId:s}),l}catch{return X[e]={value:false,expiresAt:a+o},k$1(`Failed to acquire lock (already held): ${e}`,{source:"lock",resource:e,instanceId:s}),false}}var qn=async({resource:e,staleThresholdDate:t,instanceId:r})=>{try{return await io({resource:e,staleThresholdDate:t,instanceId:r})}catch(o){if(vt(o)&&await Gn({error:o,resource:e})){if(!await co({resource:e,staleThresholdDate:t,instanceId:r}))return false;try{return await io({resource:e,staleThresholdDate:t,instanceId:r})}catch(n){if(vt(n))return false;throw n}}if(vt(o))return false;throw o}};async function Ee(e,{instanceId:t=ao}={}){Fn(e);try{let r=await Y.deleteOne({_id:e,instanceId:t});return r.deletedCount===0?await co({resource:e,instanceId:t}):r.deletedCount>0}catch{return false}finally{delete X[e];}}var Z={},Ct=null,kt=new c("_modelenceCronJobs",{schema:{alias:d.string(),lastStartDate:d.date().optional()},indexes:[{key:{alias:1},unique:true,background:true}]});function uo(e,{description:t="",interval:r,timeout:o=Math.min(Math.max(r,a$1.minutes(1)),a$1.days(1)),handler:i}){if(Z[e])throw new Error(`Duplicate cron job declaration: '${e}' already exists`);if(Ct)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}]`);Z[e]={alias:e,params:{description:t,interval:r,timeout:o},handler:i,state:{isRunning:false}};}async function mo(){if(Ct)throw new Error("Cron jobs already started");let e=Object.keys(Z);if(e.length>0){if(!N()){console.log("MongoDB URI is not configured. Skipping cron jobs.");return}let t={alias:{$in:e}},r=await kt.fetch(t),o=Date.now();r.forEach(i=>{let n=Z[i.alias];n&&(n.state.scheduledRunTs=i.lastStartDate?i.lastStartDate.getTime()+n.params.interval:o);}),Object.values(Z).forEach(i=>{i.state.scheduledRunTs||(i.state.scheduledRunTs=o);}),Ct=setInterval(zn,a$1.seconds(1));}}async function zn(){let e=Date.now();if(await Q("cron",{successfulLockCacheDuration:a$1.seconds(10),failedLockCacheDuration:a$1.seconds(30)}))for(let r of Object.values(Z)){let{alias:o,params:i,state:n}=r;if(n.isRunning){if(n.startTs&&n.startTs+i.timeout<e){let s=new Error(`Cron job '${o}' timed out after ${i.timeout}ms`);o$1(s),n.isRunning=false;}continue}n.scheduledRunTs&&n.scheduledRunTs<=e&&Wn(r);}}async function Wn(e){let{alias:t,params:r,handler:o,state:i}=e;i.isRunning=true,i.startTs=Date.now();let n=n$1("cron",`cron:${t}`);try{await kt.upsertOne({alias:t},{$set:{lastStartDate:new Date(i.startTs)},$setOnInsert:{alias:t}}),await o(),lo(i,r),n.end("success");}catch(s){lo(i,r);let a=s instanceof Error?s:new Error(String(s));o$1(a),n.end("error"),console.error(`Error in cron job '${t}':`,s);}}function lo(e,t){e.scheduledRunTs=e.startTs?e.startTs+t.interval:Date.now(),e.startTs=void 0,e.isRunning=false;}function po(){return Object.values(Z).map(({alias:e,params:t})=>({alias:e,description:t.description,interval:t.interval,timeout:t.timeout}))}var fo=new a("_system.cron",{stores:[kt]});function go(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 St=new a("_system.lock",{stores:[Y]});var be=new c("_modelenceMigrations",{schema:{version:d.number(),status:d.enum(["completed","failed"]),description:d.string().optional(),output:d.string().optional(),appliedAt:d.date()},indexes:[{key:{version:1},unique:true},{key:{version:1,status:1}}]});async function At(e,{lockMode:t="acquire"}={}){if(e.length!==0){if(t==="acquire"&&!await Q("migrations")){l$1("Another instance is running migrations. Skipping migration run.",{source:"migrations"});return}try{let r=e.map(({version:s})=>s),o=await be.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;l$1(`Running migrations (${n.length})...`,{source:"migrations"});for(let{version:s,description:a,handler:c}of n){l$1(`Running migration v${s}: ${a}`,{source:"migrations"});try{let d=(await c()||"").toString().trim(),u=15*1024*1024,m=d.length>u?d.slice(0,u)+`
|
|
29
|
+
[Output truncated - exceeded size limit]`:d;await be.upsertOne({version:s},{$set:{version:s,status:"completed",description:a,output:m,appliedAt:new Date}}),l$1(`Migration v${s} complete`,{source:"migrations"});}catch(l){l instanceof Error&&(await be.upsertOne({version:s},{$set:{version:s,status:"failed",description:a,output:l.message||"",appliedAt:new Date}}),l$1(`Migration v${s} is failed: ${l.message}`,{source:"migrations"}));}}}finally{t==="acquire"&&await Ee("migrations");}}}function ho(e){setTimeout(()=>{At(e).catch(t=>{console.error("Error running migrations:",t);});},0);}var wo=new a("_system.migration",{stores:[be]});var yo=new a("_system.rateLimit",{stores:[we]});async function Jn({filePath:e,contentType:t,visibility:r}){return await P("/api/files/upload","POST",{filePath:e,contentType:t,visibility:r})}async function Kn(e){await P("/api/files/delete","POST",{filePath:e});}async function Yn(e){return await P("/api/files/download","POST",{filePath:e})}async function Xn(e){return await P("/api/files/url","POST",{filePath:e})}var Eo=new a("_system.files",{});function Ot(e){return e.replace(/[<>&\u2028\u2029]/g,t=>`\\u${t.charCodeAt(0).toString(16).padStart(4,"0")}`)}var ve="./.modelence/build/client".replace(/\\/g,"/"),vo="./.modelence/build/ssr".replace(/\\/g,"/"),Co="/index.tsx",oi=/(<div\b[^>]*\bid\s*=\s*["']root["'][^>]*>)\s*<\/div>/i,ni="</head>",Rt=class{constructor(){this.ssrEnabled=false;this.ssrTransportInstalled=false;this.prodEntryLoaded=false;}enableSsr(){this.ssrEnabled=true;}async init({httpServer:t}){if(this.config=await ui(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=ee.resolve(process.cwd(),vo,"index.mjs");if(!Ie.existsSync(r))throw new Error(`Modelence: SSR is enabled (startApp({ ssr: true })) but the SSR bundle is missing at ${r}.
|
|
30
30
|
|
|
31
31
|
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:
|
|
32
32
|
\u2022 remove \`postBuildCommand\` so Modelence builds the SSR bundle, or
|
|
33
|
-
\u2022 remove \`ssr: true\` from startApp() if your custom toolchain handles SSR itself.`)}if(this.ssrEnabled&&!this.ssrTransportInstalled){let{installSsrCallMethodTransport:r}=await import('./transport-
|
|
33
|
+
\u2022 remove \`ssr: true\` from startApp() if your custom toolchain handles SSR itself.`)}if(this.ssrEnabled&&!this.ssrTransportInstalled){let{installSsrCallMethodTransport:r}=await import('./transport-RJFMTIDK.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(ve,t)];return this.config?.publicDir&&r.push(q$1.static(this.config.publicDir,t)),r}async handler(t,r){if(this.ssrEnabled&&ii(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-WY23X5RN.js'),import('./server-J75POKU5.js'),import('./collectCss-4YETFI7P.js')]),c=await s(t,r),l=this.collectCssAssets(a);ci(r,a.buildEarlyHintsLink(l));let{sessionState:d,pipe:u,getQueryState:m}=await n({callContext:c,loadingElement:i.loadingElement,routesElement:i.routesElement,router:i.router,location:t.originalUrl}),{prelude:g,rootOpenTag:h,epilogue:v}=si(o),S=ai(g,a.renderStylesheetLinks(l));r.setHeader("Content-Type","text/html; charset=utf-8"),r.setHeader("Cache-Control","no-store"),r.status(200),r.write(S),r.write(`<script id="__MODELENCE_STATE__" type="application/json">${Ot(d)}</script>`),r.write(h),await u(r),r.write("</div>"),r.write(`<script id="__MODELENCE_QUERY_STATE__" type="application/json">${Ot(m())}</script>`),r.end(v);}collectCssAssets(t){return this.isDev()?this.viteServer?t.collectDevCssAssets(this.viteServer,Co):{hrefs:[],source:"dev"}:(this.prodCssAssetsCache||(this.prodCssAssetsCache=t.loadProdCssAssets(ve)),this.prodCssAssetsCache)}async getTemplate(t){if(this.isDev()){let r=ee.resolve(process.cwd(),"src/client/index.html"),o=Ie.readFileSync(r,"utf-8");return this.viteServer&&(o=await this.viteServer.transformIndexHtml(t,o)),o}if(!this.prodTemplateCache){let r=ee.resolve(process.cwd(),ve,"index.html");this.prodTemplateCache=Ie.readFileSync(r,"utf-8");}return this.prodTemplateCache}async captureSsrSnapshot(){let{_getSsrSnapshot:t}=await import('./renderApp-FRZBJICP.js');if(this.isDev()){if(!this.viteServer)throw new Error("Vite dev server not initialized");return await this.viteServer.ssrLoadModule(Co),t()}return this.prodEntryLoaded||(await import(ee.resolve(process.cwd(),vo,"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:ve});}isDev(){return process.env.NODE_ENV!=="production"}};function ii(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 si(e){let t=e.match(oi);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 ai(e,t){if(!t)return e;let r=e.lastIndexOf(ni);return r===-1?t+e:e.slice(0,r)+t+e.slice(r)}function ci(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 li(){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 di(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 ui(e,t={}){let r=process.cwd(),o=await li(),i=[".eslintrc.js",".eslintrc.json",".eslintrc","eslint.config.js",".eslintrc.yml",".eslintrc.yaml"].find(a=>Ie.existsSync(ee.join(r,a))),n=[ri(),mi()];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:ee.resolve(r,i)}));}let s=defineConfig({plugins:n,build:{outDir:ve,emptyOutDir:true},server:{middlewareMode:true,hmr:e?{server:e}:void 0},appType:t.ssr?"custom":"spa",root:"./src/client",resolve:{alias:{"@":ee.resolve(r,"src").replace(/\\/g,"/")}}});return di(s,o)}function mi(){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 Ne=new Rt;function pi(e){return e?e.match(/^\s*"?([^"<]+?)"?\s*<[^>]+>\s*$/)?.[1]?.trim():void 0}function fi(e){if(e)return Array.isArray(e)?e:[e]}function gi(e){return {to:Array.isArray(e.to)?e.to:[e.to],subject:e.subject,html:e.html,text:e.text,fromName:pi(e.from),replyTo:fi(e.replyTo)}}function hi(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 ko={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",gi(e));}catch(t){throw hi(t)}}};var xt=Object.freeze({});function wi(e){if(typeof e!="string"||e.trim()==="")throw new Error(`Invalid security.allowedOrigins entry: expected a non-empty string, received ${JSON.stringify(e)}.`);let t=e.trim();if(t==="*")throw new Error("Invalid security.allowedOrigins entry '*': wildcards are not supported, since the response echoes one concrete origin to keep credentialed requests working. List each allowed origin explicitly.");let r;try{r=new URL(t);}catch{throw new Error(`Invalid security.allowedOrigins entry ${JSON.stringify(e)}: expected an origin of the form 'scheme://host[:port]' (for example 'http://localhost:8081').`)}if(r.username||r.password)throw new Error(`Invalid security.allowedOrigins entry ${JSON.stringify(e)}: an origin must not carry credentials.`);if(r.search||r.hash)throw new Error(`Invalid security.allowedOrigins entry ${JSON.stringify(e)}: an origin must not carry a query or fragment.`);if(r.origin==="null")throw new Error(`Invalid security.allowedOrigins entry ${JSON.stringify(e)}: expected an origin of the form 'scheme://host[:port]' (for example 'http://localhost:8081'). Scheme ${JSON.stringify(r.protocol.replace(":",""))} does not form a comparable origin.`);if(r.hostname.includes("*"))throw new Error(`Invalid security.allowedOrigins entry ${JSON.stringify(e)}: wildcards are not supported, since the response echoes one concrete origin to keep credentialed requests working. List each allowed origin explicitly.`);if(r.pathname!=="/")throw new Error(`Invalid security.allowedOrigins entry ${JSON.stringify(e)}: an origin must not include a path. Use ${JSON.stringify(r.origin)} instead.`);return r.origin}function yi(e){if(!Array.isArray(e))throw new Error(`Invalid security.allowedOrigins: expected an array of origin strings, received ${JSON.stringify(e)}.`);return e.map(wi)}function So(e){let t=e.allowedOrigins?{...e,allowedOrigins:yi(e.allowedOrigins)}:e;xt=Object.freeze(Object.assign({},xt,t));}function se(){return xt}var _t=Object.freeze({});function Ao(e){_t=Object.freeze(Object.assign({},_t,e));}function De(){return _t}async function Ci({modules:e=[],roles:t={},defaultRoles:r$1={},server:o=Ne,migrations:i=[],email:n={},auth:s={},security:a={},websocket:c={},ssr:l=false}){l&&o===Ne&&Ne.enableSsr(),Oo.config(),Oo.config({path:".modelence.env"});let d=!!process.env.MODELENCE_SERVICE_ENDPOINT;Ti().then(()=>{}).catch(()=>{});for(let te of e)if(te.name.toLowerCase().startsWith("_system."))throw new Error(`Invalid module name: '${te.name}'
|
|
34
34
|
|
|
35
35
|
The '_system.' prefix is reserved for internal use and cannot be used in user-defined modules.
|
|
36
36
|
|
|
37
|
-
Rename your module to something that does not start with '_system.'`);let u=[gt,r,fo,wo,yo,pe,St,Eo],m=[...u,...e];f(),Si(u),ki(e),x$1(t,r$1);let g$1=Li(m);e$1(g$1);let h=Ai(m),v=Oi(m);Ui(m),gt.rateLimits=ft(s.rateLimits);let S=Ri(m);Er(S);let{storesToInit:T,effectiveStores:A}=go(h);if(d){let{configs:te,environmentId:Fo,appAlias:qo,environmentAlias:zo,telemetry:Wo}=await Zr({configSchema:g$1,cronJobsMetadata:po(),stores:A,roles:t});bt(te),g({environmentId:Fo,appAlias:qo,environmentAlias:zo,telemetry:Wo});}else c$2(Pe(g$1));if(d&&!n.provider?et({...n,provider:ko}):et(n),gr(s),So(a),Ao({...c,provider:c.provider||ar}),N()){await ir();let te=[...new Set([...T,...A])];Pi(te),await _i(A,i);}else ho(i);d&&(await i$1(),ro()),mo().catch(console.error),await Ro(o,{combinedModules:m,channels:v});}function ki(e){for(let t of e){for(let[r,o]of Object.entries(t.queries))C(`${t.name}.${r}`,o);for(let[r,o]of Object.entries(t.mutations))D(`${t.name}.${r}`,o);}}function Si(e){for(let t of e){for(let[r,o]of Object.entries(t.queries))E$1(`${t.name}.${r}`,o);for(let[r,o]of Object.entries(t.mutations))F(`${t.name}.${r}`,o);}}function Ai(e){return e.flatMap(t=>t.stores)}function Oi(e){return e.flatMap(t=>t.channels)}function Ri(e){return e.flatMap(t=>t.rateLimits)}function xi(e,t){console.warn(`Failed to create indexes for store '${e}'. Continuing startup.`,t);}var Lt="migrations";async function _i(e,t){if(!await Q(Lt,{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 Ut(a,"full");for(let a of i)await Ut(a,"drop-only");}catch(a){throw await ye(Lt),a}let n=(async()=>{for(let a of i)await Ut(a,"create-only");})(),s=At(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 ye(Lt);});}async function Ut(e,t="full"){let r=e.getName();try{await e.createIndexes(t);}catch(o){xi(r,o);}}function Li(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 Ui(e){for(let t of e)for(let[r,o]of Object.entries(t.cronJobs))uo(`${t.name}.${r}`,o);}function Pi(e){let t=Ae();if(!t)throw new Error("Failed to initialize stores: MongoDB client not initialized");for(let r of e)r.init(t);}async function Ti(){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 Mi(),i=await import('./package-PKGSNHLQ.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:Xr.hostname(),environmentId:r})});}}async function Mi(){try{let e=ee.join(process.cwd(),"package.json"),t=await Ei.readFile(e,"utf-8");return {name:JSON.parse(t).name||"unknown"}}catch{return {name:"unknown"}}}async function xo(e){await u.deleteMany({userId:e}),await v.deleteMany({userId:e});let t=await s.findOne({_id:e}),r=Array.from(new Set((t?.emails??[]).map(o=>o.address?.toLowerCase()).filter(o=>!!o)));r.length>0&&await w.deleteMany({email:{$in:r}});}async function Ni(e){await xo(e),await s.updateOne(e,{$set:{status:"disabled",disabledAt:new Date}});}async function Di(e){await xo(e),await s.updateOne({_id:e},{$set:{handle:`deleted-${e}-${randomUUID()}`,status:"deleted",deletedAt:new Date,authMethods:{},emails:[]}});}var Pt=class{constructor(t,r){this.category=t,this.canAccessChannel=r||null;}broadcast(t,r){let o=Ne().provider;if(!o){m$1("Websockets provider should be added to startApp",{});return}o.broadcast({category:this.category,id:t,data:r});}};function $i(e){if(!b().provider)throw new Error("Email provider is not configured, see https://docs.modelence.com/email for more details.");return b().provider?.sendEmail(e)}var _o=new Set(["javascript:","data:","file:","vbscript:","blob:"]);function Lo(e){try{return new URL(e)}catch{return null}}function De(){let e=String(a$2("_system.user.auth.mobile.redirectUrls")??"").split(/[\n,]/).map(r=>r.trim()).filter(Boolean),t=(y().mobile?.redirectUrls??[]).map(r=>String(r).trim()).filter(Boolean);return [...new Set([...e,...t])]}function Tt(e){if(!e||typeof e!="string")return false;let t=Lo(e);return !t||_o.has(t.protocol.toLowerCase())||Uo(t)?false:De().some(r=>{let o=Lo(r);return !o||_o.has(o.protocol.toLowerCase())||Uo(o)?false:t.protocol.toLowerCase()===o.protocol.toLowerCase()&&t.host.toLowerCase()===o.host.toLowerCase()&&Po(t.pathname)===Po(o.pathname)})}function Uo(e){return e.username!==""||e.password!==""}function Po(e){let t=e.replace(/\/+$/,"");return t===""?"/":t}var ji=["code","error","errorCode","linked"];function $e(e,t){let r=new URL(e);for(let o of ji)r.searchParams.delete(o);for(let[o,i]of Object.entries(t))r.searchParams.set(o,i);return r.toString()}var Hi=["error","errorCode"];function To(e,t,r){let o=new URL(t,e);for(let i of Hi)o.searchParams.delete(i);for(let[i,n]of Object.entries(r))o.searchParams.set(i,n);return o.toString()}function je(e){return e.platform==="mobile"&&e.redirectUri?{platform:"mobile",redirectUri:e.redirectUri,...e.codeChallenge?{codeChallenge:e.codeChallenge}:{}}:{platform:"web"}}function Gi(e){return e.platform==="mobile"&&typeof e.codeChallenge=="string"}function Io(e){return e.platform!=="mobile"}async function Fi(e){return !e||typeof e!="string"?null:g$1(e)}function E(e,t,r,o={platform:"web"},i="oauth_failed"){if(o.platform==="mobile")return e.set("Referrer-Policy","no-referrer"),e.redirect($e(o.redirectUri,{error:r,errorCode:i}));let n=y();if(n.oauthErrorRedirectUrl&&o.platform==="web"){let a=a$2("_system.site.url")||K(),c=null;try{c=To(a,n.oauthErrorRedirectUrl,{error:r,errorCode:i});}catch(l){console.error(`[modelence] Could not build the OAuth error redirect from ${JSON.stringify(n.oauthErrorRedirectUrl)} and site URL ${JSON.stringify(a)}. Falling back to the default error response.`,l);}if(c)return e.set("Referrer-Policy","no-referrer"),e.redirect(c)}let s=e.status(t);if(n.errorComponent)try{let a=n.errorComponent({error:r,statusCode:t});if(a)return s.send(a)}catch(a){console.error("Unhandled error in authConfig.errorComponent:",a);}return s.json({error:r})}async function Mt(e,t,r,o$1={platform:"web"}){if(o$1.platform==="mobile"){if(!Gi(o$1)){E(e,400,"This sign-in could not be completed. Please try signing in again.",o$1,"invalid_state");return}let n=await h(t.toString(),r,o$1.codeChallenge);e.set("Referrer-Policy","no-referrer"),e.redirect($e(o$1.redirectUri,{code:n}));return}let{authToken:i}=await o(t);p(e,i),e.redirect("/");}async function qi(e,t,r,o,i,n){let s$1=y();try{if(r.status==="disabled"||r.status==="deleted"){E(e,400,"User account is not active.",n);return}let a={};r.firstName===void 0&&t.firstName&&(a.firstName=t.firstName),r.lastName===void 0&&t.lastName&&(a.lastName=t.lastName),r.avatarUrl===void 0&&t.avatarUrl&&(a.avatarUrl=t.avatarUrl);let c=r;Object.keys(a).length>0&&(await s.updateOne({_id:r._id},{$set:a}),c={...r,...a}),await Mt(e,r._id,t.providerName,n),Io(n)&&(s$1.onAfterLogin?.({provider:t.providerName,user:c,session:o,connectionInfo:i}),s$1.login?.onSuccess?.(c));}catch(a){throw a instanceof Error&&(s$1.login?.onError?.(a),s$1.onLoginError?.({provider:t.providerName,error:a,session:o,connectionInfo:i})),a}}async function zi(e,t,r,o,i,n){let s$1=y();if((s$1.oauthAccountLinking??"manual")==="auto"&&t.emailVerified){if(r.status==="disabled"||r.status==="deleted"){E(e,400,"User account is not active.",n);return}if(!r.emails?.find(l=>l.address.toLowerCase()===t.email.toLowerCase())?.verified){E(e,400,"User with this email already exists. Please log in instead.",n);return}try{let l={...r.firstName===void 0&&t.firstName&&{firstName:t.firstName},...r.lastName===void 0&&t.lastName&&{lastName:t.lastName},...r.avatarUrl===void 0&&t.avatarUrl&&{avatarUrl:t.avatarUrl}};if(!((await s.updateOne({_id:r._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)){E(e,400,"User with this email already exists. Please log in instead.",n);return}await Mt(e,r._id,t.providerName,n);let m={...r,...l,authMethods:{...r.authMethods,[t.providerName]:{id:t.id}}};Io(n)&&(s$1.onAfterLogin?.({provider:t.providerName,user:m,session:o,connectionInfo:i}),s$1.login?.onSuccess?.(m));return}catch(l){throw l instanceof Error&&(s$1.login?.onError?.(l),s$1.onLoginError?.({provider:t.providerName,error:l,session:o,connectionInfo:i})),l}}E(e,400,"User with this email already exists. Please log in instead.",n);}async function Wi(e,t,r,o,i){let n=y();try{let s$1;if(n.generateHandle){let d=await n.generateHandle({email:t.email,firstName:t.firstName,lastName:t.lastName});s$1=await U(d,t.email,{throwOnConflict:!1});}else s$1=await U(void 0,t.email);let a={handle:s$1,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 s.insertOne(a);await Mt(e,c.insertedId,t.providerName,i);let l=await s.findOne({_id:c.insertedId},{readPreference:"primary"});l&&(n.onAfterSignup?.({provider:t.providerName,user:l,session:r,connectionInfo:o}),n.signup?.onSuccess?.(l));}catch(s){throw s instanceof Error&&(n.onSignupError?.({provider:t.providerName,error:s,session:r,connectionInfo:o}),n.signup?.onError?.(s)),s}}function ce(e){return `${a$2("_system.site.url")}/api/_internal/auth/${e}/callback`}async function He(e,t,r,o={platform:"web"}){let i=await s.findOne({[`authMethods.${r.providerName}.id`]:r.id}),{session:n,connectionInfo:s$1}=await le(e,t);if(i)return qi(t,r,i,n,s$1,o);if(!r.email){E(t,400,`Email address is required for ${r.providerName} authentication.`,o);return}let a;try{a=await s.findOne({"emails.address":r.email,status:{$ne:"deleted"}},{collation:{locale:"en",strength:2}});}catch(c){if(c instanceof Error){let l=y();l.onSignupError?.({provider:r.providerName,error:c,session:n,connectionInfo:s$1}),l.signup?.onError?.(c);}throw c}return a?zi(t,r,a,n,s$1,o):Wi(t,r,n,s$1,o)}function x(e){e.cookie("oauthLinkToken","",{httpOnly:true,maxAge:0,path:"/api/_internal/auth/",sameSite:"lax",secure:process.env.NODE_ENV==="production"});}function ae(e){if(e)try{e();}catch(t){console.error("Error executing OAuth hook:",t);}}function Ji(e){let{state:t,mode:r,linkedUserId:o,platform:i="web",redirectUri:n,codeChallenge:s}=e,a=[t,r,o??""];return (i!=="web"||n)&&(a.push(i),a.push(n?Buffer.from(n,"utf8").toString("base64url"):""),a.push(s??"")),a.join(":")}function No(e){let[t,r,o,i,n,s]=(e||"").split(":"),a=n&&Buffer.from(n,"base64url").toString("utf8")||void 0;return {stateValue:t,mode:r||"login",...o?{linkedUserId:o}:{},platform:i==="mobile"?"mobile":"web",...a?{redirectUri:a}:{},...s?{codeChallenge:s}:{}}}function Be(e,t,r){let o=e.query.state,i=e.cookies[r],n=No(i||""),s=Do(n);return !o||!i||o!==n.stateValue?(E(t,400,"Your sign-in session has expired. Please sign in again.",s??{platform:"web"},"invalid_state"),null):(t.clearCookie(r),n.platform==="mobile"&&!s?(E(t,400,"Invalid OAuth redirect target.",{platform:"web"},"invalid_redirect"),null):{mode:n.mode,...n.linkedUserId?{linkedUserId:n.linkedUserId}:{},platform:n.platform,...n.redirectUri?{redirectUri:n.redirectUri}:{},...n.codeChallenge?{codeChallenge:n.codeChallenge}:{}})}function Do(e){return e.platform!=="mobile"||!e.redirectUri||!Tt(e.redirectUri)?null:{platform:"mobile",redirectUri:e.redirectUri}}function Ve(e,t){return Do(No(e.cookies?.[t]||""))}function Ki(e){if(De().length===0)return "Mobile sign-in is not configured: auth.mobile.redirectUrls is empty. Add your app's deep link (e.g. 'myapp://auth') to enable it.";let r;try{r=new URL(e).protocol.toLowerCase();}catch{return "This redirectUri is not a valid URL. Pass your app's deep link, e.g. 'myapp://auth', and list it in auth.mobile.redirectUrls."}return r==="http:"||r==="https:"||r==="exp:"?"This redirectUri is not in auth.mobile.redirectUrls. Add it verbatim. Note that Linking.createURL returns a different value per build target \u2014 your app's scheme in a native build, an https URL on Expo Web, an exp:// URL in Expo Go \u2014 so each one you test needs its own entry.":"This redirectUri is not in auth.mobile.redirectUrls. Add it verbatim \u2014 entries match on scheme, host and path, so a differing path or port is a different target."}function Yi(e,t,r){if(e.query.platform!=="mobile")return {ok:true,redirectUri:null,codeChallenge:null};let o=typeof e.query.redirectUri=="string"?e.query.redirectUri:"";if(!o)return E(t,400,"A redirectUri is required for mobile authentication.",{platform:"api"}),{ok:false};if(!Tt(o))return console.error(`[modelence] Rejected mobile OAuth redirectUri: ${JSON.stringify(o)}. Allowed: ${JSON.stringify(De())}`),E(t,400,Ki(o),{platform:"api"},"invalid_redirect"),{ok:false};let i=typeof e.query.codeChallenge=="string"?e.query.codeChallenge:"",n=/^[A-Za-z0-9._~-]{16,256}$/.test(i);return r!=="link"&&!n?(E(t,400,"This sign-in request is missing a valid codeChallenge. Update the Modelence client package \u2014 signInWithOAuth generates it automatically.",{platform:"api"}),{ok:false}):{ok:true,redirectUri:o,codeChallenge:n?i:null}}async function Ge(e,t,r){let o=randomBytes(32).toString("hex"),i=e.query.mode==="link"?"link":"login",n=Yi(e,t,i);if(!n.ok)return null;let{redirectUri:s,codeChallenge:a}=n,c=null;if(i==="link"&&e.query.linkNonce&&(c=await Fi(e.query.linkNonce),!c))return E(t,401,"Invalid or expired link nonce for OAuth linking.",s?{platform:"mobile",redirectUri:s}:{platform:"api"},"invalid_link_nonce"),null;let l=Ji({state:o,mode:i,linkedUserId:c,platform:s?"mobile":"web",redirectUri:s,codeChallenge:a});return t.cookie(r,l,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",maxAge:a$1.minutes(10)}),{state:o,mode:i}}async function Fe(e,t,r,o,i={platform:"web"}){let n=y(),{session:s$1,connectionInfo:a}=await le(e,t),c=null;if(o){if(!ObjectId.isValid(o)){x(t),E(t,400,"Invalid OAuth linking state.",i);return}c=new ObjectId(o);}else c=s$1?.userId??null;if(!c){x(t),E(t,401,"You must be signed in to link a provider.",i);return}let l=c;try{let d=`authMethods.${r.providerName}.id`;if((await s.updateOne({_id:l,status:{$nin:["deleted","disabled"]},$or:[{[d]:{$exists:!1}},{[d]:r.id}]},{$set:{[d]:r.id}})).matchedCount===0){let g=await s.findOne({_id:l});if(!g||g.status==="deleted"||g.status==="disabled"){ae(()=>n.onOAuthLinkError?.({provider:r.providerName,error:new Error("User account not found or not active"),session:s$1,connectionInfo:a})),x(t),E(t,400,"User account is not active.",i);return}let h=g?.authMethods?.[r.providerName]?.id;if(h&&h!==r.id){ae(()=>n.onOAuthLinkError?.({provider:r.providerName,error:new Error(`User already has a different ${r.providerName} account linked`),session:s$1,connectionInfo:a})),x(t),E(t,400,`You have already linked a different ${r.providerName} account.`,i);return}ae(()=>n.onOAuthLinkError?.({provider:r.providerName,error:new Error(`Unexpected OAuth linking state for ${r.providerName}`),session:s$1,connectionInfo:a})),x(t),E(t,400,`Unable to link ${r.providerName} account.`,i);return}let m=await s.findOne({_id:l},{readPreference:"primary"});if(m&&ae(()=>n.onAfterOAuthLink?.({provider:r.providerName,user:m,session:s$1,connectionInfo:a})),x(t),i.platform==="mobile"){t.set("Referrer-Policy","no-referrer"),t.redirect($e(i.redirectUri,{linked:r.providerName}));return}t.redirect("/");}catch(d){if(d instanceof MongoServerError&&d.code===11e3){ae(()=>n.onOAuthLinkError?.({provider:r.providerName,error:d,session:s$1,connectionInfo:a})),x(t),E(t,400,`This ${r.providerName} account is already linked to a different user.`,i);return}if(d instanceof Error&&ae(()=>n.onOAuthLinkError?.({provider:r.providerName,error:d,session:s$1,connectionInfo:a})),x(t),!t.headersSent)throw d}}function qe(e){return !e||typeof e!="string"?null:e}async function Qi(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 Zi(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 es(e,t){let r=qe(e.query.code);if(!r){E(t,400,"Missing authorization code",Ve(e,"authStateGoogle")??void 0,"missing_code");return}let o=Be(e,t,"authStateGoogle");if(!o)return;let{mode:i,linkedUserId:n}=o,s=je(o),a=String(a$2("_system.user.auth.google.clientId")),c=String(a$2("_system.user.auth.google.clientSecret")),l=ce("google");try{let d=await Qi(r,a,c,l),u=await Zi(d.access_token),m={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 Fe(e,t,m,n,s):await He(e,t,m,s);}catch(d){console.error("Google OAuth error:",d),i==="link"&&x(t),E(t,500,"Authentication failed",s);}}function ts(){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){E(o,503,"Google authentication is not configured",{platform:"api"});return}i();};return e.get("/api/_internal/auth/google",t,async(r,o)=>{let i=String(a$2("_system.user.auth.google.clientId")),n=ce("google"),s=await Ge(r,o,"authStateGoogle");if(!s)return;let{state:a}=s,c=new URL("https://accounts.google.com/o/oauth2/v2/auth");c.searchParams.append("client_id",i),c.searchParams.append("redirect_uri",n),c.searchParams.append("response_type","code"),c.searchParams.append("scope","profile email"),c.searchParams.append("access_type","online"),c.searchParams.append("state",a),o.redirect(c.toString());}),e.get("/api/_internal/auth/google/callback",t,es),e}var $o=ts;async function os(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 ns(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 is(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 ss(e,t){return e.email?e.email:(await is(t)).find(o=>o.primary&&o.verified)?.email??null}async function as(e,t){let r=qe(e.query.code);if(!r){E(t,400,"Missing authorization code",Ve(e,"authStateGithub")??void 0,"missing_code");return}let o=Be(e,t,"authStateGithub");if(!o)return;let{mode:i,linkedUserId:n}=o,s=je(o),a=String(a$2("_system.user.auth.github.clientId")),c=String(a$2("_system.user.auth.github.clientSecret")),l=ce("github");try{let d=await os(r,a,c,l),u=await ns(d.access_token),m=await ss(u,d.access_token);if(!m){i==="link"&&x(t),E(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 g=u.name?u.name.trim().split(/\s+/):[],h=g[0]||void 0,v=g.length>1?g.slice(1).join(" "):void 0,S={id:String(u.id),email:m,emailVerified:!0,providerName:"github",firstName:h,lastName:v,avatarUrl:u.avatar_url||void 0};i==="link"?await Fe(e,t,S,n,s):await He(e,t,S,s);}catch(d){console.error("GitHub OAuth error:",d),i==="link"&&x(t),E(t,500,"Authentication failed",s);}}function cs(){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){E(o,503,"GitHub authentication is not configured",{platform:"api"});return}i();};return e.get("/api/_internal/auth/github",t,async(r,o)=>{let i=String(a$2("_system.user.auth.github.clientId")),n=ce("github"),s=a$2("_system.user.auth.github.scopes"),a=s?String(s).split(",").map(u=>u.trim()).join(" "):"user:email",c=await Ge(r,o,"authStateGithub");if(!c)return;let{state:l}=c,d=new URL("https://github.com/login/oauth/authorize");d.searchParams.append("client_id",i),d.searchParams.append("redirect_uri",n),d.searchParams.append("scope",a),d.searchParams.append("state",l),o.redirect(d.toString());}),e.get("/api/_internal/auth/github/callback",t,as),e}var jo=cs;function Ho(e,t,r){return async(o,i,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 z$1(s);a={session:l,user:d};}catch{}let c=n$1("route",`route:${e.toLowerCase()}:${t}`,{method:e,path:t,query:j(o.query),body:j(o.body),params:j(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,next:n},a);c.end(),l&&(i.status(l.status||200),l.contentType&&i.setHeader("Content-Type",l.contentType),l.headers&&Object.entries(l.headers).forEach(([d,u])=>{i.setHeader(d,u);}),l.redirect?i.redirect(l.redirect):i.send(l.data));}catch(l){c.end("error"),l instanceof a$4?i.status(l.status).send(l.message):(console.error(`Error in route handler: ${o.path}`),console.error(l),i.status(500).send(String(l)));}}}function us(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 ms(e,t,r){for(let o of t)for(let i of o.routes){let{path:n,handlers:s,body:a}=i,c=us(a);Object.entries(s).forEach(([l,d])=>{e[l](n,r,...c,Ho(l,n,d));});}}var Bo=false;async function Ro(e,{combinedModules:t,channels:r}){let o=q$1(),{trustedProxies:i}=se(),s=Es(process.env.MODELENCE_TRUSTED_PROXIES)??i;o.set("trust proxy",s===void 0?true:s),o.use(ls()),o.use(gs()),o.use(hs());let a=ws();ms(o,t,a),o.use(q$1.json({limit:"16mb"})),o.use(q$1.urlencoded({extended:true,limit:"16mb"})),o.use("/api/_internal/auth",a),o.use($o()),o.use(jo()),o.post("/api/_internal/auth/set-link-cookie",a,async(m,g)=>{let{session:h}=await le(m,g);if(!h?.userId){g.status(401).json({error:"Not authenticated"});return}g.cookie("oauthLinkToken",h.authToken,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:"/api/_internal/auth/",maxAge:10*60*1e3}),g.json({ok:true});}),o.post("/api/_internal/auth/issue-link-nonce",a,async(m,g)=>{let{session:h}=await le(m,g);if(!h?.userId){g.status(401).json({error:"Not authenticated"});return}let v=await f$1(String(h.userId));g.json({nonce:v});}),o.post("/api/_internal/method/:methodName(*)",a,async(m,g)=>{let h=m.params.methodName,v=await le(m,g);try{let S=a$3(await G$1(h,m.body.args,v));g.json({data:S,typeMap:b$3(S)});}catch(S){ps(g,h,S);}});let c=ds.createServer(o),l=Number(process.env.MODELENCE_KEEP_ALIVE_TIMEOUT_MS)||65e3;c.keepAliveTimeout=l,c.headersTimeout=l+5e3,await e.init({httpServer:c}),e.middlewares&&o.use(e.middlewares()),o.all("*",(m,g,h)=>{Promise.resolve(e.handler(m,g)).catch(h);}),Bo||(Bo=true,process.on("unhandledRejection",(m,g)=>{console.error("Unhandled Promise Rejection:"),console.error(m instanceof Error?m.stack:m),console.error("Promise:",g);}),process.on("uncaughtException",m=>{console.error("Uncaught Exception:"),console.error(m.stack),console.trace("Full application stack:");}));let d=Ne()?.provider;d&&d.init({httpServer:c,channels:r});let u=process.env.MODELENCE_PORT||process.env.PORT||3e3;c.listen(u,()=>{l$1("Application started",{source:"app"});let m=a$2("_system.site.url")||K();console.log(`
|
|
37
|
+
Rename your module to something that does not start with '_system.'`);let u=[gt,r,fo,wo,yo,fe,St,Eo],m=[...u,...e];f(),Si(u),ki(e),x$1(t,r$1);let g$1=Li(m);e$1(g$1);let h=Ai(m),v=Oi(m);Ui(m),gt.rateLimits=ft(s.rateLimits);let S=Ri(m);Er(S);let{storesToInit:T,effectiveStores:A}=go(h);if(d){let{configs:te,environmentId:Fo,appAlias:qo,environmentAlias:zo,telemetry:Wo}=await Zr({configSchema:g$1,cronJobsMetadata:po(),stores:A,roles:t});bt(te),g({environmentId:Fo,appAlias:qo,environmentAlias:zo,telemetry:Wo});}else c$2(Te(g$1));if(d&&!n.provider?et({...n,provider:ko}):et(n),gr(s),So(a),Ao({...c,provider:c.provider||ar}),N()){await ir();let te=[...new Set([...T,...A])];Pi(te),await _i(A,i);}else ho(i);d&&(await i$1(),ro()),mo().catch(console.error),await Ro(o,{combinedModules:m,channels:v});}function ki(e){for(let t of e){for(let[r,o]of Object.entries(t.queries))C(`${t.name}.${r}`,o);for(let[r,o]of Object.entries(t.mutations))D(`${t.name}.${r}`,o);}}function Si(e){for(let t of e){for(let[r,o]of Object.entries(t.queries))E$1(`${t.name}.${r}`,o);for(let[r,o]of Object.entries(t.mutations))F(`${t.name}.${r}`,o);}}function Ai(e){return e.flatMap(t=>t.stores)}function Oi(e){return e.flatMap(t=>t.channels)}function Ri(e){return e.flatMap(t=>t.rateLimits)}function xi(e,t){console.warn(`Failed to create indexes for store '${e}'. Continuing startup.`,t);}var Lt="migrations";async function _i(e,t){if(!await Q(Lt,{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 Ut(a,"full");for(let a of i)await Ut(a,"drop-only");}catch(a){throw await Ee(Lt),a}let n=(async()=>{for(let a of i)await Ut(a,"create-only");})(),s=At(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 Ee(Lt);});}async function Ut(e,t="full"){let r=e.getName();try{await e.createIndexes(t);}catch(o){xi(r,o);}}function Li(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 Ui(e){for(let t of e)for(let[r,o]of Object.entries(t.cronJobs))uo(`${t.name}.${r}`,o);}function Pi(e){let t=Oe();if(!t)throw new Error("Failed to initialize stores: MongoDB client not initialized");for(let r of e)r.init(t);}async function Ti(){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 Mi(),i=await import('./package-GGPYIET6.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:Xr.hostname(),environmentId:r})});}}async function Mi(){try{let e=ee.join(process.cwd(),"package.json"),t=await Ei.readFile(e,"utf-8");return {name:JSON.parse(t).name||"unknown"}}catch{return {name:"unknown"}}}async function xo(e){await u.deleteMany({userId:e}),await v.deleteMany({userId:e});let t=await s.findOne({_id:e}),r=Array.from(new Set((t?.emails??[]).map(o=>o.address?.toLowerCase()).filter(o=>!!o)));r.length>0&&await w.deleteMany({email:{$in:r}});}async function Ni(e){await xo(e),await s.updateOne(e,{$set:{status:"disabled",disabledAt:new Date}});}async function Di(e){await xo(e),await s.updateOne({_id:e},{$set:{handle:`deleted-${e}-${randomUUID()}`,status:"deleted",deletedAt:new Date,authMethods:{},emails:[]}});}var Pt=class{constructor(t,r){this.category=t,this.canAccessChannel=r||null;}broadcast(t,r){let o=De().provider;if(!o){m$1("Websockets provider should be added to startApp",{});return}o.broadcast({category:this.category,id:t,data:r});}};function $i(e){if(!b().provider)throw new Error("Email provider is not configured, see https://docs.modelence.com/email for more details.");return b().provider?.sendEmail(e)}var _o=new Set(["javascript:","data:","file:","vbscript:","blob:"]);function Lo(e){try{return new URL(e)}catch{return null}}function $e(){let e=String(a$2("_system.user.auth.mobile.redirectUrls")??"").split(/[\n,]/).map(r=>r.trim()).filter(Boolean),t=(y().mobile?.redirectUrls??[]).map(r=>String(r).trim()).filter(Boolean);return [...new Set([...e,...t])]}function Tt(e){if(!e||typeof e!="string")return false;let t=Lo(e);return !t||_o.has(t.protocol.toLowerCase())||Uo(t)?false:$e().some(r=>{let o=Lo(r);return !o||_o.has(o.protocol.toLowerCase())||Uo(o)?false:t.protocol.toLowerCase()===o.protocol.toLowerCase()&&t.host.toLowerCase()===o.host.toLowerCase()&&Po(t.pathname)===Po(o.pathname)})}function Uo(e){return e.username!==""||e.password!==""}function Po(e){let t=e.replace(/\/+$/,"");return t===""?"/":t}var ji=["code","error","errorCode","linked"];function je(e,t){let r=new URL(e);for(let o of ji)r.searchParams.delete(o);for(let[o,i]of Object.entries(t))r.searchParams.set(o,i);return r.toString()}var Hi=["error","errorCode"];function To(e,t,r){let o=new URL(t,e);for(let i of Hi)o.searchParams.delete(i);for(let[i,n]of Object.entries(r))o.searchParams.set(i,n);return o.toString()}function He(e){return e.platform==="mobile"&&e.redirectUri?{platform:"mobile",redirectUri:e.redirectUri,...e.codeChallenge?{codeChallenge:e.codeChallenge}:{}}:{platform:"web"}}function Gi(e){return e.platform==="mobile"&&typeof e.codeChallenge=="string"}function Io(e){return e.platform!=="mobile"}async function Fi(e){return !e||typeof e!="string"?null:g$1(e)}function E(e,t,r,o={platform:"web"},i="oauth_failed"){if(o.platform==="mobile")return e.set("Referrer-Policy","no-referrer"),e.redirect(je(o.redirectUri,{error:r,errorCode:i}));let n=y();if(n.oauthErrorRedirectUrl&&o.platform==="web"){let a=a$2("_system.site.url")||K(),c=null;try{c=To(a,n.oauthErrorRedirectUrl,{error:r,errorCode:i});}catch(l){console.error(`[modelence] Could not build the OAuth error redirect from ${JSON.stringify(n.oauthErrorRedirectUrl)} and site URL ${JSON.stringify(a)}. Falling back to the default error response.`,l);}if(c)return e.set("Referrer-Policy","no-referrer"),e.redirect(c)}let s=e.status(t);if(n.errorComponent)try{let a=n.errorComponent({error:r,statusCode:t});if(a)return s.send(a)}catch(a){console.error("Unhandled error in authConfig.errorComponent:",a);}return s.json({error:r})}async function Mt(e,t,r,o$1={platform:"web"}){if(o$1.platform==="mobile"){if(!Gi(o$1)){E(e,400,"This sign-in could not be completed. Please try signing in again.",o$1,"invalid_state");return}let n=await h(t.toString(),r,o$1.codeChallenge);e.set("Referrer-Policy","no-referrer"),e.redirect(je(o$1.redirectUri,{code:n}));return}let{authToken:i}=await o(t);p(e,i),e.redirect("/");}async function qi(e,t,r,o,i,n){let s$1=y();try{if(r.status==="disabled"||r.status==="deleted"){E(e,400,"User account is not active.",n);return}let a={};r.firstName===void 0&&t.firstName&&(a.firstName=t.firstName),r.lastName===void 0&&t.lastName&&(a.lastName=t.lastName),r.avatarUrl===void 0&&t.avatarUrl&&(a.avatarUrl=t.avatarUrl);let c=r;Object.keys(a).length>0&&(await s.updateOne({_id:r._id},{$set:a}),c={...r,...a}),await Mt(e,r._id,t.providerName,n),Io(n)&&(s$1.onAfterLogin?.({provider:t.providerName,user:c,session:o,connectionInfo:i}),s$1.login?.onSuccess?.(c));}catch(a){throw a instanceof Error&&(s$1.login?.onError?.(a),s$1.onLoginError?.({provider:t.providerName,error:a,session:o,connectionInfo:i})),a}}async function zi(e,t,r,o,i,n){let s$1=y();if((s$1.oauthAccountLinking??"manual")==="auto"&&t.emailVerified){if(r.status==="disabled"||r.status==="deleted"){E(e,400,"User account is not active.",n);return}if(!r.emails?.find(l=>l.address.toLowerCase()===t.email.toLowerCase())?.verified){E(e,400,"User with this email already exists. Please log in instead.",n);return}try{let l={...r.firstName===void 0&&t.firstName&&{firstName:t.firstName},...r.lastName===void 0&&t.lastName&&{lastName:t.lastName},...r.avatarUrl===void 0&&t.avatarUrl&&{avatarUrl:t.avatarUrl}};if(!((await s.updateOne({_id:r._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)){E(e,400,"User with this email already exists. Please log in instead.",n);return}await Mt(e,r._id,t.providerName,n);let m={...r,...l,authMethods:{...r.authMethods,[t.providerName]:{id:t.id}}};Io(n)&&(s$1.onAfterLogin?.({provider:t.providerName,user:m,session:o,connectionInfo:i}),s$1.login?.onSuccess?.(m));return}catch(l){throw l instanceof Error&&(s$1.login?.onError?.(l),s$1.onLoginError?.({provider:t.providerName,error:l,session:o,connectionInfo:i})),l}}E(e,400,"User with this email already exists. Please log in instead.",n);}async function Wi(e,t,r,o,i){let n=y();try{let s$1;if(n.generateHandle){let d=await n.generateHandle({email:t.email,firstName:t.firstName,lastName:t.lastName});s$1=await U(d,t.email,{throwOnConflict:!1});}else s$1=await U(void 0,t.email);let a={handle:s$1,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 s.insertOne(a);await Mt(e,c.insertedId,t.providerName,i);let l=await s.findOne({_id:c.insertedId},{readPreference:"primary"});l&&(n.onAfterSignup?.({provider:t.providerName,user:l,session:r,connectionInfo:o}),n.signup?.onSuccess?.(l));}catch(s){throw s instanceof Error&&(n.onSignupError?.({provider:t.providerName,error:s,session:r,connectionInfo:o}),n.signup?.onError?.(s)),s}}function ce(e){return `${a$2("_system.site.url")}/api/_internal/auth/${e}/callback`}async function Be(e,t,r,o={platform:"web"}){let i=await s.findOne({[`authMethods.${r.providerName}.id`]:r.id}),{session:n,connectionInfo:s$1}=await le(e,t);if(i)return qi(t,r,i,n,s$1,o);if(!r.email){E(t,400,`Email address is required for ${r.providerName} authentication.`,o);return}let a;try{a=await s.findOne({"emails.address":r.email,status:{$ne:"deleted"}},{collation:{locale:"en",strength:2}});}catch(c){if(c instanceof Error){let l=y();l.onSignupError?.({provider:r.providerName,error:c,session:n,connectionInfo:s$1}),l.signup?.onError?.(c);}throw c}return a?zi(t,r,a,n,s$1,o):Wi(t,r,n,s$1,o)}function x(e){e.cookie("oauthLinkToken","",{httpOnly:true,maxAge:0,path:"/api/_internal/auth/",sameSite:"lax",secure:process.env.NODE_ENV==="production"});}function ae(e){if(e)try{e();}catch(t){console.error("Error executing OAuth hook:",t);}}function Ji(e){let{state:t,mode:r,linkedUserId:o,platform:i="web",redirectUri:n,codeChallenge:s}=e,a=[t,r,o??""];return (i!=="web"||n)&&(a.push(i),a.push(n?Buffer.from(n,"utf8").toString("base64url"):""),a.push(s??"")),a.join(":")}function No(e){let[t,r,o,i,n,s]=(e||"").split(":"),a=n&&Buffer.from(n,"base64url").toString("utf8")||void 0;return {stateValue:t,mode:r||"login",...o?{linkedUserId:o}:{},platform:i==="mobile"?"mobile":"web",...a?{redirectUri:a}:{},...s?{codeChallenge:s}:{}}}function Ve(e,t,r){let o=e.query.state,i=e.cookies[r],n=No(i||""),s=Do(n);return !o||!i||o!==n.stateValue?(E(t,400,"Your sign-in session has expired. Please sign in again.",s??{platform:"web"},"invalid_state"),null):(t.clearCookie(r),n.platform==="mobile"&&!s?(E(t,400,"Invalid OAuth redirect target.",{platform:"web"},"invalid_redirect"),null):{mode:n.mode,...n.linkedUserId?{linkedUserId:n.linkedUserId}:{},platform:n.platform,...n.redirectUri?{redirectUri:n.redirectUri}:{},...n.codeChallenge?{codeChallenge:n.codeChallenge}:{}})}function Do(e){return e.platform!=="mobile"||!e.redirectUri||!Tt(e.redirectUri)?null:{platform:"mobile",redirectUri:e.redirectUri}}function Ge(e,t){return Do(No(e.cookies?.[t]||""))}function Ki(e){if($e().length===0)return "Mobile sign-in is not configured: auth.mobile.redirectUrls is empty. Add your app's deep link (e.g. 'myapp://auth') to enable it.";let r;try{r=new URL(e).protocol.toLowerCase();}catch{return "This redirectUri is not a valid URL. Pass your app's deep link, e.g. 'myapp://auth', and list it in auth.mobile.redirectUrls."}return r==="http:"||r==="https:"||r==="exp:"?"This redirectUri is not in auth.mobile.redirectUrls. Add it verbatim. Note that Linking.createURL returns a different value per build target \u2014 your app's scheme in a native build, an https URL on Expo Web, an exp:// URL in Expo Go \u2014 so each one you test needs its own entry.":"This redirectUri is not in auth.mobile.redirectUrls. Add it verbatim \u2014 entries match on scheme, host and path, so a differing path or port is a different target."}function Yi(e,t,r){if(e.query.platform!=="mobile")return {ok:true,redirectUri:null,codeChallenge:null};let o=typeof e.query.redirectUri=="string"?e.query.redirectUri:"";if(!o)return E(t,400,"A redirectUri is required for mobile authentication.",{platform:"api"}),{ok:false};if(!Tt(o))return console.error(`[modelence] Rejected mobile OAuth redirectUri: ${JSON.stringify(o)}. Allowed: ${JSON.stringify($e())}`),E(t,400,Ki(o),{platform:"api"},"invalid_redirect"),{ok:false};let i=typeof e.query.codeChallenge=="string"?e.query.codeChallenge:"",n=/^[A-Za-z0-9._~-]{16,256}$/.test(i);return r!=="link"&&!n?(E(t,400,"This sign-in request is missing a valid codeChallenge. Update the Modelence client package \u2014 signInWithOAuth generates it automatically.",{platform:"api"}),{ok:false}):{ok:true,redirectUri:o,codeChallenge:n?i:null}}async function Fe(e,t,r){let o=randomBytes(32).toString("hex"),i=e.query.mode==="link"?"link":"login",n=Yi(e,t,i);if(!n.ok)return null;let{redirectUri:s,codeChallenge:a}=n,c=null;if(i==="link"&&e.query.linkNonce&&(c=await Fi(e.query.linkNonce),!c))return E(t,401,"Invalid or expired link nonce for OAuth linking.",s?{platform:"mobile",redirectUri:s}:{platform:"api"},"invalid_link_nonce"),null;let l=Ji({state:o,mode:i,linkedUserId:c,platform:s?"mobile":"web",redirectUri:s,codeChallenge:a});return t.cookie(r,l,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",maxAge:a$1.minutes(10)}),{state:o,mode:i}}async function qe(e,t,r,o,i={platform:"web"}){let n=y(),{session:s$1,connectionInfo:a}=await le(e,t),c=null;if(o){if(!ObjectId.isValid(o)){x(t),E(t,400,"Invalid OAuth linking state.",i);return}c=new ObjectId(o);}else c=s$1?.userId??null;if(!c){x(t),E(t,401,"You must be signed in to link a provider.",i);return}let l=c;try{let d=`authMethods.${r.providerName}.id`;if((await s.updateOne({_id:l,status:{$nin:["deleted","disabled"]},$or:[{[d]:{$exists:!1}},{[d]:r.id}]},{$set:{[d]:r.id}})).matchedCount===0){let g=await s.findOne({_id:l});if(!g||g.status==="deleted"||g.status==="disabled"){ae(()=>n.onOAuthLinkError?.({provider:r.providerName,error:new Error("User account not found or not active"),session:s$1,connectionInfo:a})),x(t),E(t,400,"User account is not active.",i);return}let h=g?.authMethods?.[r.providerName]?.id;if(h&&h!==r.id){ae(()=>n.onOAuthLinkError?.({provider:r.providerName,error:new Error(`User already has a different ${r.providerName} account linked`),session:s$1,connectionInfo:a})),x(t),E(t,400,`You have already linked a different ${r.providerName} account.`,i);return}ae(()=>n.onOAuthLinkError?.({provider:r.providerName,error:new Error(`Unexpected OAuth linking state for ${r.providerName}`),session:s$1,connectionInfo:a})),x(t),E(t,400,`Unable to link ${r.providerName} account.`,i);return}let m=await s.findOne({_id:l},{readPreference:"primary"});if(m&&ae(()=>n.onAfterOAuthLink?.({provider:r.providerName,user:m,session:s$1,connectionInfo:a})),x(t),i.platform==="mobile"){t.set("Referrer-Policy","no-referrer"),t.redirect(je(i.redirectUri,{linked:r.providerName}));return}t.redirect("/");}catch(d){if(d instanceof MongoServerError&&d.code===11e3){ae(()=>n.onOAuthLinkError?.({provider:r.providerName,error:d,session:s$1,connectionInfo:a})),x(t),E(t,400,`This ${r.providerName} account is already linked to a different user.`,i);return}if(d instanceof Error&&ae(()=>n.onOAuthLinkError?.({provider:r.providerName,error:d,session:s$1,connectionInfo:a})),x(t),!t.headersSent)throw d}}function ze(e){return !e||typeof e!="string"?null:e}async function Qi(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 Zi(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 es(e,t){let r=ze(e.query.code);if(!r){E(t,400,"Missing authorization code",Ge(e,"authStateGoogle")??void 0,"missing_code");return}let o=Ve(e,t,"authStateGoogle");if(!o)return;let{mode:i,linkedUserId:n}=o,s=He(o),a=String(a$2("_system.user.auth.google.clientId")),c=String(a$2("_system.user.auth.google.clientSecret")),l=ce("google");try{let d=await Qi(r,a,c,l),u=await Zi(d.access_token),m={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 qe(e,t,m,n,s):await Be(e,t,m,s);}catch(d){console.error("Google OAuth error:",d),i==="link"&&x(t),E(t,500,"Authentication failed",s);}}function ts(){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){E(o,503,"Google authentication is not configured",{platform:"api"});return}i();};return e.get("/api/_internal/auth/google",t,async(r,o)=>{let i=String(a$2("_system.user.auth.google.clientId")),n=ce("google"),s=await Fe(r,o,"authStateGoogle");if(!s)return;let{state:a}=s,c=new URL("https://accounts.google.com/o/oauth2/v2/auth");c.searchParams.append("client_id",i),c.searchParams.append("redirect_uri",n),c.searchParams.append("response_type","code"),c.searchParams.append("scope","profile email"),c.searchParams.append("access_type","online"),c.searchParams.append("state",a),o.redirect(c.toString());}),e.get("/api/_internal/auth/google/callback",t,es),e}var $o=ts;async function os(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 ns(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 is(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 ss(e,t){return e.email?e.email:(await is(t)).find(o=>o.primary&&o.verified)?.email??null}async function as(e,t){let r=ze(e.query.code);if(!r){E(t,400,"Missing authorization code",Ge(e,"authStateGithub")??void 0,"missing_code");return}let o=Ve(e,t,"authStateGithub");if(!o)return;let{mode:i,linkedUserId:n}=o,s=He(o),a=String(a$2("_system.user.auth.github.clientId")),c=String(a$2("_system.user.auth.github.clientSecret")),l=ce("github");try{let d=await os(r,a,c,l),u=await ns(d.access_token),m=await ss(u,d.access_token);if(!m){i==="link"&&x(t),E(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 g=u.name?u.name.trim().split(/\s+/):[],h=g[0]||void 0,v=g.length>1?g.slice(1).join(" "):void 0,S={id:String(u.id),email:m,emailVerified:!0,providerName:"github",firstName:h,lastName:v,avatarUrl:u.avatar_url||void 0};i==="link"?await qe(e,t,S,n,s):await Be(e,t,S,s);}catch(d){console.error("GitHub OAuth error:",d),i==="link"&&x(t),E(t,500,"Authentication failed",s);}}function cs(){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){E(o,503,"GitHub authentication is not configured",{platform:"api"});return}i();};return e.get("/api/_internal/auth/github",t,async(r,o)=>{let i=String(a$2("_system.user.auth.github.clientId")),n=ce("github"),s=a$2("_system.user.auth.github.scopes"),a=s?String(s).split(",").map(u=>u.trim()).join(" "):"user:email",c=await Fe(r,o,"authStateGithub");if(!c)return;let{state:l}=c,d=new URL("https://github.com/login/oauth/authorize");d.searchParams.append("client_id",i),d.searchParams.append("redirect_uri",n),d.searchParams.append("scope",a),d.searchParams.append("state",l),o.redirect(d.toString());}),e.get("/api/_internal/auth/github/callback",t,as),e}var jo=cs;function Ho(e,t,r){return async(o,i,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 z$1(s);a={session:l,user:d};}catch{}let c=n$1("route",`route:${e.toLowerCase()}:${t}`,{method:e,path:t,query:j(o.query),body:j(o.body),params:j(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,next:n},a);c.end(),l&&(i.status(l.status||200),l.contentType&&i.setHeader("Content-Type",l.contentType),l.headers&&Object.entries(l.headers).forEach(([d,u])=>{i.setHeader(d,u);}),l.redirect?i.redirect(l.redirect):i.send(l.data));}catch(l){o$1(l instanceof Error?l:new Error(String(l))),c.end("error"),l instanceof a$4?i.status(l.status).send(l.message):(console.error(`Error in route handler: ${o.path}`),console.error(l),i.status(500).send(String(l)));}}}function us(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 ms(e,t,r){for(let o of t)for(let i of o.routes){let{path:n,handlers:s,body:a}=i,c=us(a);Object.entries(s).forEach(([l,d])=>{e[l](n,r,...c,Ho(l,n,d));});}}var Bo=false;async function Ro(e,{combinedModules:t,channels:r}){let o=q$1(),{trustedProxies:i}=se(),s=Es(process.env.MODELENCE_TRUSTED_PROXIES)??i;o.set("trust proxy",s===void 0?true:s),o.use(ls()),o.use(gs()),o.use(hs());let a=ws();ms(o,t,a),o.use(q$1.json({limit:"16mb"})),o.use(q$1.urlencoded({extended:true,limit:"16mb"})),o.use("/api/_internal/auth",a),o.use($o()),o.use(jo()),o.post("/api/_internal/auth/set-link-cookie",a,async(m,g)=>{let{session:h}=await le(m,g);if(!h?.userId){g.status(401).json({error:"Not authenticated"});return}g.cookie("oauthLinkToken",h.authToken,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:"/api/_internal/auth/",maxAge:10*60*1e3}),g.json({ok:true});}),o.post("/api/_internal/auth/issue-link-nonce",a,async(m,g)=>{let{session:h}=await le(m,g);if(!h?.userId){g.status(401).json({error:"Not authenticated"});return}let v=await f$1(String(h.userId));g.json({nonce:v});}),o.post("/api/_internal/method/:methodName(*)",a,async(m,g)=>{let h=m.params.methodName,v=await le(m,g);try{let S=a$3(await G$1(h,m.body.args,v));g.json({data:S,typeMap:b$3(S)});}catch(S){ps(g,h,S);}});let c=ds.createServer(o),l=Number(process.env.MODELENCE_KEEP_ALIVE_TIMEOUT_MS)||65e3;c.keepAliveTimeout=l,c.headersTimeout=l+5e3,await e.init({httpServer:c}),e.middlewares&&o.use(e.middlewares()),o.all("*",(m,g,h)=>{Promise.resolve(e.handler(m,g)).catch(h);}),Bo||(Bo=true,process.on("unhandledRejection",(m,g)=>{console.error("Unhandled Promise Rejection:"),console.error(m instanceof Error?m.stack:m),console.error("Promise:",g);}),process.on("uncaughtException",m=>{console.error("Uncaught Exception:"),console.error(m.stack),console.trace("Full application stack:");}));let d=De()?.provider;d&&d.init({httpServer:c,channels:r});let u=process.env.MODELENCE_PORT||process.env.PORT||3e3;c.listen(u,()=>{l$1("Application started",{source:"app"});let m=a$2("_system.site.url")||K();console.log(`
|
|
38
38
|
Application started on ${m}
|
|
39
39
|
`),b$1()&&console.log("This project is not connected to a backend yet, so the app serves setup instructions instead of its UI.\nTo connect it to Modelence Cloud, run `npx modelence@latest setup` and restart the dev server.\n");});}async function le(e,t=null){let r=(e.path??e.url??"").split("?")[0],o=r.startsWith("/api/_internal/auth/")&&r.endsWith("/callback"),i=e.body??{},n=F$1.string().nullish().transform(l=>l??null).parse(e.cookies.authToken||(o?e.cookies.oauthLinkToken:null)||i.authToken),s=F$1.object({screenWidth:F$1.number(),screenHeight:F$1.number(),windowWidth:F$1.number(),windowHeight:F$1.number(),pixelRatio:F$1.number(),orientation:F$1.string().nullable()}).nullish().parse(i.clientInfo)??{screenWidth:0,screenHeight:0,windowWidth:0,windowHeight:0,pixelRatio:1,orientation:null},a={ip:vs(e),userAgent:e.get("user-agent"),acceptLanguage:e.get("accept-language"),referrer:e.get("referrer"),baseUrl:ys(e)};if(!!N()){let{session:l,user:d,roles:u}=await z$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:y$1(),req:e,res:t}}function ps(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=fs(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 fs(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 gs(){let{frameAncestors:e}=se(),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 Go(e,t,r){t.vary("Origin");let o=e.headers.origin;if(!(typeof o=="string"&&r.has(o)))return false;t.setHeader("Access-Control-Allow-Origin",o),t.setHeader("Access-Control-Allow-Credentials","true");let n=e.headers["access-control-request-headers"];return t.setHeader("Access-Control-Allow-Headers",typeof n=="string"?n:"Content-Type"),t.setHeader("Access-Control-Allow-Methods","GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS"),t.setHeader("Access-Control-Expose-Headers","X-Modelence-Error-Code"),true}function hs(){let{allowedOrigins:e}=se(),t=new Set(e??[]);return (r,o,i)=>{let n=r.method==="OPTIONS"&&typeof r.headers["access-control-request-method"]=="string";if(t.size===0||!n){i();return}let s=Go(r,o,t);o.vary("Access-Control-Request-Headers"),s&&o.setHeader("Access-Control-Max-Age","600"),o.sendStatus(s?204:403);}}function ws(){let{allowedOrigins:e}=se(),t=new Set(e??[]);return (r,o,i)=>{t.size>0&&Go(r,o,t),i();}}function ys(e){let t=e.headers["x-forwarded-host"],r=(Array.isArray(t)?t[0]:t?.split(",")[0])?.trim()||e.get("host");return `${e.protocol}://${r}`}function Es(e){let t=e?.split(",").map(r=>r.trim()).filter(r=>r.length>0);return t?.length?t:void 0}function bs(e){let t=e.socket?.remoteAddress;if(!t)return false;let r=e.app?.get?.("trust proxy fn");return typeof r!="function"?e.app?.get?.("trust proxy")!==false:!!r(t,0)}function vs(e){let{clientIpHeader:t}=se();if(t&&bs(e)){let o=e.headers[t.toLowerCase()],i=(Array.isArray(o)?o[0]:o)?.trim();if(i)return Vo(i)}let r=e.ip||e.socket?.remoteAddress;if(r)return Vo(r)}function Vo(e){return e.startsWith("::ffff:")?e.substring(7):e}
|
|
40
|
-
export{k as a,Jn as b,Kn as c,Yn as d,Xn as e,Ro as f,le as g,Ci as h,Ni as i,Di as j,Pt as k,$i as l};//# sourceMappingURL=chunk-
|
|
41
|
-
//# sourceMappingURL=chunk-
|
|
40
|
+
export{k as a,Jn as b,Kn as c,Yn as d,Xn as e,Ro as f,le as g,Ci as h,Ni as i,Di as j,Pt as k,$i as l};//# sourceMappingURL=chunk-IKIOVFVD.js.map
|
|
41
|
+
//# sourceMappingURL=chunk-IKIOVFVD.js.map
|