modelence 0.18.0-dev.5 → 0.18.0-dev.rn.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/modelence.js +2 -2
- package/dist/bin/modelence.js.map +1 -1
- package/dist/chunk-M2IGSDQG.js +3 -0
- package/dist/chunk-M2IGSDQG.js.map +1 -0
- package/dist/client.d.ts +47 -67
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/dist/{index-pPrHYnzB.d.ts → index-CLpVWWuj.d.ts} +1 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{package-U4D5AOYA.js → package-5JKWTBGJ.js} +2 -2
- package/dist/{package-U4D5AOYA.js.map → package-5JKWTBGJ.js.map} +1 -1
- package/dist/server.d.ts +5 -5
- package/dist/server.js +20 -1
- package/dist/server.js.map +1 -1
- package/dist/{types-BmVlYelB.d.ts → types-CzGfkwti.d.ts} +6 -14
- package/dist/{types-V74rNt-g.d.ts → types-JMIT4IDG.d.ts} +23 -2
- package/dist/types.d.ts +3 -3
- package/package.json +1 -3
- package/dist/chunk-3XTC4WGD.js +0 -19
- package/dist/chunk-3XTC4WGD.js.map +0 -1
- package/dist/chunk-DRDY7GOT.js +0 -2
- package/dist/chunk-DRDY7GOT.js.map +0 -1
- package/dist/chunk-FL573BOT.js +0 -2
- package/dist/chunk-FL573BOT.js.map +0 -1
- package/dist/chunk-GZI4X3CV.js +0 -3
- package/dist/chunk-GZI4X3CV.js.map +0 -1
- package/dist/chunk-R6OOTUGO.js +0 -2
- package/dist/chunk-R6OOTUGO.js.map +0 -1
- package/dist/chunk-SABBG2XG.js +0 -2
- package/dist/chunk-SABBG2XG.js.map +0 -1
- package/dist/chunk-TQI5WDPR.js +0 -2
- package/dist/chunk-TQI5WDPR.js.map +0 -1
- package/dist/chunk-X22U5KA3.js +0 -3
- package/dist/chunk-X22U5KA3.js.map +0 -1
- package/dist/collectCss-4V7I3QV3.js +0 -2
- package/dist/collectCss-4V7I3QV3.js.map +0 -1
- package/dist/render-DLVPZOA6.js +0 -2
- package/dist/render-DLVPZOA6.js.map +0 -1
- package/dist/renderApp-ZQEZU2MT.js +0 -2
- package/dist/renderApp-ZQEZU2MT.js.map +0 -1
- package/dist/server-Z77W2F6P.js +0 -2
- package/dist/server-Z77W2F6P.js.map +0 -1
- package/dist/transport-ZSBKZIXH.js +0 -2
- package/dist/transport-ZSBKZIXH.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{b as AuthError,a as ModelenceError,d as RateLimitError,c as ValidationError}from'./chunk-C3UESBRX.js';
|
|
1
|
+
export{b as AuthError,a as ModelenceError,d as RateLimitError,c as ValidationError}from'./chunk-C3UESBRX.js';export{a as time}from'./chunk-DO5TZLF5.js';import'./chunk-55J6XMHW.js';//# sourceMappingURL=index.js.map
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{l as author,i as bin,n as bugs,s as default,q as dependencies,d as description,p as devDependencies,g as exports,h as files,o as homepage,m as license,e as main,b as name,r as peerDependencies,k as repository,j as scripts,a as type,f as types,c as version}from'./chunk-
|
|
2
|
-
//# sourceMappingURL=package-
|
|
1
|
+
export{l as author,i as bin,n as bugs,s as default,q as dependencies,d as description,p as devDependencies,g as exports,h as files,o as homepage,m as license,e as main,b as name,r as peerDependencies,k as repository,j as scripts,a as type,f as types,c as version}from'./chunk-M2IGSDQG.js';//# sourceMappingURL=package-5JKWTBGJ.js.map
|
|
2
|
+
//# sourceMappingURL=package-5JKWTBGJ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"package-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"package-5JKWTBGJ.js"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { A as AppServer } from './index-
|
|
2
|
-
import {
|
|
3
|
-
export {
|
|
4
|
-
import { S as Store, R as RouteDefinition, C as CronJobInputParams, a as RateLimitRule, E as EmailProvider, b as RateLimitType, I as InferDocumentType, c as EmailPayload } from './types-
|
|
5
|
-
export { H as HttpMethod, d as RouteHandler, e as RouteParams, f as RouteResponse, s as schema } from './types-
|
|
1
|
+
import { A as AppServer } from './index-CLpVWWuj.js';
|
|
2
|
+
import { d as ConfigParams, C as ConfigSchema, A as AnyMethodShape, S as ServerChannel, V as ValueType, g as SignupProps, U as UpdateProfileProps, h as AuthSuccessProps, i as AuthErrorProps, j as ConnectionInfo, k as User, l as OAuthErrorInfo, a as WebsocketServerProvider, R as RoleDefinition, M as MethodDefinition, c as ConfigKey, m as AppConfig, n as Session, o as UserInfo, p as Role } from './types-CzGfkwti.js';
|
|
3
|
+
export { e as ConfigType } from './types-CzGfkwti.js';
|
|
4
|
+
import { S as Store, R as RouteDefinition, C as CronJobInputParams, a as RateLimitRule, E as EmailProvider, b as RateLimitType, I as InferDocumentType, c as EmailPayload } from './types-JMIT4IDG.js';
|
|
5
|
+
export { H as HttpMethod, d as RouteHandler, e as RouteParams, f as RouteResponse, s as schema } from './types-JMIT4IDG.js';
|
|
6
6
|
import { ObjectId as ObjectId$1 } from 'mongodb';
|
|
7
7
|
export { ObjectId } from 'mongodb';
|
|
8
8
|
import * as zod from 'zod';
|
package/dist/server.js
CHANGED
|
@@ -1,2 +1,21 @@
|
|
|
1
|
-
export{m as ObjectId,k as ServerChannel,a as consumeRateLimit,c as deleteFile,j as deleteUser,i as disableUser,d as downloadFile,e as getFileUrl,b as getUploadUrl,l as sendEmail,h as startApp}from'./chunk-3XTC4WGD.js';import'./chunk-X22U5KA3.js';export{r as LiveData,a as Module,b as Store,q as authenticate,t as createQuery,k as dbUsers,c as schema}from'./chunk-GZI4X3CV.js';import'./chunk-C3UESBRX.js';export{a as getConfig}from'./chunk-3SPXJEOR.js';import'./chunk-FL573BOT.js';import'./chunk-5M6FUMUK.js';import'./chunk-DO5TZLF5.js';//# sourceMappingURL=server.js.map
|
|
1
|
+
import {a as a$2,b as b$1}from'./chunk-5M6FUMUK.js';import {d as d$1,a as a$3}from'./chunk-C3UESBRX.js';import {a}from'./chunk-DO5TZLF5.js';import {a as a$1,b,f as f$1,e,g,c,h,k,d as d$2,j as j$1,i,l,m}from'./chunk-3SPXJEOR.js';export{a as getConfig}from'./chunk-3SPXJEOR.js';import {s}from'./chunk-M2IGSDQG.js';import lr from'dotenv';import ni from'fs/promises';import oo from'os';import bt from'path';import {Server}from'socket.io';import {createAdapter}from'@socket.io/mongo-adapter';import {MongoError,ObjectId,MongoClient,MongoServerError}from'mongodb';export{ObjectId}from'mongodb';import {randomBytes,randomUUID}from'crypto';import {isDeepStrictEqual}from'util';import Z,{z as z$1}from'zod';import Fr from'bcrypt';import {createServer,defineConfig,loadConfigFromFile,mergeConfig}from'vite';import So from'@vitejs/plugin-react';import xo from'fs';import H,{Router}from'express';import Ho from'cookie-parser';import Wo from'http';var C=class{constructor(e,{stores:n=[],queries:r={},mutations:o={},routes:i=[],cronJobs:s={},configSchema:a={},rateLimits:c=[],channels:l=[]}={}){this.name=e,this.stores=n,this.queries=r,this.mutations=o,this.routes=i,this.cronJobs=s,this.configSchema=a,this.rateLimits=c,this.channels=l;}getConfig(e){return a$1(`${this.name}.${e}`)}};function $(t){let e=t._def;if(e.typeName==="ZodString")return {type:"string"};if(e.typeName==="ZodNumber")return {type:"number"};if(e.typeName==="ZodBoolean")return {type:"boolean"};if(e.typeName==="ZodDate")return {type:"date"};if(e.typeName==="ZodArray")return {type:"array",items:$(e.type)};if(e.typeName==="ZodObject"){let r=e.shape(),o={};for(let[i,s]of Object.entries(r))o[i]=$(s);return {type:"object",items:o}}if(e.typeName==="ZodOptional")return {...$(e.innerType),optional:true};if(e.typeName==="ZodNullable")return {...$(e.innerType),optional:true};if(e.typeName==="ZodEnum")return {type:"enum",items:e.values};if(e.typeName==="ZodUnion")return {type:"union",items:e.options.map($)};if(e.typeName==="ZodEffects"){let n=e;return n.description?{type:"custom",typeName:n.description}:$(n.schema)}return {type:"custom",typeName:e.typeName}}function xe(t){let e={};for(let[n,r]of Object.entries(t))Array.isArray(r)?e[n]=r.map(o=>typeof o=="object"&&"_def"in o?$(o):xe(o)):typeof r=="object"&&"_def"in r?e[n]=$(r):e[n]=xe(r);return e}var Ce=t=>typeof t=="object"&&t!==null&&!Array.isArray(t),Lt=t=>Ce(t)&&"_def"in t,He=t=>t._def,Ut=t=>{let e=He(t);if(e.typeName==="ZodOptional"||e.typeName==="ZodNullable"||e.typeName==="ZodDefault"||e.typeName==="ZodCatch"||e.typeName==="ZodReadonly")return e.innerType;if(e.typeName==="ZodEffects")return e.schema;if(e.typeName==="ZodBranded")return e.type;if(e.typeName==="ZodPipeline")return e.out},$t=t=>{let e=He(t);if(e.typeName==="ZodDefault")return {hasDefault:true,value:e.defaultValue()};let n=Ut(t);return n?$t(n):{hasDefault:false}},Ze=(t,e)=>{let n=He(t);if(n.typeName==="ZodObject"&&Ce(e))return Ee(n.shape(),e);if(n.typeName==="ZodArray"&&Array.isArray(e))return e.map(o=>Ze(n.type,o));let r=Ut(t);return r?Ze(r,e):e},ve=(t,e)=>Lt(t)?Ze(t,e):Array.isArray(t)&&Array.isArray(e)?t.length===1?e.map(n=>ve(t[0],n)):e.map((n,r)=>ve(t[r],n)):Ce(t)&&Ce(e)?Ee(t,e):e,Ee=(t,e)=>{let n={...e};for(let[r,o]of Object.entries(t)){let i=n[r];if(i===void 0){if(Lt(o)){let s=$t(o);s.hasDefault&&(n[r]=ve(o,s.value));}continue}n[r]=ve(o,i);}return n};var pr=["background","bits","bucketSize","collation","default_language","expireAfterSeconds","hidden","language_override","max","min","partialFilterExpression","sparse","storageEngine","textIndexVersion","unique","weights","wildcardProjection","2dsphereIndexVersion"],Be=t=>typeof t=="object"&&t!==null&&!Array.isArray(t),fr=t=>t.startsWith("_modelence_"),Ge=t=>{let e={};for(let n of pr){let r=t[n];r!==void 0&&(e[n]=r);}return e},hr=(t,e)=>{if(!Be(t)||!Be(e))return false;let n=Object.entries(t),r=Object.entries(e);return n.length!==r.length?false:n.every(([o,i],s)=>{let[a,c]=r[s]||[];return o===a&&isDeepStrictEqual(i,c)})},jt=(t,e)=>hr(t.key,e.key)?isDeepStrictEqual(Ge(t),Ge(e)):false,We=t=>Be(t)?Object.entries(t).map(([e,n])=>`${e}:${JSON.stringify(n)}`).join("|"):null,gr=async t=>{try{return await t.listIndexes().toArray()}catch(e){if(e instanceof MongoError&&e.code===26)return [];throw e}},yr=t=>Object.entries(t).map(([e,n])=>`${e}_${n}`).join("_"),wr=t=>{if(t.name){let n=t.name.startsWith("_modelence_")?t.name:`_modelence_${t.name}`;return {...t,name:n}}let e=yr(t.key);return {...t,name:`_modelence_${e}`}},T=class t{constructor(e,n){this._chainParent=null;this._chainChild=null;this.name=e,this.schema=n.schema,this.methods=n.methods,this.indexes=n.indexes.map(wr),this.searchIndexes=n.searchIndexes||[],this.indexCreationMode=n.indexCreationMode??"background";}getName(){return this.name}getIndexCreationMode(){return this.indexCreationMode}getSchema(){return this.schema}getSerializedSchema(){return xe(this.schema)}getIndexes(){return this.indexes}getSearchIndexes(){return this.searchIndexes}getChainTail(){let e=this;for(;e._chainChild;)e=e._chainChild;return e}getChainRoot(){let e=this;for(;e._chainParent;)e=e._chainParent;return e}extend(e){let n=this.getChainTail();if(this.client||n.client)throw new Error(`Store.extend() must be called before startApp(). Store '${this.name}' has already been initialized and cannot be extended.`);let r={...n.schema,...e.schema||{}},o=[...n.indexes,...e.indexes||[]],i=[...n.searchIndexes,...e.searchIndexes||[]],s={...n.methods||{},...e.methods||{}},a=new t(this.name,{schema:r,methods:s,indexes:o,searchIndexes:i,indexCreationMode:e.indexCreationMode??n.indexCreationMode});return n._chainChild=a,a._chainParent=n,a}init(e){if(this.collection)throw new Error(`Collection ${this.name} is already initialized`);this.client=e,this.collection=this.client.db().collection(this.name);}async createIndexes(e="full"){let n=this.requireCollection(),r=e!=="create-only",o=e!=="drop-only",i=await gr(n),s=new Map,a=new Map,c=new Set,l=m=>{s.set(m.name,m);let y=We(m.key);if(!y)return;let g=a.get(y);g?g.add(m.name):a.set(y,new Set([m.name]));},u=m=>{let y=s.get(m);if(!y)return;s.delete(m);let g=We(y.key);if(!g)return;let E=a.get(g);E&&(E.delete(m),E.size===0&&a.delete(g));};for(let m of i)typeof m.name=="string"&&l({...m,name:m.name});let p=async m=>{if(!(m==="_id_"||c.has(m))){try{await n.dropIndex(m);}catch(y){if(!(y instanceof MongoError&&y.code===27))throw y}c.add(m),u(m);}};if(r){let m=new Set(this.indexes.map(g=>g.name).filter(g=>typeof g=="string")),y=[...s.values()].filter(g=>fr(g.name)&&!m.has(g.name));for(let g of y)await p(g.name);}if(this.indexes.length>0)for(let m of this.indexes){if(!m.name)continue;let y=false,g=s.get(m.name);g&&!jt(g,m)&&(r?await p(g.name):y=true);let E=We(m.key);if(E){let I=[...a.get(E)||[]];for(let A of I)A!==m.name&&(r?await p(A):y=true);}let L=s.get(m.name);!(!!L&&jt(L,m))&&o&&!y&&(await n.createIndexes([m]),l({name:m.name,key:m.key,...Ge(m)}));}if(o&&this.searchIndexes.length>0)for(let m of this.searchIndexes)try{await n.createSearchIndexes([m]);}catch(y){if(y instanceof MongoError&&y.code===68&&m.name)await n.dropSearchIndex(m.name),await n.createSearchIndexes([m]);else throw y}}wrapDocument(e){return this.methods?Object.create(null,Object.getOwnPropertyDescriptors({...e,...this.methods})):e}getSelector(e){return typeof e=="string"?{_id:new ObjectId(e)}:e instanceof ObjectId?{_id:e}:e}requireCollection(){if(!this.collection)throw new Error(`Collection ${this.name} is not provisioned`);return this.collection}requireClient(){if(!this.client)throw new Error("Database is not connected");return this.client}async findOne(e,n){let r=await this.requireCollection().findOne(e,n);return r?this.wrapDocument(r):null}async requireOne(e,n,r){let o=await this.findOne(e,n);if(!o)throw r?r():new Error(`Record not found in ${this.name}`);return o}find(e,n){let r=this.requireCollection().find(e,n?.projection?{projection:n.projection}:void 0);return n?.sort&&r.sort(n.sort),n?.limit&&r.limit(n.limit),n?.skip&&r.skip(n.skip),r}async findById(e){let n=typeof e=="string"?{_id:new ObjectId(e)}:{_id:e};return await this.findOne(n)}async requireById(e,n){let r=await this.findById(e);if(!r)throw n?n():new Error(`Record with id ${e} not found in ${this.name}`);return r}countDocuments(e){return this.requireCollection().countDocuments(e)}async fetch(e,n){return (await this.find(e,n).toArray()).map(this.wrapDocument.bind(this))}async insertOne(e,n){return await this.requireCollection().insertOne(e,n)}async create(e,n){let r=Ee(this.schema,{_id:new ObjectId,...e});return await this.requireCollection().insertOne(r,n),this.wrapDocument(r)}async insertMany(e,n){return await this.requireCollection().insertMany(e,n)}async updateOne(e,n,r){return await this.requireCollection().updateOne(this.getSelector(e),n,r)}async upsertOne(e,n,r){return await this.requireCollection().updateOne(this.getSelector(e),n,{upsert:true,...r})}async updateMany(e,n,r){return await this.requireCollection().updateMany(e,n,r)}async upsertMany(e,n,r){return await this.requireCollection().updateMany(e,n,{upsert:true,...r})}async deleteOne(e,n){return await this.requireCollection().deleteOne(this.getSelector(e),n)}async deleteMany(e,n){return await this.requireCollection().deleteMany(e,n)}async findOneAndUpdate(e,n,r){let o=await this.requireCollection().findOneAndUpdate(this.getSelector(e),n,r??{});return o?this.wrapDocument(o):null}async findOneAndDelete(e,n){let r=await this.requireCollection().findOneAndDelete(this.getSelector(e),n??{});return r?this.wrapDocument(r):null}async findOneAndReplace(e,n,r){let o=await this.requireCollection().findOneAndReplace(this.getSelector(e),n,r??{});return o?this.wrapDocument(o):null}async replaceOne(e,n,r){return await this.requireCollection().replaceOne(this.getSelector(e),n,r)}async distinct(e,n,r){let o=n??{};return r!==void 0?await this.requireCollection().distinct(e,o,r):await this.requireCollection().distinct(e,o)}watch(e,n){return this.requireCollection().watch(e,n)}aggregate(e,n){return this.requireCollection().aggregate(e,n)}bulkWrite(e){return this.requireCollection().bulkWrite(e)}getDatabase(){return this.requireClient().db()}rawCollection(){return this.requireCollection()}async renameFrom(e,n){let r=this.getDatabase();if(!this.collection||!r)throw new Error(`Store ${this.name} is not provisioned`);if((await r.listCollections({name:e}).toArray()).length===0)throw new Error(`Collection ${e} not found`);if((await r.listCollections({name:this.name}).toArray()).length>0)throw new Error(`Collection ${this.name} already exists`);await r.collection(e).rename(this.name,n);}async vectorSearch({field:e,embedding:n,numCandidates:r,limit:o,projection:i,indexName:s}){return this.aggregate([{$vectorSearch:{index:s||e+"VectorSearch",path:e,queryVector:n,numCandidates:r||100,limit:o||10}},{$project:{_id:1,score:{$meta:"vectorSearchScore"},...i}}])}static vectorIndex({field:e,dimensions:n,similarity:r="cosine",indexName:o}){return {type:"vectorSearch",name:o||e+"VectorSearch",definition:{fields:[{type:"vector",path:e,numDimensions:n,similarity:r}]}}}};var br=z$1.string.bind(z$1),Sr=z$1.number.bind(z$1),xr=z$1.date.bind(z$1),Cr=z$1.boolean.bind(z$1),vr=z$1.array.bind(z$1),Er=z$1.object.bind(z$1),Tr=z$1.enum.bind(z$1),d={string:br,number:Sr,date:xr,boolean:Cr,array:vr,object:Er,enum:Tr,embedding(){return z$1.array(z$1.number())},objectId(){return z$1.instanceof(ObjectId).describe("ObjectId")},userId(){return z$1.instanceof(ObjectId).describe("UserId")},ref(t){return z$1.instanceof(ObjectId).describe("Ref")},union:z$1.union.bind(z$1),infer(t){return {}}};var B=new T("_modelenceSessions",{schema:{authToken:d.string(),createdAt:d.date(),expiresAt:d.date(),userId:d.userId().nullable()},indexes:[{key:{authToken:1},unique:true},{key:{expiresAt:1},expireAfterSeconds:0},{key:{userId:1}}]});async function zt(t){let e=t?await B.findOne({authToken:t}):null;return e?{authToken:String(e.authToken),expiresAt:new Date(e.expiresAt),userId:e.userId??null}:await ce()}async function qt(t,e){await B.updateOne({authToken:t},{$set:{userId:e}});}async function Zt(t){await B.updateOne({authToken:t},{$set:{userId:null}});}async function Ht(t){await B.deleteMany({userId:t});}async function ce(t=null){let e=randomBytes(32).toString("base64url"),n=Date.now(),r=new Date(n+a.days(7));return await B.insertOne({authToken:e,createdAt:new Date(n),expiresAt:r,userId:t}),{authToken:e,expiresAt:r,userId:t}}async function Ar(t){let e=Date.now(),n=new Date(e+a.days(7));await B.updateOne({authToken:t.authToken},{$set:{lastActiveDate:new Date(e),expiresAt:n}});}function ke(t,e){t.cookie("authToken",e,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"strict",path:"/"});}var Wt=new C("_system.session",{stores:[B],mutations:{init:async function(t,{session:e,user:n}){return {session:e,user:n,configs:b()}},heartbeat:async function(t,{session:e}){e&&await Ar(e);}}});var f=new T("_modelenceUsers",{schema:{handle:d.string(),emails:d.array(d.object({address:d.string(),verified:d.boolean()})).optional(),status:d.enum(["active","disabled","deleted"]).optional(),firstName:d.string().optional(),lastName:d.string().optional(),avatarUrl:d.string().optional(),createdAt:d.date(),disabledAt:d.date().optional(),deletedAt:d.date().optional(),roles:d.array(d.string()).optional(),authMethods:d.object({password:d.object({hash:d.string()}).optional(),google:d.object({id:d.string()}).optional(),github:d.object({id:d.string()}).optional()})},indexes:[{key:{handle:1},unique:true,collation:{locale:"en",strength:2}},{key:{"emails.address":1,status:1}},{key:{"authMethods.google.id":1},sparse:true,unique:true},{key:{"authMethods.github.id":1},sparse:true,unique:true}]}),le=new T("_modelenceDisposableEmailDomains",{schema:{domain:d.string(),addedAt:d.date()},indexes:[{key:{domain:1},unique:true}]}),j=new T("_modelenceEmailVerificationTokens",{schema:{userId:d.objectId(),email:d.string().optional(),token:d.string(),createdAt:d.date(),expiresAt:d.date()},indexes:[{key:{token:1},unique:true},{key:{expiresAt:1},expireAfterSeconds:0}]}),P=new T("_modelenceResetPasswordTokens",{schema:{userId:d.objectId(),email:d.string().optional(),token:d.string(),createdAt:d.date(),expiresAt:d.date()},indexes:[{key:{token:1},unique:true},{key:{expiresAt:1},expireAfterSeconds:0}]});var Vt=new Map,ne={authenticated:null,unauthenticated:null};function Bt(t,e){ne.authenticated=e.authenticated,ne.unauthenticated=e.unauthenticated;for(let[n,r]of Object.entries(t))Vt.set(n,r);}function Ae(){return ne.unauthenticated?[ne.unauthenticated]:[]}function Gt(){return ne.authenticated?[ne.authenticated]:[]}function Je(t,e){let n=e.find(r=>!Or(t,r));if(n)throw new Error(`Access denied - missing permission: '${n}'`)}function Or(t,e){for(let n of t)if(Vt.get(n)?.permissions?.includes(e))return true;return false}async function N(t){let e=await zt(t),n=e.userId?await f.findOne({_id:new ObjectId(e.userId),status:{$nin:["deleted","disabled"]}}):null,r=n?{id:n._id.toString(),handle:n.handle,roles:n.roles||[],hasRole:i=>(n.roles||[]).includes(i),requireRole:i=>{if(!(n.roles||[]).includes(i))throw new Error(`Access denied - role '${i}' required`)},firstName:n.firstName??void 0,lastName:n.lastName??void 0,avatarUrl:n.avatarUrl??void 0}:null,o=r?Gt():Ae();return {user:r,session:e,roles:o}}var de=new C("_system",{configSchema:{mongodbUri:{type:"secret",isPublic:false,default:""},mongodbPoolSize:{type:"number",isPublic:false,default:10},"env.type":{type:"string",isPublic:true,default:""},"site.url":{type:"string",isPublic:true,default:""},multiInstance:{type:"boolean",isPublic:false,default:false}}});var F=null;async function Kt(){if(F)return F;let t=G();if(!t)throw new Error("MongoDB URI is not set");let e=de.getConfig("mongodbPoolSize");F=new MongoClient(t,{driverInfo:{name:"Modelence",version:s.version},ignoreUndefined:true,maxPoolSize:e});try{return await F.connect(),await F.db("admin").command({ping:1}),console.log("Pinged your deployment. You successfully connected to MongoDB!"),F}catch(n){throw console.error(n),F=null,n}}function G(){return de.getConfig("mongodbUri")||void 0}function Oe(){return F}var re=class{constructor(e){this.fetch=e.fetch,this.watch=e.watch;}};function Mr(){return typeof window!="object"}function z(){if(!Mr())throw new Error("This function can only be called on the server")}function Re(t){return t.replace(/<[^>]*>/g,"").replace(/\s+/g," ").trim()}var _e={};function Qe(t,e){return z(),Xt(t),Me("query",t,e)}function Jt(t,e){return z(),Xt(t),Me("mutation",t,e)}function Qt(t,e){return z(),en(t),Me("query",t,e)}function Yt(t,e){return z(),en(t),Me("mutation",t,e)}function Xt(t){if(t.toLowerCase().startsWith("_system."))throw new Error(`Method name cannot start with a reserved prefix: '_system.' (${t})`)}function en(t){if(!t.toLowerCase().startsWith("_system."))throw new Error(`System method name must start with a prefix: '_system.' (${t})`)}function Me(t,e,n){if(z(),_e[e])throw new Error(`Method with name '${e}' is already defined.`);let r=typeof n=="function"?n:n.handler,o=typeof n=="function"?[]:n.permissions??[];_e[e]={type:t,name:e,handler:r,permissions:o};}async function tn(t,e,n){z();let r=_e[t];if(!r)throw new Error(`Method with name '${t}' is not defined.`);let{type:o,handler:i}=r,s=l("method",`method:${t}`,{type:o,args:e}),a;try{Je(n.roles,r.permissions),a=await i(e,n);}catch(c){throw s.end("error"),c}return s.end(),a}async function nn(t,e,n){z();let r=_e[t];if(!r)throw new Error(`Method with name '${t}' is not defined.`);let{type:o,handler:i}=r;if(o!=="query")throw new Error("Live methods are only supported for queries");let s=l("method",`method:${t}:live`,{type:o,args:e}),a;try{if(Je(n.roles,r.permissions),a=await i(e,n),!(a instanceof re))throw new Error(`Live query handler for '${t}' must return a LiveData object with fetch and watch functions. See https://docs.modelence.com/live-queries`)}catch(c){throw s.end("error"),c}return s.end(),a}var ue=new Map;function Ir(t){let e=ue.get(t.id);return e||(e=new Map,ue.set(t.id,e)),e}async function Ye(t,e){let n=z$1.object({subscriptionId:z$1.string().min(1),method:z$1.string().min(1),args:z$1.record(z$1.unknown()).default({}),authToken:z$1.string().nullish(),clientInfo:z$1.object({screenWidth:z$1.number(),screenHeight:z$1.number(),windowWidth:z$1.number(),windowHeight:z$1.number(),pixelRatio:z$1.number(),orientation:z$1.string().nullable()}).optional()}).safeParse(e);if(!n.success){t.emit("liveQueryError",{subscriptionId:null,error:`Invalid payload: ${n.error.message}`});return}let{subscriptionId:r,method:o,args:i,authToken:s,clientInfo:a}=n.data,c=Ir(t),l=c.get(r);if(l)if(l.cleanup)try{l.cleanup();}catch(p){console.error("[LiveQuery] Error cleaning up existing subscription:",p);}else l.aborted=true;let u={cleanup:null};c.set(r,u);try{let{session:p,user:m,roles:y}=await N(s??null),g={session:p,user:m,roles:y,clientInfo:a??{screenWidth:0,screenHeight:0,windowWidth:0,windowHeight:0,pixelRatio:1,orientation:null},connectionInfo:{ip:t.handshake.address,userAgent:t.handshake.headers["user-agent"]}},E=await nn(o,i,g),L=async()=>{let _=a$2(await E.fetch());u.aborted||t.emit("liveQueryData",{subscriptionId:r,data:_,typeMap:b$1(_)});},O=!0,I=!1,A=()=>{u.aborted||!O||I||(O=!1,I=!0,L().catch(_=>{u.aborted||(console.error(`[LiveQuery] Error fetching data for ${o}:`,_),t.emit("liveQueryError",{subscriptionId:r,error:_ instanceof Error?_.message:String(_)}));}).finally(()=>{I=!1,A();}));},W=E.watch({publish:()=>{O=!0,A();}});if(u.aborted){if(W)try{W();}catch(_){console.error("[LiveQuery] Error cleaning up after disconnect during setup:",_);}return}u.cleanup=W||null,A();}catch(p){c.delete(r),console.error(`[LiveQuery] Error in ${o}:`,p),t.emit("liveQueryError",{subscriptionId:r,error:p instanceof Error?p.message:String(p)});}}function Xe(t,e){let n=z$1.object({subscriptionId:z$1.string().min(1)}).safeParse(e);if(!n.success){console.warn(`[LiveQuery] Invalid unsubscribe payload: ${n.error.message}`);return}let{subscriptionId:r}=n.data,o=ue.get(t.id);if(!o)return;let i=o.get(r);if(i){if(i.cleanup)try{i.cleanup();}catch(s){console.error("[LiveQuery] Error in cleanup:",s);}else i.aborted=true;o.delete(r);}}function et(t){let e=ue.get(t.id);if(e){for(let n of e.values())if(n.cleanup)try{n.cleanup();}catch(r){console.error("[LiveQuery] Error in cleanup on disconnect:",r);}else n.aborted=true;ue.delete(t.id);}}var me=null,Nr="_modelenceSocketio",rn=60;async function Lr({httpServer:t,channels:e}){let n=Oe(),r=!!a$1("_system.multiInstance");console.log("Initializing Socket.IO server...");let o=null;if(r&&n){o=n.db().collection(Nr);try{await o.createIndex({createdAt:1},{expireAfterSeconds:rn,background:!0});}catch(i){if(i instanceof Error&&"code"in i&&i.code===85)try{await o.dropIndex("createdAt_1"),await o.createIndex({createdAt:1},{expireAfterSeconds:rn,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:",i);}}me=new Server(t,{cors:{origin:"*",methods:["GET","POST"]},adapter:o?createAdapter(o):void 0,transports:["websocket"],perMessageDeflate:false}),me.on("error",i=>{console.error("Socket.IO error:",i);}),me.use(async(i,s)=>{let a=i.handshake.auth.token;try{i.data=await N(a);}finally{s();}}),me.on("connection",i=>{i.on("disconnect",()=>{et(i);}),i.on("joinChannel",async s=>{let[a]=s.split(":"),c=false;for(let l of e)if(l.category===a){(!l.canAccessChannel||await l.canAccessChannel(i.data))&&(i.join(s),c=true,i.emit("joinedChannel",s));break}c||i.emit("joinError",{channel:s,error:"Access denied"});}),i.on("leaveChannel",s=>{i.leave(s),console.log(`User ${i.id} left channel ${s}`),i.emit("leftChannel",s);}),i.on("subscribeLiveQuery",s=>Ye(i,s)),i.on("unsubscribeLiveQuery",s=>Xe(i,s));}),console.log("Socket.IO server initialized");}function Ur({category:t,id:e,data:n}){me?.to(`${t}:${e}`).emit(t,n);}var on={init:Lr,broadcast:Ur};async function sn(t){let e=t.toLowerCase().trim().split("@");if(e.length!==2)return false;let n=e[1];return !!await le.findOne({domain:n})}var an={interval:a.days(1),async handler(){let t=await fetch("https://disposable.github.io/disposable-email-domains/domains.txt");if(!t.ok)throw new Error(`HTTP ${t.status}: ${t.statusText}`);let n=(await t.text()).split(`
|
|
2
|
+
`).map(i=>i.trim().toLowerCase()).filter(i=>i.length>0),r=new Date,o=500;for(let i=0;i<n.length;i+=o){let s=n.slice(i,i+o);try{await le.insertMany(s.map(a=>({domain:a,addedAt:r})));}catch(a){a&&typeof a=="object"&&"name"in a&&a.name;}}}};var Ie=3,K=50,cn=8,ln=128,dn=254,un=t=>z$1.string().trim().min(t.min??1,{message:`must be at least ${t.min??1} characters`}).max(t.max,{message:`must be at most ${t.max} characters`}),tt=t=>z$1.string().trim().max(t.max,{message:`must be at most ${t.max} characters`}).transform(e=>e===""?void 0:e).optional(),$r=z$1.object({firstName:tt({max:50}),lastName:tt({max:50}),avatarUrl:tt({max:400}),handle:un({min:Ie,max:K})}).strict();function De(t){let e=$r.partial().safeParse(t);if(!e.success){let n=e.error.issues[0],r=n.path.join("."),o=r?`${r}: ${n.message}`:n.message;throw new Error(o)}return e.data}function Pe(t){return z$1.string().min(cn,{message:`Password must contain at least ${cn} characters`}).max(ln,{message:`Password must be at most ${ln} characters`}).parse(t)}function q(t){return z$1.string().max(dn,{message:`Email must be at most ${dn} characters`}).email({message:"Invalid email address"}).parse(t).toLowerCase()}function mn(t){return un({min:Ie,max:K}).parse(t)}function Ne(t){return {id:t._id,handle:t.handle,roles:t.roles||[],firstName:t.firstName??void 0,lastName:t.lastName??void 0,avatarUrl:t.avatarUrl??void 0}}async function pn(t){let e=t.slice(0,K);try{if(!await f.findOne({handle:e},{collation:{locale:"en",strength:2}}))return e}catch(o){throw new Error(`Database error while checking handle availability: ${o}`)}let n=51;for(let o=2;o<=n;o++){let i=`_${o}`,s=`${e.slice(0,K-i.length)}${i}`;try{if(!await f.findOne({handle:s},{collation:{locale:"en",strength:2}}))return s}catch(a){throw new Error(`Database error while checking handle "${s}": ${a}`)}}let r=10;for(let o=0;o<r;o++){let i=`_${randomBytes(3).toString("hex")}`,s=`${e.slice(0,K-i.length)}${i}`;try{if(!await f.findOne({handle:s},{collation:{locale:"en",strength:2}}))return s}catch(a){throw new Error(`Database error while checking handle "${s}": ${a}`)}}throw new Error(`Could not generate a unique handle for base "${t}" after exhausting all attempts.`)}async function J(t,e,{throwOnConflict:n=true}={}){if(t!=null&&String(t).trim()!==""){let o=mn(String(t).trim());if(n){if(await f.findOne({handle:o},{collation:{locale:"en",strength:2}}))throw new Error("Handle already taken.");return o}return pn(o)}let r=e.split("@")[0].padEnd(Ie,"_").slice(0,K);return pn(r)}var nt=Object.freeze({});function rt(t){nt=Object.freeze(Object.assign({},nt,t));}function x(){return nt}var ot=Object.freeze({});function fn(t){ot=Object.freeze(Object.assign({},ot,t));}function v(){return ot}async function gn(t,{user:e,session:n,connectionInfo:r}){try{if(!n)throw new Error("Session is not initialized");let o=r?.ip;o&&await M({bucket:"signin",type:"ip",value:o});let i=q(t.email),s=z$1.string().parse(t.password),a=await f.findOne({"emails.address":i,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}}),c=a?.authMethods?.password?.hash;if(!c)throw hn();if(!a.emails?.find(p=>p.address.toLowerCase()===i)?.verified&&x()?.provider)throw new Error("Your email address hasn't been verified yet. Please check your inbox for the verification email.");if(!await Fr.compare(s,c))throw hn();return await qt(n.authToken,a._id),v().onAfterLogin?.({provider:"email",user:a,session:n,connectionInfo:r}),v().login?.onSuccess?.(a),{user:Ne(a)}}catch(o){throw o instanceof Error&&(v().onLoginError?.({provider:"email",error:o,session:n,connectionInfo:r}),v().login?.onError?.(o)),o}}async function yn(t,{session:e}){if(!e)throw new Error("Session is not initialized");await Zt(e.authToken);}function hn(){return new Error("Incorrect email/password combination")}async function wn(t,{user:e}){if(!e)throw new Error("Not authenticated");let n=await f.requireById(e.id);return {handle:n.handle,emails:n.emails,authMethods:Object.keys(n.authMethods||{}),firstName:n.firstName??void 0,lastName:n.lastName??void 0,avatarUrl:n.avatarUrl??void 0}}async function bn(t,{user:e}){if(!e)throw new Error("Not authenticated");let n=await f.requireById(e.id),r=De(t);if(await v().validateProfileUpdate?.(r),"handle"in r&&r.handle!==void 0&&await f.findOne({handle:r.handle,_id:{$ne:n._id}},{collation:{locale:"en",strength:2}}))throw new Error("Handle already taken.");if(Object.keys(r).length>0){let o={},i={};for(let[a,c]of Object.entries(r))c===void 0?i[a]="":o[a]=c;let s={};Object.keys(o).length>0&&(s.$set=o),Object.keys(i).length>0&&(s.$unset=i);try{await f.updateOne({_id:n._id},s);let a=Object.fromEntries(Object.keys(i).map(c=>[c,void 0]));n={...n,...o,...a};}catch(a){throw a instanceof Error&&"code"in a&&a.code===11e3?new Error("Handle already taken."):a}}return {user:Ne(n)}}var it=["google","github"];async function Sn({provider:t},{user:e}){if(!e)throw new Error("You must be signed in to unlink a provider.");if(typeof t!="string"||!it.includes(t))throw new Error(`Invalid provider. Supported providers are: ${it.join(", ")}.`);let n=await f.requireById(e.id),r=n.authMethods??{};if(!r[t])throw new Error(`${t} is not linked to your account.`);if(Object.values(r).filter(Boolean).length<=1)throw new Error("Cannot unlink your only authentication method. Please add another method first.");let s=Object.keys(r).filter(l=>l!==t&&r[l]),a=s.length>0?{$or:s.map(l=>({[`authMethods.${l}`]:{$exists:true}}))}:{};if((await f.updateOne({_id:n._id,...a},{$unset:{[`authMethods.${t}`]:""}})).matchedCount===0)throw new Error("Cannot unlink your only authentication method. Please add another method first.")}var fe=new T("_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 st=[];function xn(t){if(st.length>0)throw new Error("Duplicate call to initRateLimits - already initialized");st=t;}async function M(t){let{bucket:e,type:n,value:r,message:o}=t,i=st.filter(a=>a.bucket===e&&a.type===n),s=o?()=>new d$1(o):void 0;for(let a of i)await qr(a,r,s);}async function qr(t,e,n){let r=()=>n?n():new d$1(`Rate limit exceeded for ${t.bucket}`),o=await fe.findOne({bucket:t.bucket,type:t.type,value:e,windowMs:t.window}),i=Date.now(),s=Math.floor(i/t.window)*t.window,{count:a,modifier:c}=o?Zr(o,s,i):{count:0,modifier:{$setOnInsert:{windowStart:new Date(s),windowCount:1,prevWindowCount:0,expiresAt:new Date(s+t.window+t.window)}}};if(a>=t.limit)throw r();await fe.upsertOne({bucket:t.bucket,type:t.type,value:e,windowMs:t.window},c);}function Zr(t,e,n){let r=e-t.windowMs;if(t.windowStart.getTime()===e){let o=t.windowCount,i=t.prevWindowCount,s=1-(n-e)/t.windowMs;return {count:Math.round(o+i*s),modifier:{$inc:{windowCount:1},$setOnInsert:{windowStart:new Date(e),prevWindowCount:0,expiresAt:new Date(e+t.windowMs+t.windowMs)}}}}if(t.windowStart.getTime()===r){let o=1-(n-e)/t.windowMs;return {count:Math.round(t.windowCount*o),modifier:{$set:{windowStart:new Date(e),windowCount:1,prevWindowCount:t.windowCount,expiresAt:new Date(e+t.windowMs+t.windowMs)}}}}return {count:0,modifier:{$set:{windowStart:new Date(e),windowCount:1,prevWindowCount:0,expiresAt:new Date(e+t.windowMs+t.windowMs)}}}}function Cn({name:t,email:e,verificationUrl:n}){return `
|
|
3
|
+
<p>Hi${t?` ${t}`:""},</p>
|
|
4
|
+
<p>Please verify your email address ${e} by clicking the link below:</p>
|
|
5
|
+
<p><a href="${n}">${n}</a></p>
|
|
6
|
+
<p>If you did not request this, please ignore this email.</p>
|
|
7
|
+
`}async function Vr(t){let e=await j.findOne({token:t,expiresAt:{$gt:new Date}});if(!e)throw new Error("Invalid or expired verification token");if(!await f.findOne({_id:e.userId,status:{$nin:["deleted","disabled"]}}))throw new Error("User not found");let r=e.email;if(!r)throw new Error("Email not found in token");let o=await f.findOneAndUpdate({_id:e.userId,status:{$nin:["deleted","disabled"]},"emails.address":r,"emails.verified":{$ne:true}},{$set:{"emails.$.verified":true}},{returnDocument:"after"});if(!o)throw await f.findOne({_id:e.userId,"emails.address":r})?new Error("Email is already verified"):new Error("Email address not found for this user");return await j.deleteOne({_id:e._id}),{userDoc:o,email:r}}async function vn(t){let e=a$1("_system.site.url"),n=x().verification?.redirectUrl||x().emailVerifiedRedirectUrl||e||"/";try{let r=z$1.string().parse(t.query.token),{userDoc:o}=await Vr(r);v().onAfterEmailVerification?.({provider:"email",user:o,session:null,connectionInfo:{baseUrl:e,ip:t.req.ip||t.req.socket.remoteAddress,userAgent:t.headers["user-agent"],acceptLanguage:t.headers["accept-language"],referrer:t.headers.referer}});let{authToken:s}=await ce(o._id);return ke(t.res,s),{status:301,redirect:`${n}?status=verified`}}catch(r){let o=r instanceof Error?r.message:"An unexpected error occurred";return r instanceof Error&&(v().onEmailVerificationError?.({provider:"email",error:r,session:null,connectionInfo:{baseUrl:e,ip:t.req.ip||t.req.socket.remoteAddress,userAgent:t.headers["user-agent"],acceptLanguage:t.headers["accept-language"],referrer:t.headers.referer}}),console.error("Error verifying email:",r)),{status:301,redirect:`${n}?status=error&message=${encodeURIComponent(o)}`}}}async function ct({userId:t,email:e,baseUrl:n=a$1("_system.site.url")}){if(x().provider){let r=x().provider,o=randomBytes(32).toString("hex"),i=new Date(Date.now()+a.hours(24));await j.insertOne({userId:t,email:e,token:o,createdAt:new Date,expiresAt:i});let s=`${n}/api/_internal/auth/verify-email?token=${o}`,c=(x()?.verification?.template||Cn)({name:"",email:e,verificationUrl:s}),l=Re(c);await r?.sendEmail({to:e,from:x()?.from||"noreply@modelence.com",subject:x()?.verification?.subject||"Verify your email address",text:l,html:c});}}var at={success:true,message:"If that email is registered and not yet verified, a verification email has been sent"};async function En(t,{connectionInfo:e}){let n=q(t.email),r=await f.findOne({"emails.address":n,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}});if(!r)return at;let o=r.emails?.find(i=>i.address.toLowerCase()===n);if(!o||o.verified)return at;if(!x().provider)throw new Error("Email provider is not configured");return await M({bucket:"verification",type:"user",value:r._id.toString(),message:"Please wait at least 60 seconds before requesting another verification email"}),await ct({userId:r._id,email:n,baseUrl:e?.baseUrl}),at}async function Tn(t,{user:e,session:n,connectionInfo:r}){let o=v();try{let i=t,{firstName:s,lastName:a,avatarUrl:c,handle:l}=i,u=q(i.email),p=Pe(i.password),m=r?.ip;if(m&&await M({bucket:"signupAttempt",type:"ip",value:m}),!o.allowDisposableEmails&&await sn(u))throw new Error("Please use a permanent email address");let y=await f.findOne({"emails.address":u},{collation:{locale:"en",strength:2}});if(y){let A=y.emails?.find(W=>W.address.toLowerCase()===u);throw y.status==="disabled"?new Error("User is marked for deletion, please contact support if you want to restore the account."):new Error(`User with email already exists: ${A?.address}`)}await o.onBeforeSignup?.({email:u,firstName:s,lastName:a,handle:l,provider:"email",connectionInfo:r}),m&&await M({bucket:"signup",type:"ip",value:m});let g=De({firstName:s,lastName:a,avatarUrl:c,handle:l});await o.validateSignup?.({email:u,password:p,...g});let E;if(g.handle)E=await J(g.handle,u);else if(o.generateHandle){let A=await o.generateHandle({email:u,firstName:g.firstName,lastName:g.lastName});E=await J(A,u,{throwOnConflict:!1});}else E=await J(void 0,u);let L=await Fr.hash(p,10),O=await f.insertOne({handle:E,status:"active",emails:[{address:u,verified:!1}],createdAt:new Date,authMethods:{password:{hash:L}},...g.firstName!==void 0&&{firstName:g.firstName},...g.lastName!==void 0&&{lastName:g.lastName},...g.avatarUrl!==void 0&&{avatarUrl:g.avatarUrl}}),I=await f.findOne({_id:O.insertedId},{readPreference:"primary"});if(!I)throw new Error("User not found");return await ct({userId:O?.insertedId,email:u,baseUrl:r?.baseUrl}),o.onAfterSignup?.({provider:"email",user:I,session:n,connectionInfo:r}),o.signup?.onSuccess?.(I),O.insertedId}catch(i){throw i instanceof Error&&(o.onSignupError?.({provider:"email",error:i,session:n,connectionInfo:r}),o.signup?.onError?.(i)),i}}function Qr(t,e){return e?e.startsWith("http://")||e.startsWith("https://")?e:`${t}${e.startsWith("/")?"":"/"}${e}`:t}function Yr({email:t,resetUrl:e}){return `
|
|
8
|
+
<p>Hi,</p>
|
|
9
|
+
<p>We received a request to reset your password for ${t}.</p>
|
|
10
|
+
<p>Click the link below to reset your password:</p>
|
|
11
|
+
<p><a href="${e}">${e}</a></p>
|
|
12
|
+
<p>This link will expire in 1 hour.</p>
|
|
13
|
+
<p>If you did not request this password reset, please ignore this email.</p>
|
|
14
|
+
`}var lt={success:true,message:"If an account with that email exists, a password reset link has been sent"};async function kn(t,{connectionInfo:e}){let n=q(t.email),r=e?.ip;r&&await M({bucket:"passwordReset",type:"ip",value:r}),await M({bucket:"passwordReset",type:"email",value:n});let o=await f.findOne({"emails.address":n,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}});if(!o||!o.authMethods?.password)return lt;let i=x().provider;if(!i)throw new Error("Email provider is not configured");let s=randomBytes(32).toString("hex"),a$2=Date.now(),c=new Date(a$2),l=new Date(a$2+a.hours(1));await P.insertOne({userId:o._id,email:n,token:s,createdAt:c,expiresAt:l});let u=a$1("_system.site.url")||e?.baseUrl,m=`${Qr(u,x().passwordReset?.redirectUrl)}?token=${s}`,g=(x()?.passwordReset?.template||Yr)({email:n,resetUrl:m,name:""}),E=Re(g);return await i.sendEmail({to:n,from:x()?.from||"noreply@modelence.com",subject:x()?.passwordReset?.subject||"Reset your password",text:E,html:g}),lt}async function An(t,{}){let e=z$1.string().parse(t.token),n=Pe(t.password),r=await P.findOne({token:e});if(!r)throw new Error("Invalid or expired reset token");if(r.expiresAt<new Date)throw await P.deleteOne({token:e}),new Error("Reset token has expired");let o=await f.findOne({_id:r.userId});if(!o)throw new Error("User not found");let i=await Fr.hash(n,10);return await f.updateOne({_id:o._id},{$set:{"authMethods.password.hash":i}}),r.email&&await f.updateOne({_id:o._id,"emails.address":r.email},{$set:{"emails.$.verified":true}}),await Ht(o._id),await P.deleteOne({token:e}),{success:true,message:"Password has been reset successfully"}}function On(t){return `${t.bucket}
|
|
15
|
+
${t.type}
|
|
16
|
+
${t.window}`}function Xr(){return [{bucket:"signup",type:"ip",window:a.minutes(15),limit:20},{bucket:"signup",type:"ip",window:a.days(1),limit:200},{bucket:"signupAttempt",type:"ip",window:a.minutes(15),limit:50},{bucket:"signupAttempt",type:"ip",window:a.days(1),limit:500},{bucket:"signin",type:"ip",window:a.minutes(15),limit:50},{bucket:"signin",type:"ip",window:a.days(1),limit:500},{bucket:"verification",type:"user",window:a.seconds(60),limit:1},{bucket:"verification",type:"user",window:a.days(1),limit:10},{bucket:"passwordReset",type:"ip",window:a.minutes(15),limit:10},{bucket:"passwordReset",type:"ip",window:a.days(1),limit:100},{bucket:"passwordReset",type:"email",window:a.hours(1),limit:5},{bucket:"passwordReset",type:"email",window:a.days(1),limit:10}]}function eo(t){let e=[],n=["signup","signupAttempt","signin","verification","passwordReset"];for(let r of n){let o=t[r];if(o!==void 0)for(let i of o)e.push({bucket:r,...i});}return e}function dt(t={}){let e=Xr(),n=eo(t),r=new Map;for(let s of n)r.set(On(s),s);let o=[],i=new Set;for(let s of e){let a=On(s),c=r.get(a);c!==void 0?(o.push(c),i.add(a)):o.push(s);}for(let[s,a]of r)i.has(s)||o.push(a);return o}var ut=new C("_system.user",{stores:[f,le,j,P],queries:{getOwnProfile:wn},mutations:{signupWithPassword:Tn,loginWithPassword:gn,logout:yn,resendEmailVerification:En,sendResetPasswordToken:kn,resetPassword:An,updateProfile:bn,unlinkOAuthProvider:Sn},cronJobs:{updateDisposableEmailList:an},rateLimits:dt(),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:false},"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:""}},routes:[{path:"/api/_internal/auth/verify-email",handlers:{get:vn}}]});var to={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_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 no(t,e){if(e==="number"){let n=Number(t);if(isNaN(n))throw new Error(`Invalid number value for config: ${t}`);return n}if(e==="boolean"){if(t.toLowerCase()==="true")return true;if(t.toLowerCase()==="false")return false;throw new Error(`Invalid boolean value for config: ${t}`)}return t}function ro(t,e){let n=[];for(let[r,o]of Object.entries(t)){let i=process.env[r],s=e[o];if(i){let a=s?.type??"string";n.push({key:o,type:a,value:no(i,a)});}}return n}function Le(t,e="withoutRemoteServer"){let n=to[e];return ro(n,t)}async function Rn({configSchema:t,cronJobsMetadata:e,stores:n,roles:r}){let o=process.env.MODELENCE_CONTAINER_ID;if(!o)throw new Error("Unable to connect to Modelence Cloud: MODELENCE_CONTAINER_ID is not set");try{let i=(n??[]).map(a=>({name:a.getName(),schema:a.getSerializedSchema(),collections:[a.getName()],version:2,indexes:a.getIndexes(),searchIndexes:a.getSearchIndexes(),indexCreationMode:a.getIndexCreationMode()})),s=await D("/api/connect","POST",{hostname:oo.hostname(),containerId:o,dataModels:i,configSchema:t,cronJobsMetadata:e,roles:r});if(s.status==="error")throw new Error(s.error);return console.log("Successfully connected to Modelence Cloud"),s}catch(i){throw console.error("Unable to connect to Modelence Cloud:",i),i}}async function _n(){return D("/api/configs","GET")}async function Mn(){return await D("/api/sync","POST",{containerId:process.env.MODELENCE_CONTAINER_ID})}async function D(t,e,n){let{MODELENCE_SERVICE_ENDPOINT:r,MODELENCE_SERVICE_TOKEN:o}=process.env;if(!r)throw new Error("Unable to connect to Modelence Cloud: MODELENCE_SERVICE_ENDPOINT is not set");let i=await fetch(`${r}${t}`,{method:e,headers:{Authorization:`Bearer ${o}`,...n?{"Content-Type":"application/json"}:{}},body:n?JSON.stringify(n):void 0});if(!i.ok){let s=await i.text(),a,c=s;try{a=JSON.parse(s);let u=a.error;if(typeof u=="string")c=u;else if(u&&typeof u=="object"){let p=u.message;typeof p=="string"&&(c=p);}}catch{}let l=new Error(`Unable to connect to Modelence Cloud: HTTP status: ${i.status}, ${c}`);throw a!==void 0&&(l.responseBody=a),l.status=i.status,l}if(!(i.status===204||i.headers?.get("content-length")==="0"))return await i.json()}var mt=false,io=a.seconds(10);function In(){setInterval(async()=>{if(!mt){mt=true;try{await Mn();}catch(t){console.error("Error syncing status",t);}try{await so();}catch(t){console.error("Error syncing config",t);}mt=false;}},io);}function pt(t){c(t),c(Le(d$2(),"withRemoteServer"));}async function so(){let{configs:t}=await _n();pt(t);}var Q=new T("_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 Y={},Dn=a.seconds(10),Un=randomBytes(32).toString("base64url"),lo=a.seconds(30),oe=new Map,ft=t=>t instanceof MongoError&&t.code===11e3,Pn=(t,e)=>typeof t.keyPattern=="object"&&t.keyPattern!==null&&Object.prototype.hasOwnProperty.call(t.keyPattern,e),uo=async({error:t,resource:e})=>{if(Pn(t,"resource"))return true;if(Pn(t,"_id"))return false;let n=await Q.findOne({resource:e});return !!n&&n._id!==e},Nn=async({resource:t,staleThresholdDate:e,instanceId:n})=>{let r=await Q.upsertOne({_id:t,$or:[{instanceId:n},{acquiredAt:{$lt:e}}]},{$set:{resource:t,instanceId:n,acquiredAt:new Date},$setOnInsert:{_id:t}});return r.upsertedCount>0||r.modifiedCount>0},$n=async({resource:t,instanceId:e,staleThresholdDate:n})=>{let r=n?{resource:t,_id:{$ne:t},$or:[{instanceId:e},{acquiredAt:{$lt:n}}]}:{resource:t,instanceId:e};return (await Q.deleteOne(r)).deletedCount>0},mo=t=>{let e=t,n=oe.get(e);n&&(n.stopRequested=true,n.timer&&(clearTimeout(n.timer),n.timer=null),oe.delete(e));},Ln=({resource:t,lockDuration:e,instanceId:n})=>{let r=Math.floor(e/3),o=t,i$1=oe.get(o);if(i$1&&!i$1.stopRequested&&i$1.heartbeatInterval===r&&i$1.lockDuration===e)return;i$1&&(i$1.stopRequested=true,i$1.timer&&(clearTimeout(i$1.timer),i$1.timer=null),oe.delete(o));let s={timer:null,stopRequested:false,lockDuration:e,heartbeatInterval:r},a=()=>{s.timer=setTimeout(()=>{X(t,{lockDuration:e,bypassCache:true,instanceId:n}).then(c=>{c||(s.stopRequested=true,i(`Lost lock while refreshing heartbeat: ${t}`,{source:"lock",resource:t,instanceId:n}));}).finally(()=>{if(s.stopRequested){oe.delete(o);return}a();});},r);};oe.set(o,s),a();};async function X(t,{lockDuration:e=lo,successfulLockCacheDuration:n=Dn,failedLockCacheDuration:r=Dn,heartbeat:o,bypassCache:i$1,instanceId:s=Un}={}){let a=Date.now();if(!i$1&&Y[t]&&a<Y[t].expiresAt)return Y[t].value&&o&&Ln({resource:t,lockDuration:e,instanceId:s}),Y[t].value;let c=new Date(a-e);i(`Attempting to acquire lock: ${t}`,{source:"lock",resource:t,instanceId:s});try{let l=await po({resource:t,staleThresholdDate:c,instanceId:s});return Y[t]={value:l,expiresAt:a+(l?n:r)},l?(o&&Ln({resource:t,lockDuration:e,instanceId:s}),i(`Lock acquired: ${t}`,{source:"lock",resource:t,instanceId:s})):i(`Failed to acquire lock (already held): ${t}`,{source:"lock",resource:t,instanceId:s}),l}catch{return Y[t]={value:false,expiresAt:a+r},i(`Failed to acquire lock (already held): ${t}`,{source:"lock",resource:t,instanceId:s}),false}}var po=async({resource:t,staleThresholdDate:e,instanceId:n})=>{try{return await Nn({resource:t,staleThresholdDate:e,instanceId:n})}catch(r){if(ft(r)&&await uo({error:r,resource:t})){if(!await $n({resource:t,staleThresholdDate:e,instanceId:n}))return false;try{return await Nn({resource:t,staleThresholdDate:e,instanceId:n})}catch(i){if(ft(i))return false;throw i}}if(ft(r))return false;throw r}};async function he(t,{instanceId:e=Un}={}){mo(t);try{let n=await Q.deleteOne({_id:t,instanceId:e});return n.deletedCount===0?await $n({resource:t,instanceId:e}):n.deletedCount>0}catch{return false}finally{delete Y[t];}}var ee={},ht=null,gt=new T("_modelenceCronJobs",{schema:{alias:d.string(),lastStartDate:d.date().optional()},indexes:[{key:{alias:1},unique:true,background:true}]});function Fn(t,{description:e="",interval:n,timeout:r=Math.min(Math.max(n,a.minutes(1)),a.days(1)),handler:o}){if(ee[t])throw new Error(`Duplicate cron job declaration: '${t}' already exists`);if(ht)throw new Error(`Unable to add a cron job - cron jobs have already been initialized: [${t}]`);if(n<a.seconds(5))throw new Error(`Cron job interval should not be less than 5 second [${t}]`);if(r>a.days(1))throw new Error(`Cron job timeout should not be longer than 1 day [${t}]`);ee[t]={alias:t,params:{description:e,interval:n,timeout:r},handler:o,state:{isRunning:false}};}async function zn(){if(ht)throw new Error("Cron jobs already started");let t=Object.keys(ee);if(t.length>0){let e={alias:{$in:t}},n=await gt.fetch(e),r=Date.now();n.forEach(o=>{let i=ee[o.alias];i&&(i.state.scheduledRunTs=o.lastStartDate?o.lastStartDate.getTime()+i.params.interval:r);}),Object.values(ee).forEach(o=>{o.state.scheduledRunTs||(o.state.scheduledRunTs=r);}),ht=setInterval(fo,a.seconds(1));}}async function fo(){let t=Date.now();await X("cron",{successfulLockCacheDuration:a.seconds(10),failedLockCacheDuration:a.seconds(30)})&&Object.values(ee).forEach(async n=>{let{params:r,state:o}=n;if(o.isRunning){o.startTs&&o.startTs+r.timeout<t&&(o.isRunning=false);return}o.scheduledRunTs&&o.scheduledRunTs<=t&&await ho(n);});}async function ho(t){let{alias:e,params:n,handler:r,state:o}=t;o.isRunning=true,o.startTs=Date.now(),await gt.updateOne({alias:e},{$set:{lastStartDate:new Date(o.startTs)}});let i=l("cron",`cron:${e}`);try{await r(),jn(o,n),i.end("success");}catch(s){jn(o,n);let a=s instanceof Error?s:new Error(String(s));m(a),i.end("error"),console.error(`Error in cron job '${e}':`,s);}}function jn(t,e){t.scheduledRunTs=t.startTs?t.startTs+e.interval:Date.now(),t.startTs=void 0,t.isRunning=false;}function qn(){return Object.values(ee).map(({alias:t,params:e})=>({alias:t,description:e.description,interval:e.interval,timeout:e.timeout}))}var Zn=new C("_system.cron",{stores:[gt]});function Hn(t){let e=[...new Set(t)],n=new Map;for(let i of e){let s=i.getChainRoot();n.set(s,s.getChainTail());}let r=[...new Set(n.values())],o=new Map;for(let[i,s]of n){let a=s.getName(),c=o.get(a);if(c!==void 0&&c!==i)throw new Error(`Store collision: multiple unrelated stores use collection name '${a}'. Use .extend() to create a single extension chain instead of independent stores.`);o.set(a,i);}return {storesToInit:e,effectiveStores:r}}var yt=new C("_system.lock",{stores:[Q]});var ge=new T("_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 wt(t,{lockMode:e="acquire"}={}){if(t.length!==0){if(e==="acquire"&&!await X("migrations")){j$1("Another instance is running migrations. Skipping migration run.",{source:"migrations"});return}try{let n=t.map(({version:s})=>s),r=await ge.fetch({version:{$in:n}}),o=new Set(r.map(({version:s})=>s)),i=t.filter(({version:s})=>!o.has(s));if(i.length===0)return;j$1(`Running migrations (${i.length})...`,{source:"migrations"});for(let{version:s,description:a,handler:c}of i){j$1(`Running migration v${s}: ${a}`,{source:"migrations"});try{let u=(await c()||"").toString().trim(),p=15*1024*1024,m=u.length>p?u.slice(0,p)+`
|
|
17
|
+
[Output truncated - exceeded size limit]`:u;await ge.upsertOne({version:s},{$set:{version:s,status:"completed",description:a,output:m,appliedAt:new Date}}),j$1(`Migration v${s} complete`,{source:"migrations"});}catch(l){l instanceof Error&&(await ge.upsertOne({version:s},{$set:{version:s,status:"failed",description:a,output:l.message||"",appliedAt:new Date}}),j$1(`Migration v${s} is failed: ${l.message}`,{source:"migrations"}));}}}finally{e==="acquire"&&await he("migrations");}}}function Wn(t){setTimeout(()=>{wt(t).catch(e=>{console.error("Error running migrations:",e);});},0);}var Vn=new C("_system.migration",{stores:[ge]});var Bn=new C("_system.rateLimit",{stores:[fe]});async function Gn({filePath:t,contentType:e,visibility:n}){return await D("/api/files/upload","POST",{filePath:t,contentType:e,visibility:n})}async function Kn(t){await D("/api/files/delete","POST",{filePath:t});}async function Jn(t){return await D("/api/files/download","POST",{filePath:t})}async function Qn(t){return await D("/api/files/url","POST",{filePath:t})}var Yn=new C("_system.files",{queries:{async downloadFile({filePath:t}){return Jn(t)},async getFileUrl({filePath:t}){return Qn(t)}},mutations:{async getUploadUrl({filePath:t,contentType:e,visibility:n}){return Gn({filePath:t,contentType:e,visibility:n})},async deleteFile({filePath:t}){return Kn(t)}}});var St=class{async init({httpServer:e}){this.config=await Eo(this.isDev()?e:void 0),this.isDev()&&(console.log("Starting Vite dev server..."),this.viteServer=await createServer(this.config));}middlewares(){if(this.isDev())return this.viteServer?.middlewares??[];let e=[H.static("./.modelence/build/client".replace(/\\/g,"/"))];return this.config?.publicDir&&e.push(H.static(this.config.publicDir)),e}handler(e,n){if(this.isDev())try{n.setHeader("Cache-Control","no-store"),n.sendFile("index.html",{root:"./src/client"});}catch(r){console.error("Error serving index.html:",r),n.status(500).send("Internal Server Error");}else n.sendFile("index.html",{root:"./.modelence/build/client".replace(/\\/g,"/")});}isDev(){return process.env.NODE_ENV!=="production"}};async function Co(){let t=process.cwd();try{return (await loadConfigFromFile({command:"serve",mode:"development"},void 0,t))?.config||{}}catch(e){return console.warn("Could not load vite config:",e),{}}}function vo(t,e){let n=mergeConfig(t,e);if(n.plugins&&Array.isArray(n.plugins)){let r=new Set;n.plugins=n.plugins.flat().filter(o=>{if(!o||typeof o!="object"||Array.isArray(o))return true;let i=o.name;return !i||r.has(i)?false:(r.add(i),true)}).reverse(),n.plugins.reverse();}return n}async function Eo(t){let e=process.cwd(),n=await Co(),r=[".eslintrc.js",".eslintrc.json",".eslintrc","eslint.config.js",".eslintrc.yml",".eslintrc.yaml"].find(s=>xo.existsSync(bt.join(e,s))),o=[So(),To()];if(r){let s=(await import('vite-plugin-eslint')).default;o.push(s({failOnError:false,include:["src/**/*.js","src/**/*.jsx","src/**/*.ts","src/**/*.tsx"],cwd:e,overrideConfigFile:bt.resolve(e,r)}));}let i=defineConfig({plugins:o,build:{outDir:".modelence/build/client".replace(/\\/g,"/"),emptyOutDir:true},server:{middlewareMode:true,hmr:t?{server:t}:void 0},root:"./src/client",resolve:{alias:{"@":bt.resolve(e,"src").replace(/\\/g,"/")}}});return vo(i,n)}function To(){return {name:"modelence-asset-handler",async transform(t,e){if(/\.(png|jpe?g|gif|svg|mpwebm|ogg|mp3|wav|flac|aac)$/.test(e))return process.env.NODE_ENV==="development",t}}}var er=new St;function S(t,e,n){let r=v(),o=t.status(e);if(r.errorComponent)try{let i=r.errorComponent({error:n,statusCode:e});if(i)return o.send(i)}catch(i){console.error("Unhandled error in authConfig.errorComponent:",i);}return o.json({error:n})}async function xt(t,e){let{authToken:n}=await ce(e);ke(t,n),t.status(302),t.redirect("/");}async function Ao(t,e,n,r,o){let i=v();try{if(n.status==="disabled"||n.status==="deleted"){S(t,400,"User account is not active.");return}let s={};n.firstName===void 0&&e.firstName&&(s.firstName=e.firstName),n.lastName===void 0&&e.lastName&&(s.lastName=e.lastName),n.avatarUrl===void 0&&e.avatarUrl&&(s.avatarUrl=e.avatarUrl);let a=n;Object.keys(s).length>0&&(await f.updateOne({_id:n._id},{$set:s}),a={...n,...s}),await xt(t,n._id),i.onAfterLogin?.({provider:e.providerName,user:a,session:r,connectionInfo:o}),i.login?.onSuccess?.(a);}catch(s){throw s instanceof Error&&(i.login?.onError?.(s),i.onLoginError?.({provider:e.providerName,error:s,session:r,connectionInfo:o})),s}}async function Oo(t,e,n,r,o){let i=v();if((i.oauthAccountLinking??"manual")==="auto"&&e.emailVerified){if(n.status==="disabled"||n.status==="deleted"){S(t,400,"User account is not active.");return}if(!n.emails?.find(c=>c.address.toLowerCase()===e.email.toLowerCase())?.verified){S(t,400,"User with this email already exists. Please log in instead.");return}try{let c={...n.firstName===void 0&&e.firstName&&{firstName:e.firstName},...n.lastName===void 0&&e.lastName&&{lastName:e.lastName},...n.avatarUrl===void 0&&e.avatarUrl&&{avatarUrl:e.avatarUrl}};if(!((await f.updateOne({_id:n._id,status:{$nin:["deleted","disabled"]},$or:[{[`authMethods.${e.providerName}.id`]:{$exists:!1}},{[`authMethods.${e.providerName}.id`]:e.id}]},{$set:{[`authMethods.${e.providerName}.id`]:e.id,...c}})).matchedCount>0)){S(t,400,"User with this email already exists. Please log in instead.");return}await xt(t,n._id);let p={...n,...c,authMethods:{...n.authMethods,[e.providerName]:{id:e.id}}};i.onAfterLogin?.({provider:e.providerName,user:p,session:r,connectionInfo:o}),i.login?.onSuccess?.(p);return}catch(c){throw c instanceof Error&&(i.login?.onError?.(c),i.onLoginError?.({provider:e.providerName,error:c,session:r,connectionInfo:o})),c}}S(t,400,"User with this email already exists. Please log in instead.");}async function Ro(t,e,n,r){let o=v();try{let i;if(o.generateHandle){let l=await o.generateHandle({email:e.email,firstName:e.firstName,lastName:e.lastName});i=await J(l,e.email,{throwOnConflict:!1});}else i=await J(void 0,e.email);let s={handle:i,status:"active",emails:[{address:e.email,verified:e.emailVerified}],createdAt:new Date,authMethods:{[e.providerName]:{id:e.id}},...e.firstName!==void 0&&{firstName:e.firstName},...e.lastName!==void 0&&{lastName:e.lastName},...e.avatarUrl!==void 0&&{avatarUrl:e.avatarUrl}},a=await f.insertOne(s);await xt(t,a.insertedId);let c=await f.findOne({_id:a.insertedId},{readPreference:"primary"});c&&(o.onAfterSignup?.({provider:e.providerName,user:c,session:n,connectionInfo:r}),o.signup?.onSuccess?.(c));}catch(i){throw i instanceof Error&&(o.onSignupError?.({provider:e.providerName,error:i,session:n,connectionInfo:r}),o.signup?.onError?.(i)),i}}function se(t){return `${a$1("_system.site.url")}/api/_internal/auth/${t}/callback`}async function Ue(t,e,n){let r=await f.findOne({[`authMethods.${n.providerName}.id`]:n.id}),{session:o,connectionInfo:i}=await ye(t,e);if(r)return Ao(e,n,r,o,i);if(!n.email){S(e,400,`Email address is required for ${n.providerName} authentication.`);return}let s;try{s=await f.findOne({"emails.address":n.email,status:{$ne:"deleted"}},{collation:{locale:"en",strength:2}});}catch(a){if(a instanceof Error){let c=v();c.onSignupError?.({provider:n.providerName,error:a,session:o,connectionInfo:i}),c.signup?.onError?.(a);}throw a}return s?Oo(e,n,s,o,i):Ro(e,n,o,i)}function R(t){t.cookie("oauthLinkToken","",{httpOnly:true,maxAge:0,path:"/api/_internal/auth/",sameSite:"lax",secure:process.env.NODE_ENV==="production"});}function ie(t){if(t)try{t();}catch(e){console.error("Error executing OAuth hook:",e);}}function $e(t,e,n){let r=t.query.state,o=t.cookies[n],[i,s]=(o||"").split(":");return !r||!o||r!==i?(S(e,400,"Invalid OAuth state - possible CSRF attack"),null):(e.clearCookie(n),s||"login")}async function je(t,e,n){let r=v(),{session:o,connectionInfo:i}=await ye(t,e);if(!o?.userId){R(e),S(e,401,"You must be signed in to link a provider.");return}let s=o.userId;try{let a=`authMethods.${n.providerName}.id`;if((await f.updateOne({_id:s,status:{$nin:["deleted","disabled"]},$or:[{[a]:{$exists:!1}},{[a]:n.id}]},{$set:{[a]:n.id}})).matchedCount===0){let u=await f.findOne({_id:s});if(!u||u.status==="deleted"||u.status==="disabled"){ie(()=>r.onOAuthLinkError?.({provider:n.providerName,error:new Error("User account not found or not active"),session:o,connectionInfo:i})),R(e),S(e,400,"User account is not active.");return}let p=u?.authMethods?.[n.providerName]?.id;if(p&&p!==n.id){ie(()=>r.onOAuthLinkError?.({provider:n.providerName,error:new Error(`User already has a different ${n.providerName} account linked`),session:o,connectionInfo:i})),R(e),S(e,400,`You have already linked a different ${n.providerName} account.`);return}ie(()=>r.onOAuthLinkError?.({provider:n.providerName,error:new Error(`Unexpected OAuth linking state for ${n.providerName}`),session:o,connectionInfo:i})),R(e),S(e,400,`Unable to link ${n.providerName} account.`);return}let l=await f.findOne({_id:s},{readPreference:"primary"});l&&ie(()=>r.onAfterOAuthLink?.({provider:n.providerName,user:l,session:o,connectionInfo:i})),R(e),e.status(302).redirect("/");}catch(a){if(a instanceof MongoServerError&&a.code===11e3){ie(()=>r.onOAuthLinkError?.({provider:n.providerName,error:a,session:o,connectionInfo:i})),R(e),S(e,400,`This ${n.providerName} account is already linked to a different user.`);return}if(a instanceof Error&&ie(()=>r.onOAuthLinkError?.({provider:n.providerName,error:a,session:o,connectionInfo:i})),R(e),!e.headersSent)throw a}}function Fe(t){return !t||typeof t!="string"?null:t}async function Io(t,e,n,r){let o=await fetch("https://oauth2.googleapis.com/token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({code:t,client_id:e,client_secret:n,redirect_uri:r,grant_type:"authorization_code"})});if(!o.ok)throw new Error(`Failed to exchange code for token: ${o.statusText}`);return o.json()}async function Do(t){let e=await fetch("https://www.googleapis.com/oauth2/v2/userinfo",{headers:{Authorization:`Bearer ${t}`}});if(!e.ok)throw new Error(`Failed to fetch user info: ${e.statusText}`);return e.json()}async function Po(t,e){let n=Fe(t.query.code);if(!n){S(e,400,"Missing authorization code");return}let r=$e(t,e,"authStateGoogle");if(!r)return;let o=String(a$1("_system.user.auth.google.clientId")),i=String(a$1("_system.user.auth.google.clientSecret")),s=se("google");try{let a=await Io(n,o,i,s),c=await Do(a.access_token),l={id:c.id,email:c.email,emailVerified:c.verified_email,providerName:"google",firstName:c.given_name||void 0,lastName:c.family_name||void 0,avatarUrl:c.picture||void 0};r==="link"?await je(t,e,l):await Ue(t,e,l);}catch(a){console.error("Google OAuth error:",a),r==="link"&&R(e),S(e,500,"Authentication failed");}}function No(){let t=Router(),e=(n,r,o)=>{let i=!!a$1("_system.user.auth.google.enabled"),s=String(a$1("_system.user.auth.google.clientId")),a=String(a$1("_system.user.auth.google.clientSecret"));if(!i||!s||!a){S(r,503,"Google authentication is not configured");return}o();};return t.get("/api/_internal/auth/google",e,(n,r)=>{let o=String(a$1("_system.user.auth.google.clientId")),i=se("google"),s=randomBytes(32).toString("hex"),a$2=n.query.mode==="link"?"link":"login";r.cookie("authStateGoogle",`${s}:${a$2}`,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",maxAge:a.minutes(10)});let c=new URL("https://accounts.google.com/o/oauth2/v2/auth");c.searchParams.append("client_id",o),c.searchParams.append("redirect_uri",i),c.searchParams.append("response_type","code"),c.searchParams.append("scope","profile email"),c.searchParams.append("access_type","online"),c.searchParams.append("state",s),r.redirect(c.toString());}),t.get("/api/_internal/auth/google/callback",e,Po),t}var tr=No;async function $o(t,e,n,r){let o=await fetch("https://github.com/login/oauth/access_token",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({client_id:e,client_secret:n,code:t,redirect_uri:r})});if(!o.ok)throw new Error(`Failed to exchange code for token: ${o.statusText}`);return o.json()}async function jo(t){let e=await fetch("https://api.github.com/user",{headers:{Authorization:`Bearer ${t}`,Accept:"application/vnd.github.v3+json"}});if(!e.ok)throw new Error(`Failed to fetch user info: ${e.statusText}`);return e.json()}async function Fo(t){let e=await fetch("https://api.github.com/user/emails",{headers:{Authorization:`Bearer ${t}`,Accept:"application/vnd.github.v3+json"}});if(!e.ok)throw new Error(`Failed to fetch user emails: ${e.statusText}`);return e.json()}async function zo(t,e){return t.email?t.email:(await Fo(e)).find(r=>r.primary&&r.verified)?.email??null}async function qo(t,e){let n=Fe(t.query.code);if(!n){S(e,400,"Missing authorization code");return}let r=$e(t,e,"authStateGithub");if(!r)return;let o=String(a$1("_system.user.auth.github.clientId")),i=String(a$1("_system.user.auth.github.clientSecret")),s=se("github");try{let a=await $o(n,o,i,s),c=await jo(a.access_token),l=await zo(c,a.access_token);if(!l){r==="link"&&R(e),S(e,400,"Unable to retrieve a primary verified email from GitHub. Please ensure your GitHub account has a verified email set as primary.");return}let u=c.name?c.name.trim().split(/\s+/):[],p=u[0]||void 0,m=u.length>1?u.slice(1).join(" "):void 0,y={id:String(c.id),email:l,emailVerified:!0,providerName:"github",firstName:p,lastName:m,avatarUrl:c.avatar_url||void 0};r==="link"?await je(t,e,y):await Ue(t,e,y);}catch(a){console.error("GitHub OAuth error:",a),r==="link"&&R(e),S(e,500,"Authentication failed");}}function Zo(){let t=Router(),e=(n,r,o)=>{let i=!!a$1("_system.user.auth.github.enabled"),s=String(a$1("_system.user.auth.github.clientId")),a=String(a$1("_system.user.auth.github.clientSecret"));if(!i||!s||!a){S(r,503,"GitHub authentication is not configured");return}o();};return t.get("/api/_internal/auth/github",e,(n,r)=>{let o=String(a$1("_system.user.auth.github.clientId")),i=se("github"),s=a$1("_system.user.auth.github.scopes"),a$2=s?String(s).split(",").map(p=>p.trim()).join(" "):"user:email",c=randomBytes(32).toString("hex"),l=n.query.mode==="link"?"link":"login";r.cookie("authStateGithub",`${c}:${l}`,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",maxAge:a.minutes(10)});let u=new URL("https://github.com/login/oauth/authorize");u.searchParams.append("client_id",o),u.searchParams.append("redirect_uri",i),u.searchParams.append("scope",a$2),u.searchParams.append("state",c),r.redirect(u.toString());}),t.get("/api/_internal/auth/github/callback",e,qo),t}var nr=Zo;function rr(t,e,n){return async(r,o,i)=>{let s=r.headers["x-modelence-auth-token"],a={session:null,user:null};if(typeof s=="string"&&G())try{let{session:l,user:u}=await N(s);a={session:l,user:u};}catch{}let c=l("route",`route:${t.toLowerCase()}:${e}`,{method:t,path:e,query:r.query,body:r.body,params:r.params});try{let l=await n({query:r.query,body:r.body,params:r.params,headers:r.headers,cookies:r.cookies,rawBody:Buffer.isBuffer(r.body)?r.body:void 0,req:r,res:o,next:i},a);c.end(),l&&(o.status(l.status||200),l.redirect&&o.redirect(l.redirect),l.headers&&Object.entries(l.headers).forEach(([u,p])=>{o.setHeader(u,p);}),o.send(l.data));}catch(l){c.end("error"),l instanceof a$3?o.status(l.status).send(l.message):(console.error(`Error in route handler: ${r.path}`),console.error(l),o.status(500).send(String(l)));}}}var Ct=Object.freeze({});function or(t){Ct=Object.freeze(Object.assign({},Ct,t));}function ir(){return Ct}var vt=Object.freeze({});function sr(t){vt=Object.freeze(Object.assign({},vt,t));}function ze(){return vt}function Vo(t){let e=[];if(!t)return e.push(H.json({limit:"16mb"})),e.push(H.urlencoded({extended:true,limit:"16mb"})),e;if(t.json!==false){let n=typeof t.json=="object"?t.json:{limit:"16mb"};e.push(H.json(n));}if(t.urlencoded!==false){let n=typeof t.urlencoded=="object"?t.urlencoded:{extended:true,limit:"16mb"};e.push(H.urlencoded(n));}if(t.raw){let n=typeof t.raw=="object"?t.raw:{},r={limit:n.limit||"16mb",type:n.type||"*/*"};e.push(H.raw(r));}return e}function Bo(t,e){for(let n of e)for(let r of n.routes){let{path:o,handlers:i,body:s}=r,a=Vo(s);Object.entries(i).forEach(([c,l])=>{t[c](o,...a,rr(c,o,l));});}}async function ar(t,{combinedModules:e,channels:n}){let r=H();r.use(Ho()),r.use(Jo()),Bo(r,e),r.use(H.json({limit:"16mb"})),r.use(H.urlencoded({extended:true,limit:"16mb"})),r.use(tr()),r.use(nr()),r.post("/api/_internal/auth/set-link-cookie",async(a,c)=>{let{session:l}=await ye(a,c);if(!l?.userId){c.status(401).json({error:"Not authenticated"});return}c.cookie("oauthLinkToken",l.authToken,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:"/api/_internal/auth/",maxAge:10*60*1e3}),c.json({ok:true});}),r.post("/api/_internal/method/:methodName(*)",async(a,c)=>{let l=a.params.methodName,u=await ye(a,c);try{let p=a$2(await tn(l,a.body.args,u));c.json({data:p,typeMap:b$1(p)});}catch(p){Go(c,l,p);}});let o=Wo.createServer(r);await t.init({httpServer:o}),t.middlewares&&r.use(t.middlewares()),r.all("*",(a,c)=>t.handler(a,c)),process.on("unhandledRejection",(a,c)=>{console.error("Unhandled Promise Rejection:"),console.error(a instanceof Error?a.stack:a),console.error("Promise:",c);}),process.on("uncaughtException",a=>{console.error("Uncaught Exception:"),console.error(a.stack),console.trace("Full application stack:");});let i=ze()?.provider;i&&i.init({httpServer:o,channels:n});let s=process.env.MODELENCE_PORT||process.env.PORT||3e3;o.listen(s,()=>{j$1("Application started",{source:"app"});let a=a$1("_system.site.url")||`http://localhost:${s}`;console.log(`
|
|
18
|
+
Application started on ${a}
|
|
19
|
+
`);});}async function ye(t,e){let n=(t.path??t.url??"").split("?")[0],r=n.startsWith("/api/_internal/auth/")&&n.endsWith("/callback"),o=Z.string().nullish().transform(c=>c??null).parse(t.cookies.authToken||(r?t.cookies.oauthLinkToken:null)||t.body.authToken),i=Z.object({screenWidth:Z.number(),screenHeight:Z.number(),windowWidth:Z.number(),windowHeight:Z.number(),pixelRatio:Z.number(),orientation:Z.string().nullable()}).nullish().parse(t.body.clientInfo)??{screenWidth:0,screenHeight:0,windowWidth:0,windowHeight:0,pixelRatio:1,orientation:null},s={ip:Qo(t),userAgent:t.get("user-agent"),acceptLanguage:t.get("accept-language"),referrer:t.get("referrer"),baseUrl:t.protocol+"://"+t.get("host")};if(!!G()){let{session:c,user:l,roles:u}=await N(o);return {clientInfo:i,connectionInfo:s,session:c,user:l,roles:u,req:t,res:e}}return {clientInfo:i,connectionInfo:s,session:null,user:null,roles:Ae(),req:t,res:e}}function Go(t,e,n){if(n instanceof a$3){n.status>=500&&n.status<600&&console.error(`Error calling ${e}:`,n),t.status(n.status).send(n.message);return}if(n instanceof Error&&n?.constructor?.name==="ZodError"&&"errors"in n){let r="";try{r=Ko(n);}catch(o){console.error(`Error parsing Zod error in ${e}:`,o),r="Validation failed";}t.status(400).send(r);return}console.error(`Error calling ${e}:`,n),t.status(500).send(n instanceof Error?n.message:String(n));}function Ko(t){let e=t.flatten(),n=Object.entries(e.fieldErrors).map(([i,s])=>`${i}: ${(s??[]).join(", ")}`),r=e.formErrors;return [...n,...r].filter(Boolean).join("; ")}function Jo(){let{frameAncestors:t}=ir(),e=t&&t.length>0,n=e?["'self'",...t].join(" "):"'self'";return (r,o,i)=>{o.setHeader("Content-Security-Policy",`frame-ancestors ${n}`),e||o.setHeader("X-Frame-Options","SAMEORIGIN"),i();}}function Qo(t){let e=t.headers["x-forwarded-for"];if(e)return (Array.isArray(e)?e[0]:e.split(",")[0]).trim();let n=t.ip||t.socket?.remoteAddress;if(n)return n.startsWith("::ffff:")?n.substring(7):n}function Yo(t){return t?t.match(/^\s*"?([^"<]+?)"?\s*<[^>]+>\s*$/)?.[1]?.trim():void 0}function Xo(t){if(t)return Array.isArray(t)?t:[t]}function ei(t){return {to:Array.isArray(t.to)?t.to:[t.to],subject:t.subject,html:t.html,text:t.text,fromName:Yo(t.from),replyTo:Xo(t.replyTo)}}function ti(t){if(!(t instanceof Error))return new Error("Managed email send failed");let e=t.responseBody,n=e?.error?.code,r=e?.error?.message;return n&&r?new Error(`Managed email rejected (${n}): ${r}`):t}var cr={async sendEmail(t){if(t.cc||t.bcc||t.attachments||t.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 D("/api/email/send","POST",ei(t));}catch(e){throw ti(e)}}};async function ii({modules:t=[],roles:e$1={},defaultRoles:n={},server:r=er,migrations:o=[],email:i={},auth:s={},security:a={},websocket:c$1={}}){lr.config(),lr.config({path:".modelence.env"});let l=!!process.env.MODELENCE_SERVICE_ENDPOINT;gi().then(()=>{}).catch(()=>{});let u=[ut,Wt,Zn,Vn,Bn,de,yt,Yn],p=[...u,...t];f$1(),ai(u),si(t),Bt(e$1,n);let m=pi(p);e(m);let y=ci(p),g$1=li(p);fi(p),ut.rateLimits=dt(s.rateLimits);let E=di(p);xn(E);let{storesToInit:L,effectiveStores:O}=Hn(y);if(l){let{configs:A,environmentId:W,appAlias:_,environmentAlias:ur,telemetry:mr}=await Rn({configSchema:m,cronJobsMetadata:qn(),stores:O,roles:e$1});pt(A),g({environmentId:W,appAlias:_,environmentAlias:ur,telemetry:mr});}else c(Le(m));if(l&&!i.provider?rt({...i,provider:cr}):rt(i),fn(s),or(a),sr({...c$1,provider:c$1.provider||on}),G()){await Kt();let A=[...new Set([...L,...O])];hi(A),await mi(O,o);}else Wn(o);l&&(await h(),In()),zn().catch(console.error),await ar(r,{combinedModules:p,channels:g$1});}function si(t){for(let e of t){for(let[n,r]of Object.entries(e.queries))Qe(`${e.name}.${n}`,r);for(let[n,r]of Object.entries(e.mutations))Jt(`${e.name}.${n}`,r);}}function ai(t){for(let e of t){for(let[n,r]of Object.entries(e.queries))Qt(`${e.name}.${n}`,r);for(let[n,r]of Object.entries(e.mutations))Yt(`${e.name}.${n}`,r);}}function ci(t){return t.flatMap(e=>e.stores)}function li(t){return t.flatMap(e=>e.channels)}function di(t){return t.flatMap(e=>e.rateLimits)}function ui(t,e){console.warn(`Failed to create indexes for store '${t}'. Continuing startup.`,e);}var Et="migrations";async function mi(t,e){if(!await X(Et,{lockDuration:a.seconds(30),heartbeat:true}))return;let r,o;try{r=t.filter(a=>a.getIndexCreationMode()==="blocking"),o=t.filter(a=>a.getIndexCreationMode()==="background");for(let a of r)await Tt(a,"full");for(let a of o)await Tt(a,"drop-only");}catch(a){throw await he(Et),a}let i=(async()=>{for(let a of o)await Tt(a,"create-only");})(),s=wt(e,{lockMode:"skip"});Promise.allSettled([i,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 he(Et);});}async function Tt(t,e="full"){let n=t.getName();try{await t.createIndexes(e);}catch(r){ui(n,r);}}function pi(t){let e={};for(let n of t)for(let[r,o]of Object.entries(n.configSchema)){let i=`${n.name}.${r}`;if(i in e)throw new Error(`Duplicate config schema key: ${i} (${n.name})`);e[i]=o;}return e}function fi(t){for(let e of t)for(let[n,r]of Object.entries(e.cronJobs))Fn(`${e.name}.${n}`,r);}function hi(t){let e=Oe();if(!e)throw new Error("Failed to initialize stores: MongoDB client not initialized");for(let n of t)n.init(e);}async function gi(){if(process.env.MODELENCE_TRACKING_ENABLED!=="false"){let e=process.env.MODELENCE_SERVICE_ENDPOINT??"https://cloud.modelence.com",n=process.env.MODELENCE_ENVIRONMENT_ID,r=await yi(),o=await import('./package-5JKWTBGJ.js');await fetch(`${e}/api/track/app-start`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({projectName:r.name,version:o.default.version,localHostname:oo.hostname(),environmentId:n})});}}async function yi(){try{let t=bt.join(process.cwd(),"package.json"),e=await ni.readFile(t,"utf-8");return {name:JSON.parse(e).name||"unknown"}}catch{return {name:"unknown"}}}async function dr(t){await j.deleteMany({userId:t}),await P.deleteMany({userId:t});}async function bi(t){await dr(t),await f.updateOne(t,{$set:{status:"disabled",disabledAt:new Date}});}async function Si(t){await dr(t),await f.updateOne({_id:t},{$set:{handle:`deleted-${t}-${randomUUID()}`,status:"deleted",deletedAt:new Date,authMethods:{},emails:[]}});}var kt=class{constructor(e,n){this.category=e,this.canAccessChannel=n||null;}broadcast(e,n){let r=ze().provider;if(!r){k("Websockets provider should be added to startApp",{});return}r.broadcast({category:this.category,id:e,data:n});}};function xi(t){if(!x().provider)throw new Error("Email provider is not configured, see https://docs.modelence.com/email for more details.");return x().provider?.sendEmail(t)}
|
|
20
|
+
export{re as LiveData,C as Module,kt as ServerChannel,T as Store,N as authenticate,M as consumeRateLimit,Qe as createQuery,f as dbUsers,Kn as deleteFile,Si as deleteUser,bi as disableUser,Jn as downloadFile,Qn as getFileUrl,Gn as getUploadUrl,d as schema,xi as sendEmail,ii as startApp};//# sourceMappingURL=server.js.map
|
|
2
21
|
//# sourceMappingURL=server.js.map
|