modelence 0.18.0-dev.1 → 0.18.0-dev.3
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 +1 -1
- package/dist/bin/modelence.js.map +1 -1
- package/dist/chunk-C26FT6MS.js +19 -0
- package/dist/chunk-C26FT6MS.js.map +1 -0
- package/dist/chunk-DRDY7GOT.js +2 -0
- package/dist/chunk-DRDY7GOT.js.map +1 -0
- package/dist/chunk-GZI4X3CV.js +3 -0
- package/dist/chunk-GZI4X3CV.js.map +1 -0
- package/dist/chunk-Q3SEQPTY.js +3 -0
- package/dist/chunk-Q3SEQPTY.js.map +1 -0
- package/dist/chunk-R6OOTUGO.js +2 -0
- package/dist/chunk-R6OOTUGO.js.map +1 -0
- package/dist/chunk-SABBG2XG.js +2 -0
- package/dist/chunk-SABBG2XG.js.map +1 -0
- package/dist/{chunk-S77LRZU6.js → chunk-X6CSJYLY.js} +2 -2
- package/dist/{chunk-S77LRZU6.js.map → chunk-X6CSJYLY.js.map} +1 -1
- package/dist/client.d.ts +34 -2
- package/dist/client.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/{package-XQQF6NGT.js → package-2YZCMUAD.js} +2 -2
- package/dist/{package-XQQF6NGT.js.map → package-2YZCMUAD.js.map} +1 -1
- package/dist/render-DLVPZOA6.js +2 -0
- package/dist/render-DLVPZOA6.js.map +1 -0
- package/dist/renderApp-KKWGQKMM.js +2 -0
- package/dist/{renderApp-3FQ6KUQ2.js.map → renderApp-KKWGQKMM.js.map} +1 -1
- package/dist/server-GBPVLS3G.js +2 -0
- package/dist/{server-JB4DTGBT.js.map → server-GBPVLS3G.js.map} +1 -1
- package/dist/server.d.ts +137 -46
- package/dist/server.js +1 -1
- package/dist/transport-ZSBKZIXH.js +2 -0
- package/dist/{transport-BOPYDAVH.js.map → transport-ZSBKZIXH.js.map} +1 -1
- package/dist/{types-mkbhnQN2.d.ts → types-BT2k9L7Q.d.ts} +2 -2
- package/dist/{types-DV0J5rPI.d.ts → types-DANNMU1V.d.ts} +6 -1
- package/dist/types.d.ts +2 -2
- package/package.json +8 -8
- package/dist/chunk-IJ5BS7PM.js +0 -2
- package/dist/chunk-IJ5BS7PM.js.map +0 -1
- package/dist/chunk-JBTEZOY2.js +0 -2
- package/dist/chunk-JBTEZOY2.js.map +0 -1
- package/dist/chunk-KU4GANYW.js +0 -3
- package/dist/chunk-KU4GANYW.js.map +0 -1
- package/dist/chunk-LDVLXJLS.js +0 -3
- package/dist/chunk-LDVLXJLS.js.map +0 -1
- package/dist/chunk-S2E4OO6G.js +0 -19
- package/dist/chunk-S2E4OO6G.js.map +0 -1
- package/dist/chunk-VFOGVWJK.js +0 -2
- package/dist/chunk-VFOGVWJK.js.map +0 -1
- package/dist/render-57TPXKHI.js +0 -2
- package/dist/render-57TPXKHI.js.map +0 -1
- package/dist/renderApp-3FQ6KUQ2.js +0 -2
- package/dist/server-JB4DTGBT.js +0 -2
- package/dist/transport-BOPYDAVH.js +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/system/index.ts","../src/db/client.ts","../src/websocket/socketio/server.ts","../src/auth/disposableEmails.ts","../src/auth/validators.ts","../src/auth/utils.ts","../src/app/emailConfig.ts","../src/app/authConfig.ts","../src/auth/login.ts","../src/auth/profile.ts","../src/auth/types.ts","../src/auth/unlinkOAuthProvider.ts","../src/rate-limit/db.ts","../src/rate-limit/rules.ts","../src/auth/templates/emailVerficationTemplate.ts","../src/auth/verification.ts","../src/auth/signup.ts","../src/auth/resetPassword.ts","../src/auth/user.ts","../src/config/local.ts","../src/app/backendApi.ts","../src/config/sync.ts","../src/lock/db.ts","../src/lock/helpers.ts","../src/cron/jobs.ts","../src/data/resolveStores.ts","../src/lock/module.ts","../src/migration/db.ts","../src/migration/index.ts","../src/rate-limit/index.ts","../src/files/index.ts","../src/viteServer.ts","../src/app/securityConfig.ts","../src/app/websocketConfig.ts","../src/app/index.ts","../src/auth/deleteUser.ts","../src/websocket/serverChannel.ts","../src/app/email.ts","../src/auth/providers/oauth-common.ts","../src/auth/providers/google.ts","../src/auth/providers/github.ts","../src/routes/handler.ts","../src/app/server.ts"],"names":["system_default","Module","client","connect","mongodbUri","getMongodbUri","maxPoolSize","MongoClient","package_default","err","getClient","socketServer","COLLECTION","ADAPTER_TTL_SECONDS","init","httpServer","channels","mongodbClient","isMultiInstance","getConfig","mongoCollection","error","retryError","SocketServer","createAdapter","socket","next","token","authenticate","handleLiveQueryDisconnect","channelName","category","authorized","channel","payload","handleSubscribeLiveQuery","handleUnsubscribeLiveQuery","broadcast","id","data","server_default","isDisposableEmail","email","emailParts","domain","dbDisposableEmailDomains","updateDisposableEmailListCron","time","response","domains","now","batchSize","i","batch","MIN_HANDLE_LENGTH","MAX_HANDLE_LENGTH","MIN_PASSWORD_LENGTH","MAX_PASSWORD_LENGTH","MAX_EMAIL_LENGTH","trimmedNonEmptyString","opts","z","trimmedOptionalString","val","profileFieldsSchema","validateProfileFields","fields","result","issue","path","msg","validatePassword","value","validateEmail","validateHandle","serializeUserForClient","userDoc","findAvailableHandle","baseHandle","truncatedBase","usersCollection","MAX_SUFFIX_VALUE","suffix","suffixStr","candidate","MAX_RANDOM_ATTEMPTS","attempt","randomSuffix","randomBytes","resolveUniqueHandle","rawHandle","throwOnConflict","handle","emailConfig","setEmailConfig","newEmailConfig","getEmailConfig","authConfig","setAuthConfig","newAuthConfig","getAuthConfig","handleLoginWithPassword","args","user","session","connectionInfo","res","ip","consumeRateLimit","password","passwordHash","incorrectCredentialsError","e","bcrypt","setSessionUser","setAuthTokenCookie","handleLogout","clearSessionUser","clearAuthTokenCookie","getOwnProfile","props","profile","handleUpdateProfile","update","setFields","unsetFields","key","mongoUpdate","clearedFields","SUPPORTED_OAUTH_PROVIDERS","handleUnlinkOAuthProvider","provider","methods","otherMethods","otherMethodGuard","dbRateLimits","Store","schema","allRules","initRateLimits","rateLimits","options","bucket","type","message","rules","rule","createError","RateLimitError","checkRateLimitRule","createRateLimitError","record","currentWindowStart","count","modifier","getCount","prevWindowStart","currentWindowCount","prevWindowCount","prevWindowWeight","weight","emailVerificationTemplate","name","verificationUrl","verifyEmailToken","tokenDoc","emailVerificationTokensCollection","updatedUserDoc","handleVerifyEmail","params","baseUrl","emailVerifiedRedirectUrl","authToken","createSession","sendVerificationEmail","userId","emailProvider","verificationToken","expiresAt","htmlTemplate","textContent","htmlToText","resendVerificationResponse","handleResendEmailVerification","emailDoc","handleSignupWithPassword","signupProps","firstName","lastName","avatarUrl","existingUser","existingEmail","profileFields","resolvedHandle","generated","hash","userDocument","resolveUrl","configuredUrl","defaultPasswordResetTemplate","resetUrl","passwordResetSent","handleSendResetPasswordToken","resetToken","createdAt","resetPasswordTokensCollection","handleResetPassword","resetTokenDoc","invalidateAllUserSessions","warnedLegacyRateLimits","warnLegacyRateLimits","ruleKey","defaultAuthRateLimits","legacyOverridesFor","legacy","v","ipBased","pw","collectOverrides","config","overrides","buckets","buildAuthRateLimits","defaults","overrideByKey","merged","consumed","def","override","user_default","localConfigMap","formatLocalConfigValue","numValue","getConfigsFromEnvMap","configMap","configSchema","configs","envVar","configKey","configSchemaEntry","getLocalConfigs","variant","connectCloudBackend","cronJobsMetadata","stores","roles","containerId","dataStores","store","callApi","os","fetchConfigs","syncStatus","endpoint","method","callCloudApi","body","extraHeaders","MODELENCE_SERVICE_ENDPOINT","MODELENCE_SERVICE_TOKEN","json","isSyncing","SYNC_INTERVAL","startConfigSync","syncConfig","loadRemoteConfigs","loadConfigs","getSchema","locksCollection","lockCache","DEFAULT_CACHE_DURATION","INSTANCE_ID","DEFAULT_LOCK_DURATION","lockHeartbeats","isDuplicateKeyError","MongoError","hasKeyPatternField","field","shouldFallbackToLegacyStrategy","resource","existingLock","tryAcquireLockById","staleThresholdDate","instanceId","deleteLegacyLock","selector","stopLockHeartbeat","heartbeatKey","heartbeat","startLockHeartbeat","lockDuration","heartbeatInterval","existingHeartbeat","scheduleRefresh","acquireLock","isLockAcquired","logDebug","successfulLockCacheDuration","failedLockCacheDuration","bypassCache","acquireLockById","releaseLock","cronJobs","cronJobsInterval","cronJobsCollection","defineCronJob","alias","description","interval","timeout","handler","startCronJobs","aliasList","aliasSelector","cronJobRecords","job","tickCronJobs","state","runCronJob","transaction","startTransaction","handleCronJobCompletion","captureError","getCronJobsMetadata","jobs_default","resolveStores","uniqueStores","rootToTail","root","effectiveStores","nameToRoot","tail","existing","module_default","dbMigrations","runMigrations","migrations","lockMode","logInfo","versions","version","existingVersions","existingVersionSet","pendingMigrations","outputStr","maxSize","truncatedOutput","startMigrations","migration_default","rate_limit_default","getUploadUrl","filePath","contentType","visibility","deleteFile","downloadFile","getFileUrl","files_default","CLIENT_BUILD_DIR","SSR_BUILD_DIR","SSR_ENTRY_VIRTUAL_PATH","ROOT_PLACEHOLDER_REGEX","HEAD_CLOSE_TAG","ViteServer","createServer","installSsrCallMethodTransport","staticFolders","express","req","isDocumentRequest","template","snapshot","renderSsrTreeStream","getCallContext","cssModule","callContext","cssAssets","sendEarlyHints","sessionState","pipe","getQueryState","rawPrelude","rawEpilogue","splitTemplateAtRoot","prelude","injectStylesheets","escapeJsonForScript","url","templatePath","fs","_getSsrSnapshot","pathname","lastSegment","dotIndex","ext","ch","match","epilogue","linksHtml","headCloseIndex","links","target","loadUserViteConfig","appDir","loadConfigFromFile","safelyMergeConfig","baseConfig","userConfig","mergedConfig","mergeConfig","seenPlugins","plugin","pluginName","eslintConfigFile","file","plugins","reactPlugin","modelenceAssetPlugin","eslintPlugin","defineConfig","code","viteServer","securityConfig","setSecurityConfig","newSecurityConfig","getSecurityConfig","websocketConfig","setWebsocketConfig","newWebsocketConfig","getWebsocketConfig","startApp","modules","defaultRoles","server","auth","security","websocket","ssr","dotenv","hasRemoteBackend","trackAppStart","systemModules","session_default","combinedModules","markAppStarted","initSystemMethods","initCustomMethods","initRoles","getConfigSchema","setSchema","rawStores","getStores","getChannels","defineCronJobs","getRateLimits","storesToInit","environmentId","appAlias","environmentAlias","telemetry","setMetadata","allStoresToInit","initStores","createIndexesAndMigrationsWithLock","initMetrics","startServer","module","createQuery","createMutation","_createSystemQuery","_createSystemMutation","warnIndexCreationFailure","storeName","MIGRATIONS_LOCK_RESOURCE","blockingStores","backgroundStores","createStoreIndexes","backgroundIndexCreationPromise","migrationPromise","backgroundIndexesResult","migrationResult","reconcileMode","absoluteKey","cronAlias","cronJobParams","serviceEndpoint","appDetails","getAppDetails","modelencePackageJson","packageJsonPath","packageJsonContent","clearTokens","disableUser","deleteUser","randomUUID","ServerChannel","canAccessChannel","websocketProvider","logError","sendEmail","sendOAuthError","statusCode","errorMessage","html","authenticateUser","handleExistingProviderLogin","userData","handleExistingEmailLogin","existingUserByEmail","profileUpdate","updatedUser","handleNewUserSignup","newUser","getRedirectUri","handleOAuthUserAuthentication","clearOAuthLinkCookie","safelyCallHook","hook","validateOAuthStateAndGetMode","stateCookieName","storedState","storedStateValue","storedMode","handleOAuthProviderLink","providerField","currentUser","existingProviderId","MongoServerError","validateOAuthCode","exchangeCodeForToken","clientId","clientSecret","redirectUri","tokenResponse","fetchGoogleUserInfo","accessToken","userInfoResponse","handleGoogleAuthenticationCallback","mode","googleClientId","googleClientSecret","tokenData","googleUser","getRouter","googleAuthRouter","Router","checkGoogleEnabled","_req","googleEnabled","authUrl","google_default","fetchGitHubUserInfo","fetchGitHubUserEmails","getGitHubUserEmail","githubUser","handleGitHubAuthenticationCallback","githubClientId","githubClientSecret","githubEmail","nameParts","githubAuthRouter","checkGitHubEnabled","githubEnabled","githubScopes","scopes","s","github_default","createRouteHandler","context","ModelenceError","getBodyParserMiddleware","middlewares","jsonOptions","urlencodedOptions","rawOptions","defaultRawOptions","registerModuleRoutes","app","route","handlers","cookieParser","securityHeadersMiddleware","methodName","sanitizeResult","runMethod","getResponseTypeMap","handleMethodError","http","reason","promise","port","siteUrl","isOAuthCallback","clientInfo","getClientIp","getUnauthenticatedRoles","parseZodError","parsingError","zodError","flattened","fieldMessages","errors","formMessages","frameAncestors","hasCustomAncestors","ancestors","forwardedFor","directIp"],"mappings":"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","file":"chunk-C26FT6MS.js","sourcesContent":["import { Module } from '../app/module';\n\nexport default new Module('_system', {\n configSchema: {\n mongodbUri: {\n type: 'secret',\n isPublic: false,\n default: '',\n },\n mongodbPoolSize: {\n type: 'number',\n isPublic: false,\n default: 10,\n },\n 'env.type': {\n type: 'string',\n isPublic: true,\n default: '',\n },\n 'site.url': {\n type: 'string',\n isPublic: true,\n default: '',\n },\n multiInstance: {\n type: 'boolean',\n isPublic: false,\n default: false,\n },\n },\n});\n","import { MongoClient } from 'mongodb';\nimport systemModule from '../system';\nimport packageJson from '../../package.json';\n\nlet client: MongoClient | null = null;\n\nexport async function connect() {\n if (client) return client;\n\n const mongodbUri = getMongodbUri();\n if (!mongodbUri) {\n throw new Error('MongoDB URI is not set');\n }\n\n const maxPoolSize = systemModule.getConfig('mongodbPoolSize');\n\n client = new MongoClient(mongodbUri, {\n driverInfo: {\n name: 'Modelence',\n version: packageJson.version,\n },\n ignoreUndefined: true,\n maxPoolSize,\n });\n\n try {\n // Connect the client to the server\n await client.connect();\n // Send a ping to confirm a successful connection\n await client.db('admin').command({ ping: 1 });\n console.log('Pinged your deployment. You successfully connected to MongoDB!');\n return client;\n } catch (err) {\n console.error(err);\n client = null;\n throw err;\n }\n}\n\nexport function getMongodbUri() {\n return systemModule.getConfig('mongodbUri') || undefined;\n}\n\nexport function getClient() {\n return client;\n}\n\n// export async function closeConnection() {\n// if (client) {\n// await client.close();\n// client = null;\n// }\n// }\n","import { Server } from 'http';\nimport { Server as SocketServer, Socket } from 'socket.io';\nimport { createAdapter } from '@socket.io/mongo-adapter';\nimport { authenticate } from '@/auth';\nimport { getConfig } from '@/config/server';\nimport { getClient } from '@/db/client';\nimport { WebsocketServerProvider } from '../types';\nimport { ServerChannel } from '../serverChannel';\nimport {\n handleSubscribeLiveQuery,\n handleUnsubscribeLiveQuery,\n handleLiveQueryDisconnect,\n} from '@/live-query';\nimport type { Collection, Document } from 'mongodb';\n\nlet socketServer: SocketServer | null = null;\n\nconst COLLECTION = '_modelenceSocketio';\nconst ADAPTER_TTL_SECONDS = 60;\n\nexport async function init({\n httpServer,\n channels,\n}: {\n httpServer: Server;\n channels: ServerChannel[];\n}) {\n const mongodbClient = getClient();\n const isMultiInstance = Boolean(getConfig('_system.multiInstance'));\n\n console.log('Initializing Socket.IO server...');\n\n let mongoCollection: Collection<Document> | null = null;\n\n if (isMultiInstance && mongodbClient) {\n mongoCollection = mongodbClient.db().collection(COLLECTION);\n\n try {\n await mongoCollection.createIndex(\n { createdAt: 1 },\n { expireAfterSeconds: ADAPTER_TTL_SECONDS, background: true }\n );\n } catch (error: unknown) {\n if (error instanceof Error && 'code' in error && (error as { code: number }).code === 85) {\n try {\n await mongoCollection.dropIndex('createdAt_1');\n await mongoCollection.createIndex(\n { createdAt: 1 },\n { expireAfterSeconds: ADAPTER_TTL_SECONDS, background: true }\n );\n } catch (retryError: unknown) {\n console.error(\n 'Failed to recreate index on MongoDB collection for Socket.IO:',\n retryError\n );\n }\n } else {\n console.error('Failed to create index on MongoDB collection for Socket.IO:', error);\n }\n }\n }\n\n socketServer = new SocketServer(httpServer, {\n cors: {\n origin: '*',\n methods: ['GET', 'POST'],\n },\n adapter: mongoCollection ? createAdapter(mongoCollection) : undefined,\n transports: ['websocket'],\n perMessageDeflate: false,\n });\n\n socketServer.on('error', (error) => {\n console.error('Socket.IO error:', error);\n });\n\n socketServer.use(async (socket, next) => {\n const token = socket.handshake.auth.token;\n\n try {\n socket.data = await authenticate(token);\n } finally {\n next();\n }\n });\n\n socketServer.on('connection', (socket: Socket) => {\n socket.on('disconnect', () => {\n handleLiveQueryDisconnect(socket);\n });\n\n socket.on('joinChannel', async (channelName: string) => {\n const [category] = channelName.split(':');\n let authorized = false;\n\n for (const channel of channels) {\n if (channel.category === category) {\n if (!channel.canAccessChannel || (await channel.canAccessChannel(socket.data))) {\n socket.join(channelName);\n authorized = true;\n socket.emit('joinedChannel', channelName);\n }\n break; // Found matching channel - stop searching\n }\n }\n\n if (!authorized) {\n socket.emit('joinError', { channel: channelName, error: 'Access denied' });\n }\n });\n\n socket.on('leaveChannel', (channelName: string) => {\n socket.leave(channelName);\n console.log(`User ${socket.id} left channel ${channelName}`);\n socket.emit('leftChannel', channelName);\n });\n\n socket.on('subscribeLiveQuery', (payload) => handleSubscribeLiveQuery(socket, payload));\n socket.on('unsubscribeLiveQuery', (payload) => handleUnsubscribeLiveQuery(socket, payload));\n });\n\n console.log('Socket.IO server initialized');\n}\n\nfunction broadcast<T>({ category, id, data }: { category: string; id: string; data: T }) {\n socketServer?.to(`${category}:${id}`).emit(category, data);\n}\n\nexport default {\n init,\n broadcast,\n} as WebsocketServerProvider;\n","import { time } from '../time';\nimport { dbDisposableEmailDomains } from './db';\n\nexport async function isDisposableEmail(email: string): Promise<boolean> {\n const emailParts = email.toLowerCase().trim().split('@');\n if (emailParts.length !== 2) {\n return false;\n }\n\n const domain = emailParts[1];\n const result = await dbDisposableEmailDomains.findOne({ domain });\n return Boolean(result);\n}\n\nexport const updateDisposableEmailListCron = {\n interval: time.days(1),\n async handler() {\n const response = await fetch(\n 'https://disposable.github.io/disposable-email-domains/domains.txt'\n );\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const domainsText = await response.text();\n\n const domains = domainsText\n .split('\\n')\n .map((domain) => domain.trim().toLowerCase())\n .filter((domain) => domain.length > 0);\n\n const now = new Date();\n\n // Insert domains in batches to avoid overwhelming the database\n const batchSize = 500;\n for (let i = 0; i < domains.length; i += batchSize) {\n const batch = domains.slice(i, i + batchSize);\n\n try {\n await dbDisposableEmailDomains.insertMany(\n batch.map((domain) => ({\n domain,\n addedAt: now,\n }))\n );\n } catch (error: unknown) {\n // MongoDB throws BulkWriteError when some documents are duplicates\n if (\n error &&\n typeof error === 'object' &&\n 'name' in error &&\n error.name === 'MongoBulkWriteError'\n ) {\n // console.warn(`Error inserting batch starting at index ${i}:`, error.message);\n }\n }\n }\n },\n};\n","import { z } from 'zod';\nimport { UpdateProfileProps } from '../methods/types';\n\nexport const MIN_HANDLE_LENGTH = 3;\nexport const MAX_HANDLE_LENGTH = 50;\n\nexport const MIN_PASSWORD_LENGTH = 8;\nexport const MAX_PASSWORD_LENGTH = 128;\n\nexport const MAX_EMAIL_LENGTH = 254;\n\n// Reusable string validators\nconst trimmedNonEmptyString = (opts: { min?: number; max: number }) =>\n z\n .string()\n .trim()\n .min(opts.min ?? 1, { message: `must be at least ${opts.min ?? 1} characters` })\n .max(opts.max, { message: `must be at most ${opts.max} characters` });\n\nconst trimmedOptionalString = (opts: { max: number }) =>\n z\n .string()\n .trim()\n .max(opts.max, { message: `must be at most ${opts.max} characters` })\n .transform((val) => (val === '' ? undefined : val))\n .optional();\n\n// Base schema (used for both full & partial validation)\nconst profileFieldsSchema = z\n .object({\n firstName: trimmedOptionalString({ max: 50 }),\n lastName: trimmedOptionalString({ max: 50 }),\n avatarUrl: trimmedOptionalString({ max: 400 }),\n handle: trimmedNonEmptyString({ min: MIN_HANDLE_LENGTH, max: MAX_HANDLE_LENGTH }),\n })\n .strict();\n\n/**\n * Validates and trims profile fields against the defined rules.\n *\n * For each field present in `fields`:\n * - Trims whitespace\n * - Sets fields to `undefined` when cleared (empty string)\n * - Enforces min/max length constraints\n *\n * @returns An object containing only the validated, trimmed fields that were provided.\n */\nexport function validateProfileFields(\n fields: Partial<UpdateProfileProps>\n): Partial<UpdateProfileProps> {\n const result = profileFieldsSchema.partial().safeParse(fields);\n\n if (!result.success) {\n const issue = result.error.issues[0];\n const path = issue.path.join('.');\n const msg = path ? `${path}: ${issue.message}` : issue.message;\n throw new Error(msg);\n }\n\n return result.data;\n}\n\nexport function validatePassword(value: string) {\n return z\n .string()\n .min(MIN_PASSWORD_LENGTH, {\n message: `Password must contain at least ${MIN_PASSWORD_LENGTH} characters`,\n })\n .max(MAX_PASSWORD_LENGTH, {\n message: `Password must be at most ${MAX_PASSWORD_LENGTH} characters`,\n })\n .parse(value);\n}\n\nexport function validateEmail(value: string) {\n return z\n .string()\n .max(MAX_EMAIL_LENGTH, {\n message: `Email must be at most ${MAX_EMAIL_LENGTH} characters`,\n })\n .email({ message: 'Invalid email address' })\n .parse(value)\n .toLowerCase();\n}\n\nexport function validateHandle(value: string) {\n return trimmedNonEmptyString({ min: MIN_HANDLE_LENGTH, max: MAX_HANDLE_LENGTH }).parse(value);\n}\n","import { randomBytes } from 'crypto';\nimport { usersCollection } from './db';\nimport { User } from './types';\nimport { validateHandle, MAX_HANDLE_LENGTH, MIN_HANDLE_LENGTH } from './validators';\n\nexport function serializeUserForClient(userDoc: User) {\n return {\n id: userDoc._id,\n handle: userDoc.handle,\n roles: userDoc.roles || [],\n firstName: userDoc.firstName ?? undefined,\n lastName: userDoc.lastName ?? undefined,\n avatarUrl: userDoc.avatarUrl ?? undefined,\n };\n}\n\n/**\nFinds an available handle by appending incremental suffixes (_2, _3, …)\nto the base handle until a unique one is found.\nThe base handle is truncated so that the suffixed candidate never exceeds MAX_HANDLE_LENGTH.\n */\nasync function findAvailableHandle(baseHandle: string): Promise<string> {\n // Truncate base handle to MAX_HANDLE_LENGTH so the unsuffixed form is valid.\n const truncatedBase = baseHandle.slice(0, MAX_HANDLE_LENGTH);\n\n // Check the unsuffixed base handle first.\n try {\n const firstCheck = await usersCollection.findOne(\n { handle: truncatedBase },\n { collation: { locale: 'en', strength: 2 } }\n );\n\n if (!firstCheck) {\n return truncatedBase;\n }\n } catch (err) {\n throw new Error(`Database error while checking handle availability: ${err}`);\n }\n\n // Try sequential suffixes _2 through _51 (50 attempts).\n const MAX_SUFFIX_VALUE = 51;\n\n for (let suffix = 2; suffix <= MAX_SUFFIX_VALUE; suffix++) {\n const suffixStr = `_${suffix}`;\n const candidate = `${truncatedBase.slice(0, MAX_HANDLE_LENGTH - suffixStr.length)}${suffixStr}`;\n\n try {\n const conflict = await usersCollection.findOne(\n { handle: candidate },\n { collation: { locale: 'en', strength: 2 } }\n );\n\n if (!conflict) {\n return candidate;\n }\n } catch (err) {\n throw new Error(`Database error while checking handle \"${candidate}\": ${err}`);\n }\n }\n\n // Fallback: sequential suffixes exhausted — use random hex suffixes.\n // Limit the number of attempts to avoid an infinite loop in case of persistent DB issues\n const MAX_RANDOM_ATTEMPTS = 10;\n\n for (let attempt = 0; attempt < MAX_RANDOM_ATTEMPTS; attempt++) {\n const randomSuffix = `_${randomBytes(3).toString('hex')}`;\n const candidate = `${truncatedBase.slice(0, MAX_HANDLE_LENGTH - randomSuffix.length)}${randomSuffix}`;\n\n try {\n const conflict = await usersCollection.findOne(\n { handle: candidate },\n { collation: { locale: 'en', strength: 2 } }\n );\n\n if (!conflict) {\n return candidate;\n }\n } catch (err) {\n throw new Error(`Database error while checking handle \"${candidate}\": ${err}`);\n }\n }\n\n throw new Error(\n `Could not generate a unique handle for base \"${baseHandle}\" after exhausting all attempts.`\n );\n}\n\n/**\n * Resolves a unique handle for a new user.\n *\n * If the caller supplied a handle it is validated and checked for uniqueness.\n * - When `throwOnConflict` is true (default), an error is thrown if the handle is taken.\n * - When `throwOnConflict` is false, a numeric suffix (_2, _3, …) is appended to make\n * it unique. This is intended for system-generated handles (e.g. from `generateHandle`).\n *\n * If no handle is supplied, the local part of the email address is used as the base handle,\n * and a numeric suffix is appended until an unused handle is found.\n */\nexport async function resolveUniqueHandle(\n rawHandle: string | undefined,\n email: string,\n { throwOnConflict = true }: { throwOnConflict?: boolean } = {}\n): Promise<string> {\n if (rawHandle !== undefined && rawHandle !== null && String(rawHandle).trim() !== '') {\n // Caller explicitly provided a handle – trim and validate it.\n const handle = validateHandle(String(rawHandle).trim());\n\n if (throwOnConflict) {\n const existing = await usersCollection.findOne(\n { handle },\n { collation: { locale: 'en', strength: 2 } }\n );\n\n if (existing) {\n throw new Error('Handle already taken.');\n }\n\n return handle;\n }\n\n // System-generated handle – find an available variant with suffix if needed.\n return findAvailableHandle(handle);\n }\n\n // Derive handle from the email local-part (everything before '@').\n // Truncate to MAX_HANDLE_LENGTH since RFC 5321 allows local parts up to 64 chars.\n const baseHandle = email.split('@')[0].padEnd(MIN_HANDLE_LENGTH, '_').slice(0, MAX_HANDLE_LENGTH);\n return findAvailableHandle(baseHandle);\n}\n","import type { EmailProvider } from '../types';\n\nexport type EmailConfig = {\n provider?: EmailProvider;\n from?: string;\n verification?: {\n subject?: string;\n template?: (props: { name: string; email: string; verificationUrl: string }) => string;\n redirectUrl?: string;\n };\n passwordReset?: {\n subject?: string;\n template?: (props: { name: string; email: string; resetUrl: string }) => string;\n redirectUrl?: string;\n };\n // @deprecated use verification.redirectUrl instead\n emailVerifiedRedirectUrl?: string;\n};\n\nlet emailConfig: EmailConfig = Object.freeze({});\n\nexport function setEmailConfig(newEmailConfig: EmailConfig) {\n emailConfig = Object.freeze(Object.assign({}, emailConfig, newEmailConfig));\n}\n\nexport function getEmailConfig() {\n return emailConfig;\n}\n","import { AuthErrorProps, AuthSuccessProps, OAuthErrorInfo, User } from '@/auth/types';\nimport { UpdateProfileProps, SignupProps } from '@/methods/types';\nimport type { RateLimitType } from '@/rate-limit/types';\n\n/**\n * A single rate-limit rule for an authentication bucket. The `bucket` is\n * implied by which auth action you're configuring (e.g. `signup`), so callers\n * only specify the actor type, window size, and limit.\n *\n * @example\n * ```typescript\n * import { time } from 'modelence/server';\n *\n * const rule: AuthRateLimitOverride = {\n * type: 'ip',\n * window: time.minutes(15),\n * limit: 10,\n * };\n * ```\n */\nexport type AuthRateLimitOverride = {\n /** Identifier type of the actor this rule applies to. */\n type: RateLimitType;\n /** Time window size in milliseconds. Use `time.minutes(15)` etc. */\n window: number;\n /** Maximum allowed hits within the window. */\n limit: number;\n};\n\n/** @internal Remove in 1.0.0 — superseded by `AuthRateLimitOverride[]`. */\nexport type LegacySignupRateLimits = {\n perIp15Minutes?: number;\n perIpPerDay?: number;\n};\n\n/** @internal Remove in 1.0.0 — superseded by `AuthRateLimitOverride[]`. */\nexport type LegacySignupAttemptRateLimits = {\n perIp15Minutes?: number;\n perIpPerDay?: number;\n};\n\n/** @internal Remove in 1.0.0 — superseded by `AuthRateLimitOverride[]`. */\nexport type LegacySigninRateLimits = {\n perIp15Minutes?: number;\n perIpPerDay?: number;\n};\n\n/** @internal Remove in 1.0.0 — superseded by `AuthRateLimitOverride[]`. */\nexport type LegacyVerificationRateLimits = {\n perUserPerMinute?: number;\n perUserPerDay?: number;\n};\n\n/** @internal Remove in 1.0.0 — superseded by `AuthRateLimitOverride[]`. */\nexport type LegacyPasswordResetRateLimits = {\n perIp15Minutes?: number;\n perIpPerDay?: number;\n perEmailPerHour?: number;\n perEmailPerDay?: number;\n};\n\n/**\n * Per-action rate limit overrides for authentication endpoints.\n *\n * Each bucket accepts an array of rules that are merged into the built-in\n * defaults by `(type, window)` tuple:\n * - A rule whose `(type, window)` matches a default replaces that default's\n * `limit`.\n * - A rule whose `(type, window)` does not match any default is added as\n * an extra rule for the bucket.\n * - Defaults whose `(type, window)` is not overridden are kept.\n *\n * This means you can tighten a single window without accidentally dropping\n * the other built-in protections for that bucket.\n *\n * @example Tighten the 15-minute signup cap; per-day default is preserved.\n * ```typescript\n * import { startApp, time } from 'modelence/server';\n *\n * startApp({\n * auth: {\n * rateLimits: {\n * signup: [\n * { type: 'ip', window: time.minutes(15), limit: 5 },\n * ],\n * },\n * },\n * });\n * ```\n *\n * @example Add an extra window alongside the defaults.\n * ```typescript\n * startApp({\n * auth: {\n * rateLimits: {\n * signup: [\n * { type: 'ip', window: time.minutes(1), limit: 2 },\n * ],\n * },\n * },\n * });\n * ```\n */\nexport type AuthRateLimitsConfig = {\n /** Per-IP limits for the signup endpoint (successful signups only). */\n signup?: AuthRateLimitOverride[];\n /** Per-IP limits for signup attempts (checked before duplicate detection). */\n signupAttempt?: AuthRateLimitOverride[];\n /** Per-IP limits for login attempts. */\n signin?: AuthRateLimitOverride[];\n /** Per-user limits for email verification requests. */\n verification?: AuthRateLimitOverride[];\n /** Rate limits for password reset requests. */\n passwordReset?: AuthRateLimitOverride[];\n};\n\n/**\n * @internal Internal shape used by `buildAuthRateLimits` to accept both the\n * public array form and the deprecated legacy object form for back-compat.\n * Not part of the public API surface.\n *\n * Remove the legacy union arms in 1.0.0 — collapse this back to\n * `AuthRateLimitsConfig` once the object shape is gone.\n */\nexport type InternalAuthRateLimitsConfig = {\n signup?: AuthRateLimitOverride[] | LegacySignupRateLimits;\n signupAttempt?: AuthRateLimitOverride[] | LegacySignupAttemptRateLimits;\n signin?: AuthRateLimitOverride[] | LegacySigninRateLimits;\n verification?: AuthRateLimitOverride[] | LegacyVerificationRateLimits;\n passwordReset?: AuthRateLimitOverride[] | LegacyPasswordResetRateLimits;\n};\n\ntype GenerateHandleProps = {\n email: string;\n firstName?: string;\n lastName?: string;\n};\n\n/**\n * Callback options for authentication operations\n */\nexport type AuthOption = {\n /** Callback executed when authentication succeeds */\n onSuccess?: (user: User) => void;\n /** Callback executed when authentication fails */\n onError?: (error: Error) => void;\n};\n\n/**\n * Authentication configuration for the application\n *\n * @example\n * ```typescript\n * import { startApp } from 'modelence/server';\n *\n * startApp({\n * auth: {\n * validateSignup: ({ email, firstName, lastName, password, handle, avatarUrl }) => {\n * // Validating the signup data\n * if (!email || !password) {\n * throw new Error('Email and password are required');\n * }\n * },\n * onAfterLogin: ({ user }) => {\n * console.log('User logged in:', user.name);\n * // Redirect to dashboard\n * },\n * onLoginError: ({ error }) => {\n * console.error('Login failed:', error.message);\n * // Show error toast\n * },\n * onAfterSignup: ({ user }) => {\n * console.log('User signed up:', user.email);\n * // Send welcome email\n * },\n * onSignupError: ({ error }) => {\n * console.error('Signup failed:', error.message);\n * },\n * generateHandle: ({ email }) => {\n * console.log('Generating handle for:', email);\n * // Generate handle\n * return 'user123';\n * },\n * }\n * });\n * ```\n */\nexport type AuthConfig = {\n /**\n * Pre-signup validation hook. Runs before a new user is created during\n * email/password signup, after format checks but before duplicate detection.\n * Throw to reject the signup — the thrown message is surfaced to the client.\n *\n * Receives the raw signup payload (`email`, `password`, and optional\n * `firstName`, `lastName`, `avatarUrl`, `handle`). May be async.\n */\n validateSignup?: (props: SignupProps) => void | Promise<void>;\n\n /**\n * Pre-update validation hook. Runs before a user's profile fields\n * (`firstName`, `lastName`, `avatarUrl`, `handle`) are written.\n * Throw to reject the update — the thrown message is surfaced to the client.\n * May be async.\n */\n validateProfileUpdate?: (props: UpdateProfileProps) => void | Promise<void>;\n\n /**\n * Fires after a successful login (email/password or OAuth) once the session\n * has been linked to the user. Receives `{ provider, user, session, connectionInfo }`.\n * Use for analytics, audit logging, or post-login side effects.\n */\n onAfterLogin?: (props: AuthSuccessProps) => void;\n\n /**\n * Fires when a login attempt fails. Receives `{ provider, error, session, connectionInfo }`.\n * Use for failure analytics or alerting — does NOT change the response sent to the client.\n */\n onLoginError?: (props: AuthErrorProps) => void;\n\n /**\n * Fires after a successful signup once the user record is created and the\n * session is linked. Receives `{ provider, user, session, connectionInfo }`.\n * Common uses: send welcome email, create default workspace, track activation.\n */\n onAfterSignup?: (props: AuthSuccessProps) => void;\n\n /**\n * Fires when a signup attempt fails (validation, duplicate email, etc.).\n * Receives `{ provider, error, session, connectionInfo }`.\n * Use for failure analytics — does NOT change the response sent to the client.\n */\n onSignupError?: (props: AuthErrorProps) => void;\n\n /**\n * Fires after a user's email is successfully verified (via the verification\n * link or implicitly via password reset). Receives `{ provider, user, session, connectionInfo }`.\n */\n onAfterEmailVerification?: (props: AuthSuccessProps) => void;\n\n /**\n * Fires when email verification fails (invalid or expired token).\n * Receives `{ provider, error, session, connectionInfo }`.\n */\n onEmailVerificationError?: (props: AuthErrorProps) => void;\n\n /**\n * Fires after an OAuth provider is linked to an existing account\n * (either automatically when `oauthAccountLinking: 'auto'` or via an\n * explicit link flow). Receives `{ provider, user, session, connectionInfo }`.\n */\n onAfterOAuthLink?: (props: AuthSuccessProps) => void;\n\n /**\n * Fires when OAuth account linking fails. Receives\n * `{ provider, error, session, connectionInfo }`.\n */\n onOAuthLinkError?: (props: AuthErrorProps) => void;\n\n /**\n * Custom handle generator. If provided, overrides the default behavior\n * (which derives the handle from the email local-part). Receives\n * `{ email, firstName?, lastName? }` and returns the desired handle\n * synchronously or as a `Promise<string>`. If the returned handle collides\n * with an existing one, Modelence appends a numeric suffix automatically.\n */\n generateHandle?: (props: GenerateHandleProps) => Promise<string> | string;\n\n /** @deprecated Use {@link AuthConfig.onAfterLogin} and {@link AuthConfig.onLoginError} instead. */\n login?: AuthOption;\n /** @deprecated Use {@link AuthConfig.onAfterSignup} and {@link AuthConfig.onSignupError} instead. */\n signup?: AuthOption;\n\n /**\n * Controls how OAuth providers handle existing accounts with matching email.\n * - 'manual' (default): Returns an error when an OAuth login matches an existing email.\n * - 'auto': Automatically links the OAuth provider to the existing account\n * if the provider email is verified.\n */\n oauthAccountLinking?: 'auto' | 'manual';\n\n /**\n * Customizes how OAuth authentication errors are rendered. By default,\n * OAuth errors are returned as JSON; providing this returns a custom HTML\n * response instead, which is useful when the OAuth flow runs in a browser\n * context. Receives `{ error, statusCode }` and returns an HTML string\n * (or `null`/`undefined` to fall back to the default JSON response).\n *\n * Always escape interpolated values to prevent XSS.\n */\n errorComponent?: (props: OAuthErrorInfo) => string | null | undefined;\n\n /**\n * Overrides the built-in rate limits for authentication endpoints. Each rule\n * you provide is merged into the defaults by `(bucket, type, window)`:\n * matching tuples replace the default `limit`, new tuples are added, and\n * unspecified defaults are preserved. See {@link AuthRateLimitsConfig} for\n * full semantics and examples.\n */\n rateLimits?: AuthRateLimitsConfig;\n};\n\nlet authConfig: AuthConfig = Object.freeze({});\n\nexport function setAuthConfig(newAuthConfig: AuthConfig) {\n authConfig = Object.freeze(Object.assign({}, authConfig, newAuthConfig));\n}\n\nexport function getAuthConfig() {\n return authConfig;\n}\n","import bcrypt from 'bcrypt';\nimport { z } from 'zod';\n\nimport { Args, Context } from '../methods/types';\nimport { usersCollection } from './db';\nimport { serializeUserForClient } from './utils';\nimport {\n clearAuthTokenCookie,\n clearSessionUser,\n setAuthTokenCookie,\n setSessionUser,\n} from './session';\nimport { getEmailConfig } from '@/app/emailConfig';\nimport { consumeRateLimit } from '@/server';\nimport { validateEmail } from './validators';\nimport { getAuthConfig } from '@/app/authConfig';\n\nexport async function handleLoginWithPassword(\n args: Args,\n { user, session, connectionInfo, res }: Context\n) {\n try {\n if (!session) {\n throw new Error('Session is not initialized');\n }\n\n const ip = connectionInfo?.ip;\n if (ip) {\n await consumeRateLimit({\n bucket: 'signin',\n type: 'ip',\n value: ip,\n });\n }\n\n const email = validateEmail(args.email as string);\n // password is accepted just as a string, so users can still sign in if the password validation rules are changed\n const password = z.string().parse(args.password);\n\n // TODO: add rate limiting by email (and perhaps IP address overall)\n\n if (user) {\n // TODO: handle cases where a user is already logged in\n }\n\n const userDoc = await usersCollection.findOne(\n { 'emails.address': email, status: { $nin: ['deleted', 'disabled'] } },\n { collation: { locale: 'en', strength: 2 } }\n );\n\n const passwordHash = userDoc?.authMethods?.password?.hash;\n if (!passwordHash) {\n throw incorrectCredentialsError();\n }\n\n const emailDoc = userDoc.emails?.find((e) => e.address.toLowerCase() === email);\n\n if (!emailDoc?.verified && getEmailConfig()?.provider) {\n throw new Error(\n \"Your email address hasn't been verified yet. Please check your inbox for the verification email.\"\n );\n }\n\n const isValidPassword = await bcrypt.compare(password, passwordHash);\n if (!isValidPassword) {\n throw incorrectCredentialsError();\n }\n\n await setSessionUser(session.authToken, userDoc._id);\n\n if (res) {\n setAuthTokenCookie(res, session.authToken);\n }\n\n getAuthConfig().onAfterLogin?.({\n provider: 'email',\n user: userDoc,\n session,\n connectionInfo,\n });\n getAuthConfig().login?.onSuccess?.(userDoc);\n\n return {\n user: serializeUserForClient(userDoc),\n };\n } catch (error) {\n if (error instanceof Error) {\n getAuthConfig().onLoginError?.({\n provider: 'email',\n error,\n session,\n connectionInfo,\n });\n getAuthConfig().login?.onError?.(error);\n }\n throw error;\n }\n}\n\nexport async function handleLogout(args: Args, { session, res }: Context) {\n if (!session) {\n throw new Error('Session is not initialized');\n }\n\n await clearSessionUser(session.authToken);\n\n if (res) {\n clearAuthTokenCookie(res);\n }\n}\n\n/*\n It is important to return the same exact error both in case the email\n or password is incorrect so that the client cannot tell the difference,\n otherwise it would allow for an enumeration attack.\n*/\nfunction incorrectCredentialsError() {\n return new Error('Incorrect email/password combination');\n}\n","import { usersCollection } from './db';\nimport { Args, Context, UpdateProfileProps } from '../methods/types';\nimport { serializeUserForClient } from './utils';\nimport { validateProfileFields } from './validators';\nimport { getAuthConfig } from '@/app/authConfig';\n\nexport async function getOwnProfile(props: Args, { user }: Context) {\n if (!user) {\n throw new Error('Not authenticated');\n }\n\n const profile = await usersCollection.requireById(user.id);\n\n return {\n handle: profile.handle,\n emails: profile.emails,\n authMethods: Object.keys(profile.authMethods || {}),\n firstName: profile.firstName ?? undefined,\n lastName: profile.lastName ?? undefined,\n avatarUrl: profile.avatarUrl ?? undefined,\n };\n}\n\nexport async function handleUpdateProfile(props: Args, { user }: Context) {\n if (!user) {\n throw new Error('Not authenticated');\n }\n\n let profile = await usersCollection.requireById(user.id);\n\n const update = validateProfileFields(props as UpdateProfileProps);\n\n await getAuthConfig().validateProfileUpdate?.(update);\n\n //Check if handle is already taken\n if ('handle' in update && update.handle !== undefined) {\n const existing = await usersCollection.findOne(\n {\n handle: update.handle,\n _id: { $ne: profile._id }, // excludes the current user\n },\n { collation: { locale: 'en', strength: 2 } }\n );\n\n if (existing) {\n throw new Error('Handle already taken.');\n }\n }\n\n //Update profile\n if (Object.keys(update).length > 0) {\n const setFields: Record<string, unknown> = {}; //Used to set the fields\n const unsetFields: Record<string, ''> = {}; //Used to clear the fields the mongodb, because mongodb rejects undefined values when updating fields\n\n for (const [key, value] of Object.entries(update)) {\n if (value === undefined) {\n unsetFields[key] = '';\n } else {\n setFields[key] = value;\n }\n }\n\n const mongoUpdate: Record<string, unknown> = {};\n if (Object.keys(setFields).length > 0) mongoUpdate.$set = setFields;\n if (Object.keys(unsetFields).length > 0) mongoUpdate.$unset = unsetFields;\n\n try {\n await usersCollection.updateOne({ _id: profile._id }, mongoUpdate);\n\n //Also pass Cleared Fields as UNDEFINED in profile\n const clearedFields = Object.fromEntries(\n Object.keys(unsetFields).map((key) => [key, undefined])\n );\n profile = { ...profile, ...setFields, ...clearedFields } as typeof profile;\n } catch (error) {\n if (error instanceof Error && 'code' in error && (error as { code: number }).code === 11000) {\n throw new Error('Handle already taken.');\n }\n throw error;\n }\n }\n\n return {\n user: serializeUserForClient(profile),\n };\n}\n","import { Document, ObjectId } from 'mongodb';\nimport { ConnectionInfo } from '@/methods/types';\n\nexport interface UserEmail {\n address: string;\n verified: boolean;\n}\n\nexport interface User extends Document {\n _id: ObjectId;\n\n handle: string;\n\n emails?: UserEmail[];\n\n status?: 'active' | 'disabled' | 'deleted';\n\n firstName?: string;\n lastName?: string;\n avatarUrl?: string;\n\n createdAt: Date;\n disabledAt?: Date;\n deletedAt?: Date;\n\n roles?: string[];\n\n authMethods: {\n password?: {\n hash: string;\n };\n google?: {\n id: string;\n };\n github?: {\n id: string;\n };\n };\n}\n\nexport type UserInfo = {\n /** The user's unique identifier. */\n id: string;\n /** The user's display handle. */\n handle: string;\n /** The role strings assigned to this user in the database. */\n roles: string[];\n /** Returns `true` if the user has the given role. */\n hasRole: (role: string) => boolean;\n /** Throws an error if the user does not have the given role. */\n requireRole: (role: string) => void;\n firstName?: string;\n lastName?: string;\n avatarUrl?: string;\n};\n\nexport type Role = string;\n\nexport type DefaultRoles = Record<'authenticated' | 'unauthenticated', Role | null>;\n\nexport type Session = {\n authToken: string;\n expiresAt: Date;\n userId: ObjectId | null;\n};\n\nexport type Permission = string;\n\n/**\n * Defines a role that can be assigned to users.\n *\n * Roles are registered via the `roles` option in {@link AppOptions} and\n * are synced to the Modelence Cloud dashboard for user management.\n *\n * @example\n * ```typescript\n * import { startApp } from 'modelence/server';\n *\n * startApp({\n * roles: {\n * admin: { description: 'Full access to all features' },\n * editor: { description: 'Can edit content' },\n * viewer: {},\n * },\n * });\n * ```\n */\nexport type RoleDefinition = {\n /** Human-readable description of the role, shown in the Modelence Cloud dashboard. */\n description?: string;\n /** @internal */\n permissions?: Permission[];\n};\n\nexport const SUPPORTED_OAUTH_PROVIDERS = ['google', 'github'] as const;\nexport type OAuthProvider = (typeof SUPPORTED_OAUTH_PROVIDERS)[number];\n\nexport type AuthProvider = OAuthProvider | 'email';\n\nexport type AuthSuccessProps = {\n provider: AuthProvider;\n user: User;\n session: Session | null;\n connectionInfo: ConnectionInfo;\n};\n\nexport type AuthErrorProps = {\n provider: AuthProvider;\n error: Error;\n session: Session | null;\n connectionInfo: ConnectionInfo;\n};\n\nexport type OAuthErrorInfo = {\n error: string;\n statusCode: number;\n};\n","import { usersCollection } from './db';\nimport { Args, Context } from '@/methods/types';\nimport { OAuthProvider, SUPPORTED_OAUTH_PROVIDERS } from './types';\n\nexport async function handleUnlinkOAuthProvider({ provider }: Args, { user }: Context) {\n if (!user) {\n throw new Error('You must be signed in to unlink a provider.');\n }\n\n if (\n typeof provider !== 'string' ||\n !SUPPORTED_OAUTH_PROVIDERS.includes(provider as OAuthProvider)\n ) {\n throw new Error(\n `Invalid provider. Supported providers are: ${SUPPORTED_OAUTH_PROVIDERS.join(', ')}.`\n );\n }\n\n // requireById throws if user is not found, so no null check needed\n const userDoc = await usersCollection.requireById(user.id);\n\n const methods = userDoc.authMethods ?? {};\n const providerKey = provider as keyof typeof methods;\n\n if (!methods[providerKey]) {\n throw new Error(`${provider} is not linked to your account.`);\n }\n\n const activeMethodsCount = Object.values(methods).filter(Boolean).length;\n if (activeMethodsCount <= 1) {\n throw new Error(\n 'Cannot unlink your only authentication method. Please add another method first.'\n );\n }\n\n // Determine the OTHER auth method fields that must still exist for lockout prevention.\n // This atomic filter ensures that between our read and write, at least one other method\n // hasn't been concurrently removed (prevents two simultaneous unlinks from both succeeding).\n const otherMethods = Object.keys(methods).filter(\n (key) => key !== provider && methods[key as keyof typeof methods]\n );\n const otherMethodGuard =\n otherMethods.length > 0\n ? { $or: otherMethods.map((key) => ({ [`authMethods.${key}`]: { $exists: true } })) }\n : {};\n\n const result = await usersCollection.updateOne(\n { _id: userDoc._id, ...otherMethodGuard },\n { $unset: { [`authMethods.${provider}`]: '' } }\n );\n\n if (result.matchedCount === 0) {\n throw new Error(\n 'Cannot unlink your only authentication method. Please add another method first.'\n );\n }\n}\n","import { Store } from '../data/store';\nimport { schema } from '../data/types';\n\n/**\n * Two-bucket sliding window approximation to track rate limits.\n * This is a trade-off between storage and accuracy.\n * We're not keeping exact event logs, so we can't track the exact number of events in a window.\n * Instead, we're adding a weighted average from the previous window to the current window.\n */\nexport const dbRateLimits = new Store('_modelenceRateLimits', {\n schema: {\n bucket: schema.string(),\n type: schema.enum(['ip', 'user', 'email']),\n value: schema.string(),\n windowMs: schema.number(),\n\n windowStart: schema.date(),\n windowCount: schema.number(),\n prevWindowCount: schema.number(),\n\n expiresAt: schema.date(),\n },\n indexes: [\n { key: { bucket: 1, type: 1, value: 1, windowMs: 1 }, unique: true },\n { key: { expiresAt: 1 }, expireAfterSeconds: 0 },\n ],\n});\n","import { RateLimitRule, RateLimitType } from './types';\nimport { dbRateLimits } from './db';\nimport { RateLimitError } from '../error';\n\nlet allRules: Array<RateLimitRule> = [];\n\nexport function initRateLimits(rateLimits: RateLimitRule[]) {\n if (allRules.length > 0) {\n throw new Error('Duplicate call to initRateLimits - already initialized');\n }\n\n allRules = rateLimits;\n}\n\n/**\n * This function will check all rate limit rules on the specified bucket and type,\n * throw an error if any of them are exceeded and increase the count of the rate limit record.\n *\n * @category Rate Limits\n *\n * @example\n * ```ts\n * await consumeRateLimit({ bucket: 'api', type: 'ip', value: '127.0.0.1' });\n * ```\n * @param options.bucket - The bucket for the rate limit.\n * @param options.type - The type of the rate limit.\n * @param options.value - The value for the rate limit.\n * @param options.message - Optional custom error message when the rate limit is exceeded.\n */\nexport async function consumeRateLimit(options: {\n bucket: string;\n type: RateLimitType;\n value: string;\n message?: string;\n}) {\n const { bucket, type, value, message } = options;\n const rules = allRules.filter((rule) => rule.bucket === bucket && rule.type === type);\n const createError = message ? () => new RateLimitError(message) : undefined;\n\n for (const rule of rules) {\n await checkRateLimitRule(rule, value, createError);\n }\n}\n\n// Two-bucket sliding window approximation to track rate limits.\nasync function checkRateLimitRule(rule: RateLimitRule, value: string, createError?: () => Error) {\n const createRateLimitError = () => {\n return createError\n ? createError()\n : new RateLimitError(`Rate limit exceeded for ${rule.bucket}`);\n };\n\n const record = await dbRateLimits.findOne({\n bucket: rule.bucket,\n type: rule.type,\n value,\n windowMs: rule.window,\n });\n\n const now = Date.now();\n const currentWindowStart = Math.floor(now / rule.window) * rule.window;\n\n const { count, modifier } = record\n ? getCount(record, currentWindowStart, now)\n : {\n count: 0,\n modifier: {\n $setOnInsert: {\n windowStart: new Date(currentWindowStart),\n windowCount: 1,\n prevWindowCount: 0,\n expiresAt: new Date(currentWindowStart + rule.window + rule.window),\n },\n },\n };\n\n if (count >= rule.limit) {\n throw createRateLimitError();\n }\n\n /*\n Always use upsert, because there is a small chance the document might be auto-removed\n based on the expiration TTL index in between the check and the update\n */\n await dbRateLimits.upsertOne(\n { bucket: rule.bucket, type: rule.type, value, windowMs: rule.window },\n modifier\n );\n}\n\nfunction getCount(record: (typeof dbRateLimits)['Doc'], currentWindowStart: number, now: number) {\n const prevWindowStart = currentWindowStart - record.windowMs;\n\n if (record.windowStart.getTime() === currentWindowStart) {\n const currentWindowCount = record.windowCount;\n const prevWindowCount = record.prevWindowCount;\n const prevWindowWeight = 1 - (now - currentWindowStart) / record.windowMs;\n return {\n count: Math.round(currentWindowCount + prevWindowCount * prevWindowWeight),\n modifier: {\n $inc: { windowCount: 1 },\n $setOnInsert: {\n windowStart: new Date(currentWindowStart),\n prevWindowCount: 0,\n expiresAt: new Date(currentWindowStart + record.windowMs + record.windowMs),\n },\n },\n };\n }\n\n if (record.windowStart.getTime() === prevWindowStart) {\n const weight = 1 - (now - currentWindowStart) / record.windowMs;\n return {\n count: Math.round(record.windowCount * weight),\n modifier: {\n $set: {\n windowStart: new Date(currentWindowStart),\n windowCount: 1,\n prevWindowCount: record.windowCount,\n expiresAt: new Date(currentWindowStart + record.windowMs + record.windowMs),\n },\n },\n };\n }\n\n return {\n count: 0,\n modifier: {\n $set: {\n windowStart: new Date(currentWindowStart),\n windowCount: 1,\n prevWindowCount: 0,\n expiresAt: new Date(currentWindowStart + record.windowMs + record.windowMs),\n },\n },\n };\n}\n","export function emailVerificationTemplate({\n name,\n email,\n verificationUrl,\n}: {\n name?: string;\n email: string;\n verificationUrl: string;\n}) {\n return `\n <p>Hi${name ? ` ${name}` : ''},</p>\n <p>Please verify your email address ${email} by clicking the link below:</p>\n <p><a href=\"${verificationUrl}\">${verificationUrl}</a></p>\n <p>If you did not request this, please ignore this email.</p>\n `;\n}\n","import { z } from 'zod';\n\nimport { usersCollection, emailVerificationTokensCollection } from './db';\nimport { ObjectId, RouteParams, RouteResponse } from '@/server';\nimport { getEmailConfig } from '@/app/emailConfig';\nimport { randomBytes } from 'crypto';\nimport { time } from '@/time';\nimport { htmlToText } from '@/utils';\nimport { emailVerificationTemplate } from './templates/emailVerficationTemplate';\nimport { getAuthConfig } from '@/app/authConfig';\nimport { User } from './types';\nimport { Args, Context } from '@/methods/types';\nimport { validateEmail } from './validators';\nimport { consumeRateLimit } from '@/rate-limit/rules';\nimport { getConfig } from '@/config/server';\nimport { createSession, setAuthTokenCookie } from './session';\n\nasync function verifyEmailToken(token: string) {\n const tokenDoc = await emailVerificationTokensCollection.findOne({\n token,\n expiresAt: { $gt: new Date() },\n });\n\n if (!tokenDoc) {\n throw new Error('Invalid or expired verification token');\n }\n\n const userDoc = await usersCollection.findOne({\n _id: tokenDoc.userId,\n status: { $nin: ['deleted', 'disabled'] },\n });\n\n if (!userDoc) {\n throw new Error('User not found');\n }\n\n const email = tokenDoc.email;\n\n if (!email) {\n throw new Error('Email not found in token');\n }\n\n // Mark the specific email as verified atomically, returning the updated doc\n const updatedUserDoc = await usersCollection.findOneAndUpdate(\n {\n _id: tokenDoc.userId,\n status: { $nin: ['deleted', 'disabled'] },\n 'emails.address': email,\n 'emails.verified': { $ne: true },\n },\n { $set: { 'emails.$.verified': true } },\n { returnDocument: 'after' }\n );\n\n if (!updatedUserDoc) {\n const existingUser = await usersCollection.findOne({\n _id: tokenDoc.userId,\n 'emails.address': email,\n });\n\n if (existingUser) {\n throw new Error('Email is already verified');\n } else {\n throw new Error('Email address not found for this user');\n }\n }\n\n // Delete the used token\n await emailVerificationTokensCollection.deleteOne({ _id: tokenDoc._id });\n\n return { userDoc: updatedUserDoc, email };\n}\n\nexport async function handleVerifyEmail(params: RouteParams): Promise<RouteResponse> {\n const baseUrl = getConfig('_system.site.url') as string | undefined;\n const emailVerifiedRedirectUrl =\n getEmailConfig().verification?.redirectUrl ||\n getEmailConfig().emailVerifiedRedirectUrl ||\n baseUrl ||\n '/';\n try {\n const token = z.string().parse(params.query.token);\n const { userDoc } = await verifyEmailToken(token);\n\n const authConfig = getAuthConfig();\n authConfig.onAfterEmailVerification?.({\n provider: 'email',\n user: userDoc as User,\n session: null,\n connectionInfo: {\n baseUrl,\n ip: params.req.ip || params.req.socket.remoteAddress,\n userAgent: params.headers['user-agent'],\n acceptLanguage: params.headers['accept-language'],\n referrer: params.headers['referer'],\n },\n });\n\n const { authToken } = await createSession(userDoc._id);\n\n setAuthTokenCookie(params.res, authToken);\n\n return {\n status: 301,\n redirect: `${emailVerifiedRedirectUrl}?status=verified`,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'An unexpected error occurred';\n if (error instanceof Error) {\n const authConfig = getAuthConfig();\n authConfig.onEmailVerificationError?.({\n provider: 'email',\n error,\n session: null,\n connectionInfo: {\n baseUrl,\n ip: params.req.ip || params.req.socket.remoteAddress,\n userAgent: params.headers['user-agent'],\n acceptLanguage: params.headers['accept-language'],\n referrer: params.headers['referer'],\n },\n });\n console.error('Error verifying email:', error);\n }\n\n return {\n status: 301,\n redirect: `${emailVerifiedRedirectUrl}?status=error&message=${encodeURIComponent(message)}`,\n };\n }\n}\n\nexport async function sendVerificationEmail({\n userId,\n email,\n baseUrl = getConfig('_system.site.url') as string | undefined,\n}: {\n userId: ObjectId;\n email: string;\n baseUrl?: string;\n}) {\n if (getEmailConfig().provider) {\n const emailProvider = getEmailConfig().provider;\n\n // Generate verification token\n const verificationToken = randomBytes(32).toString('hex');\n const expiresAt = new Date(Date.now() + time.hours(24));\n\n // Store token in database\n await emailVerificationTokensCollection.insertOne({\n userId,\n email,\n token: verificationToken,\n createdAt: new Date(),\n expiresAt,\n });\n\n const verificationUrl = `${baseUrl}/api/_internal/auth/verify-email?token=${verificationToken}`;\n\n const template = getEmailConfig()?.verification?.template || emailVerificationTemplate;\n // TODO: we should have also the name on this step\n const htmlTemplate = template({ name: '', email, verificationUrl });\n const textContent = htmlToText(htmlTemplate);\n\n await emailProvider?.sendEmail({\n to: email,\n from: getEmailConfig()?.from || 'noreply@modelence.com',\n subject: getEmailConfig()?.verification?.subject || 'Verify your email address',\n text: textContent,\n html: htmlTemplate,\n });\n }\n}\n\nconst resendVerificationResponse = {\n success: true,\n message: 'If that email is registered and not yet verified, a verification email has been sent',\n};\n\nexport async function handleResendEmailVerification(args: Args, { connectionInfo }: Context) {\n const email = validateEmail(args.email as string);\n\n // Find user by email, excluding deleted/disabled accounts\n const userDoc = await usersCollection.findOne(\n { 'emails.address': email, status: { $nin: ['deleted', 'disabled'] } },\n { collation: { locale: 'en', strength: 2 } }\n );\n\n // Return the same generic response whether the email is unknown,\n // already verified, or successfully sent — to prevent user enumeration.\n if (!userDoc) {\n return resendVerificationResponse;\n }\n\n const emailDoc = userDoc.emails?.find((e) => e.address.toLowerCase() === email);\n\n if (!emailDoc || emailDoc.verified) {\n return resendVerificationResponse;\n }\n\n if (!getEmailConfig().provider) {\n throw new Error('Email provider is not configured');\n }\n\n await consumeRateLimit({\n bucket: 'verification',\n type: 'user',\n value: userDoc._id.toString(),\n message: 'Please wait at least 60 seconds before requesting another verification email',\n });\n\n await sendVerificationEmail({\n userId: userDoc._id,\n email,\n baseUrl: connectionInfo?.baseUrl,\n });\n\n return resendVerificationResponse;\n}\n","import bcrypt from 'bcrypt';\nimport { SignupProps, Context, Args } from '../methods/types';\nimport { usersCollection } from './db';\nimport { isDisposableEmail } from './disposableEmails';\nimport { consumeRateLimit } from '../rate-limit/rules';\nimport { sendVerificationEmail } from './verification';\nimport { validateEmail, validatePassword, validateProfileFields } from './validators';\nimport { getAuthConfig } from '@/app/authConfig';\nimport { resolveUniqueHandle } from './utils';\n\nexport async function handleSignupWithPassword(\n props: Args,\n { user, session, connectionInfo }: Context\n) {\n const authConfig = getAuthConfig();\n try {\n // Narrow once at the boundary\n const signupProps = props as SignupProps;\n const { firstName, lastName, avatarUrl, handle } = signupProps;\n\n const email = validateEmail(signupProps.email);\n const password = validatePassword(signupProps.password);\n\n const ip = connectionInfo?.ip;\n if (ip) {\n await consumeRateLimit({\n bucket: 'signupAttempt',\n type: 'ip',\n value: ip,\n });\n }\n\n if (await isDisposableEmail(email)) {\n throw new Error('Please use a permanent email address');\n }\n\n // TODO: captcha check\n\n if (user) {\n // TODO: handle cases where a user is already logged in\n }\n\n const existingUser = await usersCollection.findOne(\n { 'emails.address': email },\n { collation: { locale: 'en', strength: 2 } }\n );\n\n if (existingUser) {\n const existingEmail = existingUser.emails?.find((e) => e.address.toLowerCase() === email);\n if (existingUser.status === 'disabled') {\n throw new Error(\n `User is marked for deletion, please contact support if you want to restore the account.`\n );\n }\n throw new Error(`User with email already exists: ${existingEmail?.address}`);\n }\n\n if (ip) {\n await consumeRateLimit({\n bucket: 'signup',\n type: 'ip',\n value: ip,\n });\n }\n\n // Validate optional profile fields (firstName, lastName, avatarUrl, handle)\n const profileFields = validateProfileFields({\n firstName,\n lastName,\n avatarUrl,\n handle,\n });\n\n await authConfig.validateSignup?.({\n email,\n password,\n ...profileFields,\n });\n\n // Resolve unique handle\n let resolvedHandle: string;\n\n if (profileFields.handle) {\n resolvedHandle = await resolveUniqueHandle(profileFields.handle, email);\n } else if (authConfig.generateHandle) {\n const generated = await authConfig.generateHandle({\n email,\n firstName: profileFields.firstName,\n lastName: profileFields.lastName,\n });\n\n resolvedHandle = await resolveUniqueHandle(generated, email, {\n throwOnConflict: false,\n });\n } else {\n resolvedHandle = await resolveUniqueHandle(undefined, email);\n }\n\n // Hash password with bcrypt (salt is automatically generated)\n const hash = await bcrypt.hash(password, 10);\n\n const result = await usersCollection.insertOne({\n handle: resolvedHandle,\n status: 'active',\n emails: [\n {\n address: email,\n verified: false,\n },\n ],\n createdAt: new Date(),\n authMethods: {\n password: {\n hash,\n },\n },\n ...(profileFields.firstName !== undefined && { firstName: profileFields.firstName }),\n ...(profileFields.lastName !== undefined && { lastName: profileFields.lastName }),\n ...(profileFields.avatarUrl !== undefined && { avatarUrl: profileFields.avatarUrl }),\n });\n\n const userDocument = await usersCollection.findOne(\n { _id: result.insertedId },\n { readPreference: 'primary' }\n );\n\n if (!userDocument) {\n throw new Error('User not found');\n }\n\n await sendVerificationEmail({\n userId: result?.insertedId,\n email,\n baseUrl: connectionInfo?.baseUrl,\n });\n\n authConfig.onAfterSignup?.({\n provider: 'email',\n user: userDocument,\n session,\n connectionInfo,\n });\n\n authConfig.signup?.onSuccess?.(userDocument);\n\n return result.insertedId;\n } catch (error) {\n if (error instanceof Error) {\n authConfig.onSignupError?.({\n provider: 'email',\n error,\n session,\n connectionInfo,\n });\n\n authConfig.signup?.onError?.(error);\n }\n throw error;\n }\n}\n","import { z } from 'zod';\nimport bcrypt from 'bcrypt';\nimport { randomBytes } from 'crypto';\n\nimport { Args, Context } from '@/methods/types';\nimport { usersCollection, resetPasswordTokensCollection } from './db';\nimport { getEmailConfig } from '@/app/emailConfig';\nimport { time } from '@/time';\nimport { htmlToText } from '@/utils';\nimport { validateEmail, validatePassword } from './validators';\nimport { consumeRateLimit } from '@/server';\nimport { getConfig } from '@/config/server';\nimport { invalidateAllUserSessions } from './session';\n\nfunction resolveUrl(baseUrl: string, configuredUrl?: string): string {\n if (!configuredUrl) {\n return baseUrl;\n }\n\n if (configuredUrl.startsWith('http://') || configuredUrl.startsWith('https://')) {\n return configuredUrl;\n }\n\n // Handle relative URL\n return `${baseUrl}${configuredUrl.startsWith('/') ? '' : '/'}${configuredUrl}`;\n}\n\nfunction defaultPasswordResetTemplate({ email, resetUrl }: { email: string; resetUrl: string }) {\n return `\n <p>Hi,</p>\n <p>We received a request to reset your password for ${email}.</p>\n <p>Click the link below to reset your password:</p>\n <p><a href=\"${resetUrl}\">${resetUrl}</a></p>\n <p>This link will expire in 1 hour.</p>\n <p>If you did not request this password reset, please ignore this email.</p>\n `;\n}\n\nconst passwordResetSent = {\n success: true,\n message: 'If an account with that email exists, a password reset link has been sent',\n};\n\nexport async function handleSendResetPasswordToken(args: Args, { connectionInfo }: Context) {\n const email = validateEmail(args.email as string);\n const ip = connectionInfo?.ip;\n\n if (ip) {\n await consumeRateLimit({\n bucket: 'passwordReset',\n type: 'ip',\n value: ip,\n });\n }\n\n await consumeRateLimit({\n bucket: 'passwordReset',\n type: 'email',\n value: email,\n });\n\n // Find user by email\n const userDoc = await usersCollection.findOne(\n { 'emails.address': email, status: { $nin: ['deleted', 'disabled'] } },\n { collation: { locale: 'en', strength: 2 } }\n );\n\n if (!userDoc) {\n // For security, don't reveal if email exists or not\n return passwordResetSent;\n }\n\n // Check if user has password auth method\n if (!userDoc.authMethods?.password) {\n return passwordResetSent;\n }\n\n const emailProvider = getEmailConfig().provider;\n if (!emailProvider) {\n throw new Error('Email provider is not configured');\n }\n\n // Generate reset token\n const resetToken = randomBytes(32).toString('hex');\n const now = Date.now();\n const createdAt = new Date(now);\n const expiresAt = new Date(now + time.hours(1)); // 1 hour expiry\n\n // Store reset token\n await resetPasswordTokensCollection.insertOne({\n userId: userDoc._id,\n email,\n token: resetToken,\n createdAt,\n expiresAt,\n });\n\n // Build reset URL\n const baseUrl = (getConfig('_system.site.url') as string | undefined) || connectionInfo?.baseUrl;\n const resetPasswordUrl = resolveUrl(baseUrl!, getEmailConfig().passwordReset?.redirectUrl);\n const resetUrl = `${resetPasswordUrl}?token=${resetToken}`;\n\n // Send email\n const template = getEmailConfig()?.passwordReset?.template || defaultPasswordResetTemplate;\n const htmlTemplate = template({ email, resetUrl, name: '' });\n const textContent = htmlToText(htmlTemplate);\n\n await emailProvider.sendEmail({\n to: email,\n from: getEmailConfig()?.from || 'noreply@modelence.com',\n subject: getEmailConfig()?.passwordReset?.subject || 'Reset your password',\n text: textContent,\n html: htmlTemplate,\n });\n\n return passwordResetSent;\n}\n\nexport async function handleResetPassword(args: Args, {}: Context) {\n const token = z.string().parse(args.token);\n const password = validatePassword(args.password as string);\n\n // Find the reset token\n const resetTokenDoc = await resetPasswordTokensCollection.findOne({ token });\n if (!resetTokenDoc) {\n throw new Error('Invalid or expired reset token');\n }\n\n // Check if token is expired\n if (resetTokenDoc.expiresAt < new Date()) {\n await resetPasswordTokensCollection.deleteOne({ token });\n throw new Error('Reset token has expired');\n }\n\n // Find the user\n const userDoc = await usersCollection.findOne({ _id: resetTokenDoc.userId });\n if (!userDoc) {\n throw new Error('User not found');\n }\n\n // Hash the new password\n const hash = await bcrypt.hash(password, 10);\n\n // Update user's password\n await usersCollection.updateOne(\n { _id: userDoc._id },\n { $set: { 'authMethods.password.hash': hash } }\n );\n\n // Mark the email as verified since the user proved ownership via the reset token\n if (resetTokenDoc.email) {\n await usersCollection.updateOne(\n { _id: userDoc._id, 'emails.address': resetTokenDoc.email },\n { $set: { 'emails.$.verified': true } }\n );\n }\n\n // Invalidate all existing sessions for this user so that other browsers/devices\n // are forced to re-authenticate with the new password\n await invalidateAllUserSessions(userDoc._id);\n\n // Delete the used reset token\n await resetPasswordTokensCollection.deleteOne({ token });\n\n return { success: true, message: 'Password has been reset successfully' };\n}\n","import { randomBytes } from 'crypto';\n\nimport type {\n InternalAuthRateLimitsConfig,\n LegacyPasswordResetRateLimits,\n LegacySigninRateLimits,\n LegacySignupAttemptRateLimits,\n LegacySignupRateLimits,\n LegacyVerificationRateLimits,\n} from '../app/authConfig';\nimport { Module } from '../app/module';\nimport { RateLimitRule } from '../rate-limit/types';\nimport { time } from '../time';\nimport {\n dbDisposableEmailDomains,\n emailVerificationTokensCollection,\n resetPasswordTokensCollection,\n usersCollection,\n} from './db';\nimport { updateDisposableEmailListCron } from './disposableEmails';\nimport { handleLoginWithPassword, handleLogout } from './login';\nimport { getOwnProfile, handleUpdateProfile } from './profile';\nimport { handleUnlinkOAuthProvider } from './unlinkOAuthProvider';\nimport { handleSignupWithPassword } from './signup';\nimport { handleVerifyEmail, handleResendEmailVerification } from './verification';\nimport { handleResetPassword, handleSendResetPasswordToken } from './resetPassword';\n\n/**\n * Builds the rate limit rules for all authentication endpoints, merging any\n * caller-supplied overrides with the built-in defaults.\n *\n * Exposed so that `startApp` can pass user-configured limits at startup rather\n * than relying on static values baked into the Module constructor.\n */\nlet warnedLegacyRateLimits = false;\n\nfunction warnLegacyRateLimits(bucket: string) {\n if (warnedLegacyRateLimits) return;\n warnedLegacyRateLimits = true;\n console.warn(\n `[modelence] auth.rateLimits.${bucket}: the legacy object form (e.g. { perIp15Minutes, perIpPerDay }) is deprecated and will be removed in 1.0.0. ` +\n `Use the array form: [{ type: 'ip', window: time.minutes(15), limit: 10 }, ...].`\n );\n}\n\nfunction ruleKey(rule: Pick<RateLimitRule, 'bucket' | 'type' | 'window'>): string {\n return `${rule.bucket}\u0000${rule.type}\u0000${rule.window}`;\n}\n\nfunction defaultAuthRateLimits(): RateLimitRule[] {\n return [\n { bucket: 'signup', type: 'ip', window: time.minutes(15), limit: 20 },\n { bucket: 'signup', type: 'ip', window: time.days(1), limit: 200 },\n { bucket: 'signupAttempt', type: 'ip', window: time.minutes(15), limit: 50 },\n { bucket: 'signupAttempt', type: 'ip', window: time.days(1), limit: 500 },\n { bucket: 'signin', type: 'ip', window: time.minutes(15), limit: 50 },\n { bucket: 'signin', type: 'ip', window: time.days(1), limit: 500 },\n { bucket: 'verification', type: 'user', window: time.seconds(60), limit: 1 },\n { bucket: 'verification', type: 'user', window: time.days(1), limit: 10 },\n { bucket: 'passwordReset', type: 'ip', window: time.minutes(15), limit: 10 },\n { bucket: 'passwordReset', type: 'ip', window: time.days(1), limit: 100 },\n { bucket: 'passwordReset', type: 'email', window: time.hours(1), limit: 5 },\n { bucket: 'passwordReset', type: 'email', window: time.days(1), limit: 10 },\n ];\n}\n\nfunction legacyOverridesFor(\n bucket: string,\n legacy:\n | LegacySignupRateLimits\n | LegacySignupAttemptRateLimits\n | LegacySigninRateLimits\n | LegacyVerificationRateLimits\n | LegacyPasswordResetRateLimits\n): RateLimitRule[] {\n const rules: RateLimitRule[] = [];\n if (bucket === 'verification') {\n const v = legacy as LegacyVerificationRateLimits;\n if (v.perUserPerMinute !== undefined) {\n rules.push({ bucket, type: 'user', window: time.seconds(60), limit: v.perUserPerMinute });\n }\n if (v.perUserPerDay !== undefined) {\n rules.push({ bucket, type: 'user', window: time.days(1), limit: v.perUserPerDay });\n }\n return rules;\n }\n\n const ipBased = legacy as LegacySignupRateLimits & LegacyPasswordResetRateLimits;\n if (ipBased.perIp15Minutes !== undefined) {\n rules.push({ bucket, type: 'ip', window: time.minutes(15), limit: ipBased.perIp15Minutes });\n }\n if (ipBased.perIpPerDay !== undefined) {\n rules.push({ bucket, type: 'ip', window: time.days(1), limit: ipBased.perIpPerDay });\n }\n if (bucket === 'passwordReset') {\n const pw = legacy as LegacyPasswordResetRateLimits;\n if (pw.perEmailPerHour !== undefined) {\n rules.push({ bucket, type: 'email', window: time.hours(1), limit: pw.perEmailPerHour });\n }\n if (pw.perEmailPerDay !== undefined) {\n rules.push({ bucket, type: 'email', window: time.days(1), limit: pw.perEmailPerDay });\n }\n }\n return rules;\n}\n\nfunction collectOverrides(config: InternalAuthRateLimitsConfig): RateLimitRule[] {\n const overrides: RateLimitRule[] = [];\n\n const buckets: Array<keyof InternalAuthRateLimitsConfig> = [\n 'signup',\n 'signupAttempt',\n 'signin',\n 'verification',\n 'passwordReset',\n ];\n\n for (const bucket of buckets) {\n const value = config[bucket];\n if (value === undefined) continue;\n\n if (Array.isArray(value)) {\n for (const rule of value) {\n overrides.push({ bucket, ...rule });\n }\n } else {\n warnLegacyRateLimits(bucket);\n for (const rule of legacyOverridesFor(bucket, value)) {\n overrides.push(rule);\n }\n }\n }\n\n return overrides;\n}\n\n/**\n * Builds the rate limit rules for all authentication endpoints by merging\n * caller-supplied overrides into the built-in defaults.\n *\n * Merge semantics for the array form:\n * - Each override rule replaces the default rule with the same\n * (bucket, type, window) tuple.\n * - Defaults whose tuple is not overridden are preserved.\n * - Override rules with no matching default are added.\n *\n * This means `signup: [{ type: 'ip', window: time.minutes(15), limit: 10 }]`\n * tightens the 15-minute signup cap without dropping the per-day cap.\n *\n * Legacy object form is supported for back-compat and uses the same merge\n * semantics on a per-field basis. Remove the legacy branch in 1.0.0.\n */\nexport function buildAuthRateLimits(config: InternalAuthRateLimitsConfig = {}): RateLimitRule[] {\n const defaults = defaultAuthRateLimits();\n const overrides = collectOverrides(config);\n\n const overrideByKey = new Map<string, RateLimitRule>();\n for (const rule of overrides) {\n overrideByKey.set(ruleKey(rule), rule);\n }\n\n const merged: RateLimitRule[] = [];\n const consumed = new Set<string>();\n for (const def of defaults) {\n const key = ruleKey(def);\n const override = overrideByKey.get(key);\n if (override !== undefined) {\n merged.push(override);\n consumed.add(key);\n } else {\n merged.push(def);\n }\n }\n for (const [key, rule] of overrideByKey) {\n if (!consumed.has(key)) {\n merged.push(rule);\n }\n }\n return merged;\n}\n\nexport async function createGuestUser() {\n // TODO: add rate-limiting and captcha handling\n\n const guestId = randomBytes(9)\n .toString('base64')\n .replace(/[+/]/g, (c) => (c === '+' ? 'a' : 'b'));\n\n const handle = `guest_${guestId}`;\n // TODO: re-try on handle collision\n\n const result = await usersCollection.insertOne({\n handle,\n status: 'active',\n createdAt: new Date(),\n authMethods: {},\n });\n\n return result.insertedId;\n}\n\nexport default new Module('_system.user', {\n stores: [\n usersCollection,\n dbDisposableEmailDomains,\n emailVerificationTokensCollection,\n resetPasswordTokensCollection,\n ],\n queries: {\n getOwnProfile,\n },\n mutations: {\n signupWithPassword: handleSignupWithPassword,\n loginWithPassword: handleLoginWithPassword,\n logout: handleLogout,\n resendEmailVerification: handleResendEmailVerification,\n sendResetPasswordToken: handleSendResetPasswordToken,\n resetPassword: handleResetPassword,\n updateProfile: handleUpdateProfile,\n unlinkOAuthProvider: handleUnlinkOAuthProvider,\n },\n cronJobs: {\n updateDisposableEmailList: updateDisposableEmailListCron,\n },\n rateLimits: buildAuthRateLimits(),\n configSchema: {\n 'auth.email.enabled': {\n type: 'boolean',\n isPublic: true,\n default: true,\n },\n 'auth.email.from': {\n type: 'string',\n isPublic: false,\n default: '',\n },\n 'auth.email.verification': {\n type: 'boolean',\n isPublic: true,\n default: false,\n },\n 'auth.google.enabled': {\n type: 'boolean',\n isPublic: true,\n default: false,\n },\n 'auth.google.clientId': {\n type: 'string',\n isPublic: false,\n default: '',\n },\n 'auth.google.clientSecret': {\n type: 'secret',\n isPublic: false,\n default: '',\n },\n 'auth.github.enabled': {\n type: 'boolean',\n isPublic: true,\n default: false,\n },\n 'auth.github.clientId': {\n type: 'string',\n isPublic: false,\n default: '',\n },\n 'auth.github.clientSecret': {\n type: 'secret',\n isPublic: false,\n default: '',\n },\n },\n routes: [\n {\n path: '/api/_internal/auth/verify-email',\n handlers: {\n get: handleVerifyEmail,\n },\n },\n ],\n});\n","import { AppConfig, ConfigSchema, ConfigType } from './types';\n\ntype LocalConfigVariant = 'withRemoteServer' | 'withoutRemoteServer';\n\nconst localConfigMap = {\n withoutRemoteServer: {\n MONGODB_URI: '_system.mongodbUri',\n MONGODB_POOL_SIZE: '_system.mongodbPoolSize',\n MODELENCE_AUTH_GOOGLE_ENABLED: '_system.user.auth.google.enabled',\n MODELENCE_AUTH_GOOGLE_CLIENT_ID: '_system.user.auth.google.clientId',\n MODELENCE_AUTH_GOOGLE_CLIENT_SECRET: '_system.user.auth.google.clientSecret',\n MODELENCE_AUTH_GITHUB_ENABLED: '_system.user.auth.github.enabled',\n MODELENCE_AUTH_GITHUB_CLIENT_ID: '_system.user.auth.github.clientId',\n MODELENCE_AUTH_GITHUB_CLIENT_SECRET: '_system.user.auth.github.clientSecret',\n MODELENCE_AUTH_GITHUB_CLIENT_SCOPES: '_system.user.auth.github.scopes',\n MODELENCE_EMAIL_RESEND_API_KEY: '_system.email.resend.apiKey',\n MODELENCE_EMAIL_AWS_SES_REGION: '_system.email.awsSes.region',\n MODELENCE_EMAIL_AWS_SES_ACCESS_KEY_ID: '_system.email.awsSes.accessKeyId',\n MODELENCE_EMAIL_AWS_SES_SECRET_ACCESS_KEY: '_system.email.awsSes.secretAccessKey',\n MODELENCE_EMAIL_SMTP_HOST: '_system.email.smtp.host',\n MODELENCE_EMAIL_SMTP_PORT: '_system.email.smtp.port',\n MODELENCE_EMAIL_SMTP_USER: '_system.email.smtp.user',\n MODELENCE_EMAIL_SMTP_PASS: '_system.email.smtp.pass',\n MODELENCE_SITE_URL: '_system.site.url',\n MODELENCE_ENV_TYPE: '_system.env.type',\n MODELENCE_MULTI_INSTANCE: '_system.multiInstance',\n // deprecated\n MODELENCE_ENV: '_system.env',\n GOOGLE_AUTH_ENABLED: '_system.user.auth.google.enabled',\n GOOGLE_AUTH_CLIENT_ID: '_system.user.auth.google.clientId',\n GOOGLE_AUTH_CLIENT_SECRET: '_system.user.auth.google.clientSecret',\n },\n withRemoteServer: {\n MODELENCE_SITE_URL: '_system.site.url',\n },\n} as const;\n\nfunction formatLocalConfigValue(value: string, type: ConfigType): string | number | boolean {\n if (type === 'number') {\n const numValue = Number(value);\n if (isNaN(numValue)) {\n throw new Error(`Invalid number value for config: ${value}`);\n }\n return numValue;\n }\n if (type === 'boolean') {\n if (value.toLowerCase() === 'true') {\n return true;\n }\n if (value.toLowerCase() === 'false') {\n return false;\n }\n throw new Error(`Invalid boolean value for config: ${value}`);\n }\n return value;\n}\n\nfunction getConfigsFromEnvMap(\n configMap: Record<string, string>,\n configSchema: ConfigSchema\n): AppConfig[] {\n const configs: AppConfig[] = [];\n\n for (const [envVar, configKey] of Object.entries(configMap)) {\n const value = process.env[envVar];\n const configSchemaEntry = configSchema[configKey];\n if (value) {\n const type = configSchemaEntry?.type ?? 'string';\n configs.push({\n key: configKey,\n type: type,\n value: formatLocalConfigValue(value, type),\n });\n }\n }\n\n return configs;\n}\n\nexport function getLocalConfigs(\n configSchema: ConfigSchema,\n variant: LocalConfigVariant = 'withoutRemoteServer'\n): AppConfig[] {\n const configMap = localConfigMap[variant];\n return getConfigsFromEnvMap(configMap, configSchema);\n}\n","import os from 'os';\nimport { ConfigSchema } from '../config/types';\nimport { CronJobMetadata } from '../cron/types';\nimport { RoleDefinition } from '../auth/types';\nimport { Store } from '../data/store';\nimport { AppConfig } from '../config/types';\nimport { ModelSchema } from '../data/types';\n\ntype CloudBackendConnectOkResponse = {\n status: 'ok';\n configs: AppConfig[];\n environmentId: string;\n appAlias: string;\n environmentAlias: string;\n telemetry: {\n isEnabled: boolean;\n serviceName: string;\n };\n};\n\ntype CloudBackendConnectErrorResponse = {\n status: 'error';\n error: string;\n};\n\nexport type CloudBackendConnectResponse =\n | CloudBackendConnectOkResponse\n | CloudBackendConnectErrorResponse;\n\nexport async function connectCloudBackend({\n configSchema,\n cronJobsMetadata,\n stores,\n roles,\n}: {\n configSchema?: ConfigSchema;\n cronJobsMetadata?: CronJobMetadata[];\n stores?: Store<ModelSchema, Record<string, never>>[];\n roles?: Record<string, RoleDefinition>;\n}): Promise<CloudBackendConnectOkResponse> {\n const containerId = process.env.MODELENCE_CONTAINER_ID;\n if (!containerId) {\n throw new Error('Unable to connect to Modelence Cloud: MODELENCE_CONTAINER_ID is not set');\n }\n\n try {\n const dataStores = (stores ?? []).map((store) => ({\n name: store.getName(),\n schema: store.getSerializedSchema(),\n collections: [store.getName()],\n version: 2,\n indexes: store.getIndexes(),\n searchIndexes: store.getSearchIndexes(),\n indexCreationMode: store.getIndexCreationMode(),\n }));\n\n const data = await callApi<CloudBackendConnectResponse>('/api/connect', 'POST', {\n hostname: os.hostname(),\n containerId,\n dataModels: dataStores,\n configSchema,\n cronJobsMetadata,\n roles,\n });\n\n if (data.status === 'error') {\n throw new Error(data.error);\n }\n\n console.log('Successfully connected to Modelence Cloud');\n\n return data;\n } catch (error) {\n console.error('Unable to connect to Modelence Cloud:', error);\n throw error;\n }\n}\n\nexport async function fetchConfigs() {\n return callApi<{ configs: AppConfig[] }>('/api/configs', 'GET');\n}\n\nexport async function syncStatus() {\n const data = await callApi('/api/sync', 'POST', {\n containerId: process.env.MODELENCE_CONTAINER_ID,\n });\n return data;\n}\n\nasync function callApi<T = unknown>(endpoint: string, method: string, payload?: object) {\n return callCloudApi<T>(\n endpoint,\n method,\n payload ? JSON.stringify(payload) : undefined,\n payload ? { 'Content-Type': 'application/json' } : {}\n );\n}\n\nexport async function callCloudApi<T>(\n endpoint: string,\n method: string,\n body?: BodyInit,\n extraHeaders?: Record<string, string>\n): Promise<T> {\n const { MODELENCE_SERVICE_ENDPOINT, MODELENCE_SERVICE_TOKEN } = process.env;\n\n if (!MODELENCE_SERVICE_ENDPOINT) {\n throw new Error('Unable to connect to Modelence Cloud: MODELENCE_SERVICE_ENDPOINT is not set');\n }\n\n const response = await fetch(`${MODELENCE_SERVICE_ENDPOINT}${endpoint}`, {\n method,\n headers: {\n Authorization: `Bearer ${MODELENCE_SERVICE_TOKEN}`,\n ...extraHeaders,\n },\n body,\n });\n\n if (!response.ok) {\n const data = await response.text();\n try {\n const json = JSON.parse(data);\n throw new Error(\n `Unable to connect to Modelence Cloud: HTTP status: ${response.status}, ${json?.error}`\n );\n } catch {\n throw new Error(\n `Unable to connect to Modelence Cloud: HTTP status: ${response.status}, ${data}`\n );\n }\n }\n\n if (response.status === 204 || response.headers?.get('content-length') === '0') {\n return undefined as T;\n }\n\n return (await response.json()) as T;\n}\n","import { time } from '../time';\nimport { fetchConfigs, syncStatus } from '../app/backendApi';\nimport { getLocalConfigs } from './local';\nimport { loadConfigs, getSchema } from './server';\nimport { AppConfig } from './types';\n\nlet isSyncing = false;\n\nconst SYNC_INTERVAL = time.seconds(10);\n\nexport function startConfigSync() {\n setInterval(async () => {\n if (isSyncing) {\n return;\n }\n\n isSyncing = true;\n\n // TODO: move this sync outside of config\n try {\n await syncStatus();\n } catch (error) {\n console.error('Error syncing status', error);\n }\n\n try {\n await syncConfig();\n } catch (error) {\n console.error('Error syncing config', error);\n }\n\n isSyncing = false;\n }, SYNC_INTERVAL);\n}\n\nexport function loadRemoteConfigs(configs: AppConfig[]) {\n loadConfigs(configs);\n loadConfigs(getLocalConfigs(getSchema(), 'withRemoteServer'));\n}\n\nasync function syncConfig() {\n const { configs } = await fetchConfigs();\n loadRemoteConfigs(configs);\n}\n","import { schema } from '../data/types';\nimport { Store } from '../data/store';\n\n/**\n * Database collection for storing distributed locks.\n *\n * Locks are used to ensure that only one instance of the application can perform\n * a specific action at a time, such as running cron jobs or migrations\n */\nexport const locksCollection = new Store('_modelenceLocks', {\n schema: {\n _id: schema.string(), // unique identifier for the lock, used as the primary key\n instanceId: schema.string(),\n acquiredAt: schema.date(),\n\n resource: schema.string(), // deprecated, will be dropped in v1.0.0 (use _id instead)\n },\n indexes: [\n {\n // TODO(v1.0.0): remove after dropping legacy `resource` compatibility.\n key: { resource: 1 },\n unique: true,\n },\n {\n // TODO(v1.0.0): remove after dropping legacy `resource` compatibility.\n key: { resource: 1, instanceId: 1 },\n },\n {\n // TODO(v1.0.0): remove after dropping legacy `resource` compatibility.\n key: { resource: 1, acquiredAt: 1 },\n },\n ],\n indexCreationMode: 'blocking',\n});\n","import { randomBytes } from 'crypto';\nimport { MongoError } from 'mongodb';\nimport { locksCollection } from './db';\nimport { logDebug } from '../telemetry';\nimport { time } from '@/time';\n\n/**\n * In-memory cache to avoid frequent lock acquisition attempts\n * for the same resource within a short time frame.\n */\nconst lockCache: Record<\n string,\n {\n value: boolean;\n expiresAt: number;\n }\n> = {};\n\n/**\n * Time duration to consider a cached lock acquisition valid\n */\nconst DEFAULT_CACHE_DURATION = time.seconds(10);\n\n/**\n * Unique identifier for this application instance.\n * Generated once per application instance to track which container owns which locks.\n */\nconst INSTANCE_ID = randomBytes(32).toString('base64url');\n\n/**\n * Time after which a lock is expired\n */\nconst DEFAULT_LOCK_DURATION = time.seconds(30);\n\ntype LockOptions = {\n lockDuration?: number;\n successfulLockCacheDuration?: number;\n failedLockCacheDuration?: number;\n heartbeat?: boolean;\n bypassCache?: boolean;\n instanceId?: string;\n};\n\ntype LockHeartbeat = {\n timer: ReturnType<typeof setTimeout> | null;\n stopRequested: boolean;\n lockDuration: number;\n heartbeatInterval: number;\n};\n\nconst lockHeartbeats = new Map<string, LockHeartbeat>();\n\ntype DuplicateKeyMongoError = MongoError & {\n code?: number;\n keyPattern?: Record<string, unknown>;\n};\n\nconst isDuplicateKeyError = (error: unknown): error is DuplicateKeyMongoError =>\n error instanceof MongoError && error.code === 11000;\n\nconst hasKeyPatternField = (error: DuplicateKeyMongoError, field: string): boolean =>\n typeof error.keyPattern === 'object' &&\n error.keyPattern !== null &&\n Object.prototype.hasOwnProperty.call(error.keyPattern, field);\n\n/**\n * TODO(v1.0.0): Remove legacy `resource` fallback support.\n * This helper only exists for pre-1.0.0 lock documents where `_id !== resource`.\n * Delete this function and its call sites when releasing 1.0.0.\n */\nconst shouldFallbackToLegacyStrategy = async ({\n error,\n resource,\n}: {\n error: DuplicateKeyMongoError;\n resource: string;\n}): Promise<boolean> => {\n if (hasKeyPatternField(error, 'resource')) {\n return true;\n }\n\n if (hasKeyPatternField(error, '_id')) {\n return false;\n }\n\n const existingLock = (await locksCollection.findOne({ resource })) as {\n _id?: unknown;\n } | null;\n\n return !!existingLock && existingLock._id !== resource;\n};\n\nconst tryAcquireLockById = async ({\n resource,\n staleThresholdDate,\n instanceId,\n}: {\n resource: string;\n staleThresholdDate: Date;\n instanceId: string;\n}): Promise<boolean> => {\n const result = await locksCollection.upsertOne(\n {\n _id: resource,\n $or: [{ instanceId }, { acquiredAt: { $lt: staleThresholdDate } }],\n },\n {\n $set: {\n resource,\n instanceId,\n acquiredAt: new Date(),\n },\n $setOnInsert: {\n _id: resource,\n },\n }\n );\n\n return result.upsertedCount > 0 || result.modifiedCount > 0;\n};\n\nconst deleteLegacyLock = async ({\n resource,\n instanceId,\n staleThresholdDate,\n}: {\n resource: string;\n instanceId: string;\n staleThresholdDate?: Date;\n}): Promise<boolean> => {\n const selector = staleThresholdDate\n ? {\n resource,\n _id: { $ne: resource },\n $or: [{ instanceId }, { acquiredAt: { $lt: staleThresholdDate } }],\n }\n : {\n resource,\n instanceId,\n };\n\n const legacyDeleteResult = await locksCollection.deleteOne(selector);\n\n return legacyDeleteResult.deletedCount > 0;\n};\n\nconst stopLockHeartbeat = (resource: string) => {\n const heartbeatKey = resource;\n const heartbeat = lockHeartbeats.get(heartbeatKey);\n if (!heartbeat) {\n return;\n }\n\n heartbeat.stopRequested = true;\n if (heartbeat.timer) {\n clearTimeout(heartbeat.timer);\n heartbeat.timer = null;\n }\n\n lockHeartbeats.delete(heartbeatKey);\n};\n\nconst startLockHeartbeat = ({\n resource,\n lockDuration,\n instanceId,\n}: {\n resource: string;\n lockDuration: number;\n instanceId: string;\n}) => {\n const heartbeatInterval = Math.floor(lockDuration / 3);\n const heartbeatKey = resource;\n const existingHeartbeat = lockHeartbeats.get(heartbeatKey);\n\n if (\n existingHeartbeat &&\n !existingHeartbeat.stopRequested &&\n existingHeartbeat.heartbeatInterval === heartbeatInterval &&\n existingHeartbeat.lockDuration === lockDuration\n ) {\n return;\n }\n\n if (existingHeartbeat) {\n existingHeartbeat.stopRequested = true;\n if (existingHeartbeat.timer) {\n clearTimeout(existingHeartbeat.timer);\n existingHeartbeat.timer = null;\n }\n lockHeartbeats.delete(heartbeatKey);\n }\n\n const heartbeat: LockHeartbeat = {\n timer: null,\n stopRequested: false,\n lockDuration,\n heartbeatInterval,\n };\n\n const scheduleRefresh = () => {\n heartbeat.timer = setTimeout(() => {\n acquireLock(resource, {\n lockDuration,\n bypassCache: true,\n instanceId,\n })\n .then((isLockAcquired) => {\n if (!isLockAcquired) {\n heartbeat.stopRequested = true;\n logDebug(`Lost lock while refreshing heartbeat: ${resource}`, {\n source: 'lock',\n resource,\n instanceId,\n });\n }\n })\n .finally(() => {\n if (heartbeat.stopRequested) {\n lockHeartbeats.delete(heartbeatKey);\n return;\n }\n scheduleRefresh();\n });\n }, heartbeatInterval);\n };\n\n lockHeartbeats.set(heartbeatKey, heartbeat);\n scheduleRefresh();\n};\n\n/**\n * Acquires a lock of the specified resource.\n * If the lock already exists and is owned by another container, this will fail.\n * If the lock is expired (no recent heartbeat), it will be taken over.\n *\n * @param resource - The type of lock to acquire\n * @param options.lockDuration - Time in ms after which a lock is considered expired (default: 30s)\n * @param options.successfulLockCacheDuration - Time in ms to cache successful lock acquisition\n * @param options.failedLockCacheDuration - Time in ms to cache failed lock acquisition\n * @param options.heartbeat - If true, auto-refreshes lock ownership at lockDuration/3 intervals\n * @param options.bypassCache - If true, skips the in-memory cache and always hits the DB\n * @param options.instanceId - The unique identifier for this application instance\n * @returns true if lock was acquired, false otherwise\n */\nexport async function acquireLock(\n resource: string,\n {\n lockDuration = DEFAULT_LOCK_DURATION,\n successfulLockCacheDuration = DEFAULT_CACHE_DURATION,\n failedLockCacheDuration = DEFAULT_CACHE_DURATION,\n heartbeat,\n bypassCache,\n instanceId = INSTANCE_ID,\n }: LockOptions = {}\n): Promise<boolean> {\n const now = Date.now();\n if (!bypassCache && lockCache[resource] && now < lockCache[resource].expiresAt) {\n if (lockCache[resource].value && heartbeat) {\n startLockHeartbeat({\n resource,\n lockDuration,\n instanceId,\n });\n }\n return lockCache[resource].value;\n }\n\n const staleThresholdDate = new Date(now - lockDuration);\n\n logDebug(`Attempting to acquire lock: ${resource}`, {\n source: 'lock',\n resource,\n instanceId,\n });\n\n try {\n const isLockAcquired = await acquireLockById({\n resource,\n staleThresholdDate,\n instanceId,\n });\n\n lockCache[resource] = {\n value: isLockAcquired,\n expiresAt: now + (isLockAcquired ? successfulLockCacheDuration : failedLockCacheDuration),\n };\n\n if (isLockAcquired) {\n if (heartbeat) {\n startLockHeartbeat({\n resource,\n lockDuration,\n instanceId,\n });\n }\n\n logDebug(`Lock acquired: ${resource}`, {\n source: 'lock',\n resource,\n instanceId,\n });\n } else {\n logDebug(`Failed to acquire lock (already held): ${resource}`, {\n source: 'lock',\n resource,\n instanceId,\n });\n }\n\n return isLockAcquired;\n } catch {\n lockCache[resource] = {\n value: false,\n expiresAt: now + failedLockCacheDuration,\n };\n logDebug(`Failed to acquire lock (already held): ${resource}`, {\n source: 'lock',\n resource,\n instanceId,\n });\n return false;\n }\n}\n\nconst acquireLockById = async ({\n resource,\n staleThresholdDate,\n instanceId,\n}: {\n resource: string;\n staleThresholdDate: Date;\n instanceId: string;\n}): Promise<boolean> => {\n try {\n return await tryAcquireLockById({ resource, staleThresholdDate, instanceId });\n } catch (error) {\n // TODO(v1.0.0): Remove the legacy fallback\n // Backward compatibility: if an old lock doc exists with a non-resource _id and\n // a unique `resource` index, upserting the new `_id = resource` shape can fail.\n // Migrate that legacy lock document to `_id = resource` and retry current strategy.\n if (isDuplicateKeyError(error) && (await shouldFallbackToLegacyStrategy({ error, resource }))) {\n const hasDeletedLegacyLock = await deleteLegacyLock({\n resource,\n staleThresholdDate,\n instanceId,\n });\n\n if (!hasDeletedLegacyLock) {\n return false;\n }\n\n try {\n return await tryAcquireLockById({ resource, staleThresholdDate, instanceId });\n } catch (retryError) {\n if (isDuplicateKeyError(retryError)) {\n return false;\n }\n throw retryError;\n }\n }\n\n // Duplicate _id means the lock exists but was not eligible for update (owned + fresh).\n if (isDuplicateKeyError(error)) {\n return false;\n }\n\n throw error;\n }\n};\n\n/**\n * Releases a lock of the specified resource owned by this container.\n *\n * @param resource - The resource to release the lock for\n * @param options.instanceId - The unique identifier for this application instance\n * @returns true if lock was released, false if lock wasn't owned by this container or release failed.\n */\nexport async function releaseLock(\n resource: string,\n {\n instanceId = INSTANCE_ID,\n }: {\n instanceId?: string;\n } = {}\n): Promise<boolean> {\n stopLockHeartbeat(resource);\n\n try {\n const result = await locksCollection.deleteOne({\n _id: resource,\n instanceId,\n });\n\n // TODO(v1.0.0): Remove the legacy fallback\n if (result.deletedCount === 0) {\n const hasDeletedLegacyLock = await deleteLegacyLock({\n resource,\n instanceId,\n });\n\n return hasDeletedLegacyLock;\n }\n\n return result.deletedCount > 0;\n } catch {\n return false;\n } finally {\n delete lockCache[resource];\n }\n}\n","// import { Worker, isMainThread, parentPort, workerData } from 'worker_threads';\n\nimport { time } from '../time';\nimport { CronJob, CronJobInputParams } from './types';\nimport { startTransaction, captureError } from '@/telemetry';\nimport { Module } from '../app/module';\nimport { schema } from '../data/types';\nimport { Store } from '../data/store';\nimport { acquireLock } from '../lock/helpers';\n\nconst cronJobs: Record<string, CronJob> = {};\nlet cronJobsInterval: NodeJS.Timeout | null = null;\n\nconst cronJobsCollection = new Store('_modelenceCronJobs', {\n schema: {\n alias: schema.string(),\n lastStartDate: schema.date().optional(),\n },\n indexes: [{ key: { alias: 1 }, unique: true, background: true }],\n});\n\n// TODO: allow changing interval and timeout with cron jobconfigs\nexport function defineCronJob(\n alias: CronJob['alias'],\n {\n description = '',\n interval,\n timeout = Math.min(Math.max(interval, time.minutes(1)), time.days(1)),\n handler,\n }: CronJobInputParams\n) {\n if (cronJobs[alias]) {\n throw new Error(`Duplicate cron job declaration: '${alias}' already exists`);\n }\n\n if (cronJobsInterval) {\n throw new Error(\n `Unable to add a cron job - cron jobs have already been initialized: [${alias}]`\n );\n }\n\n if (interval < time.seconds(5)) {\n throw new Error(`Cron job interval should not be less than 5 second [${alias}]`);\n }\n\n if (timeout > time.days(1)) {\n throw new Error(`Cron job timeout should not be longer than 1 day [${alias}]`);\n }\n\n cronJobs[alias] = {\n alias,\n params: { description, interval, timeout },\n handler,\n state: {\n isRunning: false,\n },\n };\n}\n\nexport async function startCronJobs() {\n if (cronJobsInterval) {\n throw new Error('Cron jobs already started');\n }\n\n const aliasList = Object.keys(cronJobs);\n if (aliasList.length > 0) {\n const aliasSelector = { alias: { $in: aliasList } };\n\n const cronJobRecords = await cronJobsCollection.fetch(aliasSelector);\n const now = Date.now();\n cronJobRecords.forEach((record) => {\n const job = cronJobs[record.alias];\n if (!job) {\n return;\n }\n job.state.scheduledRunTs = record.lastStartDate\n ? record.lastStartDate.getTime() + job.params.interval\n : now;\n });\n Object.values(cronJobs).forEach((job) => {\n if (!job.state.scheduledRunTs) {\n job.state.scheduledRunTs = now;\n }\n });\n\n cronJobsInterval = setInterval(tickCronJobs, time.seconds(1));\n }\n}\n\nasync function tickCronJobs() {\n const now = Date.now();\n\n const ownsLock = await acquireLock('cron', {\n successfulLockCacheDuration: time.seconds(10),\n failedLockCacheDuration: time.seconds(30),\n });\n\n if (!ownsLock) {\n return;\n }\n\n Object.values(cronJobs).forEach(async (job) => {\n const { params, state } = job;\n if (state.isRunning) {\n if (state.startTs && state.startTs + params.timeout < now) {\n // TODO: log cron trace timeout error\n state.isRunning = false;\n }\n return;\n }\n\n // TODO: limit the number of jobs running concurrently\n\n if (state.scheduledRunTs && state.scheduledRunTs <= now) {\n await runCronJob(job);\n }\n });\n}\n\nasync function runCronJob(job: CronJob) {\n const { alias, params, handler, state } = job;\n state.isRunning = true;\n state.startTs = Date.now();\n\n await cronJobsCollection.updateOne(\n { alias },\n {\n $set: {\n lastStartDate: new Date(state.startTs),\n },\n }\n );\n\n const transaction = startTransaction('cron', `cron:${alias}`);\n // TODO: enforce job timeout\n try {\n await handler();\n handleCronJobCompletion(state, params);\n transaction.end('success');\n } catch (err) {\n handleCronJobCompletion(state, params);\n const error = err instanceof Error ? err : new Error(String(err));\n captureError(error);\n transaction.end('error');\n console.error(`Error in cron job '${alias}':`, err);\n }\n}\n\nfunction handleCronJobCompletion(state: CronJob['state'], params: CronJob['params']) {\n state.scheduledRunTs = state.startTs ? state.startTs + params.interval : Date.now();\n state.startTs = undefined;\n state.isRunning = false;\n}\n\nexport function getCronJobsMetadata() {\n return Object.values(cronJobs).map(({ alias, params }) => ({\n alias,\n description: params.description,\n interval: params.interval,\n timeout: params.timeout,\n }));\n}\n\nexport default new Module('_system.cron', {\n stores: [cronJobsCollection],\n});\n\n// const runCronJob = () => {\n// const worker = new Worker(filePath, {\n// workerData: {},\n// execArgv: ['--loader', 'tsx'],\n// });\n\n// const timeoutId = setTimeout(() => {\n// worker.terminate();\n// console.error(`Cron job '${alias}' timed out after ${timeout}ms`);\n// }, timeout);\n\n// worker.on('message', (message) => {\n// if (message === 'done') {\n// clearTimeout(timeoutId);\n// worker.terminate();\n// }\n// });\n\n// worker.on('error', (err) => {\n// clearTimeout(timeoutId);\n// console.error(`Error in cron job '${alias}':`, err);\n// });\n\n// worker.on('exit', (code) => {\n// console.error(`Cron job '${alias}' exited with code ${code}`);\n// setTimeout(runCronJob, interval);\n// });\n// };\n","import { Store } from './store';\nimport { ModelSchema } from './types';\n\ntype NormalizedStore = Store<ModelSchema, Record<string, never>>;\n\nexport type ResolvedStores = {\n storesToInit: NormalizedStore[];\n effectiveStores: NormalizedStore[];\n};\n\n/**\n * Resolves module stores into two sets:\n *\n * - `storesToInit`: unique runtime instances that must be initialized.\n * - `effectiveStores`: the latest tail of each extension chain, used for\n * index reconciliation and cloud metadata.\n *\n * Throws if two unrelated chains share the same collection name.\n *\n * @internal\n */\nexport function resolveStores(stores: NormalizedStore[]): ResolvedStores {\n const uniqueStores = [...new Set(stores)];\n\n // Collect the chain tail for each unique root\n const rootToTail = new Map<NormalizedStore, NormalizedStore>();\n for (const store of uniqueStores) {\n const root = store.getChainRoot();\n rootToTail.set(root, root.getChainTail());\n }\n\n const effectiveStores = [...new Set(rootToTail.values())] as NormalizedStore[];\n\n // Detect collisions: different chains with the same collection name\n const nameToRoot = new Map<string, NormalizedStore>();\n for (const [root, tail] of rootToTail) {\n const name = tail.getName();\n const existing = nameToRoot.get(name);\n if (existing !== undefined && existing !== root) {\n throw new Error(\n `Store collision: multiple unrelated stores use collection name '${name}'. ` +\n `Use .extend() to create a single extension chain instead of independent stores.`\n );\n }\n nameToRoot.set(name, root);\n }\n\n return { storesToInit: uniqueStores, effectiveStores };\n}\n","import { Module } from '../app/module';\nimport { locksCollection } from './db';\n\n/**\n * Lock module for distributed locking across multiple instances.\n */\nexport default new Module('_system.lock', {\n stores: [locksCollection],\n});\n","import { Store } from '../data/store';\nimport { schema } from '../data/types';\n\nexport const dbMigrations = new Store('_modelenceMigrations', {\n schema: {\n version: schema.number(),\n status: schema.enum(['completed', 'failed']),\n description: schema.string().optional(),\n output: schema.string().optional(),\n appliedAt: schema.date(),\n },\n indexes: [{ key: { version: 1 }, unique: true }, { key: { version: 1, status: 1 } }],\n});\n","import { acquireLock, releaseLock } from '@/lock';\nimport { Module } from '../app/module';\nimport { dbMigrations } from './db';\nimport { logInfo } from '../telemetry';\n\nexport type MigrationScript = {\n version: number;\n description: string;\n handler: () => Promise<string | void>;\n};\n\ntype MigrationRunOptions = {\n lockMode?: 'acquire' | 'skip';\n};\n\nexport async function runMigrations(\n migrations: MigrationScript[],\n { lockMode = 'acquire' }: MigrationRunOptions = {}\n) {\n if (migrations.length === 0) {\n return;\n }\n\n if (lockMode === 'acquire') {\n const hasLock = await acquireLock('migrations');\n\n if (!hasLock) {\n logInfo('Another instance is running migrations. Skipping migration run.', {\n source: 'migrations',\n });\n return;\n }\n }\n\n try {\n const versions = migrations.map(({ version }) => version);\n\n const existingVersions = await dbMigrations.fetch({\n version: { $in: versions },\n });\n const existingVersionSet = new Set(existingVersions.map(({ version }) => version));\n const pendingMigrations = migrations.filter(({ version }) => !existingVersionSet.has(version));\n\n if (pendingMigrations.length === 0) {\n return;\n }\n\n logInfo(`Running migrations (${pendingMigrations.length})...`, {\n source: 'migrations',\n });\n for (const { version, description, handler } of pendingMigrations) {\n logInfo(`Running migration v${version}: ${description}`, {\n source: 'migrations',\n });\n try {\n const output = await handler();\n const outputStr = (output || '').toString().trim();\n const maxSize = 15 * 1024 * 1024; // 15MB (leaving 1MB buffer for other fields and MongoDB overhead)\n const truncatedOutput =\n outputStr.length > maxSize\n ? outputStr.slice(0, maxSize) + '\\n[Output truncated - exceeded size limit]'\n : outputStr;\n await dbMigrations.upsertOne(\n {\n version,\n },\n {\n $set: {\n version,\n status: 'completed',\n description,\n output: truncatedOutput,\n appliedAt: new Date(),\n },\n }\n );\n logInfo(`Migration v${version} complete`, {\n source: 'migrations',\n });\n } catch (e) {\n if (e instanceof Error) {\n await dbMigrations.upsertOne(\n {\n version,\n },\n {\n $set: {\n version,\n status: 'failed',\n description,\n output: e.message || '',\n appliedAt: new Date(),\n },\n }\n );\n logInfo(`Migration v${version} is failed: ${e.message}`, {\n source: 'migrations',\n });\n }\n }\n }\n } finally {\n if (lockMode === 'acquire') {\n await releaseLock('migrations');\n }\n }\n}\n\nexport function startMigrations(migrations: MigrationScript[]) {\n setTimeout(() => {\n runMigrations(migrations).catch((err) => {\n console.error('Error running migrations:', err);\n });\n }, 0);\n}\n\nexport default new Module('_system.migration', {\n stores: [dbMigrations],\n});\n","import { Module } from '../app/module';\nimport { dbRateLimits } from './db';\n\nexport default new Module('_system.rateLimit', {\n stores: [dbRateLimits],\n});\n","import { Module } from '../app/module';\nimport { callCloudApi } from '../app/backendApi';\nexport type { FileVisibility, GetUploadUrlResult } from './types';\nimport type { FileVisibility, GetUploadUrlResult } from './types';\n\ntype DownloadFileResult = {\n downloadUrl: string;\n};\n\ntype GetFileUrlResult = {\n url: string;\n};\n\nexport async function getUploadUrl({\n filePath,\n contentType,\n visibility,\n}: {\n filePath: string;\n contentType: string;\n visibility: FileVisibility;\n}): Promise<GetUploadUrlResult> {\n return await callCloudApi<GetUploadUrlResult>(\n '/api/files/upload',\n 'POST',\n JSON.stringify({ filePath, contentType, visibility }),\n {\n 'Content-Type': 'application/json',\n }\n );\n}\n\nexport async function deleteFile(filePath: string): Promise<void> {\n await callCloudApi<void>('/api/files/delete', 'POST', JSON.stringify({ filePath }), {\n 'Content-Type': 'application/json',\n });\n}\n\nexport async function downloadFile(filePath: string): Promise<DownloadFileResult> {\n return await callCloudApi<DownloadFileResult>(\n '/api/files/download',\n 'POST',\n JSON.stringify({ filePath }),\n {\n 'Content-Type': 'application/json',\n }\n );\n}\n\nexport async function getFileUrl(filePath: string): Promise<GetFileUrlResult> {\n return await callCloudApi<GetFileUrlResult>(\n '/api/files/url',\n 'POST',\n JSON.stringify({ filePath }),\n {\n 'Content-Type': 'application/json',\n }\n );\n}\n\nexport default new Module('_system.files', {\n queries: {\n async downloadFile({ filePath }) {\n return downloadFile(filePath as string);\n },\n async getFileUrl({ filePath }) {\n return getFileUrl(filePath as string);\n },\n },\n mutations: {\n async getUploadUrl({ filePath, contentType, visibility }) {\n return getUploadUrl({\n filePath: filePath as string,\n contentType: contentType as string,\n visibility: visibility as FileVisibility,\n });\n },\n async deleteFile({ filePath }) {\n return deleteFile(filePath as string);\n },\n },\n});\n","import {\n createServer,\n defineConfig,\n ViteDevServer,\n loadConfigFromFile,\n UserConfig,\n mergeConfig,\n Plugin,\n PluginOption,\n} from 'vite';\nimport reactPlugin from '@vitejs/plugin-react';\nimport path from 'path';\nimport fs from 'fs';\nimport express from 'express';\nimport type { AppServer, AppServerInitOptions, ExpressMiddleware } from './types';\n\nconst CLIENT_BUILD_DIR = './.modelence/build/client'.replace(/\\\\/g, '/');\nconst SSR_BUILD_DIR = './.modelence/build/ssr'.replace(/\\\\/g, '/');\n// Resolved relative to Vite's `root` (./src/client) — see getConfig() below.\nconst SSR_ENTRY_VIRTUAL_PATH = '/index.tsx';\n// Matches the empty `<div id=\"root\"></div>` placeholder shipped in the Vite\n// HTML template. Allowing whitespace inside keeps it tolerant of formatting\n// without becoming greedy across unrelated `</div>` tags.\nconst ROOT_PLACEHOLDER_REGEX = /<div id=\"root\">\\s*<\\/div>/;\nconst HEAD_CLOSE_TAG = '</head>';\n\nclass ViteServer implements AppServer {\n private viteServer?: ViteDevServer;\n private config?: UserConfig;\n private ssrEnabled = false;\n private ssrTransportInstalled = false;\n private prodEntryLoaded = false;\n // Computed once at first SSR request in prod (the manifest is immutable\n // after build). Dev mode recomputes per request because HMR can shift the\n // module graph.\n private prodCssAssetsCache?: import('./ssr/collectCss').CssAssets;\n // Same rationale as `prodCssAssetsCache`: the built index.html is immutable\n // after build, so cache it to avoid a sync fs read on every request.\n private prodTemplateCache?: string;\n\n enableSsr() {\n this.ssrEnabled = true;\n }\n\n async init({ httpServer }: AppServerInitOptions) {\n this.config = await getConfig(this.isDev() ? httpServer : undefined, { ssr: this.ssrEnabled });\n if (this.isDev()) {\n console.log('Starting Vite dev server...');\n this.viteServer = await createServer(this.config);\n }\n\n if (this.ssrEnabled && !this.ssrTransportInstalled) {\n const { installSsrCallMethodTransport } = await import('./ssr/transport');\n installSsrCallMethodTransport();\n this.ssrTransportInstalled = true;\n }\n }\n\n middlewares(): ExpressMiddleware[] {\n if (this.isDev()) {\n return (this.viteServer?.middlewares ?? []) as ExpressMiddleware[];\n }\n\n const staticFolders = [express.static(CLIENT_BUILD_DIR)];\n if (this.config?.publicDir) {\n staticFolders.push(express.static(this.config.publicDir));\n }\n return staticFolders;\n }\n\n async handler(req: express.Request, res: express.Response) {\n if (this.ssrEnabled && isDocumentRequest(req)) {\n try {\n await this.handleSsr(req, res);\n } catch (error) {\n if (this.isDev() && this.viteServer && error instanceof Error) {\n this.viteServer.ssrFixStacktrace(error);\n }\n console.error('SSR render error:', {\n url: req.originalUrl,\n method: req.method,\n userAgent: req.get('user-agent'),\n error,\n });\n // If we've already started streaming the response, we can't recover —\n // just terminate so the client gets a truncated (but usable) page.\n if (res.headersSent) {\n res.end();\n return;\n }\n // Fall back to CSR shell so the client can still recover.\n this.serveStaticShell(res);\n }\n return;\n }\n\n if (this.ssrEnabled) {\n res.status(404).end();\n return;\n }\n\n this.serveStaticShell(res);\n }\n\n private async handleSsr(req: express.Request, res: express.Response) {\n const template = await this.getTemplate(req.originalUrl);\n const snapshot = await this.captureSsrSnapshot();\n if (!snapshot) {\n throw new Error(\n 'Modelence SSR is enabled but no SSR snapshot was captured. ' +\n \"Make sure 'src/client/index.tsx' calls renderApp(...) from 'modelence/client'.\"\n );\n }\n\n // Lazy imports keep react-dom/server (and friends) out of the boot path\n // for non-SSR requests.\n const [{ renderSsrTreeStream }, { getCallContext }, cssModule] = await Promise.all([\n import('./ssr/render'),\n import('./app/server'),\n import('./ssr/collectCss'),\n ]);\n\n const callContext = await getCallContext(req, res);\n\n const cssAssets = this.collectCssAssets(cssModule);\n\n // 103 Early Hints — tell the browser to start fetching the stylesheets\n // before the SSR render has even begun. No-op if the platform doesn't\n // support it (older Node, proxies that strip 1xx, etc.).\n sendEarlyHints(res, cssModule.buildEarlyHintsLink(cssAssets));\n\n const { sessionState, pipe, getQueryState } = await renderSsrTreeStream({\n callContext,\n loadingElement: snapshot.loadingElement,\n routesElement: snapshot.routesElement,\n router: snapshot.router,\n location: req.originalUrl,\n });\n\n // Split the template at the `<div id=\"root\">` placeholder. The head\n // (plus opening body) flushes immediately with CSS links inlined; React\n // then streams the shell into the placeholder; the closing template\n // (plus dehydrated query state) flushes after the stream finishes.\n if (!ROOT_PLACEHOLDER_REGEX.test(template)) {\n throw new Error('SSR template is missing the expected `<div id=\"root\"></div>` placeholder.');\n }\n const [rawPrelude, rawEpilogue] = splitTemplateAtRoot(template);\n const prelude = injectStylesheets(rawPrelude, cssModule.renderStylesheetLinks(cssAssets));\n\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n res.setHeader('Cache-Control', 'no-store');\n res.status(200);\n\n // Flush prelude (head with CSS + opening shell up to `<div id=\"root\">`)\n // and the session state script. Session state is fully resolved before\n // the React render starts, so it's safe to inline up front.\n res.write(prelude);\n res.write(\n `<script id=\"__MODELENCE_STATE__\" type=\"application/json\">${escapeJsonForScript(\n sessionState\n )}</script>`\n );\n res.write('<div id=\"root\">');\n\n await pipe(res as unknown as import('node:stream').Writable);\n\n // Stream finished — close out the root container, emit the dehydrated\n // query state, and write the rest of the template. The state script\n // appears after </div> but before </body>; client hydration reads it\n // via getElementById, so order doesn't matter for correctness.\n res.write('</div>');\n res.write(\n `<script id=\"__MODELENCE_QUERY_STATE__\" type=\"application/json\">${escapeJsonForScript(\n getQueryState()\n )}</script>`\n );\n res.end(rawEpilogue);\n }\n\n private collectCssAssets(\n cssModule: typeof import('./ssr/collectCss')\n ): import('./ssr/collectCss').CssAssets {\n if (this.isDev()) {\n if (!this.viteServer) {\n return { hrefs: [], source: 'dev' };\n }\n return cssModule.collectDevCssAssets(this.viteServer, SSR_ENTRY_VIRTUAL_PATH);\n }\n\n if (!this.prodCssAssetsCache) {\n this.prodCssAssetsCache = cssModule.loadProdCssAssets(CLIENT_BUILD_DIR);\n }\n return this.prodCssAssetsCache;\n }\n\n private async getTemplate(url: string): Promise<string> {\n if (this.isDev()) {\n const templatePath = path.resolve(process.cwd(), 'src/client/index.html');\n let template = fs.readFileSync(templatePath, 'utf-8');\n if (this.viteServer) {\n template = await this.viteServer.transformIndexHtml(url, template);\n }\n return template;\n }\n\n if (!this.prodTemplateCache) {\n const templatePath = path.resolve(process.cwd(), CLIENT_BUILD_DIR, 'index.html');\n this.prodTemplateCache = fs.readFileSync(templatePath, 'utf-8');\n }\n return this.prodTemplateCache;\n }\n\n private async captureSsrSnapshot(): Promise<\n import('./client/renderApp').RenderAppOptions | null\n > {\n // Evaluating the user's entry runs its top-level renderApp(...) which\n // populates the SSR snapshot. Read the snapshot synchronously right\n // after evaluation so concurrent requests can't overwrite it on\n // globalThis between the load and the read.\n const { _getSsrSnapshot } = await import('./client/renderApp');\n\n if (this.isDev()) {\n // Re-evaluate every request so dev-mode HMR edits apply.\n if (!this.viteServer) {\n throw new Error('Vite dev server not initialized');\n }\n await this.viteServer.ssrLoadModule(SSR_ENTRY_VIRTUAL_PATH);\n return _getSsrSnapshot();\n }\n\n // In production, Node caches the dynamic import. Evaluate exactly once\n // so the snapshot is populated on first request and reused thereafter.\n if (!this.prodEntryLoaded) {\n await import(path.resolve(process.cwd(), SSR_BUILD_DIR, 'index.mjs'));\n this.prodEntryLoaded = true;\n }\n return _getSsrSnapshot();\n }\n\n private serveStaticShell(res: express.Response) {\n if (this.isDev()) {\n try {\n // Prevent browser from caching the HTML entrypoint in dev mode.\n // Vite's transformMiddleware uses no-cache + ETag for .ts/.tsx modules,\n // which revalidates correctly. But the HTML served by Express's sendFile\n // can be cached by the browser (e.g. bfcache on back/forward navigation).\n // Without HMR WebSocket, stale HTML leads to dynamic import() URLs that\n // reference modules the current Vite instance doesn't recognize.\n res.setHeader('Cache-Control', 'no-store');\n res.sendFile('index.html', { root: './src/client' });\n } catch (e) {\n console.error('Error serving index.html:', e);\n res.status(500).send('Internal Server Error');\n }\n } else {\n res.sendFile('index.html', { root: CLIENT_BUILD_DIR });\n }\n }\n\n private isDev() {\n return process.env.NODE_ENV !== 'production';\n }\n}\n\nfunction isDocumentRequest(req: express.Request): boolean {\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n return false;\n }\n\n const accept = req.get('accept') ?? '';\n if (!accept.includes('text/html')) {\n return false;\n }\n\n const pathname = (req.path ?? req.url ?? '').split('?')[0];\n\n // API endpoints never produce HTML, even when a curious client sends an\n // Accept header that includes text/html.\n if (pathname.startsWith('/api/')) {\n return false;\n }\n\n // Skip URLs with non-HTML extensions (dev-tools probes, favicons, sourcemaps).\n const lastSegment = pathname.split('/').pop() ?? '';\n const dotIndex = lastSegment.lastIndexOf('.');\n if (dotIndex > 0) {\n const ext = lastSegment.slice(dotIndex).toLowerCase();\n if (ext !== '.html' && ext !== '.htm') {\n return false;\n }\n }\n\n return true;\n}\n\nexport function escapeJsonForScript(json: string): string {\n // Escape </script>, HTML chars, and U+2028/U+2029 (illegal in JS source).\n // Single-pass replace avoids order-dependent double-escape pitfalls.\n return json.replace(\n /[<>&\\u2028\\u2029]/g,\n (ch) => `\\\\u${ch.charCodeAt(0).toString(16).padStart(4, '0')}`\n );\n}\n\n/**\n * Split the HTML template at the `<div id=\"root\">` placeholder so the head\n * can stream first and the React shell can pipe directly into the response.\n */\nfunction splitTemplateAtRoot(template: string): [string, string] {\n const match = template.match(ROOT_PLACEHOLDER_REGEX);\n if (!match || match.index === undefined) {\n throw new Error('SSR template is missing the expected `<div id=\"root\"></div>` placeholder.');\n }\n const prelude = template.slice(0, match.index);\n const epilogue = template.slice(match.index + match[0].length);\n return [prelude, epilogue];\n}\n\n/**\n * Inject CSS <link> tags just before `</head>` so styles arrive in the first\n * flushed chunk. Falls back to prepending the prelude if no `</head>` is found\n * (templates may legitimately omit it — the browser will still load the\n * stylesheet, it just won't be in the head).\n */\nfunction injectStylesheets(prelude: string, linksHtml: string): string {\n if (!linksHtml) {\n return prelude;\n }\n const headCloseIndex = prelude.lastIndexOf(HEAD_CLOSE_TAG);\n if (headCloseIndex === -1) {\n return linksHtml + prelude;\n }\n return prelude.slice(0, headCloseIndex) + linksHtml + prelude.slice(headCloseIndex);\n}\n\ntype EarlyHintsCapable = {\n writeEarlyHints?: (hints: { link?: string | string[] }) => void;\n};\n\n/**\n * Emit HTTP 103 Early Hints with CSS preload Link headers when the runtime\n * supports it (Node 18.11+). The browser will start fetching stylesheets\n * before the SSR render begins. Safe to call unconditionally — older Node\n * versions and proxies that strip 1xx simply ignore it.\n */\nfunction sendEarlyHints(res: express.Response, links: string[]) {\n if (links.length === 0) {\n return;\n }\n const target = res as unknown as EarlyHintsCapable;\n if (typeof target.writeEarlyHints !== 'function') {\n return;\n }\n try {\n target.writeEarlyHints({ link: links });\n } catch (error) {\n // Some proxy frontends (or future Node versions in error states) may\n // reject 1xx after headers have been touched. Treat as best-effort.\n if (process.env.NODE_ENV !== 'production') {\n console.warn('Modelence SSR: writeEarlyHints failed', error);\n }\n }\n}\n\nasync function loadUserViteConfig() {\n const appDir = process.cwd();\n\n try {\n const result = await loadConfigFromFile(\n { command: 'serve', mode: 'development' },\n undefined,\n appDir\n );\n return result?.config || {};\n } catch (error) {\n console.warn(`Could not load vite config:`, error);\n return {};\n }\n}\n\nfunction safelyMergeConfig(baseConfig: UserConfig, userConfig: UserConfig) {\n const mergedConfig = mergeConfig(baseConfig, userConfig);\n\n // Deduplicate plugins by name, keeping user plugins over framework plugins\n if (mergedConfig.plugins && Array.isArray(mergedConfig.plugins)) {\n const seenPlugins = new Set<string>();\n mergedConfig.plugins = mergedConfig.plugins\n .flat()\n .filter((plugin: PluginOption) => {\n if (!plugin || typeof plugin !== 'object' || Array.isArray(plugin)) {\n return true;\n }\n const pluginName = (plugin as Plugin).name;\n if (!pluginName || seenPlugins.has(pluginName)) {\n return false;\n }\n seenPlugins.add(pluginName);\n return true;\n })\n .reverse(); // Reverse to prioritize user plugins over framework plugins\n mergedConfig.plugins.reverse(); // Reverse back to maintain original order\n }\n\n return mergedConfig;\n}\n\nasync function getConfig(httpServer?: import('http').Server, options: { ssr?: boolean } = {}) {\n const appDir = process.cwd();\n const userConfig = await loadUserViteConfig();\n\n const eslintConfigFile = [\n '.eslintrc.js',\n '.eslintrc.json',\n '.eslintrc',\n 'eslint.config.js',\n '.eslintrc.yml',\n '.eslintrc.yaml',\n ].find((file) => fs.existsSync(path.join(appDir, file)));\n\n const plugins = [reactPlugin(), modelenceAssetPlugin()];\n\n if (eslintConfigFile) {\n const eslintPlugin = (await import('vite-plugin-eslint')).default;\n plugins.push(\n eslintPlugin({\n failOnError: false,\n include: ['src/**/*.js', 'src/**/*.jsx', 'src/**/*.ts', 'src/**/*.tsx'],\n cwd: appDir,\n overrideConfigFile: path.resolve(appDir, eslintConfigFile),\n })\n );\n }\n\n const baseConfig = defineConfig({\n plugins,\n build: {\n outDir: CLIENT_BUILD_DIR,\n emptyOutDir: true,\n },\n server: {\n middlewareMode: true,\n hmr: httpServer ? { server: httpServer } : undefined,\n },\n appType: options.ssr ? 'custom' : 'spa',\n root: './src/client',\n resolve: {\n alias: {\n '@': path.resolve(appDir, 'src').replace(/\\\\/g, '/'),\n },\n },\n });\n\n return safelyMergeConfig(baseConfig, userConfig);\n}\n\nfunction modelenceAssetPlugin(): Plugin {\n return {\n name: 'modelence-asset-handler',\n async transform(code: string, id: string) {\n const assetRegex = /\\.(png|jpe?g|gif|svg|mpwebm|ogg|mp3|wav|flac|aac)$/;\n if (assetRegex.test(id)) {\n if (process.env.NODE_ENV === 'development') {\n return code;\n }\n // TODO: Upload to CDN\n // return `export default \"${cdnUrl}\"`;\n return code;\n }\n },\n };\n}\n\nexport const viteServer = new ViteServer();\n","/**\n * Security configuration for the application\n *\n * By default, the app is protected against clickjacking by setting\n * `Content-Security-Policy: frame-ancestors 'self'` and `X-Frame-Options: SAMEORIGIN`\n * on all responses, preventing the app from being embedded in iframes on other domains.\n *\n * @example\n * ```typescript\n * import { startApp } from 'modelence/server';\n *\n * // Allow embedding in iframes on specific domains\n * startApp({\n * security: {\n * frameAncestors: ['https://modelence.com', 'https://app.example.com'],\n * },\n * });\n * ```\n */\nexport type SecurityConfig = {\n /**\n * Additional origins allowed to embed this app in an iframe.\n * The app's own origin (`'self'`) is always included automatically.\n *\n * When not set, only same-origin framing is allowed.\n * When set, `X-Frame-Options` is omitted since it cannot express multiple origins.\n */\n frameAncestors?: string[];\n};\n\nlet securityConfig: SecurityConfig = Object.freeze({});\n\nexport function setSecurityConfig(newSecurityConfig: SecurityConfig) {\n securityConfig = Object.freeze(Object.assign({}, securityConfig, newSecurityConfig));\n}\n\nexport function getSecurityConfig() {\n return securityConfig;\n}\n","import { WebsocketServerProvider } from '@/websocket/types';\n\nexport type WebsocketConfig = {\n provider?: WebsocketServerProvider;\n};\n\nlet websocketConfig: WebsocketConfig = Object.freeze({});\n\nexport function setWebsocketConfig(newWebsocketConfig: WebsocketConfig) {\n websocketConfig = Object.freeze(Object.assign({}, websocketConfig, newWebsocketConfig));\n}\n\nexport function getWebsocketConfig() {\n return websocketConfig;\n}\n","import dotenv from 'dotenv';\nimport fs from 'fs/promises';\nimport os from 'os';\nimport path from 'path';\n\nimport type { AppServer, ModelSchema } from '../types';\nimport socketioServer from '@/websocket/socketio/server';\nimport { initRoles } from '../auth/role';\nimport sessionModule from '../auth/session';\nimport { RoleDefinition } from '../auth/types';\nimport userModule from '../auth/user';\nimport { getLocalConfigs } from '../config/local';\nimport { loadConfigs, setSchema } from '../config/server';\nimport { startConfigSync, loadRemoteConfigs } from '../config/sync';\nimport { ConfigSchema } from '../config/types';\nimport cronModule, { defineCronJob, getCronJobsMetadata, startCronJobs } from '../cron/jobs';\nimport { type IndexReconcileMode, Store } from '../data/store';\nimport { resolveStores } from '../data/resolveStores';\nimport { connect, getClient, getMongodbUri } from '../db/client';\nimport { _createSystemMutation, _createSystemQuery, createMutation, createQuery } from '../methods';\nimport {\n MigrationScript,\n default as migrationModule,\n runMigrations,\n startMigrations,\n} from '../migration';\nimport rateLimitModule from '../rate-limit';\nimport { initRateLimits } from '../rate-limit/rules';\nimport systemModule from '../system';\nimport lockModule, { acquireLock, releaseLock } from '../lock';\nimport filesModule from '../files';\nimport { viteServer } from '../viteServer';\nimport { connectCloudBackend } from './backendApi';\nimport { initMetrics } from './metrics';\nimport { Module } from './module';\nimport { startServer } from './server';\nimport { markAppStarted, setMetadata } from './state';\nimport { time } from '@/time';\nimport { EmailConfig, setEmailConfig } from './emailConfig';\nimport { AuthConfig, setAuthConfig } from './authConfig';\nimport { SecurityConfig, setSecurityConfig } from './securityConfig';\nimport { WebsocketConfig, setWebsocketConfig } from './websocketConfig';\nimport { buildAuthRateLimits } from '../auth/user';\n\nexport type AppOptions = {\n modules?: Module[];\n server?: AppServer;\n email?: EmailConfig;\n auth?: AuthConfig;\n /** Security settings such as clickjacking protection. See {@link SecurityConfig}. */\n security?: SecurityConfig;\n /**\n * Custom role definitions keyed by role name. Defined roles are synced to the\n * Modelence Cloud dashboard for user management. See {@link RoleDefinition}.\n *\n * @example\n * ```typescript\n * startApp({\n * roles: {\n * admin: { description: 'Full access to all features' },\n * editor: { description: 'Can edit content' },\n * viewer: {},\n * },\n * });\n * ```\n */\n roles?: Record<string, RoleDefinition>;\n /** @internal */\n defaultRoles?: Record<string, string>;\n migrations?: Array<MigrationScript>;\n websocket?: WebsocketConfig;\n /** Enable server-side rendering of the user's React tree. */\n ssr?: boolean;\n};\n\nexport async function startApp({\n modules = [],\n roles = {},\n defaultRoles = {},\n server = viteServer,\n migrations = [],\n email = {},\n auth = {},\n security = {},\n websocket = {},\n ssr = false,\n}: AppOptions) {\n if (ssr && server === viteServer) {\n viteServer.enableSsr();\n }\n dotenv.config();\n\n dotenv.config({ path: '.modelence.env' });\n\n const hasRemoteBackend = Boolean(process.env.MODELENCE_SERVICE_ENDPOINT);\n\n trackAppStart()\n .then(() => {\n // Do nothing\n })\n .catch(() => {\n // Silently ignore tracking errors to not disrupt app startup\n });\n\n // TODO: verify that user modules don't start with `_system.` prefix\n const systemModules = [\n userModule,\n sessionModule,\n cronModule,\n migrationModule,\n rateLimitModule,\n systemModule,\n lockModule,\n filesModule,\n ];\n const combinedModules = [...systemModules, ...modules];\n\n markAppStarted();\n\n initSystemMethods(systemModules);\n initCustomMethods(modules);\n\n initRoles(roles, defaultRoles);\n\n const configSchema = getConfigSchema(combinedModules);\n setSchema(configSchema);\n const rawStores = getStores(combinedModules) as Store<ModelSchema, never>[];\n const channels = getChannels(combinedModules);\n\n defineCronJobs(combinedModules);\n\n // Apply user-provided auth rate limit overrides directly onto the user\n // module so its `rateLimits` array reflects the effective configuration\n // (the Modelence Cloud reads these from modules for display).\n userModule.rateLimits = buildAuthRateLimits(auth.rateLimits);\n\n const rateLimits = getRateLimits(combinedModules);\n initRateLimits(rateLimits);\n\n const { storesToInit, effectiveStores } = resolveStores(rawStores) as {\n storesToInit: Store<ModelSchema, never>[];\n effectiveStores: Store<ModelSchema, never>[];\n };\n\n if (hasRemoteBackend) {\n const { configs, environmentId, appAlias, environmentAlias, telemetry } =\n await connectCloudBackend({\n configSchema,\n cronJobsMetadata: getCronJobsMetadata(),\n stores: effectiveStores,\n roles,\n });\n loadRemoteConfigs(configs);\n setMetadata({ environmentId, appAlias, environmentAlias, telemetry });\n } else {\n loadConfigs(getLocalConfigs(configSchema));\n }\n\n setEmailConfig(email);\n setAuthConfig(auth);\n setSecurityConfig(security);\n setWebsocketConfig({\n ...websocket,\n provider: websocket.provider || socketioServer,\n });\n\n const mongodbUri = getMongodbUri();\n if (mongodbUri) {\n await connect();\n const allStoresToInit = [...new Set([...storesToInit, ...effectiveStores])];\n initStores(allStoresToInit);\n await createIndexesAndMigrationsWithLock(effectiveStores, migrations);\n } else {\n startMigrations(migrations);\n }\n\n if (hasRemoteBackend) {\n await initMetrics();\n startConfigSync();\n }\n\n startCronJobs().catch(console.error);\n\n await startServer(server, { combinedModules, channels });\n}\n\nfunction initCustomMethods(modules: Module[]) {\n for (const module of modules) {\n for (const [key, handler] of Object.entries(module.queries)) {\n createQuery(`${module.name}.${key}`, handler);\n }\n for (const [key, handler] of Object.entries(module.mutations)) {\n createMutation(`${module.name}.${key}`, handler);\n }\n }\n}\n\nfunction initSystemMethods(modules: Module[]) {\n for (const module of modules) {\n for (const [key, handler] of Object.entries(module.queries)) {\n _createSystemQuery(`${module.name}.${key}`, handler);\n }\n for (const [key, handler] of Object.entries(module.mutations)) {\n _createSystemMutation(`${module.name}.${key}`, handler);\n }\n }\n}\n\nfunction getStores(modules: Module[]) {\n return modules.flatMap((module) => module.stores);\n}\n\nfunction getChannels(modules: Module[]) {\n return modules.flatMap((module) => module.channels);\n}\n\nfunction getRateLimits(modules: Module[]) {\n return modules.flatMap((module) => module.rateLimits);\n}\n\nfunction warnIndexCreationFailure(storeName: string, error: unknown) {\n console.warn(`Failed to create indexes for store '${storeName}'. Continuing startup.`, error);\n}\n\nconst MIGRATIONS_LOCK_RESOURCE = 'migrations';\n\nasync function createIndexesAndMigrationsWithLock(\n effectiveStores: Store<ModelSchema, never>[],\n migrations: MigrationScript[]\n) {\n const hasLock = await acquireLock(MIGRATIONS_LOCK_RESOURCE, {\n lockDuration: time.seconds(30),\n heartbeat: true,\n });\n if (!hasLock) {\n return;\n }\n\n let blockingStores: Store<ModelSchema, never>[];\n let backgroundStores: Store<ModelSchema, never>[];\n\n try {\n blockingStores = effectiveStores.filter((store) => store.getIndexCreationMode() === 'blocking');\n backgroundStores = effectiveStores.filter(\n (store) => store.getIndexCreationMode() === 'background'\n );\n\n for (const store of blockingStores) {\n await createStoreIndexes(store, 'full');\n }\n for (const store of backgroundStores) {\n await createStoreIndexes(store, 'drop-only');\n }\n } catch (error) {\n await releaseLock(MIGRATIONS_LOCK_RESOURCE);\n throw error;\n }\n\n const backgroundIndexCreationPromise = (async () => {\n for (const store of backgroundStores) {\n await createStoreIndexes(store, 'create-only');\n }\n })();\n const migrationPromise = runMigrations(migrations, { lockMode: 'skip' });\n\n void Promise.allSettled([backgroundIndexCreationPromise, migrationPromise])\n .then(([backgroundIndexesResult, migrationResult]) => {\n if (backgroundIndexesResult.status === 'rejected') {\n console.error('Error creating background indexes:', backgroundIndexesResult.reason);\n }\n\n if (migrationResult.status === 'rejected') {\n console.error('Error running migrations:', migrationResult.reason);\n }\n })\n .finally(async () => {\n await releaseLock(MIGRATIONS_LOCK_RESOURCE);\n });\n}\n\nasync function createStoreIndexes(\n store: Store<ModelSchema, never>,\n reconcileMode: IndexReconcileMode = 'full'\n) {\n const storeName = store.getName();\n\n try {\n await store.createIndexes(reconcileMode);\n } catch (error) {\n warnIndexCreationFailure(storeName, error);\n }\n}\n\nfunction getConfigSchema(modules: Module[]): ConfigSchema {\n const merged: ConfigSchema = {};\n\n for (const module of modules) {\n for (const [key, value] of Object.entries(module.configSchema)) {\n const absoluteKey = `${module.name}.${key}`;\n if (absoluteKey in merged) {\n throw new Error(`Duplicate config schema key: ${absoluteKey} (${module.name})`);\n }\n\n merged[absoluteKey] = value;\n }\n }\n\n return merged;\n}\n\nfunction defineCronJobs(modules: Module[]) {\n for (const module of modules) {\n for (const [cronAlias, cronJobParams] of Object.entries(module.cronJobs)) {\n defineCronJob(`${module.name}.${cronAlias}`, cronJobParams);\n }\n }\n}\n\nfunction initStores(stores: Store<ModelSchema, never>[]) {\n const client = getClient();\n if (!client) {\n throw new Error('Failed to initialize stores: MongoDB client not initialized');\n }\n\n for (const store of stores) {\n store.init(client);\n }\n}\n\nasync function trackAppStart() {\n const isTrackingEnabled = process.env.MODELENCE_TRACKING_ENABLED !== 'false';\n\n if (isTrackingEnabled) {\n const serviceEndpoint = process.env.MODELENCE_SERVICE_ENDPOINT ?? 'https://cloud.modelence.com';\n const environmentId = process.env.MODELENCE_ENVIRONMENT_ID;\n\n const appDetails = await getAppDetails();\n const modelencePackageJson = await import('../../package.json');\n\n await fetch(`${serviceEndpoint}/api/track/app-start`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n projectName: appDetails.name,\n version: modelencePackageJson.default.version,\n localHostname: os.hostname(),\n environmentId,\n }),\n });\n }\n}\n\nasync function getAppDetails() {\n try {\n const packageJsonPath = path.join(process.cwd(), 'package.json');\n const packageJsonContent = await fs.readFile(packageJsonPath, 'utf-8');\n const packageJson = JSON.parse(packageJsonContent);\n\n return {\n name: packageJson.name || 'unknown',\n };\n } catch {\n return {\n name: 'unknown',\n };\n }\n}\n","import { ObjectId } from 'mongodb';\nimport { randomUUID } from 'crypto';\nimport {\n usersCollection,\n emailVerificationTokensCollection,\n resetPasswordTokensCollection,\n} from './db';\n\nexport async function clearTokens(userId: ObjectId) {\n await emailVerificationTokensCollection.deleteMany({\n userId,\n });\n\n await resetPasswordTokensCollection.deleteMany({\n userId,\n });\n}\n\nexport async function disableUser(userId: ObjectId) {\n await clearTokens(userId);\n\n await usersCollection.updateOne(userId, {\n $set: {\n status: 'disabled',\n disabledAt: new Date(),\n },\n });\n}\n\nexport async function deleteUser(userId: ObjectId) {\n await clearTokens(userId);\n\n await usersCollection.updateOne(\n {\n _id: userId,\n },\n {\n $set: {\n handle: `deleted-${userId}-${randomUUID()}`,\n status: 'deleted',\n deletedAt: new Date(),\n authMethods: {},\n emails: [],\n },\n }\n );\n}\n","import { Session, User } from '@/auth/types';\nimport { getWebsocketConfig } from '@/app/websocketConfig';\nimport { logError } from '../telemetry';\n\ntype canAccessChannel = (props: {\n user: User | null;\n session: Session | null;\n roles: string[];\n}) => Promise<boolean>;\n\nexport class ServerChannel<T = unknown> {\n public readonly category: string;\n public readonly canAccessChannel: canAccessChannel | null;\n\n constructor(category: string, canAccessChannel?: canAccessChannel) {\n this.category = category;\n this.canAccessChannel = canAccessChannel || null;\n }\n\n broadcast(id: string, data: T) {\n const websocketProvider = getWebsocketConfig().provider;\n if (!websocketProvider) {\n logError('Websockets provider should be added to startApp', {});\n return;\n }\n\n websocketProvider.broadcast({\n category: this.category,\n id,\n data,\n });\n }\n}\n","import { getEmailConfig } from '@/app/emailConfig';\nimport { EmailPayload } from '../types';\n\nexport function sendEmail(payload: EmailPayload) {\n if (!getEmailConfig().provider) {\n throw new Error(\n 'Email provider is not configured, see https://docs.modelence.com/email for more details.'\n );\n }\n return getEmailConfig().provider?.sendEmail(payload);\n}\n","import { type Request, type Response } from 'express';\nimport { MongoServerError, ObjectId } from 'mongodb';\nimport { usersCollection } from '@/auth/db';\nimport { createSession, setAuthTokenCookie } from '@/auth/session';\nimport { getAuthConfig } from '@/app/authConfig';\nimport { getCallContext } from '@/app/server';\nimport { getConfig } from '@/config/server';\nimport { resolveUniqueHandle } from '../utils';\nimport { User, Session, UserEmail, OAuthProvider } from '@/auth/types';\nimport { ConnectionInfo } from '@/methods/types';\n\nexport interface OAuthUserData {\n id: string;\n email: string;\n emailVerified: boolean;\n providerName: OAuthProvider;\n firstName?: string;\n lastName?: string;\n avatarUrl?: string;\n}\n/*\n * Sends OAuth error response.\n * If `errorComponent` is configured, renders HTML.\n * Otherwise falls back to JSON.\n */\nexport function sendOAuthError(res: Response, statusCode: number, errorMessage: string) {\n const authConfig = getAuthConfig();\n const response = res.status(statusCode);\n if (authConfig.errorComponent) {\n try {\n const html = authConfig.errorComponent({ error: errorMessage, statusCode });\n if (html) return response.send(html);\n } catch (err) {\n console.error('Unhandled error in authConfig.errorComponent:', err);\n }\n }\n return response.json({ error: errorMessage });\n}\n\nexport async function authenticateUser(res: Response, userId: ObjectId) {\n const { authToken } = await createSession(userId);\n\n setAuthTokenCookie(res, authToken);\n res.status(302);\n res.redirect('/');\n}\n\nasync function handleExistingProviderLogin(\n res: Response,\n userData: OAuthUserData,\n existingUser: User,\n session: Session | null,\n connectionInfo: ConnectionInfo\n) {\n const authConfig = getAuthConfig();\n\n try {\n if (existingUser.status === 'disabled' || existingUser.status === 'deleted') {\n sendOAuthError(res, 400, 'User account is not active.');\n return;\n }\n\n //Add User FirstName,LastName, AvatarURL if not exists\n const update: Partial<Pick<OAuthUserData, 'firstName' | 'lastName' | 'avatarUrl'>> = {};\n\n if (existingUser.firstName === undefined && userData.firstName) {\n update.firstName = userData.firstName;\n }\n if (existingUser.lastName === undefined && userData.lastName) {\n update.lastName = userData.lastName;\n }\n if (existingUser.avatarUrl === undefined && userData.avatarUrl) {\n update.avatarUrl = userData.avatarUrl;\n }\n\n let user = existingUser;\n\n if (Object.keys(update).length > 0) {\n await usersCollection.updateOne({ _id: existingUser._id }, { $set: update });\n user = { ...existingUser, ...update } as typeof existingUser;\n }\n\n await authenticateUser(res, existingUser._id);\n authConfig.onAfterLogin?.({\n provider: userData.providerName,\n user,\n session,\n connectionInfo,\n });\n authConfig.login?.onSuccess?.(user);\n } catch (error) {\n if (error instanceof Error) {\n authConfig.login?.onError?.(error);\n\n authConfig.onLoginError?.({\n provider: userData.providerName,\n error,\n session,\n connectionInfo,\n });\n }\n throw error;\n }\n}\n\nasync function handleExistingEmailLogin(\n res: Response,\n userData: OAuthUserData,\n existingUserByEmail: User,\n session: Session | null,\n connectionInfo: ConnectionInfo\n) {\n const authConfig = getAuthConfig();\n const linkingMode = authConfig.oauthAccountLinking ?? 'manual';\n\n if (linkingMode === 'auto' && userData.emailVerified) {\n if (existingUserByEmail.status === 'disabled' || existingUserByEmail.status === 'deleted') {\n sendOAuthError(res, 400, 'User account is not active.');\n return;\n }\n\n const matchedEmail = existingUserByEmail.emails?.find(\n (emailDoc: UserEmail) => emailDoc.address.toLowerCase() === userData.email.toLowerCase()\n );\n\n // Prevent pre-registration takeover by requiring local ownership verification too.\n if (!matchedEmail?.verified) {\n sendOAuthError(res, 400, 'User with this email already exists. Please log in instead.');\n return;\n }\n\n try {\n // Build profile fields to backfill from provider data if missing\n const profileUpdate: Partial<Pick<OAuthUserData, 'firstName' | 'lastName' | 'avatarUrl'>> = {\n ...(existingUserByEmail.firstName === undefined &&\n userData.firstName && { firstName: userData.firstName }),\n ...(existingUserByEmail.lastName === undefined &&\n userData.lastName && { lastName: userData.lastName }),\n ...(existingUserByEmail.avatarUrl === undefined &&\n userData.avatarUrl && { avatarUrl: userData.avatarUrl }),\n };\n\n // Single atomic update — link provider + backfill profile in one round trip\n const updateResult = await usersCollection.updateOne(\n {\n _id: existingUserByEmail._id,\n status: { $nin: ['deleted', 'disabled'] },\n $or: [\n { [`authMethods.${userData.providerName}.id`]: { $exists: false } },\n { [`authMethods.${userData.providerName}.id`]: userData.id },\n ],\n },\n {\n $set: {\n [`authMethods.${userData.providerName}.id`]: userData.id,\n ...profileUpdate,\n },\n }\n );\n\n const autoLinkSuccessful = updateResult.matchedCount > 0;\n\n if (!autoLinkSuccessful) {\n // User was deleted/disabled between findOne and updateOne, or linked to a *different* ID\n sendOAuthError(res, 400, 'User with this email already exists. Please log in instead.');\n return;\n }\n\n await authenticateUser(res, existingUserByEmail._id);\n\n // Construct updated user in-memory to provide fresh data to callbacks\n const updatedUser: User = {\n ...existingUserByEmail,\n ...profileUpdate,\n authMethods: {\n ...existingUserByEmail.authMethods,\n [userData.providerName]: {\n id: userData.id,\n },\n },\n };\n\n authConfig.onAfterLogin?.({\n provider: userData.providerName,\n user: updatedUser,\n session,\n connectionInfo,\n });\n authConfig.login?.onSuccess?.(updatedUser);\n\n return;\n } catch (error) {\n if (error instanceof Error) {\n authConfig.login?.onError?.(error);\n\n authConfig.onLoginError?.({\n provider: userData.providerName,\n error,\n session,\n connectionInfo,\n });\n }\n throw error;\n }\n }\n\n // Manual mode (default) or unverified email — reject\n sendOAuthError(res, 400, 'User with this email already exists. Please log in instead.');\n return;\n}\n\nasync function handleNewUserSignup(\n res: Response,\n userData: OAuthUserData,\n session: Session | null,\n connectionInfo: ConnectionInfo\n) {\n const authConfig = getAuthConfig();\n\n try {\n let handle: string;\n\n if (authConfig.generateHandle) {\n const generated = await authConfig.generateHandle!({\n email: userData.email,\n firstName: userData.firstName,\n lastName: userData.lastName,\n });\n //Don't throw error if handle is already taken, instead add a suffix '_2', '_3', etc. to the handle\n handle = await resolveUniqueHandle(generated, userData.email, {\n throwOnConflict: false,\n });\n } else {\n handle = await resolveUniqueHandle(undefined, userData.email);\n }\n\n const userDoc = {\n handle: handle,\n status: 'active' as const,\n emails: [\n {\n address: userData.email,\n verified: userData.emailVerified,\n },\n ],\n createdAt: new Date(),\n authMethods: {\n [userData.providerName]: {\n id: userData.id,\n },\n },\n ...(userData.firstName !== undefined && { firstName: userData.firstName }),\n ...(userData.lastName !== undefined && { lastName: userData.lastName }),\n ...(userData.avatarUrl !== undefined && { avatarUrl: userData.avatarUrl }),\n };\n\n const newUser = await usersCollection.insertOne(userDoc);\n\n await authenticateUser(res, newUser.insertedId);\n\n const userDocument = await usersCollection.findOne(\n { _id: newUser.insertedId },\n { readPreference: 'primary' }\n );\n\n if (userDocument) {\n authConfig.onAfterSignup?.({\n provider: userData.providerName,\n user: userDocument,\n session,\n connectionInfo,\n });\n\n authConfig.signup?.onSuccess?.(userDocument);\n }\n } catch (error) {\n if (error instanceof Error) {\n authConfig.onSignupError?.({\n provider: userData.providerName,\n error,\n session,\n connectionInfo,\n });\n\n authConfig.signup?.onError?.(error);\n }\n throw error;\n }\n}\n\nexport function getRedirectUri(provider: string): string {\n return `${getConfig('_system.site.url')}/api/_internal/auth/${provider}/callback`;\n}\n\nexport async function handleOAuthUserAuthentication(\n req: Request,\n res: Response,\n userData: OAuthUserData\n): Promise<void> {\n // 1. Try to fetch existing user by OAuth ID\n const existingUser = await usersCollection.findOne({\n [`authMethods.${userData.providerName}.id`]: userData.id,\n });\n\n const { session, connectionInfo } = await getCallContext(req, res);\n\n if (existingUser) {\n return handleExistingProviderLogin(res, userData, existingUser, session, connectionInfo);\n }\n\n // 2. Validate Email is provided by Provider\n if (!userData.email) {\n sendOAuthError(\n res,\n 400,\n `Email address is required for ${userData.providerName} authentication.`\n );\n return;\n }\n\n // 3. Try to fetch existing user by Email\n let existingUserByEmail;\n\n try {\n existingUserByEmail = await usersCollection.findOne(\n { 'emails.address': userData.email, status: { $ne: 'deleted' } },\n { collation: { locale: 'en', strength: 2 } }\n );\n } catch (error) {\n if (error instanceof Error) {\n const authConfig = getAuthConfig();\n authConfig.onSignupError?.({\n provider: userData.providerName,\n error,\n session,\n connectionInfo,\n });\n\n authConfig.signup?.onError?.(error);\n }\n throw error;\n }\n\n //User Already existed via email verification but now trying to login via OAuth Providers from the same email\n if (existingUserByEmail) {\n return handleExistingEmailLogin(res, userData, existingUserByEmail, session, connectionInfo);\n }\n\n //New User\n return handleNewUserSignup(res, userData, session, connectionInfo);\n}\n\nexport function clearOAuthLinkCookie(res: Response) {\n // Important: must clear the httpOnly cookie used during OAuth linking\n res.cookie('oauthLinkToken', '', {\n httpOnly: true,\n maxAge: 0,\n path: '/api/_internal/auth/',\n sameSite: 'lax',\n secure: process.env.NODE_ENV === 'production',\n });\n}\n\nfunction safelyCallHook(hook?: () => void) {\n if (!hook) return;\n\n try {\n hook();\n } catch (err) {\n console.error('Error executing OAuth hook:', err);\n }\n}\n\nexport function validateOAuthStateAndGetMode(\n req: Request,\n res: Response,\n stateCookieName: string\n): string | null {\n const state = req.query.state as string;\n const storedState = req.cookies[stateCookieName];\n\n const [storedStateValue, storedMode] = (storedState || '').split(':');\n\n if (!state || !storedState || state !== storedStateValue) {\n sendOAuthError(res, 400, 'Invalid OAuth state - possible CSRF attack');\n return null;\n }\n\n res.clearCookie(stateCookieName);\n return storedMode || 'login';\n}\n\nexport async function handleOAuthProviderLink(\n req: Request,\n res: Response,\n userData: OAuthUserData\n): Promise<void> {\n const authConfig = getAuthConfig();\n const { session, connectionInfo } = await getCallContext(req, res);\n\n if (!session?.userId) {\n clearOAuthLinkCookie(res);\n sendOAuthError(res, 401, 'You must be signed in to link a provider.');\n return;\n }\n\n const userId = session.userId;\n\n try {\n // Atomically attach the provider to the current user while preventing\n // overwriting an existing provider ID on the same user.\n // A unique index on the provider ID ensures it cannot be linked to another user.\n const providerField = `authMethods.${userData.providerName}.id`;\n\n const updateResult = await usersCollection.updateOne(\n {\n _id: userId,\n status: { $nin: ['deleted', 'disabled'] },\n $or: [{ [providerField]: { $exists: false } }, { [providerField]: userData.id }],\n },\n {\n $set: {\n [providerField]: userData.id,\n },\n }\n );\n\n // If no document matched, figure out why\n if (updateResult.matchedCount === 0) {\n const currentUser = await usersCollection.findOne({ _id: userId });\n\n if (!currentUser || currentUser.status === 'deleted' || currentUser.status === 'disabled') {\n safelyCallHook(() =>\n authConfig.onOAuthLinkError?.({\n provider: userData.providerName,\n error: new Error('User account not found or not active'),\n session,\n connectionInfo,\n })\n );\n\n clearOAuthLinkCookie(res);\n\n sendOAuthError(res, 400, 'User account is not active.');\n return;\n }\n\n // Detect if the user already linked a different OAuth account\n const existingProviderId = currentUser?.authMethods?.[userData.providerName]?.id;\n\n if (existingProviderId && existingProviderId !== userData.id) {\n safelyCallHook(() =>\n authConfig.onOAuthLinkError?.({\n provider: userData.providerName,\n error: new Error(\n `User already has a different ${userData.providerName} account linked`\n ),\n session,\n connectionInfo,\n })\n );\n\n clearOAuthLinkCookie(res);\n\n sendOAuthError(\n res,\n 400,\n `You have already linked a different ${userData.providerName} account.`\n );\n return;\n }\n\n // Fallback safety guard in case the DB state does not match any expected branch\n safelyCallHook(() =>\n authConfig.onOAuthLinkError?.({\n provider: userData.providerName,\n error: new Error(`Unexpected OAuth linking state for ${userData.providerName}`),\n session,\n connectionInfo,\n })\n );\n\n clearOAuthLinkCookie(res);\n\n sendOAuthError(res, 400, `Unable to link ${userData.providerName} account.`);\n return;\n }\n\n const updatedUser = await usersCollection.findOne(\n { _id: userId },\n { readPreference: 'primary' }\n );\n\n if (updatedUser) {\n safelyCallHook(() =>\n authConfig.onAfterOAuthLink?.({\n provider: userData.providerName,\n user: updatedUser,\n session,\n connectionInfo,\n })\n );\n }\n\n // Redirect back to the app after successful link\n clearOAuthLinkCookie(res);\n\n res.status(302).redirect('/');\n } catch (error) {\n if (error instanceof MongoServerError && error.code === 11000) {\n safelyCallHook(() =>\n authConfig.onOAuthLinkError?.({\n provider: userData.providerName,\n error,\n session,\n connectionInfo,\n })\n );\n\n clearOAuthLinkCookie(res);\n\n sendOAuthError(\n res,\n 400,\n `This ${userData.providerName} account is already linked to a different user.`\n );\n return;\n }\n\n if (error instanceof Error) {\n safelyCallHook(() =>\n authConfig.onOAuthLinkError?.({\n provider: userData.providerName,\n error,\n session,\n connectionInfo,\n })\n );\n }\n\n clearOAuthLinkCookie(res);\n if (!res.headersSent) {\n throw error;\n }\n }\n}\n\nexport function validateOAuthCode(code: unknown): string | null {\n if (!code || typeof code !== 'string') {\n return null;\n }\n return code;\n}\n","import { getConfig } from '@/server';\nimport { time } from '@/time';\nimport { randomBytes } from 'crypto';\nimport {\n Router,\n type Request,\n type Response,\n type NextFunction,\n type Router as ExpressRouter,\n} from 'express';\nimport {\n getRedirectUri,\n handleOAuthUserAuthentication,\n handleOAuthProviderLink,\n validateOAuthCode,\n type OAuthUserData,\n clearOAuthLinkCookie,\n validateOAuthStateAndGetMode,\n sendOAuthError,\n} from './oauth-common';\n\ninterface GoogleTokenResponse {\n access_token: string;\n expires_in: number;\n scope: string;\n token_type: string;\n id_token: string;\n}\n\ninterface GoogleUserInfo {\n id: string;\n name: string;\n given_name?: string;\n family_name?: string;\n email: string;\n verified_email: boolean;\n picture?: string;\n}\n\nasync function exchangeCodeForToken(\n code: string,\n clientId: string,\n clientSecret: string,\n redirectUri: string\n): Promise<GoogleTokenResponse> {\n const tokenResponse = await fetch('https://oauth2.googleapis.com/token', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n code,\n client_id: clientId,\n client_secret: clientSecret,\n redirect_uri: redirectUri,\n grant_type: 'authorization_code',\n }),\n });\n\n if (!tokenResponse.ok) {\n throw new Error(`Failed to exchange code for token: ${tokenResponse.statusText}`);\n }\n\n return tokenResponse.json();\n}\n\nasync function fetchGoogleUserInfo(accessToken: string): Promise<GoogleUserInfo> {\n const userInfoResponse = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (!userInfoResponse.ok) {\n throw new Error(`Failed to fetch user info: ${userInfoResponse.statusText}`);\n }\n\n return userInfoResponse.json();\n}\n\nasync function handleGoogleAuthenticationCallback(req: Request, res: Response) {\n const code = validateOAuthCode(req.query.code);\n\n if (!code) {\n sendOAuthError(res, 400, 'Missing authorization code');\n return;\n }\n\n const mode = validateOAuthStateAndGetMode(req, res, 'authStateGoogle');\n if (!mode) return;\n\n const googleClientId = String(getConfig('_system.user.auth.google.clientId'));\n const googleClientSecret = String(getConfig('_system.user.auth.google.clientSecret'));\n const redirectUri = getRedirectUri('google');\n\n try {\n // Exchange code for tokens\n const tokenData = await exchangeCodeForToken(\n code,\n googleClientId,\n googleClientSecret,\n redirectUri\n );\n\n // Fetch user info\n const googleUser = await fetchGoogleUserInfo(tokenData.access_token);\n\n const userData: OAuthUserData = {\n id: googleUser.id,\n email: googleUser.email,\n emailVerified: googleUser.verified_email,\n providerName: 'google',\n firstName: googleUser.given_name || undefined,\n lastName: googleUser.family_name || undefined,\n avatarUrl: googleUser.picture || undefined,\n };\n if (mode === 'link') {\n await handleOAuthProviderLink(req, res, userData);\n } else {\n await handleOAuthUserAuthentication(req, res, userData);\n }\n } catch (error) {\n console.error('Google OAuth error:', error);\n if (mode === 'link') {\n clearOAuthLinkCookie(res);\n }\n sendOAuthError(res, 500, 'Authentication failed');\n }\n}\n\nfunction getRouter(): ExpressRouter {\n const googleAuthRouter = Router();\n\n // Middleware to check if Google auth is enabled and configured\n const checkGoogleEnabled = (_req: Request, res: Response, next: NextFunction) => {\n const googleEnabled = Boolean(getConfig('_system.user.auth.google.enabled'));\n const googleClientId = String(getConfig('_system.user.auth.google.clientId'));\n const googleClientSecret = String(getConfig('_system.user.auth.google.clientSecret'));\n\n if (!googleEnabled || !googleClientId || !googleClientSecret) {\n sendOAuthError(res, 503, 'Google authentication is not configured');\n return;\n }\n\n next();\n };\n\n // Initiate OAuth flow\n googleAuthRouter.get(\n '/api/_internal/auth/google',\n checkGoogleEnabled,\n (req: Request, res: Response) => {\n const googleClientId = String(getConfig('_system.user.auth.google.clientId'));\n const redirectUri = getRedirectUri('google');\n\n const state = randomBytes(32).toString('hex');\n\n const mode = req.query.mode === 'link' ? 'link' : 'login';\n\n res.cookie('authStateGoogle', `${state}:${mode}`, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: time.minutes(10), // 10 minutes\n });\n\n const authUrl = new URL('https://accounts.google.com/o/oauth2/v2/auth');\n authUrl.searchParams.append('client_id', googleClientId);\n authUrl.searchParams.append('redirect_uri', redirectUri);\n authUrl.searchParams.append('response_type', 'code');\n authUrl.searchParams.append('scope', 'profile email');\n authUrl.searchParams.append('access_type', 'online');\n authUrl.searchParams.append('state', state);\n\n res.redirect(authUrl.toString());\n }\n );\n\n // Handle OAuth callback\n googleAuthRouter.get(\n '/api/_internal/auth/google/callback',\n checkGoogleEnabled,\n handleGoogleAuthenticationCallback\n );\n\n return googleAuthRouter;\n}\n\nexport default getRouter;\n","import { getConfig } from '@/server';\nimport { time } from '@/time';\nimport { randomBytes } from 'crypto';\nimport {\n Router,\n type Request,\n type Response,\n type NextFunction,\n type Router as ExpressRouter,\n} from 'express';\nimport {\n getRedirectUri,\n handleOAuthUserAuthentication,\n handleOAuthProviderLink,\n validateOAuthCode,\n type OAuthUserData,\n clearOAuthLinkCookie,\n validateOAuthStateAndGetMode,\n sendOAuthError,\n} from './oauth-common';\n\ninterface GitHubTokenResponse {\n access_token: string;\n token_type: string;\n scope: string;\n}\n\ninterface GitHubUserInfo {\n id: number;\n login: string;\n name: string;\n email: string | null;\n avatar_url?: string;\n}\n\ninterface GitHubEmail {\n email: string;\n primary: boolean;\n verified: boolean;\n visibility: 'public' | 'private' | null;\n}\n\nasync function exchangeCodeForToken(\n code: string,\n clientId: string,\n clientSecret: string,\n redirectUri: string\n): Promise<GitHubTokenResponse> {\n const tokenResponse = await fetch('https://github.com/login/oauth/access_token', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\n body: JSON.stringify({\n client_id: clientId,\n client_secret: clientSecret,\n code,\n redirect_uri: redirectUri,\n }),\n });\n\n if (!tokenResponse.ok) {\n throw new Error(`Failed to exchange code for token: ${tokenResponse.statusText}`);\n }\n\n return tokenResponse.json();\n}\n\nasync function fetchGitHubUserInfo(accessToken: string): Promise<GitHubUserInfo> {\n const userInfoResponse = await fetch('https://api.github.com/user', {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n Accept: 'application/vnd.github.v3+json',\n },\n });\n\n if (!userInfoResponse.ok) {\n throw new Error(`Failed to fetch user info: ${userInfoResponse.statusText}`);\n }\n\n return userInfoResponse.json();\n}\n\nasync function fetchGitHubUserEmails(accessToken: string): Promise<GitHubEmail[]> {\n const response = await fetch('https://api.github.com/user/emails', {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n Accept: 'application/vnd.github.v3+json',\n },\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch user emails: ${response.statusText}`);\n }\n\n return response.json();\n}\n\nasync function getGitHubUserEmail(\n githubUser: GitHubUserInfo,\n accessToken: string\n): Promise<string | null> {\n if (githubUser.email) {\n return githubUser.email;\n }\n\n const emails = await fetchGitHubUserEmails(accessToken);\n return emails.find((e) => e.primary && e.verified)?.email ?? null;\n}\n\nasync function handleGitHubAuthenticationCallback(req: Request, res: Response) {\n const code = validateOAuthCode(req.query.code);\n\n if (!code) {\n sendOAuthError(res, 400, 'Missing authorization code');\n return;\n }\n\n const mode = validateOAuthStateAndGetMode(req, res, 'authStateGithub');\n if (!mode) return;\n\n const githubClientId = String(getConfig('_system.user.auth.github.clientId'));\n const githubClientSecret = String(getConfig('_system.user.auth.github.clientSecret'));\n const redirectUri = getRedirectUri('github');\n\n try {\n // Exchange code for access token\n const tokenData = await exchangeCodeForToken(\n code,\n githubClientId,\n githubClientSecret,\n redirectUri\n );\n\n // Fetch user info\n const githubUser = await fetchGitHubUserInfo(tokenData.access_token);\n\n // Resolve a usable GitHub email (public email or fallback to primary verified email)\n const githubEmail = await getGitHubUserEmail(githubUser, tokenData.access_token);\n\n if (!githubEmail) {\n if (mode === 'link') {\n clearOAuthLinkCookie(res);\n }\n\n sendOAuthError(\n res,\n 400,\n 'Unable to retrieve a primary verified email from GitHub. Please ensure your GitHub account has a verified email set as primary.'\n );\n return;\n }\n\n const nameParts = githubUser.name ? githubUser.name.trim().split(/\\s+/) : [];\n const firstName = nameParts[0] || undefined;\n const lastName = nameParts.length > 1 ? nameParts.slice(1).join(' ') : undefined;\n\n const userData: OAuthUserData = {\n id: String(githubUser.id),\n email: githubEmail,\n emailVerified: true, // Assume public email is verified\n providerName: 'github',\n firstName,\n lastName,\n avatarUrl: githubUser.avatar_url || undefined,\n };\n\n if (mode === 'link') {\n await handleOAuthProviderLink(req, res, userData);\n } else {\n await handleOAuthUserAuthentication(req, res, userData);\n }\n } catch (error) {\n console.error('GitHub OAuth error:', error);\n if (mode === 'link') {\n clearOAuthLinkCookie(res);\n }\n sendOAuthError(res, 500, 'Authentication failed');\n }\n}\n\nfunction getRouter(): ExpressRouter {\n const githubAuthRouter = Router();\n\n // Middleware to check if GitHub auth is enabled and configured\n const checkGitHubEnabled = (_req: Request, res: Response, next: NextFunction) => {\n const githubEnabled = Boolean(getConfig('_system.user.auth.github.enabled'));\n const githubClientId = String(getConfig('_system.user.auth.github.clientId'));\n const githubClientSecret = String(getConfig('_system.user.auth.github.clientSecret'));\n\n if (!githubEnabled || !githubClientId || !githubClientSecret) {\n sendOAuthError(res, 503, 'GitHub authentication is not configured');\n return;\n }\n\n next();\n };\n\n // Initiate OAuth flow\n githubAuthRouter.get(\n '/api/_internal/auth/github',\n checkGitHubEnabled,\n (req: Request, res: Response) => {\n const githubClientId = String(getConfig('_system.user.auth.github.clientId'));\n const redirectUri = getRedirectUri('github');\n const githubScopes = getConfig('_system.user.auth.github.scopes');\n const scopes = githubScopes\n ? String(githubScopes)\n .split(',')\n .map((s) => s.trim())\n .join(' ')\n : 'user:email';\n\n const state = randomBytes(32).toString('hex');\n\n const mode = req.query.mode === 'link' ? 'link' : 'login';\n\n res.cookie('authStateGithub', `${state}:${mode}`, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: time.minutes(10), // 10 minutes\n });\n\n const authUrl = new URL('https://github.com/login/oauth/authorize');\n authUrl.searchParams.append('client_id', githubClientId);\n authUrl.searchParams.append('redirect_uri', redirectUri);\n authUrl.searchParams.append('scope', scopes);\n authUrl.searchParams.append('state', state);\n\n res.redirect(authUrl.toString());\n }\n );\n\n // Handle OAuth callback\n githubAuthRouter.get(\n '/api/_internal/auth/github/callback',\n checkGitHubEnabled,\n handleGitHubAuthenticationCallback\n );\n\n return githubAuthRouter;\n}\n\nexport default getRouter;\n","import { Request, Response, NextFunction } from 'express';\nimport { RouteHandler } from './types';\nimport { ModelenceError } from '../error';\nimport { authenticate } from '../auth';\nimport { getMongodbUri } from '../db/client';\nimport type { Context } from '../methods/types';\nimport { startTransaction } from '../telemetry';\n\n// TODO: Use cookies for authentication and automatically add session/user to context if accessing from browser\nexport function createRouteHandler(method: string, path: string, handler: RouteHandler) {\n return async (req: Request, res: Response, next: NextFunction) => {\n const authToken = req.headers['x-modelence-auth-token'];\n let context: Pick<Context, 'session' | 'user'> = { session: null, user: null };\n\n if (typeof authToken === 'string' && getMongodbUri()) {\n try {\n const { session, user } = await authenticate(authToken);\n context = { session, user };\n } catch {\n // If authentication fails, context remains null\n }\n }\n\n const transaction = startTransaction('route', `route:${method.toLowerCase()}:${path}`, {\n method,\n path,\n query: req.query,\n body: req.body,\n params: req.params,\n });\n\n try {\n const response = await handler(\n {\n query: req.query as Record<string, string>,\n body: req.body,\n params: req.params as Record<string, string>,\n headers: req.headers as Record<string, string>,\n cookies: req.cookies,\n rawBody: Buffer.isBuffer(req.body) ? req.body : undefined,\n req,\n res,\n next,\n },\n context\n );\n\n transaction.end();\n\n // If the handler returns null, we expect it to handle the response itself\n if (response) {\n res.status(response.status || 200);\n\n if (response.redirect) {\n res.redirect(response.redirect);\n }\n\n if (response.headers) {\n Object.entries(response.headers).forEach(([key, value]) => {\n res.setHeader(key, value);\n });\n }\n\n res.send(response.data);\n }\n } catch (error) {\n transaction.end('error');\n\n if (error instanceof ModelenceError) {\n res.status(error.status).send(error.message);\n } else {\n console.error(`Error in route handler: ${req.path}`);\n console.error(error);\n res.status(500).send(String(error));\n }\n }\n };\n}\n","import googleAuthRouter from '@/auth/providers/google';\nimport githubAuthRouter from '@/auth/providers/github';\nimport { runMethod } from '@/methods';\nimport { getResponseTypeMap, sanitizeResult } from '@/methods/serialize';\nimport { createRouteHandler } from '@/routes/handler';\nimport { HttpMethod } from '@/server';\nimport { logInfo } from '@/telemetry';\nimport cookieParser from 'cookie-parser';\nimport express, { Request, Response } from 'express';\nimport http from 'http';\nimport z from 'zod';\nimport type { AppServer } from '../types';\nimport { authenticate } from '../auth';\nimport { getUnauthenticatedRoles } from '../auth/role';\nimport { getMongodbUri } from '../db/client';\nimport { ModelenceError } from '../error';\nimport { Module } from './module';\nimport { ConnectionInfo } from '@/methods/types';\nimport { ServerChannel } from '@/websocket/serverChannel';\nimport { getSecurityConfig } from './securityConfig';\nimport { getWebsocketConfig } from './websocketConfig';\nimport { getConfig } from '@/config/server';\n\nfunction getBodyParserMiddleware(config?: {\n json?: boolean | { limit?: string };\n urlencoded?: boolean | { limit?: string; extended?: boolean };\n raw?: boolean | { limit?: string; type?: string | string[] };\n}) {\n const middlewares: express.RequestHandler[] = [];\n\n if (!config) {\n // Default: apply JSON and urlencoded parsing\n middlewares.push(express.json({ limit: '16mb' }));\n middlewares.push(express.urlencoded({ extended: true, limit: '16mb' }));\n return middlewares;\n }\n\n // Handle JSON parsing\n if (config.json !== false) {\n const jsonOptions = typeof config.json === 'object' ? config.json : { limit: '16mb' };\n middlewares.push(express.json(jsonOptions));\n }\n\n // Handle URL-encoded parsing\n if (config.urlencoded !== false) {\n const urlencodedOptions =\n typeof config.urlencoded === 'object' ? config.urlencoded : { extended: true, limit: '16mb' };\n middlewares.push(express.urlencoded(urlencodedOptions));\n }\n\n // Handle raw body parsing\n if (config.raw) {\n const rawOptions = typeof config.raw === 'object' ? config.raw : {};\n const defaultRawOptions = {\n limit: rawOptions.limit || '16mb',\n type: rawOptions.type || '*/*',\n };\n middlewares.push(express.raw(defaultRawOptions));\n }\n\n return middlewares;\n}\n\nfunction registerModuleRoutes(app: express.Application, modules: Module[]) {\n for (const module of modules) {\n for (const route of module.routes) {\n const { path, handlers, body } = route;\n const middlewares = getBodyParserMiddleware(body);\n\n Object.entries(handlers).forEach(([method, handler]) => {\n app[method as HttpMethod](path, ...middlewares, createRouteHandler(method, path, handler));\n });\n }\n }\n}\n\nexport async function startServer(\n server: AppServer,\n {\n combinedModules,\n channels,\n }: {\n combinedModules: Module[];\n channels: ServerChannel[];\n }\n) {\n const app = express();\n\n app.use(cookieParser());\n\n app.use(securityHeadersMiddleware());\n\n // Register module routes first (with per-route body parser config)\n registerModuleRoutes(app, combinedModules);\n\n // Apply global body parsing for remaining routes\n app.use(express.json({ limit: '16mb' }));\n app.use(express.urlencoded({ extended: true, limit: '16mb' }));\n\n app.use(googleAuthRouter());\n app.use(githubAuthRouter());\n\n // Set httpOnly cookie for OAuth linking flow\n app.post('/api/_internal/auth/set-link-cookie', async (req: Request, res: Response) => {\n const { session } = await getCallContext(req, res);\n\n if (!session?.userId) {\n res.status(401).json({ error: 'Not authenticated' });\n return;\n }\n\n res.cookie('oauthLinkToken', session.authToken, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/api/_internal/auth/',\n maxAge: 10 * 60 * 1000, // 10 minutes\n });\n\n res.json({ ok: true });\n });\n\n app.post('/api/_internal/method/:methodName(*)', async (req: Request, res: Response) => {\n const methodName = req.params.methodName as string;\n const context = await getCallContext(req, res);\n\n try {\n const result = sanitizeResult(await runMethod(methodName, req.body.args, context));\n res.json({\n data: result,\n typeMap: getResponseTypeMap(result),\n });\n } catch (error) {\n handleMethodError(res, methodName, error);\n }\n });\n\n const httpServer = http.createServer(app);\n\n await server.init({ httpServer });\n\n if (server.middlewares) {\n app.use(server.middlewares());\n }\n\n app.all('*', (req: Request, res: Response, next) => {\n Promise.resolve(server.handler(req, res)).catch(next);\n });\n\n process.on('unhandledRejection', (reason, promise) => {\n console.error('Unhandled Promise Rejection:');\n console.error(reason instanceof Error ? reason.stack : reason);\n console.error('Promise:', promise);\n });\n\n // Global uncaught exceptions\n process.on('uncaughtException', (error) => {\n console.error('Uncaught Exception:');\n console.error(error.stack); // This gives you the full stack trace\n console.trace('Full application stack:'); // Additional context\n });\n\n const websocketProvider = getWebsocketConfig()?.provider;\n if (websocketProvider) {\n websocketProvider.init({\n httpServer,\n channels,\n });\n }\n\n const port = process.env.MODELENCE_PORT || process.env.PORT || 3000;\n httpServer.listen(port, () => {\n logInfo(`Application started`, { source: 'app' });\n const siteUrl = getConfig('_system.site.url') || `http://localhost:${port}`;\n console.log(`\\nApplication started on ${siteUrl}\\n`);\n });\n}\n\nexport async function getCallContext(req: Request, res: Response | null = null) {\n const path = (req.path ?? req.url ?? '').split('?')[0];\n\n const isOAuthCallback = path.startsWith('/api/_internal/auth/') && path.endsWith('/callback');\n\n const body = (req.body ?? {}) as Record<string, unknown>;\n\n const authToken = z\n .string()\n .nullish()\n .transform((val) => val ?? null)\n .parse(\n req.cookies.authToken ||\n (isOAuthCallback ? req.cookies.oauthLinkToken : null) ||\n body.authToken\n );\n\n const clientInfo = z\n .object({\n screenWidth: z.number(),\n screenHeight: z.number(),\n windowWidth: z.number(),\n windowHeight: z.number(),\n pixelRatio: z.number(),\n orientation: z.string().nullable(),\n })\n .nullish()\n .parse(body.clientInfo) ?? {\n screenWidth: 0,\n screenHeight: 0,\n windowWidth: 0,\n windowHeight: 0,\n pixelRatio: 1,\n orientation: null,\n };\n\n const connectionInfo: ConnectionInfo = {\n ip: getClientIp(req),\n userAgent: req.get('user-agent'),\n acceptLanguage: req.get('accept-language'),\n referrer: req.get('referrer'),\n baseUrl: req.protocol + '://' + req.get('host'),\n };\n\n const hasDatabase = Boolean(getMongodbUri());\n if (hasDatabase) {\n const { session, user, roles } = await authenticate(authToken);\n return {\n clientInfo,\n connectionInfo,\n session,\n user,\n roles,\n req,\n res,\n };\n }\n\n return {\n clientInfo,\n connectionInfo,\n session: null,\n user: null,\n roles: getUnauthenticatedRoles(),\n req,\n res,\n };\n}\n\nfunction handleMethodError(res: Response, methodName: string, error: unknown) {\n // TODO: add an option to silence these error console logs, especially when Elastic logs are configured\n\n if (error instanceof ModelenceError) {\n if (error.status >= 500 && error.status < 600) {\n console.error(`Error calling ${methodName}:`, error);\n }\n res.status(error.status).send(error.message);\n return;\n }\n\n if (error instanceof Error && error?.constructor?.name === 'ZodError' && 'errors' in error) {\n let errorMessage = '';\n try {\n errorMessage = parseZodError(error as z.ZodError);\n } catch (parsingError) {\n console.error(`Error parsing Zod error in ${methodName}:`, parsingError);\n errorMessage = 'Validation failed';\n }\n res.status(400).send(errorMessage);\n return;\n }\n\n console.error(`Error calling ${methodName}:`, error);\n res.status(500).send(error instanceof Error ? error.message : String(error));\n}\n\nfunction parseZodError(zodError: z.ZodError): string {\n const flattened = zodError.flatten();\n const fieldMessages = Object.entries(flattened.fieldErrors).map(\n ([key, errors]) => `${key}: ${(errors ?? []).join(', ')}`\n );\n const formMessages = flattened.formErrors;\n const allMessages = [...fieldMessages, ...formMessages].filter(Boolean);\n return allMessages.join('; ');\n}\n\nfunction securityHeadersMiddleware(): express.RequestHandler {\n const { frameAncestors } = getSecurityConfig();\n const hasCustomAncestors = frameAncestors && frameAncestors.length > 0;\n const ancestors = hasCustomAncestors ? [\"'self'\", ...frameAncestors].join(' ') : \"'self'\";\n\n return (_req, res, next) => {\n res.setHeader('Content-Security-Policy', `frame-ancestors ${ancestors}`);\n // X-Frame-Options only supports DENY and SAMEORIGIN (ALLOW-FROM is deprecated).\n // When custom ancestors are configured, only CSP frame-ancestors can express that,\n // so we omit X-Frame-Options to avoid conflicting with the CSP directive.\n if (!hasCustomAncestors) {\n res.setHeader('X-Frame-Options', 'SAMEORIGIN');\n }\n next();\n };\n}\n\nfunction getClientIp(req: Request): string | undefined {\n // On Heroku and other proxies, X-Forwarded-For contains the real client IP\n const forwardedFor = req.headers['x-forwarded-for'];\n if (forwardedFor) {\n const firstIp = Array.isArray(forwardedFor) ? forwardedFor[0] : forwardedFor.split(',')[0];\n return firstIp.trim();\n }\n\n const directIp = req.ip || req.socket?.remoteAddress;\n if (directIp) {\n // Remove IPv6-to-IPv4 mapping prefix\n return directIp.startsWith('::ffff:') ? directIp.substring(7) : directIp;\n }\n\n return undefined;\n}\n"]}
|