modelence 0.19.0 → 0.19.1-ssr.dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/modelence.js +2 -2
- package/dist/bin/modelence.js.map +1 -1
- package/dist/chunk-6CHWWK3O.js +3 -0
- package/dist/chunk-6CHWWK3O.js.map +1 -0
- package/dist/chunk-L36OLCF3.js +2 -0
- package/dist/chunk-L36OLCF3.js.map +1 -0
- package/dist/chunk-MIRF7FP3.js +2 -0
- package/dist/chunk-MIRF7FP3.js.map +1 -0
- package/dist/chunk-N7XT2ULQ.js +2 -0
- package/dist/chunk-N7XT2ULQ.js.map +1 -0
- package/dist/chunk-SI5I2VMN.js +25 -0
- package/dist/chunk-SI5I2VMN.js.map +1 -0
- package/dist/chunk-TNXGVFSU.js +3 -0
- package/dist/chunk-TNXGVFSU.js.map +1 -0
- package/dist/chunk-YLLX26A4.js +2 -0
- package/dist/chunk-YLLX26A4.js.map +1 -0
- package/dist/chunk-YRR32LTF.js +2 -0
- package/dist/chunk-YRR32LTF.js.map +1 -0
- package/dist/client.d.ts +75 -6
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/dist/collectCss-4YETFI7P.js +2 -0
- package/dist/collectCss-4YETFI7P.js.map +1 -0
- package/dist/{index-CLpVWWuj.d.ts → index-CgNFVSg6.d.ts} +1 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.js +1 -1
- package/dist/{package-DB7AXKLA.js → package-AGSLW64J.js} +2 -2
- package/dist/{package-DB7AXKLA.js.map → package-AGSLW64J.js.map} +1 -1
- package/dist/render-CHI3Y7PZ.js +2 -0
- package/dist/render-CHI3Y7PZ.js.map +1 -0
- package/dist/renderApp-ZDNATNY6.js +2 -0
- package/dist/renderApp-ZDNATNY6.js.map +1 -0
- package/dist/server-NZQGNLQF.js +2 -0
- package/dist/server-NZQGNLQF.js.map +1 -0
- package/dist/server.d.ts +12 -8
- package/dist/server.js +1 -20
- package/dist/server.js.map +1 -1
- package/dist/transport-4MGQHPZB.js +2 -0
- package/dist/transport-4MGQHPZB.js.map +1 -0
- package/dist/{types-CzGfkwti.d.ts → types-BHRPqQrN.d.ts} +6 -6
- package/dist/{types-JMIT4IDG.d.ts → types-cQjl1CfF.d.ts} +2 -2
- package/dist/types.d.ts +3 -3
- package/package.json +3 -1
- package/dist/chunk-C3UESBRX.js +0 -2
- package/dist/chunk-C3UESBRX.js.map +0 -1
- package/dist/chunk-JBPO3BNR.js +0 -3
- package/dist/chunk-JBPO3BNR.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/app/module.ts","../src/data/schemaSerializer.ts","../src/data/schemaDefaults.ts","../src/data/store.ts","../src/data/types.ts","../src/auth/session.ts","../src/auth/db.ts","../src/auth/role.ts","../src/auth/index.ts","../src/live-query/context.ts","../src/utils/index.ts","../src/live-query/handlers.ts","../src/methods/index.ts"],"names":["Module","name","stores","queries","mutations","routes","cronJobs","configSchema","rateLimits","channels","key","getConfig","serializeZodSchema","zodType","def","shape","serializedShape","value","effectsDef","serializeModelSchema","schema","serialized","item","isDocumentRecord","isZodType","getZodDef","getWrappedZodType","getZodDefaultValue","wrappedType","applyDefaultsToZodValue","applyDefaultsToModelSchema","applyDefaultsToSchemaDefinition","schemaDefinition","index","document","result","currentValue","defaultValue","COMPARABLE_INDEX_OPTION_FIELDS","hasModelencePrefix","getComparableIndexOptions","options","field","isSameIndexKey","left","right","leftEntries","rightEntries","leftField","leftDirection","rightField","rightDirection","isDeepStrictEqual","isSameIndexDefinition","existing","desired","getIndexKeySignature","direction","listIndexes","collection","error","MongoError","generateAutoIndexName","normalizeIndexName","autoName","Store","_Store","current","config","tail","extendedSchema","extendedIndexes","extendedSearchIndexes","combinedMethods","extendedStore","client","mode","shouldDropIndexes","shouldCreateIndexes","existingIndexes","indexByName","indexNamesByKey","droppedIndexNames","addIndexToLookup","existingIndex","keySignature","names","removeIndexFromLookup","indexName","dropIndexIfNeeded","currentIndexNames","idx","orphanedIndexes","existingIdx","orphanedIndex","requiresDropBeforeCreate","existingByName","existingNamesForKey","existingName","alignedIndex","searchIndex","selector","ObjectId","query","errorHandler","cursor","id","idSelector","docWithId","documents","update","replacement","filter","f","pipeline","operations","oldName","db","embedding","numCandidates","limit","projection","dimensions","similarity","schemaString","z","schemaNumber","schemaDate","schemaBoolean","schemaArray","schemaObject","schemaEnum","_collection","_schema","linkNoncesCollection","issueLinkNonce","userId","nonce","randomBytes","time","consumeLinkNonce","entry","sessionsCollection","obtainSession","authToken","existingSession","createSession","setSessionUser","clearSessionUser","invalidateAllUserSessions","now","expiresAt","processSessionHeartbeat","session","newExpiresAt","setAuthTokenCookie","res","clearAuthTokenCookie","session_default","args","user","getPublicConfigs","usersCollection","dbDisposableEmailDomains","emailVerificationTokensCollection","resetPasswordTokensCollection","roleMap","defaultRoles","initRoles","roles","_defaultRoles","definition","getUnauthenticatedRoles","getDefaultAuthenticatedRoles","requireAccess","requiredPermissions","missingPermission","permission","hasPermission","role","authenticate","userDoc","LiveData","isServer","requireServer","htmlToText","html","socketSubscriptions","getSocketSubs","socket","subs","handleSubscribeLiveQuery","payload","parsed","subscriptionId","method","clientInfo","existingSub","err","subscription","context","liveData","runLiveMethod","fetchAndEmit","data","sanitizeResult","getResponseTypeMap","isPendingPublish","isFetching","processPendingPublish","cleanup","handleUnsubscribeLiveQuery","sub","handleLiveQueryDisconnect","methods","createQuery","methodDef","validateMethodName","_createMethodInternal","createMutation","_createSystemQuery","validateSystemMethodName","_createSystemMutation","type","handler","permissions","runMethod","transaction","startTransaction","response"],"mappings":"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","file":"chunk-6CHWWK3O.js","sourcesContent":["import { ConfigSchema, ConfigParams, ValueType } from '../config/types';\nimport { getConfig as _getConfig } from '../config/server';\nimport { CronJobInputParams } from '../cron/types';\nimport { Store } from '../data/store';\nimport { AnyMethodShape } from '../methods/types';\nimport { RouteDefinition } from '../routes/types';\nimport { RateLimitRule } from '../rate-limit/types';\nimport { ServerChannel } from '@/websocket/serverChannel';\n\n/** Array of Store instances that will be provisioned when the module is loaded */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Stores = Store<any, any>[];\n\n/** Record of query methods that can be called from the client */\ntype Queries = Record<string, AnyMethodShape>;\n\n/** Record of mutation methods that can be called from the client */\ntype Mutations = Record<string, AnyMethodShape>;\n\n/**\n * The Module class is a core building block of a Modelence application that encapsulates related functionality.\n * Modules can contain stores, queries, mutations, routes, cron jobs and configurations.\n *\n * @category Module\n *\n * @example\n * ```ts\n * const todoModule = new Module('todo', {\n * stores: [dbTodos],\n * queries: {\n * async getAll() {\n * // Fetch and return all Todo items\n * }\n * },\n * mutations: {\n * async create({ title }, { user }) {\n * // Create a new Todo item\n * }\n * }\n * });\n * ```\n */\nexport class Module<\n TName extends string = string,\n TSchema extends Record<string, ConfigParams> = ConfigSchema,\n TQueries extends Queries = Queries,\n TMutations extends Mutations = Mutations,\n> {\n /** @internal */\n public readonly name: TName;\n\n /** @internal */\n public readonly stores: Stores;\n\n /** @internal */\n public readonly queries: TQueries;\n\n /** @internal */\n public readonly mutations: TMutations;\n\n /** @internal */\n public readonly routes: RouteDefinition[];\n\n /** @internal */\n public readonly cronJobs: Record<string, CronJobInputParams>;\n\n /** @internal */\n public readonly configSchema: TSchema;\n\n /** @internal */\n public rateLimits: RateLimitRule[];\n\n /** @internal */\n public readonly channels: ServerChannel[];\n\n /**\n * Creates a new Module instance\n *\n * @param name - The unique name of the module.\n * This name is used to namespace queries, mutations,\n * cron jobs and configuration values with a prefix (e.g. \"todo.create\")\n *\n * @param options - Module configuration options\n */\n constructor(\n name: TName,\n {\n stores = [],\n queries = {} as TQueries,\n mutations = {} as TMutations,\n routes = [],\n cronJobs = {},\n configSchema = {} as TSchema,\n rateLimits = [],\n channels = [],\n }: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n stores?: Store<any, any>[];\n queries?: TQueries;\n mutations?: TMutations;\n routes?: RouteDefinition[];\n cronJobs?: Record<string, CronJobInputParams>;\n configSchema?: TSchema;\n rateLimits?: RateLimitRule[];\n channels?: ServerChannel[];\n } = {}\n ) {\n this.name = name;\n this.stores = stores;\n this.queries = queries;\n this.mutations = mutations;\n this.routes = routes;\n this.cronJobs = cronJobs;\n this.configSchema = configSchema;\n this.rateLimits = rateLimits;\n this.channels = channels;\n }\n\n /**\n * Retrieves a typed configuration value for this module.\n * The return type is inferred from the schema — no casts needed.\n *\n * @example\n * ```ts\n * const myModule = new Module('payments', {\n * configSchema: {\n * apiKey: { type: 'secret', default: '', isPublic: false },\n * maxRetries: { type: 'number', default: 3, isPublic: false },\n * },\n * mutations: {\n * async charge({ amount }) {\n * const apiKey = myModule.getConfig('apiKey'); // string\n * const maxRetries = myModule.getConfig('maxRetries'); // number\n * },\n * },\n * });\n * ```\n */\n getConfig<K extends keyof TSchema & string>(key: K): ValueType<TSchema[K]['type']> {\n return _getConfig(`${this.name}.${key}`) as ValueType<TSchema[K]['type']>;\n }\n}\n","import { z } from 'zod';\nimport { ModelSchema } from './types';\n\ntype ObjectTypeDefinition = {\n [key: string]: z.ZodType | ObjectTypeDefinition | Array<z.ZodType | ObjectTypeDefinition>;\n};\n\nexport interface SerializedModelSchema {\n [key: string]:\n | SerializedSchema\n | (SerializedSchema | SerializedModelSchema)[]\n | SerializedModelSchema\n | 'v2';\n}\n\n// Type guards for Zod schema types\ntype ZodDefWithTypeName = {\n typeName: z.ZodFirstPartyTypeKind;\n};\n\ntype ZodArrayDef = ZodDefWithTypeName & {\n type: z.ZodType;\n};\n\ntype ZodObjectDef = ZodDefWithTypeName & {\n shape: () => Record<string, z.ZodType>;\n};\n\ntype ZodOptionalDef = ZodDefWithTypeName & {\n innerType: z.ZodType;\n};\n\ntype ZodNullableDef = ZodDefWithTypeName & {\n innerType: z.ZodType;\n};\n\ntype ZodEnumDef = ZodDefWithTypeName & {\n values: readonly [string, ...string[]];\n};\n\ntype ZodUnionDef = ZodDefWithTypeName & {\n options: readonly [z.ZodType, z.ZodType, ...z.ZodType[]];\n};\n\ntype ZodEffectsDef = ZodDefWithTypeName & {\n schema: z.ZodType;\n effect: { type: 'refinement' | 'transform' | 'preprocess' };\n description?: string;\n};\n\ntype BaseSerializedSchema =\n | { type: 'string' }\n | { type: 'number' }\n | { type: 'boolean' }\n | { type: 'date' }\n | { type: 'array'; items: SerializedSchema }\n | { type: 'object'; items: Record<string, SerializedSchema> }\n | { type: 'enum'; items: readonly string[] }\n | { type: 'union'; items: SerializedSchema[] }\n | { type: 'custom'; typeName: string };\n\ntype SerializedSchema = BaseSerializedSchema | (BaseSerializedSchema & { optional: true });\n\n/**\n * Serializes a Zod schema to a JSON-serializable format\n */\nfunction serializeZodSchema(zodType: z.ZodType): SerializedSchema {\n const def = zodType._def as ZodDefWithTypeName;\n\n if (def.typeName === 'ZodString') {\n return { type: 'string' };\n }\n if (def.typeName === 'ZodNumber') {\n return { type: 'number' };\n }\n if (def.typeName === 'ZodBoolean') {\n return { type: 'boolean' };\n }\n if (def.typeName === 'ZodDate') {\n return { type: 'date' };\n }\n if (def.typeName === 'ZodArray') {\n const arrayDef = def as ZodArrayDef;\n return {\n type: 'array',\n items: serializeZodSchema(arrayDef.type),\n };\n }\n if (def.typeName === 'ZodObject') {\n const objectDef = def as ZodObjectDef;\n const shape = objectDef.shape();\n const serializedShape: Record<string, SerializedSchema> = {};\n for (const [key, value] of Object.entries(shape)) {\n serializedShape[key] = serializeZodSchema(value as z.ZodType);\n }\n return {\n type: 'object',\n items: serializedShape,\n };\n }\n if (def.typeName === 'ZodOptional') {\n const optionalDef = def as ZodOptionalDef;\n return {\n ...serializeZodSchema(optionalDef.innerType),\n optional: true,\n };\n }\n if (def.typeName === 'ZodNullable') {\n const nullableDef = def as ZodNullableDef;\n return {\n ...serializeZodSchema(nullableDef.innerType),\n optional: true,\n };\n }\n if (def.typeName === 'ZodEnum') {\n const enumDef = def as ZodEnumDef;\n return {\n type: 'enum',\n items: enumDef.values,\n };\n }\n if (def.typeName === 'ZodUnion') {\n const unionDef = def as ZodUnionDef;\n return {\n type: 'union',\n items: unionDef.options.map(serializeZodSchema),\n };\n }\n if (def.typeName === 'ZodEffects') {\n // ZodEffects is used for z.instanceof(ObjectId), z.refine(), etc.\n const effectsDef = def as ZodEffectsDef;\n\n // Check description for custom types\n if (effectsDef.description) {\n return { type: 'custom', typeName: effectsDef.description } as SerializedSchema;\n }\n\n // For other effects, try to serialize the underlying schema\n return serializeZodSchema(effectsDef.schema);\n }\n\n // For custom types like ObjectId, ref, etc.\n return { type: 'custom', typeName: def.typeName };\n}\n\n/**\n * Serializes a model schema to a JSON-serializable format\n */\nexport function serializeModelSchema(schema: ModelSchema): SerializedModelSchema {\n const serialized: SerializedModelSchema = {};\n\n for (const [key, value] of Object.entries(schema)) {\n if (Array.isArray(value)) {\n // Handle array of schema definitions\n serialized[key] = value.map((item) => {\n if (typeof item === 'object' && '_def' in item) {\n return serializeZodSchema(item as z.ZodType);\n }\n return serializeModelSchema(item as ObjectTypeDefinition);\n });\n } else if (typeof value === 'object' && '_def' in value) {\n // It's a Zod type\n serialized[key] = serializeZodSchema(value as z.ZodType);\n } else {\n // It's a nested object definition\n serialized[key] = serializeModelSchema(value as ObjectTypeDefinition);\n }\n }\n\n return serialized;\n}\n","import { Document } from 'mongodb';\nimport { z } from 'zod';\n\ntype ZodDefWithTypeName = {\n typeName: string;\n};\n\ntype ZodWrapperDef = ZodDefWithTypeName & {\n innerType?: z.ZodType;\n schema?: z.ZodType;\n type?: z.ZodType;\n out?: z.ZodType;\n};\n\ntype ZodDefaultDef = ZodWrapperDef & {\n defaultValue: () => unknown;\n};\n\ntype ZodObjectDef = ZodDefWithTypeName & {\n shape: () => Record<string, z.ZodType>;\n};\n\ntype ZodArrayDef = ZodDefWithTypeName & {\n type: z.ZodType;\n};\n\nconst isDocumentRecord = (value: unknown): value is Document =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst isZodType = (value: unknown): value is z.ZodType =>\n isDocumentRecord(value) && '_def' in value;\n\nconst getZodDef = (zodType: z.ZodType): ZodDefWithTypeName => zodType._def as ZodDefWithTypeName;\n\nconst getWrappedZodType = (zodType: z.ZodType): z.ZodType | undefined => {\n const def = getZodDef(zodType) as ZodWrapperDef;\n\n if (\n def.typeName === 'ZodOptional' ||\n def.typeName === 'ZodNullable' ||\n def.typeName === 'ZodDefault' ||\n def.typeName === 'ZodCatch' ||\n def.typeName === 'ZodReadonly'\n ) {\n return def.innerType;\n }\n\n if (def.typeName === 'ZodEffects') {\n return def.schema;\n }\n\n if (def.typeName === 'ZodBranded') {\n return def.type;\n }\n\n if (def.typeName === 'ZodPipeline') {\n return def.out;\n }\n\n return undefined;\n};\n\nconst getZodDefaultValue = (zodType: z.ZodType): { hasDefault: boolean; value?: unknown } => {\n const def = getZodDef(zodType);\n\n if (def.typeName === 'ZodDefault') {\n return {\n hasDefault: true,\n value: (def as ZodDefaultDef).defaultValue(),\n };\n }\n\n const wrappedType = getWrappedZodType(zodType);\n if (wrappedType) {\n return getZodDefaultValue(wrappedType);\n }\n\n return { hasDefault: false };\n};\n\nconst applyDefaultsToZodValue = (zodType: z.ZodType, value: unknown): unknown => {\n const def = getZodDef(zodType);\n\n if (def.typeName === 'ZodObject' && isDocumentRecord(value)) {\n return applyDefaultsToModelSchema((def as ZodObjectDef).shape(), value);\n }\n\n if (def.typeName === 'ZodArray' && Array.isArray(value)) {\n return value.map((item) => applyDefaultsToZodValue((def as ZodArrayDef).type, item));\n }\n\n const wrappedType = getWrappedZodType(zodType);\n if (wrappedType) {\n return applyDefaultsToZodValue(wrappedType, value);\n }\n\n return value;\n};\n\nconst applyDefaultsToSchemaDefinition = (schemaDefinition: unknown, value: unknown): unknown => {\n if (isZodType(schemaDefinition)) {\n return applyDefaultsToZodValue(schemaDefinition, value);\n }\n\n if (Array.isArray(schemaDefinition) && Array.isArray(value)) {\n if (schemaDefinition.length === 1) {\n return value.map((item) => applyDefaultsToSchemaDefinition(schemaDefinition[0], item));\n }\n\n return value.map((item, index) =>\n applyDefaultsToSchemaDefinition(schemaDefinition[index], item)\n );\n }\n\n if (isDocumentRecord(schemaDefinition) && isDocumentRecord(value)) {\n return applyDefaultsToModelSchema(schemaDefinition, value);\n }\n\n return value;\n};\n\nexport const applyDefaultsToModelSchema = (\n schema: Record<string, unknown>,\n document: Document\n): Document => {\n const result: Document = { ...document };\n\n for (const [key, schemaDefinition] of Object.entries(schema)) {\n const currentValue = result[key];\n\n if (currentValue === undefined) {\n if (isZodType(schemaDefinition)) {\n const defaultValue = getZodDefaultValue(schemaDefinition);\n if (defaultValue.hasDefault) {\n result[key] = applyDefaultsToSchemaDefinition(schemaDefinition, defaultValue.value);\n }\n }\n continue;\n }\n\n result[key] = applyDefaultsToSchemaDefinition(schemaDefinition, currentValue);\n }\n\n return result;\n};\n","import { isDeepStrictEqual } from 'node:util';\n\nimport {\n AggregateOptions,\n AggregationCursor,\n Collection,\n DeleteResult,\n Document,\n IndexDescription,\n InsertOneResult,\n MongoClient,\n UpdateResult,\n Filter,\n WithId,\n WithoutId,\n OptionalUnlessRequiredId,\n FindOptions,\n UpdateFilter,\n ObjectId,\n BulkWriteResult,\n AnyBulkWriteOperation,\n InsertManyResult,\n ClientSession,\n SearchIndexDescription,\n MongoError,\n FilterOperators,\n SortDirection,\n FindOneAndUpdateOptions,\n FindOneAndDeleteOptions,\n FindOneAndReplaceOptions,\n ReplaceOptions,\n ChangeStream,\n ChangeStreamOptions,\n DistinctOptions,\n} from 'mongodb';\nimport { ModelSchema, InferDocumentType } from './types';\nimport { serializeModelSchema } from './schemaSerializer';\nimport { applyDefaultsToModelSchema } from './schemaDefaults';\n\n/**\n * Top-level query operators (logical and evaluation) - custom version without Document index signature\n * Based on MongoDB's RootFilterOperators but without the [key: string]: any from Document\n * @internal\n */\ntype StrictRootFilterOperators<TSchema> = {\n $and?: TypedFilter<TSchema>[];\n $or?: TypedFilter<TSchema>[];\n $nor?: TypedFilter<TSchema>[];\n $not?: TypedFilter<TSchema>;\n $text?: {\n $search: string;\n $language?: string;\n $caseSensitive?: boolean;\n $diacriticSensitive?: boolean;\n };\n\n $where?: string | ((this: TSchema) => boolean);\n $comment?: string | Document;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n $expr?: any;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n $jsonSchema?: any;\n};\n\n/**\n * Helper type to extract array element type\n * @internal\n */\ntype ArrayElement<T> = T extends (infer E)[] ? E : never;\ntype Flatten<T> = T extends ReadonlyArray<infer E> ? E : T;\n\n/**\n * Helper type for $in/$nin that accepts any array/tuple where elements are assignable to T\n * This solves the issue where TypeScript infers ['a', 'b'] as a tuple instead of ('a' | 'b')[]\n * and where Array<Union> gets distributed into Union1[] | Union2[] | ...\n * We wrap the Exclude in a tuple check to prevent distribution\n * @internal\n */\ntype NonUndefined<T> = T extends undefined ? never : T;\ntype ArrayLikeOfUnion<T> = [NonUndefined<T>] extends [never]\n ? never\n : ReadonlyArray<NonUndefined<T>> | Array<NonUndefined<T>>;\n\n/**\n * Enhanced FilterOperators that fixes $in and $nin to properly accept arrays of union types\n * MongoDB's native FilterOperators has issues with union types in $in/$nin arrays\n * because TypeScript distributes Array<Union> into Array1 | Array2 | ...\n * @internal\n */\ntype EnhancedFilterOperators<T> = Omit<FilterOperators<T>, '$in' | '$nin'> & {\n $in?: ArrayLikeOfUnion<T>;\n $nin?: ArrayLikeOfUnion<T>;\n};\n\ntype ExistingIndex = Document & {\n key?: Document;\n name?: string;\n};\n\ntype TypedFieldSelection<T, TValue> = {\n [K in keyof WithId<T> & string]?: TValue;\n} & {\n [key: `${string}.${string}`]: TValue;\n};\n\ntype ProjectionValue =\n | 0\n | 1\n | boolean\n | { $meta: string }\n | { $slice: number | [number, number] }\n | { $elemMatch: Document };\n\ntype TypedSort<T> = TypedFieldSelection<T, SortDirection>;\ntype TypedProjection<T> = TypedFieldSelection<T, ProjectionValue>;\n\ntype FetchOptions<T> = {\n sort?: TypedSort<T>;\n limit?: number;\n skip?: number;\n projection?: TypedProjection<T>;\n};\n\nexport type IndexCreationMode = 'blocking' | 'background';\nexport type IndexReconcileMode = 'full' | 'drop-only' | 'create-only';\n\nconst COMPARABLE_INDEX_OPTION_FIELDS = [\n 'background',\n 'bits',\n 'bucketSize',\n 'collation',\n 'default_language',\n 'expireAfterSeconds',\n 'hidden',\n 'language_override',\n 'max',\n 'min',\n 'partialFilterExpression',\n 'sparse',\n 'storageEngine',\n 'textIndexVersion',\n 'unique',\n 'weights',\n 'wildcardProjection',\n '2dsphereIndexVersion',\n] as const;\n\nconst isDocumentRecord = (value: unknown): value is Document =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst hasModelencePrefix = (name: string): boolean => name.startsWith('_modelence_');\n\nconst getComparableIndexOptions = (index: ExistingIndex | IndexDescription): Document => {\n const options: Document = {};\n\n for (const field of COMPARABLE_INDEX_OPTION_FIELDS) {\n const value = (index as Document)[field];\n if (value !== undefined) {\n options[field] = value;\n }\n }\n\n return options;\n};\n\n/**\n * MongoDB index key order is significant (e.g. { a: 1, b: 1 } !== { b: 1, a: 1 }).\n */\nconst isSameIndexKey = (left: unknown, right: unknown): boolean => {\n if (!isDocumentRecord(left) || !isDocumentRecord(right)) {\n return false;\n }\n\n const leftEntries = Object.entries(left);\n const rightEntries = Object.entries(right);\n\n if (leftEntries.length !== rightEntries.length) {\n return false;\n }\n\n return leftEntries.every(([leftField, leftDirection], index) => {\n const [rightField, rightDirection] = rightEntries[index] || [];\n return leftField === rightField && isDeepStrictEqual(leftDirection, rightDirection);\n });\n};\n\nconst isSameIndexDefinition = (existing: ExistingIndex, desired: IndexDescription): boolean => {\n if (!isSameIndexKey(existing.key, desired.key)) {\n return false;\n }\n\n return isDeepStrictEqual(getComparableIndexOptions(existing), getComparableIndexOptions(desired));\n};\n\nconst getIndexKeySignature = (key: unknown): string | null => {\n if (!isDocumentRecord(key)) {\n return null;\n }\n\n return Object.entries(key)\n .map(([field, direction]) => `${field}:${JSON.stringify(direction)}`)\n .join('|');\n};\n\n/**\n * Lists all indexes in a collection, returning an empty array if collection doesn't exist\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst listIndexes = async (collection: Collection<any>): Promise<Document[]> => {\n try {\n return await collection.listIndexes().toArray();\n } catch (error) {\n // If collection doesn't exist yet, return empty array\n // It will be created when we insert data or create indexes\n if (error instanceof MongoError && error.code === 26) {\n return [];\n }\n throw error;\n }\n};\n\n/**\n * Generates an auto-generated index name from the index keys\n * Mimics MongoDB's default naming: field1_direction1_field2_direction2\n */\nconst generateAutoIndexName = (key: Document): string => {\n return Object.entries(key)\n .map(([field, direction]) => `${field}_${direction}`)\n .join('_');\n};\n\n/**\n * Normalizes an index by ensuring it has a name with _modelence_ prefix\n */\nconst normalizeIndexName = (index: IndexDescription): IndexDescription => {\n if (index.name) {\n // If name is provided, add _modelence_ prefix if not already present\n const name = index.name.startsWith('_modelence_') ? index.name : `_modelence_${index.name}`;\n return { ...index, name };\n }\n\n // Auto-generate name with _modelence_ prefix\n const autoName = generateAutoIndexName(index.key);\n return { ...index, name: `_modelence_${autoName}` };\n};\n\n/**\n * Custom filter value type that handles array fields specially:\n * - For array fields: allows element type, full array type, or FilterOperators\n * - For non-array fields: allows exact type or FilterOperators\n * We use [T] to prevent distribution when T is a union type\n * @internal\n */\ntype FilterValue<T> = [T] extends [unknown[]]\n ? ArrayElement<T> | T | EnhancedFilterOperators<T>\n : [T] extends [never]\n ? never\n : T | EnhancedFilterOperators<[T] extends [never] ? never : T>;\n\n/**\n * Type-safe MongoDB filter that ensures only schema fields can be queried\n * while supporting all MongoDB query operators and dot notation for nested fields.\n *\n * This type combines:\n * - MongoDB's native `FilterOperators<T>` for field-level operators (comprehensive operator support)\n * - Custom `StrictRootFilterOperators<T>` for top-level operators without index signature\n * - Custom array field handling: allows passing single element when field is an array\n * - Custom restriction: only strings containing dots are allowed for nested field queries\n *\n * @example\n * ```ts\n * const dbUsers = new Store('users', {\n * schema: {\n * name: schema.string(),\n * age: schema.number(),\n * tags: schema.array(schema.string()),\n * collections: schema.array(schema.string()),\n * address: schema.object({\n * street: schema.string(),\n * city: schema.string(),\n * }),\n * },\n * indexes: []\n * });\n *\n * // ✅ Valid - field exists in schema\n * await dbUsers.findOne({ name: 'John' });\n *\n * // ✅ Valid - using MongoDB operators (from FilterOperators)\n * await dbUsers.findOne({ age: { $gt: 18 } });\n * await dbUsers.findOne({ tags: { $in: ['typescript', 'mongodb'] } });\n * await dbUsers.findOne({ $or: [{ name: 'John' }, { name: 'Jane' }] });\n *\n * // ✅ Valid - array field with single element (checks if array contains the element)\n * await dbUsers.findOne({ collections: 'users' });\n *\n * // ✅ Valid - dot notation for nested fields (must contain a dot)\n * await dbUsers.findOne({ 'address.city': 'New York' });\n * await dbUsers.findOne({ 'emails.0.address': 'test@example.com' });\n *\n * // ❌ TypeScript error - 'id' is not in schema and doesn't contain a dot\n * await dbUsers.findOne({ id: '123' });\n * ```\n */\nexport type TypedFilter<T> = {\n [K in keyof WithId<T>]?: FilterValue<WithId<T>[K]>;\n} & StrictRootFilterOperators<T> & {\n // Support for MongoDB dot notation (e.g., 'emails.address', 'profile.settings.theme')\n // Only strings containing dots are allowed, which provides better type safety\n // while still enabling MongoDB's nested field query syntax\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K: `${string}.${string}`]: any;\n };\n\n/**\n * Helper type to preserve method types when extending a store.\n * Maps each method to work with the extended schema while preserving signatures.\n * @internal\n */\ntype PreserveMethodsForExtendedSchema<\n TBaseMethods extends Record<string, (...args: never[]) => unknown>,\n TExtendedSchema extends ModelSchema,\n> = {\n [K in keyof TBaseMethods]: TBaseMethods[K] extends (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this: any,\n ...args: infer Args\n ) => infer Return\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (this: WithId<InferDocumentType<TExtendedSchema>> & any, ...args: Args) => Return\n : never;\n};\n\n/**\n * Type-erased Store reference for chain traversal.\n * Chain members carry different TSchema/TMethods, so the generic\n * parameters must be erased. This alias contains the `any` in one place.\n * @internal\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyStore = Store<any, any>;\n\n/**\n * The Store class provides a type-safe interface for MongoDB collections with built-in schema validation and helper methods.\n *\n * @category Store\n * @typeParam TSchema - The document schema type\n * @typeParam TMethods - Custom methods that will be added to documents\n *\n * @example\n * ```ts\n * const dbTodos = new Store('todos', {\n * schema: {\n * title: schema.string(),\n * completed: schema.boolean(),\n * dueDate: schema.date().optional(),\n * userId: schema.userId(),\n * },\n * methods: {\n * isOverdue() {\n * return this.dueDate < new Date();\n * }\n * }\n * });\n * ```\n */\nexport class Store<\n TSchema extends ModelSchema,\n TMethods extends Record<\n string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (this: WithId<InferDocumentType<TSchema>> & TMethods, ...args: any[]) => any\n >,\n> {\n /** @internal */\n readonly _type!: InferDocumentType<TSchema>;\n /** @internal */\n readonly _rawDoc!: WithId<this['_type']>;\n /** @internal */\n readonly _doc!: this['_rawDoc'] & TMethods;\n\n readonly Doc!: this['_doc'];\n\n private name: string;\n private readonly schema: TSchema;\n private readonly methods?: TMethods;\n private readonly indexes: IndexDescription[];\n private readonly searchIndexes: SearchIndexDescription[];\n private readonly indexCreationMode: IndexCreationMode;\n private collection?: Collection<this['_type']>;\n private client?: MongoClient;\n\n // Chain tracking for linear extension model\n private _chainParent: AnyStore | null = null;\n private _chainChild: AnyStore | null = null;\n\n /**\n * Creates a new Store instance\n *\n * @param name - The collection name in MongoDB\n * @param options - Store configuration (schema, indexes, methods, search indexes, and optional index creation mode)\n */\n constructor(\n name: string,\n options: {\n /** Document schema using Modelence schema types */\n schema: TSchema;\n /** Custom methods to add to documents */\n methods?: TMethods;\n /** MongoDB indexes to create */\n indexes: IndexDescription[];\n /** MongoDB Atlas Search */\n searchIndexes?: SearchIndexDescription[];\n /** Whether index creation should block startup or run in background (default: 'background') */\n indexCreationMode?: IndexCreationMode;\n }\n ) {\n this.name = name;\n this.schema = options.schema;\n this.methods = options.methods;\n // Normalize all indexes to have _modelence_ prefix\n this.indexes = options.indexes.map(normalizeIndexName);\n this.searchIndexes = options.searchIndexes || [];\n this.indexCreationMode = options.indexCreationMode ?? 'background';\n }\n\n getName() {\n return this.name;\n }\n\n getIndexCreationMode() {\n return this.indexCreationMode;\n }\n\n /** @internal */\n getSchema() {\n return this.schema;\n }\n\n /** @internal */\n getSerializedSchema() {\n return serializeModelSchema(this.schema);\n }\n\n /** @internal – normalized indexes (already have _modelence_ prefix) */\n getIndexes(): IndexDescription[] {\n return this.indexes;\n }\n\n /** @internal */\n getSearchIndexes(): SearchIndexDescription[] {\n return this.searchIndexes;\n }\n\n /** @internal – follows the chain to the latest extension */\n getChainTail(): AnyStore {\n let current: AnyStore = this;\n while (current._chainChild) {\n current = current._chainChild;\n }\n return current;\n }\n\n /** @internal – follows the chain back to the original store */\n getChainRoot(): AnyStore {\n let current: AnyStore = this;\n while (current._chainParent) {\n current = current._chainParent;\n }\n return current;\n }\n\n /**\n * Extends the store with additional schema fields, indexes, methods, and search indexes.\n * Returns a new Store instance with the extended schema and updated types.\n * Methods from the original store are preserved with updated type signatures.\n *\n * @param config - Additional schema fields, indexes, methods, search indexes, and optional index creation mode to add\n * @returns A new Store instance with the extended schema\n *\n * @example\n * ```ts\n * // Extend the users collection\n * export const dbUsers = baseUsersCollection.extend({\n * schema: {\n * firstName: schema.string(),\n * lastName: schema.string(),\n * companyId: schema.objectId().optional(),\n * },\n * indexes: [\n * { key: { companyId: 1 } },\n * { key: { lastName: 1, firstName: 1 } },\n * ],\n * methods: {\n * getFullName() {\n * return `${this.firstName} ${this.lastName}`;\n * }\n * }\n * });\n *\n * // Now fully typed with new fields\n * const user = await dbUsers.findOne({ firstName: 'John' });\n * console.log(user?.getFullName());\n * ```\n */\n extend<\n TExtendedSchema extends ModelSchema,\n TExtendedMethods extends Record<string, Function> = Record<string, never>,\n >(config: {\n schema?: TExtendedSchema;\n indexes?: IndexDescription[];\n methods?: TExtendedMethods;\n searchIndexes?: SearchIndexDescription[];\n /** Whether index creation should block startup or run in background */\n indexCreationMode?: IndexCreationMode;\n }): Store<\n TSchema & TExtendedSchema,\n PreserveMethodsForExtendedSchema<TMethods, TSchema & TExtendedSchema> & TExtendedMethods\n > {\n // Follow chain to the tail – extending always appends to the end\n const tail: AnyStore = this.getChainTail();\n\n if (this.client || tail.client) {\n throw new Error(\n `Store.extend() must be called before startApp(). Store '${this.name}' has already been initialized and cannot be extended.`\n );\n }\n\n type ExtendedSchema = TSchema & TExtendedSchema;\n\n const extendedSchema = {\n ...tail.schema,\n ...(config.schema || {}),\n } as ExtendedSchema;\n\n const extendedIndexes = [...tail.indexes, ...(config.indexes || [])];\n const extendedSearchIndexes = [...tail.searchIndexes, ...(config.searchIndexes || [])];\n\n type CombinedMethods = PreserveMethodsForExtendedSchema<TMethods, ExtendedSchema> &\n TExtendedMethods;\n\n const combinedMethods = {\n ...(tail.methods || {}),\n ...(config.methods || {}),\n } as CombinedMethods | undefined;\n\n const extendedStore = new Store<ExtendedSchema, CombinedMethods>(this.name, {\n schema: extendedSchema,\n methods: combinedMethods as unknown as CombinedMethods | undefined,\n indexes: extendedIndexes,\n searchIndexes: extendedSearchIndexes,\n indexCreationMode: config.indexCreationMode ?? tail.indexCreationMode,\n });\n\n // Link into the chain\n tail._chainChild = extendedStore;\n extendedStore._chainParent = tail;\n\n return extendedStore;\n }\n\n /** @internal */\n init(client: MongoClient) {\n if (this.collection) {\n throw new Error(`Collection ${this.name} is already initialized`);\n }\n\n this.client = client;\n this.collection = this.client.db().collection<this['_type']>(this.name);\n }\n\n /** @internal */\n async createIndexes(mode: IndexReconcileMode = 'full') {\n const collection = this.requireCollection();\n const shouldDropIndexes = mode !== 'create-only';\n const shouldCreateIndexes = mode !== 'drop-only';\n\n // Get all existing indexes in the collection (returns [] if collection doesn't exist)\n const existingIndexes = await listIndexes(collection);\n const indexByName = new Map<string, ExistingIndex & { name: string }>();\n const indexNamesByKey = new Map<string, Set<string>>();\n const droppedIndexNames = new Set<string>();\n\n const addIndexToLookup = (existingIndex: ExistingIndex & { name: string }) => {\n indexByName.set(existingIndex.name, existingIndex);\n\n const keySignature = getIndexKeySignature(existingIndex.key);\n if (!keySignature) {\n return;\n }\n\n const names = indexNamesByKey.get(keySignature);\n if (names) {\n names.add(existingIndex.name);\n } else {\n indexNamesByKey.set(keySignature, new Set([existingIndex.name]));\n }\n };\n\n const removeIndexFromLookup = (indexName: string) => {\n const existingIndex = indexByName.get(indexName);\n if (!existingIndex) {\n return;\n }\n\n indexByName.delete(indexName);\n\n const keySignature = getIndexKeySignature(existingIndex.key);\n if (!keySignature) {\n return;\n }\n\n const names = indexNamesByKey.get(keySignature);\n if (!names) {\n return;\n }\n\n names.delete(indexName);\n if (names.size === 0) {\n indexNamesByKey.delete(keySignature);\n }\n };\n\n for (const existingIndex of existingIndexes) {\n if (typeof existingIndex.name === 'string') {\n addIndexToLookup({\n ...existingIndex,\n name: existingIndex.name,\n });\n }\n }\n\n const dropIndexIfNeeded = async (indexName: string) => {\n if (indexName === '_id_' || droppedIndexNames.has(indexName)) {\n return;\n }\n try {\n await collection.dropIndex(indexName);\n } catch (error) {\n // Another concurrent reconciler may have already dropped it.\n if (!(error instanceof MongoError && error.code === 27)) {\n throw error;\n }\n }\n droppedIndexNames.add(indexName);\n removeIndexFromLookup(indexName);\n };\n\n if (shouldDropIndexes) {\n // Find all _modelence_ prefixed indexes that are not in the current schema\n const currentIndexNames = new Set(\n this.indexes\n .map((idx) => idx.name)\n .filter((name): name is string => typeof name === 'string')\n );\n const orphanedIndexes = [...indexByName.values()].filter(\n (existingIdx) =>\n hasModelencePrefix(existingIdx.name) && !currentIndexNames.has(existingIdx.name)\n );\n\n // Drop orphaned indexes\n for (const orphanedIndex of orphanedIndexes) {\n await dropIndexIfNeeded(orphanedIndex.name);\n }\n }\n\n // Reconcile code-defined indexes against the current DB metadata.\n // Code wins on conflicts; non-conflicting manual indexes are preserved.\n if (this.indexes.length > 0) {\n for (const index of this.indexes) {\n if (!index.name) {\n continue;\n }\n\n let requiresDropBeforeCreate = false;\n const existingByName = indexByName.get(index.name);\n if (existingByName && !isSameIndexDefinition(existingByName, index)) {\n if (shouldDropIndexes) {\n await dropIndexIfNeeded(existingByName.name);\n } else {\n requiresDropBeforeCreate = true;\n }\n }\n\n const keySignature = getIndexKeySignature(index.key);\n if (keySignature) {\n const existingNamesForKey = [...(indexNamesByKey.get(keySignature) || [])];\n for (const existingName of existingNamesForKey) {\n if (existingName !== index.name) {\n if (shouldDropIndexes) {\n await dropIndexIfNeeded(existingName);\n } else {\n requiresDropBeforeCreate = true;\n }\n }\n }\n }\n\n const alignedIndex = indexByName.get(index.name);\n const hasAlignedIndex = !!alignedIndex && isSameIndexDefinition(alignedIndex, index);\n\n if (!hasAlignedIndex && shouldCreateIndexes && !requiresDropBeforeCreate) {\n await collection.createIndexes([index]);\n addIndexToLookup({\n name: index.name,\n key: index.key,\n ...getComparableIndexOptions(index),\n });\n }\n }\n }\n if (shouldCreateIndexes && this.searchIndexes.length > 0) {\n for (const searchIndex of this.searchIndexes) {\n try {\n await collection.createSearchIndexes([searchIndex]);\n } catch (error) {\n if (error instanceof MongoError && error.code === 68 && searchIndex.name) {\n await collection.dropSearchIndex(searchIndex.name);\n await collection.createSearchIndexes([searchIndex]);\n } else {\n throw error;\n }\n }\n }\n }\n }\n\n private wrapDocument(document: this['_rawDoc']): this['_doc'] {\n if (!this.methods) {\n return document as unknown as this['_doc'];\n }\n\n const result = Object.create(\n null,\n Object.getOwnPropertyDescriptors({\n ...document,\n ...this.methods,\n })\n );\n\n return result as this['_doc'];\n }\n\n /**\n * For convenience, to also allow directy passing a string or ObjectId as the selector\n */\n private getSelector(selector: TypedFilter<this['_type']> | string | ObjectId) {\n if (typeof selector === 'string') {\n return { _id: new ObjectId(selector) } as Filter<this['_type']>;\n }\n\n if (selector instanceof ObjectId) {\n return { _id: selector } as Filter<this['_type']>;\n }\n\n return selector as Filter<this['_type']>;\n }\n\n /** @internal */\n requireCollection() {\n if (!this.collection) {\n throw new Error(`Collection ${this.name} is not provisioned`);\n }\n\n return this.collection;\n }\n\n /** @internal */\n requireClient() {\n if (!this.client) {\n throw new Error(`Database is not connected`);\n }\n\n return this.client;\n }\n\n /**\n * Finds a single document matching the query\n *\n * @param query - Type-safe query filter. Only schema fields, MongoDB operators, and dot notation are allowed.\n * @param options - Find options\n * @returns The document, or null if not found\n *\n * @example\n * ```ts\n * // ✅ Valid queries:\n * await store.findOne({ name: 'John' })\n * await store.findOne({ age: { $gt: 18 } })\n * await store.findOne({ _id: new ObjectId('...') })\n * await store.findOne({ tags: { $in: ['typescript', 'mongodb'] } })\n * await store.findOne({ $or: [{ name: 'John' }, { name: 'Jane' }] })\n * await store.findOne({ 'emails.address': 'test@example.com' }) // dot notation\n *\n * // ❌ TypeScript error - 'id' is not in schema:\n * await store.findOne({ id: '123' })\n * ```\n */\n async findOne(query: TypedFilter<this['_type']>, options?: FindOptions) {\n const document = await this.requireCollection().findOne<this['_rawDoc']>(\n query as Filter<this['_type']>,\n options\n );\n return document ? this.wrapDocument(document) : null;\n }\n\n async requireOne(\n query: TypedFilter<this['_type']>,\n options?: FindOptions,\n errorHandler?: () => Error\n ): Promise<this['_doc']> {\n const result = await this.findOne(query, options);\n if (!result) {\n throw errorHandler ? errorHandler() : new Error(`Record not found in ${this.name}`);\n }\n return result;\n }\n\n private find(query: TypedFilter<this['_type']>, options?: FetchOptions<this['_type']>) {\n const cursor = this.requireCollection().find(\n query as Filter<this['_type']>,\n options?.projection ? { projection: options.projection } : undefined\n );\n if (options?.sort) {\n cursor.sort(options.sort);\n }\n if (options?.limit) {\n cursor.limit(options.limit);\n }\n if (options?.skip) {\n cursor.skip(options.skip);\n }\n return cursor;\n }\n\n /**\n * Fetches a single document by its ID\n *\n * @param id - The ID of the document to find\n * @returns The document, or null if not found\n */\n async findById(id: string | ObjectId): Promise<this['_doc'] | null> {\n const idSelector = typeof id === 'string' ? { _id: new ObjectId(id) } : { _id: id };\n return await this.findOne(idSelector as TypedFilter<this['_type']>);\n }\n\n /**\n * Fetches a single document by its ID, or throws an error if not found\n *\n * @param id - The ID of the document to find\n * @param errorHandler - Optional error handler to return a custom error if the document is not found\n * @returns The document\n */\n async requireById(id: string | ObjectId, errorHandler?: () => Error): Promise<this['_doc']> {\n const result = await this.findById(id);\n if (!result) {\n throw errorHandler\n ? errorHandler()\n : new Error(`Record with id ${id} not found in ${this.name}`);\n }\n return result;\n }\n\n /**\n * Counts the number of documents that match a query\n *\n * @param query - The query to filter documents\n * @returns The number of documents that match the query\n */\n countDocuments(query: TypedFilter<this['_type']>): Promise<number> {\n return this.requireCollection().countDocuments(query as Filter<this['_type']>);\n }\n\n /**\n * Fetches multiple documents, equivalent to Node.js MongoDB driver's `find` and `toArray` methods combined.\n *\n * @param query - The query to filter documents\n * @param options - Optional fetch options\n * @param options.projection - Fields to include or exclude in the result documents\n * @param options.sort - Sort order for matching documents\n * @param options.limit - Maximum number of documents to return\n * @param options.skip - Number of matching documents to skip\n * @returns The documents\n *\n * @example\n * ```ts\n * // Include only selected fields\n * const docs = await store.fetch(\n * { userId: user.id },\n * { projection: { framework: 1, title: 1 }, sort: { createdAt: -1 }, limit: 50 }\n * );\n *\n * // Exclude large fields when not needed\n * const chunks = await store.fetch(\n * { documentId },\n * { projection: { embedding: 0 } }\n * );\n * ```\n */\n async fetch(\n query: TypedFilter<this['_type']>,\n options?: FetchOptions<this['_type']>\n ): Promise<this['_doc'][]> {\n const cursor = this.find(query, options);\n return (await cursor.toArray()).map(this.wrapDocument.bind(this));\n }\n\n /**\n * Inserts a single document\n *\n * @param document - The document to insert\n * @returns The result of the insert operation\n */\n async insertOne(\n document: OptionalUnlessRequiredId<InferDocumentType<TSchema>>,\n options?: { session?: ClientSession }\n ): Promise<InsertOneResult> {\n return await this.requireCollection().insertOne(document, options);\n }\n\n /**\n * Inserts a single document and returns the inserted document with its generated `_id`\n * and any helper methods applied.\n *\n * Unlike {@link insertOne}, which only returns the insert result metadata, this method\n * returns the full inserted document — useful when you need to immediately use the\n * newly created record (e.g. returning it from an API handler).\n *\n * @param document - The document to insert\n * @returns The inserted document with `_id` populated and methods applied\n *\n * @example\n * ```ts\n * const todo = await dbTodos.create({ title: 'Buy milk', completed: false });\n * console.log(todo._id); // ObjectId\n * console.log(todo.title); // 'Buy milk'\n * ```\n */\n async create(\n document: OptionalUnlessRequiredId<InferDocumentType<TSchema>>,\n options?: { session?: ClientSession }\n ): Promise<this['_doc']> {\n const docWithId = applyDefaultsToModelSchema(this.schema, {\n _id: new ObjectId(),\n ...document,\n }) as OptionalUnlessRequiredId<InferDocumentType<TSchema>>;\n\n await this.requireCollection().insertOne(docWithId, options);\n\n return this.wrapDocument(docWithId as unknown as this['_rawDoc']);\n }\n\n /**\n * Inserts multiple documents\n *\n * @param documents - The documents to insert\n * @returns The result of the insert operation\n */\n async insertMany(\n documents: OptionalUnlessRequiredId<InferDocumentType<TSchema>>[],\n options?: { session?: ClientSession }\n ): Promise<InsertManyResult> {\n return await this.requireCollection().insertMany(documents, options);\n }\n\n /**\n * Updates a single document\n *\n * @param selector - The selector to find the document to update\n * @param update - The update to apply to the document\n * @returns The result of the update operation\n */\n async updateOne(\n selector: TypedFilter<this['_type']> | string | ObjectId,\n update: UpdateFilter<this['_type']>,\n options?: { session?: ClientSession }\n ): Promise<UpdateResult> {\n return await this.requireCollection().updateOne(this.getSelector(selector), update, options);\n }\n\n /**\n * Updates a single document, or inserts it if it doesn't exist\n *\n * @param selector - The selector to find the document to update\n * @param update - The MongoDB modifier to apply to the document\n * @returns The result of the update operation\n */\n async upsertOne(\n selector: TypedFilter<this['_type']> | string | ObjectId,\n update: UpdateFilter<this['_type']>,\n options?: { session?: ClientSession }\n ): Promise<UpdateResult> {\n return await this.requireCollection().updateOne(this.getSelector(selector), update, {\n upsert: true,\n ...options,\n });\n }\n\n /**\n * Updates multiple documents\n *\n * @param selector - The selector to find the documents to update\n * @param update - The MongoDB modifier to apply to the documents\n * @returns The result of the update operation\n */\n async updateMany(\n selector: TypedFilter<this['_type']>,\n update: UpdateFilter<this['_type']>,\n options?: { session?: ClientSession }\n ): Promise<UpdateResult> {\n return await this.requireCollection().updateMany(\n selector as Filter<this['_type']>,\n update,\n options\n );\n }\n\n /**\n * Updates multiple documents, or inserts them if they don't exist\n *\n * @param selector - The selector to find the documents to update\n * @param update - The MongoDB modifier to apply to the documents\n * @returns The result of the update operation\n */\n async upsertMany(\n selector: TypedFilter<this['_type']>,\n update: UpdateFilter<this['_type']>,\n options?: { session?: ClientSession }\n ): Promise<UpdateResult> {\n return await this.requireCollection().updateMany(selector as Filter<this['_type']>, update, {\n upsert: true,\n ...options,\n });\n }\n\n /**\n * Deletes a single document\n *\n * @param selector - The selector to find the document to delete\n * @returns The result of the delete operation\n */\n async deleteOne(\n selector: TypedFilter<this['_type']> | string | ObjectId,\n options?: { session?: ClientSession }\n ): Promise<DeleteResult> {\n return await this.requireCollection().deleteOne(this.getSelector(selector), options);\n }\n\n /**\n * Deletes multiple documents\n *\n * @param selector - The selector to find the documents to delete\n * @returns The result of the delete operation\n */\n async deleteMany(\n selector: TypedFilter<this['_type']>,\n options?: { session?: ClientSession }\n ): Promise<DeleteResult> {\n return await this.requireCollection().deleteMany(selector as Filter<this['_type']>, options);\n }\n\n /**\n * Atomically finds a document and updates it, returning the document\n *\n * @param selector - The selector to find the document\n * @param update - The update to apply\n * @param options - Options including `returnDocument` ('before' or 'after'), `upsert`, `session`, etc.\n * @returns The document (before or after update, depending on options), or null if not found\n */\n async findOneAndUpdate(\n selector: TypedFilter<this['_type']> | string | ObjectId,\n update: UpdateFilter<this['_type']>,\n options?: Omit<FindOneAndUpdateOptions, 'includeResultMetadata'>\n ): Promise<this['_doc'] | null> {\n const result = await this.requireCollection().findOneAndUpdate(\n this.getSelector(selector),\n update,\n options ?? {}\n );\n return result ? this.wrapDocument(result as this['_rawDoc']) : null;\n }\n\n /**\n * Atomically finds a document and deletes it, returning the deleted document\n *\n * @param selector - The selector to find the document\n * @param options - Options including `session`, `projection`, etc.\n * @returns The deleted document, or null if not found\n */\n async findOneAndDelete(\n selector: TypedFilter<this['_type']> | string | ObjectId,\n options?: Omit<FindOneAndDeleteOptions, 'includeResultMetadata'>\n ): Promise<this['_doc'] | null> {\n const result = await this.requireCollection().findOneAndDelete(\n this.getSelector(selector),\n options ?? {}\n );\n return result ? this.wrapDocument(result as this['_rawDoc']) : null;\n }\n\n /**\n * Atomically finds a document and replaces it, returning the document\n *\n * @param selector - The selector to find the document\n * @param replacement - The replacement document\n * @param options - Options including `returnDocument` ('before' or 'after'), `upsert`, `session`, etc.\n * @returns The document (before or after replacement, depending on options), or null if not found\n */\n async findOneAndReplace(\n selector: TypedFilter<this['_type']> | string | ObjectId,\n replacement: WithoutId<this['_type']>,\n options?: Omit<FindOneAndReplaceOptions, 'includeResultMetadata'>\n ): Promise<this['_doc'] | null> {\n const result = await this.requireCollection().findOneAndReplace(\n this.getSelector(selector),\n replacement,\n options ?? {}\n );\n return result ? this.wrapDocument(result as this['_rawDoc']) : null;\n }\n\n /**\n * Replaces a single document\n *\n * @param selector - The selector to find the document to replace\n * @param replacement - The replacement document (must not contain update operators)\n * @param options - Options including `upsert`, `session`, etc.\n * @returns The result of the replace operation\n */\n async replaceOne(\n selector: TypedFilter<this['_type']> | string | ObjectId,\n replacement: WithoutId<this['_type']>,\n options?: ReplaceOptions\n ): Promise<UpdateResult> {\n return await this.requireCollection().replaceOne(\n this.getSelector(selector),\n replacement,\n options\n );\n }\n\n /**\n * Returns an array of distinct values for a field across the collection\n *\n * @param key - The field name (supports dot notation for nested fields)\n * @param filter - Optional filter to narrow the documents\n * @param options - Optional distinct options\n * @returns An array of distinct values\n */\n\n async distinct<K extends keyof this['_rawDoc'] & string>(\n key: K,\n filter?: TypedFilter<this['_type']>,\n options?: DistinctOptions\n ): Promise<Array<Flatten<this['_rawDoc'][K]>>> {\n const f = (filter ?? {}) as Filter<this['_type']>;\n return options !== undefined\n ? await this.requireCollection().distinct(key, f, options)\n : await this.requireCollection().distinct(key, f);\n }\n\n /**\n * Opens a change stream on the collection to watch for real-time changes\n *\n * @param pipeline - Optional aggregation pipeline to filter/transform change events\n * @param options - Optional change stream options\n * @returns A ChangeStream instance\n */\n watch(pipeline?: Document[], options?: ChangeStreamOptions): ChangeStream {\n return this.requireCollection().watch(pipeline, options);\n }\n\n /**\n * Aggregates documents using MongoDB's aggregation framework\n *\n * @param pipeline - The aggregation pipeline\n * @param options - Optional options\n * @returns The aggregation cursor\n */\n aggregate(pipeline: Document[], options?: AggregateOptions): AggregationCursor<Document> {\n return this.requireCollection().aggregate(pipeline, options);\n }\n\n /**\n * Performs a bulk write operation on the collection\n *\n * @param operations - The operations to perform\n * @returns The result of the bulk write operation\n */\n bulkWrite(operations: AnyBulkWriteOperation<this['_type']>[]): Promise<BulkWriteResult> {\n return this.requireCollection().bulkWrite(operations);\n }\n\n /**\n * Returns the raw MongoDB database instance for advanced operations\n * @returns The MongoDB database instance\n * @throws Error if the store is not provisioned\n */\n getDatabase() {\n return this.requireClient().db();\n }\n\n /**\n * Returns the raw MongoDB collection instance for advanced operations\n * @returns The MongoDB collection instance\n * @throws Error if the store is not provisioned\n */\n rawCollection() {\n return this.requireCollection();\n }\n\n /**\n * Renames an existing collection to this store's name, used for migrations\n * @param oldName - The previous name of the collection\n * @throws Error if the old collection doesn't exist or if this store's collection already exists\n */\n async renameFrom(oldName: string, options?: { session?: ClientSession }) {\n const db = this.getDatabase();\n\n if (!this.collection || !db) {\n throw new Error(`Store ${this.name} is not provisioned`);\n }\n\n const oldCollections = await db.listCollections({ name: oldName }).toArray();\n if (oldCollections.length === 0) {\n throw new Error(`Collection ${oldName} not found`);\n }\n\n const newCollections = await db.listCollections({ name: this.name }).toArray();\n if (newCollections.length > 0) {\n throw new Error(`Collection ${this.name} already exists`);\n }\n\n const existingCollection = db.collection<this['_type']>(oldName);\n\n await existingCollection.rename(this.name, options);\n }\n\n /**\n * Performs a vector similarity search using MongoDB Atlas Vector Search\n *\n * @param params - Vector search parameters\n * @param params.field - The field name containing the vector embeddings\n * @param params.embedding - The query vector to search for\n * @param params.numCandidates - Number of nearest neighbors to consider (default: 100)\n * @param params.limit - Maximum number of results to return (default: 10)\n * @param params.projection - Additional fields to include in the results\n * @param params.indexName - Name of index (default: field + VectorSearch)\n * @returns An aggregation cursor with search results and scores\n *\n * @example\n * ```ts\n * const results = await store.vectorSearch({\n * field: 'embedding',\n * embedding: [0.1, 0.2, 0.3, ...],\n * numCandidates: 100,\n * limit: 10,\n * projection: { title: 1, description: 1 }\n * });\n * ```\n */\n async vectorSearch({\n field,\n embedding,\n numCandidates,\n limit,\n projection,\n indexName,\n }: {\n field: string;\n embedding: number[];\n numCandidates?: number;\n limit?: number;\n projection?: Document;\n indexName?: string;\n }) {\n return this.aggregate([\n {\n $vectorSearch: {\n index: indexName || field + 'VectorSearch',\n path: field,\n queryVector: embedding,\n numCandidates: numCandidates || 100,\n limit: limit || 10,\n },\n },\n {\n $project: {\n _id: 1,\n score: { $meta: 'vectorSearchScore' },\n ...projection,\n },\n },\n ]);\n }\n\n /**\n * Creates a MongoDB Atlas Vector Search index definition\n *\n * @param params - Vector index parameters\n * @param params.field - The field name to create the vector index on\n * @param params.dimensions - The number of dimensions in the vector embeddings\n * @param params.similarity - The similarity metric to use (default: 'cosine')\n * @param params.indexName - Name of index (default: field + VectorSearch)\n * @returns A search index description object\n *\n * @example\n * ```ts\n * const store = new Store('documents', {\n * schema: {\n * title: schema.string(),\n * embedding: schema.array(schema.number()),\n * },\n * indexes: [],\n * searchIndexes: [\n * Store.vectorIndex({\n * field: 'embedding',\n * dimensions: 1536,\n * similarity: 'cosine'\n * })\n * ]\n * });\n * ```\n */\n static vectorIndex({\n field,\n dimensions,\n similarity = 'cosine',\n indexName,\n }: {\n field: string;\n dimensions: number;\n similarity?: 'cosine' | 'euclidean' | 'dotProduct';\n indexName?: string;\n }) {\n return {\n type: 'vectorSearch',\n name: indexName || field + 'VectorSearch',\n definition: {\n fields: [\n {\n type: 'vector',\n path: field,\n numDimensions: dimensions,\n similarity,\n },\n ],\n },\n };\n }\n}\n","import { ObjectId } from 'mongodb';\nimport { z, ZodArray, ZodNumber } from 'zod';\nimport { Store } from './store';\n\ntype ObjectTypeDefinition = {\n [key: string]: SchemaTypeDefinition;\n};\n\ntype SingularSchemaTypeDefinition = z.ZodType | ObjectTypeDefinition; // ReturnType<typeof schema[keyof typeof schema]>;\n\ntype SchemaTypeDefinition = SingularSchemaTypeDefinition | Array<SingularSchemaTypeDefinition>;\n\nexport type ModelSchema = {\n [key: string]: SchemaTypeDefinition;\n};\n\nconst schemaString: typeof z.string = z.string.bind(z);\n\nconst schemaNumber: typeof z.number = z.number.bind(z);\n\nconst schemaDate: typeof z.date = z.date.bind(z);\n\nconst schemaBoolean: typeof z.boolean = z.boolean.bind(z);\n\nconst schemaArray: typeof z.array = z.array.bind(z);\n\nconst schemaObject: typeof z.object = z.object.bind(z);\n\nconst schemaEnum: typeof z.enum = z.enum.bind(z);\n\nexport const schema = {\n string: schemaString,\n number: schemaNumber,\n date: schemaDate,\n boolean: schemaBoolean,\n array: schemaArray,\n object: schemaObject,\n enum: schemaEnum,\n embedding(): ZodArray<ZodNumber> {\n return z.array(z.number());\n },\n objectId(): z.ZodType<ObjectId> {\n return z.instanceof(ObjectId).describe('ObjectId');\n },\n userId(): z.ZodType<ObjectId> {\n return z.instanceof(ObjectId).describe('UserId');\n },\n ref<T extends ModelSchema>(\n _collection: string | Store<T, InferDocumentType<T>>\n ): z.ZodType<ObjectId> {\n return z.instanceof(ObjectId).describe('Ref');\n },\n union: z.union.bind(z),\n infer<T extends SchemaTypeDefinition>(_schema: T): InferDocumentType<T> {\n return {} as InferDocumentType<T>;\n },\n} as const;\n\nexport type InferDocumentType<T extends SchemaTypeDefinition> = {\n [K in keyof T as T[K] extends z.ZodOptional<z.ZodTypeAny> ? K : never]?: T[K] extends z.ZodType\n ? z.infer<T[K]>\n : never;\n} & {\n [K in keyof T as T[K] extends z.ZodOptional<z.ZodTypeAny> ? never : K]: T[K] extends z.ZodType\n ? z.infer<T[K]>\n : T[K] extends Array<infer ElementType extends SchemaTypeDefinition>\n ? Array<InferDocumentType<ElementType>>\n : T[K] extends ObjectTypeDefinition\n ? InferDocumentType<T[K]>\n : never;\n};\n\nexport namespace schema {\n export type infer<T extends SchemaTypeDefinition> = InferDocumentType<T>;\n}\n","import { randomBytes } from 'crypto';\nimport { type Response } from 'express';\nimport { ObjectId } from 'mongodb';\nimport { Module } from '../app/module';\nimport { getPublicConfigs } from '../config/server';\nimport { Store } from '../data/store';\nimport { schema } from '../data/types';\nimport { time } from '../time';\nimport { Session } from './types';\n\nexport const linkNoncesCollection = new Store('_modelenceLinkNonces', {\n schema: {\n nonce: schema.string(),\n userId: schema.string(),\n expiresAt: schema.date(),\n },\n indexes: [\n { key: { nonce: 1 }, unique: true },\n { key: { expiresAt: 1 }, expireAfterSeconds: 0 },\n ],\n});\n\nexport async function issueLinkNonce(userId: string): Promise<string> {\n const nonce = randomBytes(32).toString('hex');\n await linkNoncesCollection.insertOne({\n nonce,\n userId,\n expiresAt: new Date(Date.now() + time.minutes(10)),\n });\n return nonce;\n}\n\nexport async function consumeLinkNonce(nonce: string): Promise<string | null> {\n const entry = await linkNoncesCollection.findOneAndDelete({ nonce });\n if (!entry) return null;\n return entry.userId;\n}\n\nexport const sessionsCollection = new Store('_modelenceSessions', {\n schema: {\n authToken: schema.string(),\n createdAt: schema.date(),\n expiresAt: schema.date(),\n userId: schema.userId().nullable(),\n },\n indexes: [\n { key: { authToken: 1 }, unique: true },\n { key: { expiresAt: 1 }, expireAfterSeconds: 0 },\n { key: { userId: 1 } },\n ],\n});\n\nexport async function obtainSession(authToken: string | null): Promise<Session> {\n const existingSession = authToken ? await sessionsCollection.findOne({ authToken }) : null;\n\n if (existingSession) {\n return {\n authToken: String(existingSession.authToken),\n expiresAt: new Date(existingSession.expiresAt),\n userId: existingSession.userId ?? null,\n };\n }\n\n return await createSession();\n}\n\nexport async function setSessionUser(authToken: string, userId: ObjectId) {\n await sessionsCollection.updateOne(\n { authToken },\n {\n $set: { userId },\n }\n );\n}\n\nexport async function clearSessionUser(authToken: string) {\n await sessionsCollection.updateOne(\n { authToken },\n {\n $set: { userId: null },\n }\n );\n}\n\nexport async function invalidateAllUserSessions(userId: ObjectId) {\n await sessionsCollection.deleteMany({ userId });\n}\n\nexport async function createSession(userId: ObjectId | null = null): Promise<Session> {\n // TODO: add rate-limiting and captcha handling\n\n const authToken = randomBytes(32).toString('base64url');\n const now = Date.now();\n const expiresAt = new Date(now + time.days(7));\n\n await sessionsCollection.insertOne({\n authToken,\n createdAt: new Date(now),\n expiresAt,\n userId,\n });\n\n return {\n authToken,\n expiresAt,\n userId,\n };\n}\n\nasync function processSessionHeartbeat(session: Session) {\n const now = Date.now();\n const newExpiresAt = new Date(now + time.days(7));\n\n await sessionsCollection.updateOne(\n { authToken: session.authToken },\n {\n $set: {\n lastActiveDate: new Date(now),\n expiresAt: newExpiresAt,\n },\n }\n );\n}\n\nexport function setAuthTokenCookie(res: Response, authToken: string) {\n res.cookie('authToken', authToken, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n maxAge: time.days(7),\n });\n}\n\nexport function clearAuthTokenCookie(res: Response) {\n res.clearCookie('authToken', {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n });\n}\n\nexport default new Module('_system.session', {\n stores: [sessionsCollection, linkNoncesCollection],\n mutations: {\n init: async function (args, { session, user, res }) {\n // Only refresh the cookie for logged-in sessions. Writing one for a\n // freshly-minted anonymous session creates a Set-Cookie that the\n // browser then attaches to the client's reconciliation request,\n // shadowing the localStorage token sent in the body — see\n // getCallContext's `cookie || body.authToken` precedence.\n if (res && session?.userId) {\n setAuthTokenCookie(res, session.authToken);\n }\n\n return {\n session,\n user,\n configs: getPublicConfigs(),\n };\n },\n heartbeat: async function (args, { session }) {\n // Session might not exist if there is no database/authentication setup\n if (session) {\n await processSessionHeartbeat(session);\n }\n },\n },\n});\n","import { schema } from '../data/types';\nimport { Store } from '../data/store';\n\n/**\n * Database collection for storing user accounts with authentication methods and profile information.\n *\n * This is where **signupWithPassword** automatically creates new users.\n *\n * @example\n * ```typescript\n * // Find user by email\n * const user = await dbUsers.findOne(\n * { 'emails.address': 'john@example.com' }\n * );\n * ```\n *\n */\nexport const usersCollection = new Store('_modelenceUsers', {\n schema: {\n handle: schema.string(),\n emails: schema\n .array(\n schema.object({\n address: schema.string(),\n verified: schema.boolean(),\n })\n )\n .optional(),\n status: schema.enum(['active', 'disabled', 'deleted']).optional(),\n firstName: schema.string().optional(),\n lastName: schema.string().optional(),\n avatarUrl: schema.string().optional(),\n createdAt: schema.date(),\n disabledAt: schema.date().optional(),\n deletedAt: schema.date().optional(),\n roles: schema.array(schema.string()).optional(),\n authMethods: schema.object({\n password: schema\n .object({\n hash: schema.string(),\n })\n .optional(),\n google: schema\n .object({\n id: schema.string(),\n })\n .optional(),\n github: schema\n .object({\n id: schema.string(),\n })\n .optional(),\n }),\n },\n indexes: [\n {\n key: { handle: 1 },\n unique: true,\n collation: { locale: 'en', strength: 2 }, // Case-insensitive\n },\n {\n key: { 'emails.address': 1, status: 1 },\n },\n {\n key: { 'authMethods.google.id': 1 },\n sparse: true,\n unique: true,\n },\n {\n key: { 'authMethods.github.id': 1 },\n sparse: true,\n unique: true,\n },\n ],\n});\n\nexport const dbDisposableEmailDomains = new Store('_modelenceDisposableEmailDomains', {\n schema: {\n domain: schema.string(),\n addedAt: schema.date(),\n },\n indexes: [\n {\n key: { domain: 1 },\n unique: true,\n },\n ],\n});\n\nexport const emailVerificationTokensCollection = new Store('_modelenceEmailVerificationTokens', {\n schema: {\n userId: schema.objectId(),\n email: schema.string().optional(),\n token: schema.string(),\n createdAt: schema.date(),\n expiresAt: schema.date(),\n },\n indexes: [\n {\n key: { token: 1 },\n unique: true,\n },\n {\n key: { expiresAt: 1 },\n expireAfterSeconds: 0,\n },\n ],\n});\n\nexport const resetPasswordTokensCollection = new Store('_modelenceResetPasswordTokens', {\n schema: {\n userId: schema.objectId(),\n email: schema.string().optional(),\n token: schema.string(),\n createdAt: schema.date(),\n expiresAt: schema.date(),\n },\n indexes: [\n {\n key: { token: 1 },\n unique: true,\n },\n {\n key: { expiresAt: 1 },\n expireAfterSeconds: 0,\n },\n ],\n});\n","import { RoleDefinition, Role, DefaultRoles, Permission } from './types';\n\nconst roleMap = new Map<Role, RoleDefinition>();\nconst defaultRoles: DefaultRoles = {\n authenticated: null,\n unauthenticated: null,\n};\n\nexport function initRoles(\n roles: Record<Role, RoleDefinition>,\n _defaultRoles: Record<string, Role>\n) {\n defaultRoles.authenticated = _defaultRoles.authenticated;\n defaultRoles.unauthenticated = _defaultRoles.unauthenticated;\n\n for (const [name, definition] of Object.entries(roles)) {\n roleMap.set(name, definition);\n }\n}\n\nexport function getUnauthenticatedRoles() {\n return defaultRoles.unauthenticated ? [defaultRoles.unauthenticated] : [];\n}\n\nexport function getDefaultAuthenticatedRoles() {\n return defaultRoles.authenticated ? [defaultRoles.authenticated] : [];\n}\n\nexport function hasAccess(roles: Role[], requiredPermissions: Permission[]) {\n return requiredPermissions.every((permission) => hasPermission(roles, permission));\n}\n\nexport function requireAccess(roles: Role[], requiredPermissions: Permission[]) {\n const missingPermission = requiredPermissions.find(\n (permission) => !hasPermission(roles, permission)\n );\n\n if (missingPermission) {\n throw new Error(`Access denied - missing permission: '${missingPermission}'`);\n }\n}\n\nexport function hasPermission(roles: Role[], permission: Permission) {\n for (const role of roles) {\n const definition = roleMap.get(role);\n\n if (definition?.permissions?.includes(permission)) {\n return true;\n }\n }\n\n return false;\n}\n","import { ObjectId } from 'mongodb';\n\nimport { obtainSession } from './session';\nimport { usersCollection } from './db';\nimport { getDefaultAuthenticatedRoles, getUnauthenticatedRoles } from './role';\nimport { Role, Session, UserInfo } from './types';\n\nexport async function authenticate(\n authToken: string | null\n): Promise<{ session: Session; user: UserInfo | null; roles: Role[] }> {\n const session = await obtainSession(authToken);\n\n const userDoc = session.userId\n ? await usersCollection.findOne({\n _id: new ObjectId(session.userId),\n status: { $nin: ['deleted', 'disabled'] },\n })\n : null;\n const user = userDoc\n ? {\n id: userDoc._id.toString(),\n handle: userDoc.handle,\n roles: userDoc.roles || [],\n hasRole: (role: string) => (userDoc.roles || []).includes(role),\n requireRole: (role: string) => {\n if (!(userDoc.roles || []).includes(role)) {\n throw new Error(`Access denied - role '${role}' required`);\n }\n },\n firstName: userDoc.firstName ?? undefined,\n lastName: userDoc.lastName ?? undefined,\n avatarUrl: userDoc.avatarUrl ?? undefined,\n }\n : null;\n\n const roles = user ? getDefaultAuthenticatedRoles() : getUnauthenticatedRoles();\n\n return {\n user,\n session,\n roles,\n };\n}\n","/**\n * Publish function provided to watch handlers.\n * Call this to trigger a re-fetch and send updated data to the client.\n */\nexport type LiveQueryPublish = () => void;\n\n/**\n * Cleanup function returned by watch handlers.\n * Called when the client unsubscribes.\n */\nexport type LiveQueryCleanup = () => void;\n\n/**\n * Context passed to watch handlers.\n */\nexport interface WatchContext {\n publish: LiveQueryPublish;\n}\n\n/**\n * Watch function that sets up real-time monitoring.\n * Receives a context with publish callback to trigger re-fetches.\n * Returns a cleanup function.\n */\nexport type LiveQueryWatch = (context: WatchContext) => LiveQueryCleanup | void;\n\n/**\n * Configuration for creating LiveData.\n */\nexport interface LiveDataConfig<T = unknown> {\n /**\n * Fetches the current data. Called initially and whenever watch triggers publish.\n */\n fetch: () => Promise<T> | T;\n /**\n * Sets up watching for changes. Receives publish callback and returns cleanup.\n */\n watch: LiveQueryWatch;\n}\n\n/**\n * LiveData object returned by live query handlers.\n *\n * @example\n * ```typescript\n * import { LiveData } from 'modelence/server';\n *\n * ...\n *\n * getTodos({ userId }, context) {\n * return new LiveData({\n * fetch: async () => await dbTodos.fetch({ userId }),\n * watch: ({ publish }) => {\n * // Subscribe to changes and call publish when data changes\n * listener.onChange(publish);\n *\n * return () => {\n * // Cleanup function to unsubscribe from changes\n * };\n * }\n * });\n * }\n * ```\n */\nexport class LiveData<T = unknown> {\n readonly fetch: () => Promise<T> | T;\n readonly watch: LiveQueryWatch;\n\n constructor(config: LiveDataConfig<T>) {\n this.fetch = config.fetch;\n this.watch = config.watch;\n }\n}\n","export function isServer() {\n return typeof window !== 'object';\n}\n\nexport function requireServer() {\n if (!isServer()) {\n throw new Error('This function can only be called on the server');\n }\n}\n\nexport function htmlToText(html: string) {\n return html\n .replace(/<[^>]*>/g, '')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n","import { Socket } from 'socket.io';\nimport { z } from 'zod';\nimport { authenticate } from '../auth';\nimport { runLiveMethod } from '../methods';\nimport { getResponseTypeMap, sanitizeResult } from '../methods/serialize';\nimport { LiveQueryCleanup } from './context';\nimport { Context } from '@/methods/types';\n\ninterface ActiveSubscription {\n cleanup: LiveQueryCleanup | null;\n aborted?: boolean;\n}\n\nconst socketSubscriptions = new Map<string, Map<string, ActiveSubscription>>();\n\nfunction getSocketSubs(socket: Socket): Map<string, ActiveSubscription> {\n let subs = socketSubscriptions.get(socket.id);\n if (!subs) {\n subs = new Map();\n socketSubscriptions.set(socket.id, subs);\n }\n return subs;\n}\n\nexport async function handleSubscribeLiveQuery(socket: Socket, payload: unknown) {\n const parsed = z\n .object({\n subscriptionId: z.string().min(1),\n method: z.string().min(1),\n args: z.record(z.unknown()).default({}),\n authToken: z.string().nullish(),\n 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 .optional(),\n })\n .safeParse(payload);\n if (!parsed.success) {\n socket.emit('liveQueryError', {\n subscriptionId: null,\n error: `Invalid payload: ${parsed.error.message}`,\n });\n return;\n }\n const { subscriptionId, method, args, authToken, clientInfo } = parsed.data;\n\n const subs = getSocketSubs(socket);\n\n // Clean up any existing subscription with the same ID (handles reconnect race conditions)\n const existingSub = subs.get(subscriptionId);\n if (existingSub) {\n if (existingSub.cleanup) {\n try {\n existingSub.cleanup();\n } catch (err) {\n console.error('[LiveQuery] Error cleaning up existing subscription:', err);\n }\n } else {\n // Subscription is still initializing - mark it for abort so it cleans up when ready\n existingSub.aborted = true;\n }\n }\n\n // Create placeholder entry BEFORE the async call so disconnect handler can find it\n const subscription: ActiveSubscription = { cleanup: null };\n subs.set(subscriptionId, subscription);\n\n try {\n const { session, user, roles } = await authenticate(authToken ?? null);\n\n const context: Context = {\n session,\n user,\n roles,\n clientInfo: clientInfo ?? {\n screenWidth: 0,\n screenHeight: 0,\n windowWidth: 0,\n windowHeight: 0,\n pixelRatio: 1,\n orientation: null,\n },\n connectionInfo: {\n ip: socket.handshake.address,\n userAgent: socket.handshake.headers['user-agent'],\n },\n req: null,\n res: null,\n };\n\n const liveData = await runLiveMethod(method, args, context);\n\n const fetchAndEmit = async () => {\n const data = sanitizeResult(await liveData.fetch());\n if (subscription.aborted) {\n return;\n }\n socket.emit('liveQueryData', {\n subscriptionId,\n data,\n typeMap: getResponseTypeMap(data),\n });\n };\n\n // Set to true to perform initial fetch at the beginning\n let isPendingPublish = true;\n let isFetching = false;\n\n const processPendingPublish = () => {\n if (subscription.aborted || !isPendingPublish || isFetching) {\n return;\n }\n isPendingPublish = false;\n isFetching = true;\n fetchAndEmit()\n .catch((err) => {\n if (subscription.aborted) {\n return;\n }\n console.error(`[LiveQuery] Error fetching data for ${method}:`, err);\n socket.emit('liveQueryError', {\n subscriptionId,\n error: err instanceof Error ? err.message : String(err),\n });\n })\n .finally(() => {\n isFetching = false;\n // Process the next pending publish if another publish was triggered while fetching\n processPendingPublish();\n });\n };\n\n const cleanup = liveData.watch({\n publish: () => {\n /*\n Use a pending flag to ensure concurrent publishes are processed sequentially\n (and run only once if there have been multiple publishes while the previous one was processing)\n Without sequential processing, we could end up sending an older fetch after a newer one\n */\n isPendingPublish = true;\n processPendingPublish();\n },\n });\n\n if (subscription.aborted) {\n // Unsubscribe/disconnect happened during watch setup - clean up immediately\n if (cleanup) {\n try {\n cleanup();\n } catch (err) {\n console.error('[LiveQuery] Error cleaning up after disconnect during setup:', err);\n }\n }\n return;\n }\n\n subscription.cleanup = cleanup || null;\n\n // Process initial fetch\n processPendingPublish();\n } catch (error) {\n subs.delete(subscriptionId);\n console.error(`[LiveQuery] Error in ${method}:`, error);\n socket.emit('liveQueryError', {\n subscriptionId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n}\n\nexport function handleUnsubscribeLiveQuery(socket: Socket, payload: unknown) {\n const parsed = z\n .object({\n subscriptionId: z.string().min(1),\n })\n .safeParse(payload);\n if (!parsed.success) {\n console.warn(`[LiveQuery] Invalid unsubscribe payload: ${parsed.error.message}`);\n return;\n }\n const { subscriptionId } = parsed.data;\n\n const subs = socketSubscriptions.get(socket.id);\n if (!subs) return;\n\n const sub = subs.get(subscriptionId);\n if (sub) {\n if (sub.cleanup) {\n try {\n sub.cleanup();\n } catch (err) {\n console.error('[LiveQuery] Error in cleanup:', err);\n }\n } else {\n sub.aborted = true;\n }\n subs.delete(subscriptionId);\n }\n}\n\nexport function handleLiveQueryDisconnect(socket: Socket) {\n const subs = socketSubscriptions.get(socket.id);\n if (subs) {\n // Clean up all subscriptions for this socket\n for (const sub of subs.values()) {\n if (sub.cleanup) {\n try {\n sub.cleanup();\n } catch (err) {\n console.error('[LiveQuery] Error in cleanup on disconnect:', err);\n }\n } else {\n sub.aborted = true;\n }\n }\n socketSubscriptions.delete(socket.id);\n }\n}\n","import { requireServer } from '../utils';\nimport { startTransaction } from '@/telemetry';\nimport { requireAccess } from '../auth/role';\nimport { Method, MethodDefinition, MethodType, Args, Context } from './types';\nimport { LiveData } from '../live-query';\n\nconst methods: Record<string, Method<unknown>> = {};\n\nexport function createQuery<T extends unknown[]>(name: string, methodDef: MethodDefinition<T>) {\n requireServer();\n validateMethodName(name);\n return _createMethodInternal('query', name, methodDef);\n}\n\nexport function createMutation<T extends unknown[]>(name: string, methodDef: MethodDefinition<T>) {\n requireServer();\n validateMethodName(name);\n return _createMethodInternal('mutation', name, methodDef);\n}\n\nexport function _createSystemQuery<T extends unknown[]>(\n name: string,\n methodDef: MethodDefinition<T>\n) {\n requireServer();\n validateSystemMethodName(name);\n return _createMethodInternal('query', name, methodDef);\n}\n\nexport function _createSystemMutation<T extends unknown[]>(\n name: string,\n methodDef: MethodDefinition<T>\n) {\n requireServer();\n validateSystemMethodName(name);\n return _createMethodInternal('mutation', name, methodDef);\n}\n\nfunction validateMethodName(name: string) {\n if (name.toLowerCase().startsWith('_system.')) {\n throw new Error(`Method name cannot start with a reserved prefix: '_system.' (${name})`);\n }\n}\n\nfunction validateSystemMethodName(name: string) {\n if (!name.toLowerCase().startsWith('_system.')) {\n throw new Error(`System method name must start with a prefix: '_system.' (${name})`);\n }\n}\n\nfunction _createMethodInternal<T = unknown>(\n type: MethodType,\n name: string,\n methodDef: MethodDefinition<T>\n) {\n requireServer();\n\n if (methods[name]) {\n throw new Error(`Method with name '${name}' is already defined.`);\n }\n\n const handler = typeof methodDef === 'function' ? methodDef : methodDef.handler;\n const permissions = typeof methodDef === 'function' ? [] : (methodDef.permissions ?? []);\n methods[name] = { type, name, handler, permissions };\n}\n\nexport async function runMethod(name: string, args: Args, context: Context) {\n requireServer();\n\n const method = methods[name];\n if (!method) {\n throw new Error(`Method with name '${name}' is not defined.`);\n }\n const { type, handler } = method;\n\n const transaction = startTransaction('method', `method:${name}`, { type, args });\n\n let response;\n try {\n requireAccess(context.roles, method.permissions);\n response = await handler(args, context);\n } catch (error) {\n // TODO: log error and associate it with the transaction\n transaction.end('error');\n throw error;\n }\n\n transaction.end();\n\n return response;\n}\n\n/**\n * Run a method as a live query.\n * The handler should return a LiveData object with fetch and watch functions.\n */\nexport async function runLiveMethod(name: string, args: Args, context: Context): Promise<LiveData> {\n requireServer();\n\n const method = methods[name];\n if (!method) {\n throw new Error(`Method with name '${name}' is not defined.`);\n }\n const { type, handler } = method;\n\n if (type !== 'query') {\n throw new Error(`Live methods are only supported for queries`);\n }\n\n const transaction = startTransaction('method', `method:${name}:live`, { type, args });\n\n let result;\n try {\n requireAccess(context.roles, method.permissions);\n\n result = await handler(args, context);\n\n if (!(result instanceof LiveData)) {\n throw new Error(\n `Live query handler for '${name}' must return a LiveData object with fetch and watch functions. See https://docs.modelence.com/live-queries`\n );\n }\n } catch (error) {\n transaction.end('error');\n throw error;\n }\n\n transaction.end();\n\n return result;\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {z}from'./chunk-6CHWWK3O.js';import {a,b,c}from'./chunk-5M6FUMUK.js';import {AsyncLocalStorage}from'async_hooks';async function x(t,e,u){let n=a(await z(t,e,u)),a$1=b(n),y=JSON.parse(JSON.stringify(n));return c(y,a$1??void 0)}var p=new AsyncLocalStorage;function g(t,e){return p.run(t,e)}function d(){return p.getStore()}export{x as a,g as b,d as c};//# sourceMappingURL=chunk-L36OLCF3.js.map
|
|
2
|
+
//# sourceMappingURL=chunk-L36OLCF3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ssr/callInProcess.ts","../src/ssr/context.ts"],"names":["callInProcessMethod","methodName","args","context","sanitized","sanitizeResult","runMethod","typeMap","getResponseTypeMap","jsonRoundTripped","reviveResponseTypes","storage","AsyncLocalStorage","runWithSsrContext","ctx","fn","getSsrContext"],"mappings":"wHAOA,eAAsBA,CAAAA,CACpBC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACY,CACZ,IAAMC,CAAAA,CAAYC,CAAAA,CAAe,MAAMC,CAAAA,CAAUL,CAAAA,CAAYC,CAAAA,CAAMC,CAAO,CAAC,CAAA,CACrEI,GAAAA,CAAUC,CAAAA,CAAmBJ,CAAS,CAAA,CACtCK,CAAAA,CAAmB,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,SAAA,CAAUL,CAAS,CAAC,CAAA,CAC7D,OAAOM,CAAAA,CAAoBD,CAAAA,CAAkBF,GAAAA,EAAW,MAAS,CACnE,CCAA,IAAMI,CAAAA,CAAU,IAAIC,iBAAAA,CAEb,SAASC,CAAAA,CAAqBC,CAAAA,CAAwBC,CAAAA,CAAgB,CAC3E,OAAOJ,CAAAA,CAAQ,GAAA,CAAIG,CAAAA,CAAKC,CAAE,CAC5B,CAEO,SAASC,CAAAA,EAA+C,CAC7D,OAAOL,CAAAA,CAAQ,QAAA,EACjB","file":"chunk-L36OLCF3.js","sourcesContent":["import { runMethod } from '../methods';\nimport { sanitizeResult, getResponseTypeMap, reviveResponseTypes } from '../methods/serialize';\nimport type { Context, Args } from '../methods/types';\n\n// Invoke a method in-process and round-trip through the same JSON pipeline\n// as the HTTP transport so SSR output matches the dehydrated query cache.\n// The JSON.stringify/parse step is load-bearing: strips `undefined` props.\nexport async function callInProcessMethod<T = unknown>(\n methodName: string,\n args: Args,\n context: Context\n): Promise<T> {\n const sanitized = sanitizeResult(await runMethod(methodName, args, context));\n const typeMap = getResponseTypeMap(sanitized);\n const jsonRoundTripped = JSON.parse(JSON.stringify(sanitized));\n return reviveResponseTypes(jsonRoundTripped, typeMap ?? undefined) as T;\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { QueryClient } from '@tanstack/react-query';\nimport type { Context } from '../methods/types';\nimport type { Configs } from '../config/types';\n\nexport type SsrSessionSnapshot = {\n user: unknown;\n configs: Configs;\n};\n\nexport type SsrRequestContext = {\n callContext: Context;\n queryClient: QueryClient;\n session: SsrSessionSnapshot;\n};\n\nconst storage = new AsyncLocalStorage<SsrRequestContext>();\n\nexport function runWithSsrContext<T>(ctx: SsrRequestContext, fn: () => T): T {\n return storage.run(ctx, fn);\n}\n\nexport function getSsrContext(): SsrRequestContext | undefined {\n return storage.getStore();\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var t=class extends Error{},a=class extends t{constructor(s,o){super(s);this.status=401;this.name="AuthError",this.code=o;}},n=class extends t{constructor(s){super(s);this.status=400;this.name="ValidationError";}},c=class extends t{constructor(s){super(s);this.status=429;this.name="RateLimitError";}};export{t as a,a as b,n as c,c as d};//# sourceMappingURL=chunk-MIRF7FP3.js.map
|
|
2
|
+
//# sourceMappingURL=chunk-MIRF7FP3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/error.ts"],"names":["ModelenceError","AuthError","message","code","ValidationError","RateLimitError"],"mappings":"AAAO,IAAeA,CAAAA,CAAf,cAAsC,KAAM,EAOnD,CAEaC,CAAAA,CAAN,cAAwBD,CAAe,CAG5C,WAAA,CAAYE,CAAAA,CAAiBC,CAAAA,CAAe,CAC1C,KAAA,CAAMD,CAAO,CAAA,CAHf,IAAA,CAAA,MAAA,CAAS,GAAA,CAIP,IAAA,CAAK,IAAA,CAAO,WAAA,CACZ,IAAA,CAAK,IAAA,CAAOC,EACd,CACF,CAAA,CAEaC,CAAAA,CAAN,cAA8BJ,CAAe,CAGlD,WAAA,CAAYE,CAAAA,CAAiB,CAC3B,KAAA,CAAMA,CAAO,CAAA,CAHf,IAAA,CAAA,MAAA,CAAS,GAAA,CAIP,IAAA,CAAK,IAAA,CAAO,kBACd,CACF,CAAA,CAEaG,CAAAA,CAAN,cAA6BL,CAAe,CAGjD,WAAA,CAAYE,CAAAA,CAAiB,CAC3B,KAAA,CAAMA,CAAO,CAAA,CAHf,IAAA,CAAA,MAAA,CAAS,GAAA,CAIP,IAAA,CAAK,IAAA,CAAO,iBACd,CACF","file":"chunk-MIRF7FP3.js","sourcesContent":["export abstract class ModelenceError extends Error {\n abstract status: number;\n /**\n * Optional machine-readable error code so clients can branch on the kind of\n * error without string-matching `message` (which may be reworded or localized).\n */\n code?: string;\n}\n\nexport class AuthError extends ModelenceError {\n status = 401;\n\n constructor(message: string, code?: string) {\n super(message);\n this.name = 'AuthError';\n this.code = code;\n }\n}\n\nexport class ValidationError extends ModelenceError {\n status = 400;\n\n constructor(message: string) {\n super(message);\n this.name = 'ValidationError';\n }\n}\n\nexport class RateLimitError extends ModelenceError {\n status = 429;\n\n constructor(message: string) {\n super(message);\n this.name = 'RateLimitError';\n }\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {a,d,g,n}from'./chunk-YRR32LTF.js';import {t,v,p,w as w$1,A}from'./chunk-YLLX26A4.js';import C from'react';import v$1 from'react-dom/client';import {jsx}from'react/jsx-runtime';function h(e){return {getConfig(t){return v(`${e}.${t}`)},query(t$1,...r){let o=r[0]??{};return {queryKey:[e,t$1,o],queryFn:()=>t(`${e}.${t$1}`,o)}},mutation(t$1){return {mutationFn:r=>t(`${e}.${t$1}`,r)}},infiniteQuery(t$1,r){return {queryKey:[e,t$1,"infinite",r(void 0)],initialPageParam:void 0,queryFn:({pageParam:o})=>t(`${e}.${t$1}`,r(o))}}}}var F=h("_system");var M=class{constructor(t,r){this.category=t,this.onMessage=r;}init(){d()?.on({category:this.category,listener:this.onMessage});}joinChannel(t){d()?.joinChannel({category:this.category,id:t});}leaveChannel(t){d()?.leaveChannel({category:this.category,id:t});}};async function _(e,{filePath:t$1,contentType:r,visibility:o}){let{url:l,fields:d,filePath:c}=await t("_system.files.getUploadUrl",{filePath:t$1,contentType:r,visibility:o}),i=new FormData;for(let[p,u]of Object.entries(d))i.append(p,u);i.append("file",e);let s=await fetch(l,{method:"POST",body:i});if(!s.ok)throw new Error(`Failed to upload file: HTTP status: ${s.status}`);return {filePath:c}}async function O(e){await t("_system.files.deleteFile",{filePath:e});}async function q(e){return t("_system.files.downloadFile",{filePath:e})}async function U(e){return t("_system.files.getFileUrl",{filePath:e})}var K="useClient"in C?C.useClient(a):a;var b="__MODELENCE_STATE__";function I(){return typeof document>"u"?false:document.getElementById(b)!==null}function W(){if(typeof document>"u")return null;let e=document.getElementById(b);if(!e)return null;try{return JSON.parse(e.textContent??"")}catch(t){return console.error("Modelence: failed to parse SSR state",t),null}}var w="__modelence_ssr_snapshot__";function $(e){globalThis[w]=e;}function ze(){return globalThis[w]??null}function Q(e){if(typeof window>"u"){$(e);return}let{loadingElement:t,routesElement:r,favicon:o,errorHandler:l,router:d}=e;l&&p(l),window.addEventListener("unload",()=>{});let c=I(),i=W();i?.session&&(w$1(i.session),A());let s=document.getElementById("root"),p$1=window.location.pathname+window.location.search,u=d?d({children:r,location:p$1}):r,k=g()?u:jsx(n,{children:u}),T=jsx(C.StrictMode,{children:jsx(K,{loadingElement:t,children:k})});if(c?v$1.hydrateRoot(s,T):v$1.createRoot(s).render(T),o){let x=document.querySelector("link[rel~='icon']");if(x)x.href=o;else {let f=document.createElement("link");f.rel="icon",f.href=o,document.head.appendChild(f);}}}export{h as a,F as b,ze as c,Q as d,M as e,_ as f,O as g,q as h,U as i,K as j};//# sourceMappingURL=chunk-N7XT2ULQ.js.map
|
|
2
|
+
//# sourceMappingURL=chunk-N7XT2ULQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client/module.ts","../src/system/client.ts","../src/websocket/clientChannel.ts","../src/files/client.ts","../src/client.ts","../src/client/renderApp.tsx"],"names":["createClientModule","moduleName","key","getConfig","name","rest","args","callMethod","getArgs","pageParam","systemConfig","ClientChannel","category","onMessage","getWebsocketClientProvider","id","uploadFile","file","filePath","contentType","visibility","url","fields","resolvedFilePath","formData","value","uploadResponse","deleteFile","downloadFile","getFileUrl","AppProvider","React","SSR_STATE_SCRIPT_ID","hasSsrMarker","readSsrState","node","e","SNAPSHOT_KEY","setSnapshot","snapshot","_getSsrSnapshot","renderApp","options","loadingElement","routesElement","favicon","errorHandler","router","setErrorHandler","isHydrating","ssrState","hydrateSession","startSessionHeartbeat","container","location","routedTree","appTree","hasConnectedQueryClient","jsx","ModelenceQueryProvider","tree","ReactDOM","link","newLink"],"mappings":"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","file":"chunk-N7XT2ULQ.js","sourcesContent":["'use client';\n\nimport type { ObjectId } from 'mongodb';\nimport type { ConfigParams, ConfigType, ValueType } from '../config/types';\nimport { callMethod, type MethodArgs } from './method';\nimport type { AnyMethodShape } from '../methods/types';\n\n// Pulls the config store value without importing server-side code\nimport { getConfig as _getClientConfig } from '../config/client';\n\n// ── type helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Recursively maps ObjectId → string to match the sanitized runtime values\n * sent over the wire. Dates are preserved (revived via typeMap on the client).\n */\ntype Sanitized<T> = T extends ObjectId\n ? string\n : T extends Date\n ? Date\n : T extends (infer U)[]\n ? Sanitized<U>[]\n : T extends object\n ? { [K in keyof T]: Sanitized<T[K]> }\n : T;\n\ntype ExtractArgs<M> = M extends (args: infer A, ...rest: any[]) => any // eslint-disable-line @typescript-eslint/no-explicit-any\n ? A\n : M extends { handler: (args: infer A, ...rest: any[]) => any } // eslint-disable-line @typescript-eslint/no-explicit-any\n ? A\n : MethodArgs;\n\ntype ExtractResult<M> = M extends (...args: any[]) => Promise<infer R> // eslint-disable-line @typescript-eslint/no-explicit-any\n ? Sanitized<R>\n : M extends { handler: (...args: any[]) => Promise<infer R> } // eslint-disable-line @typescript-eslint/no-explicit-any\n ? Sanitized<R>\n : unknown;\n\ntype PublicKeyOf<TSchema extends Record<string, ConfigParams>> = {\n [K in keyof TSchema as TSchema[K] extends ConfigParams<ConfigType, true>\n ? string & K\n : never]: ValueType<TSchema[K]['type']>;\n};\n\ntype AnyModule = {\n name: string;\n configSchema: Record<string, ConfigParams>;\n queries: Record<string, AnyMethodShape>;\n mutations: Record<string, AnyMethodShape>;\n};\n\n// ── createClientModule ────────────────────────────────────────────────────────\n\n/**\n * Creates a typed client accessor for a module's public configs, queries, and mutations.\n *\n * Use `import type` to reference the module so no server code is bundled on the client.\n * Arg and return types for queries and mutations are inferred automatically from the\n * server-side handler signatures.\n *\n * @param moduleName - The module's name as passed to `new Module(name, ...)`.\n *\n * @example\n * ```ts\n * // src/client/payments.ts\n * import type paymentsModule from '../server/payments';\n * import { createClientModule } from 'modelence/client';\n *\n * export const payments = createClientModule<typeof paymentsModule>('payments');\n * ```\n *\n * ```ts\n * // src/components/Checkout.tsx\n * import { useQuery, useMutation } from '@tanstack/react-query';\n * import { payments } from '../client/payments';\n *\n * // Typed config — public keys only, private and secret keys excluded:\n * const currency = payments.getConfig('currency'); // string | undefined\n *\n * // Typed query — pass directly to useQuery:\n * const { data: products } = useQuery(payments.query('getProducts', { page: 1 }));\n *\n * // Typed mutation — pass directly to useMutation:\n * const { mutate: charge } = useMutation(payments.mutation('charge'));\n * charge({ amount: 100 }); // args typed from handler signature\n * ```\n */\nexport function createClientModule<TModule extends AnyModule>(moduleName: string) {\n return {\n getConfig<K extends keyof PublicKeyOf<TModule['configSchema']> & string>(\n key: K\n ): PublicKeyOf<TModule['configSchema']>[K] | undefined {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return _getClientConfig(`${moduleName}.${key}`) as any;\n },\n\n query<K extends keyof TModule['queries'] & string>(\n name: K,\n ...rest: {} extends ExtractArgs<TModule['queries'][K]>\n ? [args?: ExtractArgs<TModule['queries'][K]>]\n : [args: ExtractArgs<TModule['queries'][K]>]\n ) {\n const args = (rest[0] ?? {}) as ExtractArgs<TModule['queries'][K]>;\n return {\n queryKey: [moduleName, name, args] as const,\n queryFn: (): Promise<ExtractResult<TModule['queries'][K]>> =>\n callMethod<ExtractResult<TModule['queries'][K]>>(\n `${moduleName}.${name}`,\n args as MethodArgs\n ),\n };\n },\n\n mutation<K extends keyof TModule['mutations'] & string>(name: K) {\n return {\n mutationFn: (\n args: ExtractArgs<TModule['mutations'][K]>\n ): Promise<ExtractResult<TModule['mutations'][K]>> =>\n callMethod<ExtractResult<TModule['mutations'][K]>>(\n `${moduleName}.${name}`,\n args as MethodArgs\n ),\n };\n },\n\n /**\n * Returns options for `useInfiniteQuery`. The `getArgs` callback receives the\n * current `pageParam` and returns the args to pass to the query handler.\n * Spread the result into `useInfiniteQuery` alongside `getNextPageParam`.\n *\n * Annotate the `pageParam` type in the callback so TypeScript can infer the\n * page param type — no manual generic needed on `useInfiniteQuery`.\n */\n infiniteQuery<K extends keyof TModule['queries'] & string, TPageParam = unknown>(\n name: K,\n getArgs: (pageParam: TPageParam | undefined) => ExtractArgs<TModule['queries'][K]>\n ) {\n return {\n queryKey: [moduleName, name, 'infinite', getArgs(undefined)] as const,\n // Included so TanStack infers TPageParam from the callback type, not from a bare `undefined`.\n initialPageParam: undefined as TPageParam | undefined,\n queryFn: ({\n pageParam,\n }: {\n pageParam: TPageParam | undefined;\n }): Promise<ExtractResult<TModule['queries'][K]>> =>\n callMethod<ExtractResult<TModule['queries'][K]>>(\n `${moduleName}.${name}`,\n getArgs(pageParam) as MethodArgs\n ),\n };\n },\n };\n}\n","import type systemModule from './index';\nimport { createClientModule } from '../client/module';\n\nexport const systemConfig = createClientModule<typeof systemModule>('_system');\n","import { getWebsocketClientProvider } from './client';\n\nexport class ClientChannel<T = unknown> {\n public readonly category: string;\n private readonly onMessage: (data: T) => void;\n\n constructor(category: string, onMessage: (data: T) => void) {\n this.category = category;\n this.onMessage = onMessage;\n }\n\n init() {\n getWebsocketClientProvider()?.on({\n category: this.category,\n listener: this.onMessage,\n });\n }\n\n joinChannel(id: string) {\n getWebsocketClientProvider()?.joinChannel({\n category: this.category,\n id,\n });\n }\n\n leaveChannel(id: string) {\n getWebsocketClientProvider()?.leaveChannel({\n category: this.category,\n id,\n });\n }\n}\n","import { callMethod } from '../client/method';\nimport type { FileVisibility, GetUploadUrlResult } from './types';\n\ntype UploadFileParams = {\n filePath: string;\n contentType: string;\n visibility: FileVisibility;\n};\n\ntype UploadFileResult = {\n filePath: string;\n};\n\nexport async function uploadFile(\n file: File | Blob,\n { filePath, contentType, visibility }: UploadFileParams\n): Promise<UploadFileResult> {\n const {\n url,\n fields,\n filePath: resolvedFilePath,\n } = await callMethod<GetUploadUrlResult>('_system.files.getUploadUrl', {\n filePath,\n contentType,\n visibility,\n });\n\n const formData = new FormData();\n for (const [key, value] of Object.entries(fields)) {\n formData.append(key, value);\n }\n formData.append('file', file);\n\n const uploadResponse = await fetch(url, {\n method: 'POST',\n body: formData,\n });\n\n if (!uploadResponse.ok) {\n throw new Error(`Failed to upload file: HTTP status: ${uploadResponse.status}`);\n }\n\n return { filePath: resolvedFilePath };\n}\n\nexport async function deleteFile(filePath: string): Promise<void> {\n await callMethod('_system.files.deleteFile', { filePath });\n}\n\nexport async function downloadFile(filePath: string): Promise<{ downloadUrl: string }> {\n return callMethod('_system.files.downloadFile', { filePath });\n}\n\nexport async function getFileUrl(filePath: string): Promise<{ url: string }> {\n return callMethod('_system.files.getFileUrl', { filePath });\n}\n","import React from 'react';\n\nimport { AppProvider as OriginalAppProvider } from './client/AppProvider';\n\nexport { configureClient, type ClientConfig } from './client/clientConfig';\nexport { getConfig } from './config/client';\nexport { createClientModule } from './client/module';\nexport type { ValueType } from './config/types';\nexport { systemConfig } from './system/client';\n\nexport const AppProvider =\n 'useClient' in React\n ? // @ts-ignore: React.useClient only exists in Next.js\n React.useClient(OriginalAppProvider)\n : OriginalAppProvider;\n\nexport { renderApp } from './client/renderApp';\nexport { ModelenceQueryProvider } from './client/queryProvider';\nexport {\n modelenceQuery,\n modelenceLiveQuery,\n modelenceMutation,\n createQueryKey,\n connectModelenceQueryClient,\n disconnectModelenceQueryClient,\n ModelenceQueryClient,\n type ModelenceQueryKey,\n} from './client/query';\nexport { callMethod, MethodError, type MethodArgs, type CallMethodOptions } from './client/method';\nexport { useSession } from './client/session';\nexport {\n signupWithPassword,\n loginWithPassword,\n verifyEmail,\n updateProfile,\n resendEmailVerification,\n logout,\n sendResetPasswordToken,\n resetPassword,\n linkOAuthProvider,\n unlinkOAuthProvider,\n type UserInfo,\n} from './auth/client';\nexport {\n getWebsocketClientProvider,\n setWebsocketClientProvider,\n startWebsockets,\n subscribeLiveQuery,\n} from './websocket/client';\nexport { ClientChannel } from './websocket/clientChannel';\nexport { getLocalStorageSession } from './client/localStorage';\nexport { uploadFile, deleteFile, downloadFile, getFileUrl } from './files/client';\n","import React from 'react';\nimport ReactDOM from 'react-dom/client';\nimport { AppProvider } from '../client';\nimport { setErrorHandler, ErrorHandler } from './errorHandler';\nimport { hydrateSession, startSessionHeartbeat, type SessionInitPayload } from './session';\nimport { ModelenceQueryProvider } from './queryProvider';\nimport { hasConnectedQueryClient } from './query';\n\nconst SSR_STATE_SCRIPT_ID = '__MODELENCE_STATE__';\n\ntype SsrState = {\n session?: SessionInitPayload;\n};\n\nfunction hasSsrMarker(): boolean {\n if (typeof document === 'undefined') {\n return false;\n }\n return document.getElementById(SSR_STATE_SCRIPT_ID) !== null;\n}\n\nfunction readSsrState(): SsrState | null {\n if (typeof document === 'undefined') {\n return null;\n }\n\n const node = document.getElementById(SSR_STATE_SCRIPT_ID);\n if (!node) {\n return null;\n }\n\n try {\n return JSON.parse(node.textContent ?? '') as SsrState;\n } catch (e) {\n // Caller must still hydrate (marker presence drives that, not parsed payload).\n console.error('Modelence: failed to parse SSR state', e);\n return null;\n }\n}\n\nexport type SsrRouter = (props: {\n children: React.ReactNode;\n location?: string;\n}) => React.ReactElement;\n\nexport interface RenderAppOptions {\n loadingElement: React.ReactNode;\n routesElement: React.ReactNode;\n favicon?: string;\n errorHandler?: ErrorHandler;\n router?: SsrRouter;\n}\n\n// Shared via globalThis: ssrLoadModule loads the user's entry in a separate\n// module graph from the framework runtime.\nconst SNAPSHOT_KEY = '__modelence_ssr_snapshot__';\n\ntype GlobalWithSnapshot = typeof globalThis & {\n [SNAPSHOT_KEY]?: RenderAppOptions | null;\n};\n\nfunction setSnapshot(snapshot: RenderAppOptions | null) {\n (globalThis as GlobalWithSnapshot)[SNAPSHOT_KEY] = snapshot;\n}\n\n/** @internal Used by the SSR runtime after evaluating the user's entry. */\nexport function _getSsrSnapshot(): RenderAppOptions | null {\n return (globalThis as GlobalWithSnapshot)[SNAPSHOT_KEY] ?? null;\n}\n\nexport function renderApp(options: RenderAppOptions) {\n if (typeof window === 'undefined') {\n setSnapshot(options);\n return;\n }\n\n const { loadingElement, routesElement, favicon, errorHandler, router } = options;\n\n if (errorHandler) {\n setErrorHandler(errorHandler);\n }\n\n // Empty 'unload' handler prevents bfcache in most browsers.\n window.addEventListener('unload', () => {});\n\n // Hydrate session BEFORE building the tree so `isSessionInitialized()` is\n // true on the first render and matches the server output. Hydration mode\n // tracks marker presence (not parse success): a parse failure still leaves\n // server-rendered DOM that must be hydrated, not replaced.\n const isHydrating = hasSsrMarker();\n const ssrState = readSsrState();\n if (ssrState?.session) {\n hydrateSession(ssrState.session);\n // Fire-and-forget: the heartbeat loop runs in the background.\n void startSessionHeartbeat();\n }\n\n const container = document.getElementById('root')!;\n // Pass the same location the server used (req.originalUrl == path + search;\n // the hash is never sent to the server) so a location-driven router (e.g. a\n // static router) resolves the same route on hydration as it did during SSR,\n // avoiding hydration mismatches.\n const location = window.location.pathname + window.location.search;\n const routedTree = router ? router({ children: routesElement, location }) : routesElement;\n\n // If the app already connected its own QueryClient (the documented\n // bring-your-own-provider pattern connects before calling renderApp), don't\n // inject ours. A second provider would shadow the user's client: useQuery\n // would read the inner client while live-query updates write to the outer\n // one, so real-time queries would never update.\n const appTree = hasConnectedQueryClient() ? (\n routedTree\n ) : (\n <ModelenceQueryProvider>{routedTree}</ModelenceQueryProvider>\n );\n\n const tree = (\n <React.StrictMode>\n <AppProvider loadingElement={loadingElement}>{appTree}</AppProvider>\n </React.StrictMode>\n );\n\n if (isHydrating) {\n ReactDOM.hydrateRoot(container, tree);\n } else {\n ReactDOM.createRoot(container).render(tree);\n }\n\n if (favicon) {\n const link = document.querySelector(\"link[rel~='icon']\") as HTMLLinkElement;\n if (!link) {\n const newLink = document.createElement('link');\n newLink.rel = 'icon';\n newLink.href = favicon;\n document.head.appendChild(newLink);\n } else {\n link.href = favicon;\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {s as s$1}from'./chunk-TNXGVFSU.js';import {a,b as b$1,c,m,n,o,p,i,j as j$1,h,u,g,k as k$1,f,l,q,v,w as w$1,x,y,d as d$1,z as z$1,s,r,e as e$1,C,A as A$1,B as B$1}from'./chunk-6CHWWK3O.js';import {b as b$2,d,a as a$4}from'./chunk-MIRF7FP3.js';import {a as a$2,f as f$1,e,g as g$1,c as c$1,h as h$1,k as k$2,j as j$2,d as d$2,i as i$1,l as l$1,m as m$1}from'./chunk-7LPSX5A6.js';import {a as a$3,b as b$3}from'./chunk-5M6FUMUK.js';import {a as a$1}from'./chunk-DO5TZLF5.js';import No from'dotenv';import Jr from'fs/promises';import wr from'os';import B from'path';import {Server}from'socket.io';import {createAdapter}from'@socket.io/mongo-adapter';import {MongoClient,MongoError,ObjectId,MongoServerError}from'mongodb';export{ObjectId as m}from'mongodb';import Xo from'bcrypt';import N,{z}from'zod';import {randomBytes,randomUUID}from'crypto';import {createServer,defineConfig,loadConfigFromFile,mergeConfig}from'vite';import Mr from'@vitejs/plugin-react';import Ee from'fs';import U,{Router}from'express';import Mn from'cookie-parser';import Nn from'http';var oe=new a("_system",{configSchema:{mongodbUri:{type:"secret",isPublic:false,default:""},mongodbPoolSize:{type:"number",isPublic:false,default:10},"env.type":{type:"string",isPublic:true,default:""},"site.url":{type:"string",isPublic:true,default:""},multiInstance:{type:"boolean",isPublic:false,default:false}}});var L=null;async function _t(){if(L)return L;let e=$();if(!e)throw new Error("MongoDB URI is not set");let t=oe.getConfig("mongodbPoolSize");L=new MongoClient(e,{driverInfo:{name:"Modelence",version:s$1.version},ignoreUndefined:true,maxPoolSize:t});try{return await L.connect(),await L.db("admin").command({ping:1}),console.log("Pinged your deployment. You successfully connected to MongoDB!"),L}catch(o){throw console.error(o),L=null,o}}function $(){return oe.getConfig("mongodbUri")||void 0}function fe(){return L}var re=null,Jo="_modelenceSocketio",Pt=60;async function Wo({httpServer:e,channels:t}){let o=fe(),r=!!a$2("_system.multiInstance");console.log("Initializing Socket.IO server...");let n=null;if(r&&o){n=o.db().collection(Jo);try{await n.createIndex({createdAt:1},{expireAfterSeconds:Pt,background:!0});}catch(i){if(i instanceof Error&&"code"in i&&i.code===85)try{await n.dropIndex("createdAt_1"),await n.createIndex({createdAt:1},{expireAfterSeconds:Pt,background:!0});}catch(s){console.error("Failed to recreate index on MongoDB collection for Socket.IO:",s);}else console.error("Failed to create index on MongoDB collection for Socket.IO:",i);}}re=new Server(e,{cors:{origin:"*",methods:["GET","POST"]},adapter:n?createAdapter(n):void 0,transports:["websocket"],perMessageDeflate:false}),re.on("error",i=>{console.error("Socket.IO error:",i);}),re.use(async(i,s$1)=>{let a=i.handshake.auth.token;try{i.data=await s(a);}finally{s$1();}}),re.on("connection",i=>{i.on("disconnect",()=>{C(i);}),i.on("joinChannel",async s=>{let[a]=s.split(":"),c=false;for(let l of t)if(l.category===a){(!l.canAccessChannel||await l.canAccessChannel(i.data))&&(i.join(s),c=true,i.emit("joinedChannel",s));break}c||i.emit("joinError",{channel:s,error:"Access denied"});}),i.on("leaveChannel",s=>{i.leave(s),console.log(`User ${i.id} left channel ${s}`),i.emit("leftChannel",s);}),i.on("subscribeLiveQuery",s=>A$1(i,s)),i.on("unsubscribeLiveQuery",s=>B$1(i,s));}),console.log("Socket.IO server initialized");}function Ko({category:e,id:t,data:o}){re?.to(`${e}:${t}`).emit(e,o);}var Lt={init:Wo,broadcast:Ko};async function Mt(e){let t=e.toLowerCase().trim().split("@");if(t.length!==2)return false;let o=t[1];return !!await n.findOne({domain:o})}var Nt={interval:a$1.days(1),async handler(){let e=await fetch("https://disposable.github.io/disposable-email-domains/domains.txt");if(!e.ok)throw new Error(`HTTP ${e.status}: ${e.statusText}`);let o=(await e.text()).split(`
|
|
2
|
+
`).map(i=>i.trim().toLowerCase()).filter(i=>i.length>0),r=new Date,n$1=500;for(let i=0;i<o.length;i+=n$1){let s=o.slice(i,i+n$1);try{await n.insertMany(s.map(a=>({domain:a,addedAt:r})));}catch(a){a&&typeof a=="object"&&"name"in a&&a.name;}}}};var ge=3,D=50,Ut=8,Tt=128,It=254,$t=e=>z.string().trim().min(e.min??1,{message:`must be at least ${e.min??1} characters`}).max(e.max,{message:`must be at most ${e.max} characters`}),Pe=e=>z.string().trim().max(e.max,{message:`must be at most ${e.max} characters`}).transform(t=>t===""?void 0:t).optional(),Qo=z.object({firstName:Pe({max:50}),lastName:Pe({max:50}),avatarUrl:Pe({max:400}),handle:$t({min:ge,max:D})}).strict();function he(e){let t=Qo.partial().safeParse(e);if(!t.success){let o=t.error.issues[0],r=o.path.join("."),n=r?`${r}: ${o.message}`:o.message;throw new Error(n)}return t.data}function we(e){return z.string().min(Ut,{message:`Password must contain at least ${Ut} characters`}).max(Tt,{message:`Password must be at most ${Tt} characters`}).parse(e)}function M(e){return z.string().max(It,{message:`Email must be at most ${It} characters`}).email({message:"Invalid email address"}).parse(e).toLowerCase()}function Dt(e){return $t({min:ge,max:D}).parse(e)}function ye(e){return {id:e._id,handle:e.handle,roles:e.roles||[],firstName:e.firstName??void 0,lastName:e.lastName??void 0,avatarUrl:e.avatarUrl??void 0}}async function jt(e){let t=e.slice(0,D);try{if(!await m.findOne({handle:t},{collation:{locale:"en",strength:2}}))return t}catch(n){throw new Error(`Database error while checking handle availability: ${n}`)}let o=51;for(let n=2;n<=o;n++){let i=`_${n}`,s=`${t.slice(0,D-i.length)}${i}`;try{if(!await m.findOne({handle:s},{collation:{locale:"en",strength:2}}))return s}catch(a){throw new Error(`Database error while checking handle "${s}": ${a}`)}}let r=10;for(let n=0;n<r;n++){let i=`_${randomBytes(3).toString("hex")}`,s=`${t.slice(0,D-i.length)}${i}`;try{if(!await m.findOne({handle:s},{collation:{locale:"en",strength:2}}))return s}catch(a){throw new Error(`Database error while checking handle "${s}": ${a}`)}}throw new Error(`Could not generate a unique handle for base "${e}" after exhausting all attempts.`)}async function j(e,t,{throwOnConflict:o=true}={}){if(e!=null&&String(e).trim()!==""){let n=Dt(String(e).trim());if(o){if(await m.findOne({handle:n},{collation:{locale:"en",strength:2}}))throw new Error("Handle already taken.");return n}return jt(n)}let r=t.split("@")[0].padEnd(ge,"_").slice(0,D);return jt(r)}var Le=Object.freeze({});function Me(e){Le=Object.freeze(Object.assign({},Le,e));}function b(){return Le}var Ne=Object.freeze({});function Ht(e){Ne=Object.freeze(Object.assign({},Ne,e));}function E(){return Ne}function er(){return b()?.provider?!!a$2("_system.user.auth.email.verification"):false}async function Gt(e,{user:t,session:o,connectionInfo:r,res:n}){try{if(!o)throw new Error("Session is not initialized");let i=r?.ip;i&&await A({bucket:"signin",type:"ip",value:i});let s=M(e.email),a=z.string().parse(e.password),c=await m.findOne({"emails.address":s,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}}),l=c?.authMethods?.password?.hash;if(!l)throw Ft();if(!c.emails?.find(f=>f.address.toLowerCase()===s)?.verified&&er())throw new b$2("Your email address hasn't been verified yet. Please check your inbox for the verification email.","EMAIL_NOT_VERIFIED");if(!await Xo.compare(a,l))throw Ft();return await f(o.authToken,c._id),n&&j$1(n,o.authToken),E().onAfterLogin?.({provider:"email",user:c,session:o,connectionInfo:r}),E().login?.onSuccess?.(c),{user:ye(c),session:{authToken:o.authToken}}}catch(i){throw i instanceof Error&&(E().onLoginError?.({provider:"email",error:i,session:o,connectionInfo:r}),E().login?.onError?.(i)),i}}async function Vt(e,{session:t,res:o}){if(!t)throw new Error("Session is not initialized");await g(t.authToken),o&&k$1(o);}function Ft(){return new Error("Incorrect email/password combination")}async function Bt(e,{user:t}){if(!t)throw new Error("Not authenticated");let o=await m.requireById(t.id);return {handle:o.handle,emails:o.emails,authMethods:Object.keys(o.authMethods||{}),firstName:o.firstName??void 0,lastName:o.lastName??void 0,avatarUrl:o.avatarUrl??void 0}}async function zt(e,{user:t}){if(!t)throw new Error("Not authenticated");let o=await m.requireById(t.id),r=he(e);if(await E().validateProfileUpdate?.(r),"handle"in r&&r.handle!==void 0&&await m.findOne({handle:r.handle,_id:{$ne:o._id}},{collation:{locale:"en",strength:2}}))throw new Error("Handle already taken.");if(Object.keys(r).length>0){let n={},i={};for(let[a,c]of Object.entries(r))c===void 0?i[a]="":n[a]=c;let s={};Object.keys(n).length>0&&(s.$set=n),Object.keys(i).length>0&&(s.$unset=i);try{await m.updateOne({_id:o._id},s);let a=Object.fromEntries(Object.keys(i).map(c=>[c,void 0]));o={...o,...n,...a};}catch(a){throw a instanceof Error&&"code"in a&&a.code===11e3?new Error("Handle already taken."):a}}return {user:ye(o)}}var Ue=["google","github"];async function qt({provider:e},{user:t}){if(!t)throw new Error("You must be signed in to unlink a provider.");if(typeof e!="string"||!Ue.includes(e))throw new Error(`Invalid provider. Supported providers are: ${Ue.join(", ")}.`);let o=await m.requireById(t.id),r=o.authMethods??{};if(!r[e])throw new Error(`${e} is not linked to your account.`);if(Object.values(r).filter(Boolean).length<=1)throw new Error("Cannot unlink your only authentication method. Please add another method first.");let s=Object.keys(r).filter(l=>l!==e&&r[l]),a=s.length>0?{$or:s.map(l=>({[`authMethods.${l}`]:{$exists:true}}))}:{};if((await m.updateOne({_id:o._id,...a},{$unset:{[`authMethods.${e}`]:""}})).matchedCount===0)throw new Error("Cannot unlink your only authentication method. Please add another method first.")}var ie=new b$1("_modelenceRateLimits",{schema:{bucket:c.string(),type:c.enum(["ip","user","email"]),value:c.string(),windowMs:c.number(),windowStart:c.date(),windowCount:c.number(),prevWindowCount:c.number(),expiresAt:c.date()},indexes:[{key:{bucket:1,type:1,value:1,windowMs:1},unique:true},{key:{expiresAt:1},expireAfterSeconds:0}]});var Te=[];function Jt(e){if(Te.length>0)throw new Error("Duplicate call to initRateLimits - already initialized");Te=e;}async function A(e){let{bucket:t,type:o,value:r,message:n}=e,i=Te.filter(a=>a.bucket===t&&a.type===o),s=n?()=>new d(n):void 0;for(let a of i)await tr(a,r,s);}async function tr(e,t,o){let r=()=>o?o():new d(`Rate limit exceeded for ${e.bucket}`),n=await ie.findOne({bucket:e.bucket,type:e.type,value:t,windowMs:e.window}),i=Date.now(),s=Math.floor(i/e.window)*e.window,{count:a,modifier:c}=n?or(n,s,i):{count:0,modifier:{$setOnInsert:{windowStart:new Date(s),windowCount:1,prevWindowCount:0,expiresAt:new Date(s+e.window+e.window)}}};if(a>=e.limit)throw r();await ie.upsertOne({bucket:e.bucket,type:e.type,value:t,windowMs:e.window},c);}function or(e,t,o){let r=t-e.windowMs;if(e.windowStart.getTime()===t){let n=e.windowCount,i=e.prevWindowCount,s=1-(o-t)/e.windowMs;return {count:Math.round(n+i*s),modifier:{$inc:{windowCount:1},$setOnInsert:{windowStart:new Date(t),prevWindowCount:0,expiresAt:new Date(t+e.windowMs+e.windowMs)}}}}if(e.windowStart.getTime()===r){let n=1-(o-t)/e.windowMs;return {count:Math.round(e.windowCount*n),modifier:{$set:{windowStart:new Date(t),windowCount:1,prevWindowCount:e.windowCount,expiresAt:new Date(t+e.windowMs+e.windowMs)}}}}return {count:0,modifier:{$set:{windowStart:new Date(t),windowCount:1,prevWindowCount:0,expiresAt:new Date(t+e.windowMs+e.windowMs)}}}}function Wt({name:e,email:t,verificationUrl:o}){return `
|
|
3
|
+
<p>Hi${e?` ${e}`:""},</p>
|
|
4
|
+
<p>Please verify your email address ${t} by clicking the link below:</p>
|
|
5
|
+
<p><a href="${o}">${o}</a></p>
|
|
6
|
+
<p>If you did not request this, please ignore this email.</p>
|
|
7
|
+
`}async function ir(e){let t=await o.findOne({token:e,expiresAt:{$gt:new Date}});if(!t)throw new Error("Invalid or expired verification token");if(!await m.findOne({_id:t.userId,status:{$nin:["deleted","disabled"]}}))throw new Error("User not found");let r=t.email;if(!r)throw new Error("Email not found in token");let n=await m.findOneAndUpdate({_id:t.userId,status:{$nin:["deleted","disabled"]},"emails.address":r,"emails.verified":{$ne:true}},{$set:{"emails.$.verified":true}},{returnDocument:"after"});if(!n)throw await m.findOne({_id:t.userId,"emails.address":r})?new Error("Email is already verified"):new Error("Email address not found for this user");return await o.deleteOne({_id:t._id}),{userDoc:n,email:r}}async function Kt(e){let t=a$2("_system.site.url"),o=b().verification?.redirectUrl||b().emailVerifiedRedirectUrl||t||"/";try{let r=z.string().parse(e.query.token),{userDoc:n}=await ir(r);E().onAfterEmailVerification?.({provider:"email",user:n,session:null,connectionInfo:{baseUrl:t,ip:e.req.ip||e.req.socket.remoteAddress,userAgent:e.headers["user-agent"],acceptLanguage:e.headers["accept-language"],referrer:e.headers.referer}});let{authToken:s}=await i(n._id);return j$1(e.res,s),{status:301,redirect:`${o}?status=verified`}}catch(r){let n=r instanceof Error?r.message:"An unexpected error occurred";return r instanceof Error&&(E().onEmailVerificationError?.({provider:"email",error:r,session:null,connectionInfo:{baseUrl:t,ip:e.req.ip||e.req.socket.remoteAddress,userAgent:e.headers["user-agent"],acceptLanguage:e.headers["accept-language"],referrer:e.headers.referer}}),console.error("Error verifying email:",r)),{status:301,redirect:`${o}?status=error&message=${encodeURIComponent(n)}`}}}async function $e({userId:e,email:t,baseUrl:o$1}){let r=a$2("_system.site.url")||o$1;if(b().provider){let n=b().provider,i=randomBytes(32).toString("hex"),s=new Date(Date.now()+a$1.hours(24));await o.insertOne({userId:e,email:t,token:i,createdAt:new Date,expiresAt:s});let a=`${r}/api/_internal/auth/verify-email?token=${i}`,l=(b()?.verification?.template||Wt)({name:"",email:t,verificationUrl:a}),d=u(l);await n?.sendEmail({to:t,from:b()?.from||"noreply@modelence.com",subject:b()?.verification?.subject||"Verify your email address",text:d,html:l});}}var Ie={success:true,message:"If that email is registered and not yet verified, a verification email has been sent"};async function Qt(e,{connectionInfo:t}){let o=M(e.email),r=await m.findOne({"emails.address":o,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}});if(!r)return Ie;let n=r.emails?.find(i=>i.address.toLowerCase()===o);if(!n||n.verified)return Ie;if(!b().provider)throw new Error("Email provider is not configured");return await A({bucket:"verification",type:"user",value:r._id.toString(),message:"Please wait at least 60 seconds before requesting another verification email"}),await $e({userId:r._id,email:o,baseUrl:t?.baseUrl}),Ie}async function Yt(e,{user:t,session:o,connectionInfo:r}){let n=E();try{let i=e,{firstName:s,lastName:a,avatarUrl:c,handle:l}=i,d=M(i.email),m$1=we(i.password),f=r?.ip;if(f&&await A({bucket:"signupAttempt",type:"ip",value:f}),!n.allowDisposableEmails&&await Mt(d))throw new Error("Please use a permanent email address");let v=await m.findOne({"emails.address":d},{collation:{locale:"en",strength:2}});if(v){let le=v.emails?.find(Z=>Z.address.toLowerCase()===d);throw v.status==="disabled"?new Error("User is marked for deletion, please contact support if you want to restore the account."):new Error(`User with email already exists: ${le?.address}`)}await n.onBeforeSignup?.({email:d,firstName:s,lastName:a,handle:l,provider:"email",connectionInfo:r}),f&&await A({bucket:"signup",type:"ip",value:f});let y=he({firstName:s,lastName:a,avatarUrl:c,handle:l});await n.validateSignup?.({email:d,password:m$1,...y});let S;if(y.handle)S=await j(y.handle,d);else if(n.generateHandle){let le=await n.generateHandle({email:d,firstName:y.firstName,lastName:y.lastName});S=await j(le,d,{throwOnConflict:!1});}else S=await j(void 0,d);let Y=await Xo.hash(m$1,10),X=await m.insertOne({handle:S,status:"active",emails:[{address:d,verified:!1}],createdAt:new Date,authMethods:{password:{hash:Y}},...y.firstName!==void 0&&{firstName:y.firstName},...y.lastName!==void 0&&{lastName:y.lastName},...y.avatarUrl!==void 0&&{avatarUrl:y.avatarUrl}}),T=await m.findOne({_id:X.insertedId},{readPreference:"primary"});if(!T)throw new Error("User not found");return await $e({userId:X?.insertedId,email:d,baseUrl:r?.baseUrl}),n.onAfterSignup?.({provider:"email",user:T,session:o,connectionInfo:r}),n.signup?.onSuccess?.(T),X.insertedId}catch(i){throw i instanceof Error&&(n.onSignupError?.({provider:"email",error:i,session:o,connectionInfo:r}),n.signup?.onError?.(i)),i}}function dr(e,t){return t?t.startsWith("http://")||t.startsWith("https://")?t:`${e}${t.startsWith("/")?"":"/"}${t}`:e}function ur({email:e,resetUrl:t}){return `
|
|
8
|
+
<p>Hi,</p>
|
|
9
|
+
<p>We received a request to reset your password for ${e}.</p>
|
|
10
|
+
<p>Click the link below to reset your password:</p>
|
|
11
|
+
<p><a href="${t}">${t}</a></p>
|
|
12
|
+
<p>This link will expire in 1 hour.</p>
|
|
13
|
+
<p>If you did not request this password reset, please ignore this email.</p>
|
|
14
|
+
`}var De={success:true,message:"If an account with that email exists, a password reset link has been sent"};async function Xt(e,{connectionInfo:t}){let o=M(e.email),r=t?.ip;r&&await A({bucket:"passwordReset",type:"ip",value:r}),await A({bucket:"passwordReset",type:"email",value:o});let n=await m.findOne({"emails.address":o,status:{$nin:["deleted","disabled"]}},{collation:{locale:"en",strength:2}});if(!n||!n.authMethods?.password)return De;let i=b().provider;if(!i)throw new Error("Email provider is not configured");let s=randomBytes(32).toString("hex"),a=Date.now(),c=new Date(a),l=new Date(a+a$1.hours(1));await p.insertOne({userId:n._id,email:o,token:s,createdAt:c,expiresAt:l});let d=a$2("_system.site.url")||t?.baseUrl,f=`${dr(d,b().passwordReset?.redirectUrl)}?token=${s}`,y=(b()?.passwordReset?.template||ur)({email:o,resetUrl:f,name:""}),S=u(y);return await i.sendEmail({to:o,from:b()?.from||"noreply@modelence.com",subject:b()?.passwordReset?.subject||"Reset your password",text:S,html:y}),De}async function Zt(e,{}){let t=z.string().parse(e.token),o=we(e.password),r=await p.findOne({token:t});if(!r)throw new Error("Invalid or expired reset token");if(r.expiresAt<new Date)throw await p.deleteOne({token:t}),new Error("Reset token has expired");let n=await m.findOne({_id:r.userId});if(!n)throw new Error("User not found");let i=await Xo.hash(o,10);return await m.updateOne({_id:n._id},{$set:{"authMethods.password.hash":i}}),r.email&&await m.updateOne({_id:n._id,"emails.address":r.email},{$set:{"emails.$.verified":true}}),await h(n._id),await p.deleteOne({token:t}),{success:true,message:"Password has been reset successfully"}}function eo(e){return `${e.bucket}
|
|
15
|
+
${e.type}
|
|
16
|
+
${e.window}`}function mr(){return [{bucket:"signup",type:"ip",window:a$1.minutes(15),limit:20},{bucket:"signup",type:"ip",window:a$1.days(1),limit:200},{bucket:"signupAttempt",type:"ip",window:a$1.minutes(15),limit:50},{bucket:"signupAttempt",type:"ip",window:a$1.days(1),limit:500},{bucket:"signin",type:"ip",window:a$1.minutes(15),limit:50},{bucket:"signin",type:"ip",window:a$1.days(1),limit:500},{bucket:"verification",type:"user",window:a$1.seconds(60),limit:1},{bucket:"verification",type:"user",window:a$1.days(1),limit:10},{bucket:"passwordReset",type:"ip",window:a$1.minutes(15),limit:10},{bucket:"passwordReset",type:"ip",window:a$1.days(1),limit:100},{bucket:"passwordReset",type:"email",window:a$1.hours(1),limit:5},{bucket:"passwordReset",type:"email",window:a$1.days(1),limit:10}]}function pr(e){let t=[],o=["signup","signupAttempt","signin","verification","passwordReset"];for(let r of o){let n=e[r];if(n!==void 0)for(let i of n)t.push({bucket:r,...i});}return t}function je(e={}){let t=mr(),o=pr(e),r=new Map;for(let s of o)r.set(eo(s),s);let n=[],i=new Set;for(let s of t){let a=eo(s),c=r.get(a);c!==void 0?(n.push(c),i.add(a)):n.push(s);}for(let[s,a]of r)i.has(s)||n.push(a);return n}var He=new a("_system.user",{stores:[m,n,o,p],queries:{getOwnProfile:Bt},mutations:{signupWithPassword:Yt,loginWithPassword:Gt,logout:Vt,resendEmailVerification:Qt,sendResetPasswordToken:Xt,resetPassword:Zt,updateProfile:zt,unlinkOAuthProvider:qt},cronJobs:{updateDisposableEmailList:Nt},rateLimits:je(),configSchema:{"auth.email.enabled":{type:"boolean",isPublic:true,default:true},"auth.email.from":{type:"string",isPublic:false,default:""},"auth.email.verification":{type:"boolean",isPublic:true,default:true},"auth.google.enabled":{type:"boolean",isPublic:true,default:false},"auth.google.clientId":{type:"string",isPublic:false,default:""},"auth.google.clientSecret":{type:"secret",isPublic:false,default:""},"auth.github.enabled":{type:"boolean",isPublic:true,default:false},"auth.github.clientId":{type:"string",isPublic:false,default:""},"auth.github.clientSecret":{type:"secret",isPublic:false,default:""}},routes:[{path:"/api/_internal/auth/verify-email",handlers:{get:Kt}}]});var fr={withoutRemoteServer:{MONGODB_URI:"_system.mongodbUri",MONGODB_POOL_SIZE:"_system.mongodbPoolSize",MODELENCE_AUTH_GOOGLE_ENABLED:"_system.user.auth.google.enabled",MODELENCE_AUTH_GOOGLE_CLIENT_ID:"_system.user.auth.google.clientId",MODELENCE_AUTH_GOOGLE_CLIENT_SECRET:"_system.user.auth.google.clientSecret",MODELENCE_AUTH_GITHUB_ENABLED:"_system.user.auth.github.enabled",MODELENCE_AUTH_GITHUB_CLIENT_ID:"_system.user.auth.github.clientId",MODELENCE_AUTH_GITHUB_CLIENT_SECRET:"_system.user.auth.github.clientSecret",MODELENCE_AUTH_GITHUB_CLIENT_SCOPES:"_system.user.auth.github.scopes",MODELENCE_EMAIL_RESEND_API_KEY:"_system.email.resend.apiKey",MODELENCE_EMAIL_AWS_SES_REGION:"_system.email.awsSes.region",MODELENCE_EMAIL_AWS_SES_ACCESS_KEY_ID:"_system.email.awsSes.accessKeyId",MODELENCE_EMAIL_AWS_SES_SECRET_ACCESS_KEY:"_system.email.awsSes.secretAccessKey",MODELENCE_EMAIL_SMTP_HOST:"_system.email.smtp.host",MODELENCE_EMAIL_SMTP_PORT:"_system.email.smtp.port",MODELENCE_EMAIL_SMTP_USER:"_system.email.smtp.user",MODELENCE_EMAIL_SMTP_PASS:"_system.email.smtp.pass",MODELENCE_SITE_URL:"_system.site.url",MODELENCE_ENV_TYPE:"_system.env.type",MODELENCE_MULTI_INSTANCE:"_system.multiInstance",MODELENCE_ENV:"_system.env",GOOGLE_AUTH_ENABLED:"_system.user.auth.google.enabled",GOOGLE_AUTH_CLIENT_ID:"_system.user.auth.google.clientId",GOOGLE_AUTH_CLIENT_SECRET:"_system.user.auth.google.clientSecret"},withRemoteServer:{MODELENCE_SITE_URL:"_system.site.url"}};function gr(e,t){if(t==="number"){let o=Number(e);if(isNaN(o))throw new Error(`Invalid number value for config: ${e}`);return o}if(t==="boolean"){if(e.toLowerCase()==="true")return true;if(e.toLowerCase()==="false")return false;throw new Error(`Invalid boolean value for config: ${e}`)}return e}function hr(e,t){let o=[];for(let[r,n]of Object.entries(e)){let i=process.env[r],s=t[n];if(i){let a=s?.type??"string";o.push({key:n,type:a,value:gr(i,a)});}}return o}function be(e,t="withoutRemoteServer"){let o=fr[t];return hr(o,e)}async function to({configSchema:e,cronJobsMetadata:t,stores:o,roles:r}){let n=process.env.MODELENCE_CONTAINER_ID;if(!n)throw new Error("Unable to connect to Modelence Cloud: MODELENCE_CONTAINER_ID is not set");try{let i=(o??[]).map(a=>({name:a.getName(),schema:a.getSerializedSchema(),collections:[a.getName()],version:2,indexes:a.getIndexes(),searchIndexes:a.getSearchIndexes(),indexCreationMode:a.getIndexCreationMode()})),s=await R("/api/connect","POST",{hostname:wr.hostname(),containerId:n,dataModels:i,configSchema:e,cronJobsMetadata:t,roles:r});if(s.status==="error")throw new Error(s.error);return console.log("Successfully connected to Modelence Cloud"),s}catch(i){throw console.error("Unable to connect to Modelence Cloud:",i),i}}async function oo(){return R("/api/configs","GET")}async function ro(){return await R("/api/sync","POST",{containerId:process.env.MODELENCE_CONTAINER_ID})}async function R(e,t,o){let{MODELENCE_SERVICE_ENDPOINT:r,MODELENCE_SERVICE_TOKEN:n}=process.env;if(!r)throw new Error("Unable to connect to Modelence Cloud: MODELENCE_SERVICE_ENDPOINT is not set");let i=await fetch(`${r}${e}`,{method:t,headers:{Authorization:`Bearer ${n}`,...o?{"Content-Type":"application/json"}:{}},body:o?JSON.stringify(o):void 0});if(!i.ok){let s=await i.text(),a,c=s;try{a=JSON.parse(s);let d=a.error;if(typeof d=="string")c=d;else if(d&&typeof d=="object"){let m=d.message;typeof m=="string"&&(c=m);}}catch{}let l=new Error(`Unable to connect to Modelence Cloud: HTTP status: ${i.status}, ${c}`);throw a!==void 0&&(l.responseBody=a),l.status=i.status,l}if(!(i.status===204||i.headers?.get("content-length")==="0"))return await i.json()}var Fe=false,yr=a$1.seconds(10);function no(){setInterval(async()=>{if(!Fe){Fe=true;try{await ro();}catch(e){console.error("Error syncing status",e);}try{await br();}catch(e){console.error("Error syncing config",e);}Fe=false;}},yr);}function Ge(e){c$1(e),c$1(be(d$2(),"withRemoteServer"));}async function br(){let{configs:e}=await oo();Ge(e);}var H=new b$1("_modelenceLocks",{schema:{_id:c.string(),instanceId:c.string(),acquiredAt:c.date(),resource:c.string()},indexes:[{key:{resource:1},unique:true},{key:{resource:1,instanceId:1}},{key:{resource:1,acquiredAt:1}}],indexCreationMode:"blocking"});var F={},io=a$1.seconds(10),lo=randomBytes(32).toString("base64url"),Cr=a$1.seconds(30),J=new Map,Ve=e=>e instanceof MongoError&&e.code===11e3,so=(e,t)=>typeof e.keyPattern=="object"&&e.keyPattern!==null&&Object.prototype.hasOwnProperty.call(e.keyPattern,t),Sr=async({error:e,resource:t})=>{if(so(e,"resource"))return true;if(so(e,"_id"))return false;let o=await H.findOne({resource:t});return !!o&&o._id!==t},ao=async({resource:e,staleThresholdDate:t,instanceId:o})=>{let r=await H.upsertOne({_id:e,$or:[{instanceId:o},{acquiredAt:{$lt:t}}]},{$set:{resource:e,instanceId:o,acquiredAt:new Date},$setOnInsert:{_id:e}});return r.upsertedCount>0||r.modifiedCount>0},uo=async({resource:e,instanceId:t,staleThresholdDate:o})=>{let r=o?{resource:e,_id:{$ne:e},$or:[{instanceId:t},{acquiredAt:{$lt:o}}]}:{resource:e,instanceId:t};return (await H.deleteOne(r)).deletedCount>0},kr=e=>{let t=e,o=J.get(t);o&&(o.stopRequested=true,o.timer&&(clearTimeout(o.timer),o.timer=null),J.delete(t));},co=({resource:e,lockDuration:t,instanceId:o})=>{let r=Math.floor(t/3),n=e,i=J.get(n);if(i&&!i.stopRequested&&i.heartbeatInterval===r&&i.lockDuration===t)return;i&&(i.stopRequested=true,i.timer&&(clearTimeout(i.timer),i.timer=null),J.delete(n));let s={timer:null,stopRequested:false,lockDuration:t,heartbeatInterval:r},a=()=>{s.timer=setTimeout(()=>{G(e,{lockDuration:t,bypassCache:true,instanceId:o}).then(c=>{c||(s.stopRequested=true,i$1(`Lost lock while refreshing heartbeat: ${e}`,{source:"lock",resource:e,instanceId:o}));}).finally(()=>{if(s.stopRequested){J.delete(n);return}a();});},r);};J.set(n,s),a();};async function G(e,{lockDuration:t=Cr,successfulLockCacheDuration:o=io,failedLockCacheDuration:r=io,heartbeat:n,bypassCache:i,instanceId:s=lo}={}){let a=Date.now();if(!i&&F[e]&&a<F[e].expiresAt)return F[e].value&&n&&co({resource:e,lockDuration:t,instanceId:s}),F[e].value;let c=new Date(a-t);i$1(`Attempting to acquire lock: ${e}`,{source:"lock",resource:e,instanceId:s});try{let l=await Ar({resource:e,staleThresholdDate:c,instanceId:s});return F[e]={value:l,expiresAt:a+(l?o:r)},l?(n&&co({resource:e,lockDuration:t,instanceId:s}),i$1(`Lock acquired: ${e}`,{source:"lock",resource:e,instanceId:s})):i$1(`Failed to acquire lock (already held): ${e}`,{source:"lock",resource:e,instanceId:s}),l}catch{return F[e]={value:false,expiresAt:a+r},i$1(`Failed to acquire lock (already held): ${e}`,{source:"lock",resource:e,instanceId:s}),false}}var Ar=async({resource:e,staleThresholdDate:t,instanceId:o})=>{try{return await ao({resource:e,staleThresholdDate:t,instanceId:o})}catch(r){if(Ve(r)&&await Sr({error:r,resource:e})){if(!await uo({resource:e,staleThresholdDate:t,instanceId:o}))return false;try{return await ao({resource:e,staleThresholdDate:t,instanceId:o})}catch(i){if(Ve(i))return false;throw i}}if(Ve(r))return false;throw r}};async function se(e,{instanceId:t=lo}={}){kr(e);try{let o=await H.deleteOne({_id:e,instanceId:t});return o.deletedCount===0?await uo({resource:e,instanceId:t}):o.deletedCount>0}catch{return false}finally{delete F[e];}}var V={},Be=null,ze=new b$1("_modelenceCronJobs",{schema:{alias:c.string(),lastStartDate:c.date().optional()},indexes:[{key:{alias:1},unique:true,background:true}]});function po(e,{description:t="",interval:o,timeout:r=Math.min(Math.max(o,a$1.minutes(1)),a$1.days(1)),handler:n}){if(V[e])throw new Error(`Duplicate cron job declaration: '${e}' already exists`);if(Be)throw new Error(`Unable to add a cron job - cron jobs have already been initialized: [${e}]`);if(o<a$1.seconds(5))throw new Error(`Cron job interval should not be less than 5 second [${e}]`);if(r>a$1.days(1))throw new Error(`Cron job timeout should not be longer than 1 day [${e}]`);V[e]={alias:e,params:{description:t,interval:o,timeout:r},handler:n,state:{isRunning:false}};}async function fo(){if(Be)throw new Error("Cron jobs already started");let e=Object.keys(V);if(e.length>0){let t={alias:{$in:e}},o=await ze.fetch(t),r=Date.now();o.forEach(n=>{let i=V[n.alias];i&&(i.state.scheduledRunTs=n.lastStartDate?n.lastStartDate.getTime()+i.params.interval:r);}),Object.values(V).forEach(n=>{n.state.scheduledRunTs||(n.state.scheduledRunTs=r);}),Be=setInterval(Rr,a$1.seconds(1));}}async function Rr(){let e=Date.now();await G("cron",{successfulLockCacheDuration:a$1.seconds(10),failedLockCacheDuration:a$1.seconds(30)})&&Object.values(V).forEach(async o=>{let{params:r,state:n}=o;if(n.isRunning){n.startTs&&n.startTs+r.timeout<e&&(n.isRunning=false);return}n.scheduledRunTs&&n.scheduledRunTs<=e&&await xr(o);});}async function xr(e){let{alias:t,params:o,handler:r,state:n}=e;n.isRunning=true,n.startTs=Date.now(),await ze.updateOne({alias:t},{$set:{lastStartDate:new Date(n.startTs)}});let i=l$1("cron",`cron:${t}`);try{await r(),mo(n,o),i.end("success");}catch(s){mo(n,o);let a=s instanceof Error?s:new Error(String(s));m$1(a),i.end("error"),console.error(`Error in cron job '${t}':`,s);}}function mo(e,t){e.scheduledRunTs=e.startTs?e.startTs+t.interval:Date.now(),e.startTs=void 0,e.isRunning=false;}function go(){return Object.values(V).map(({alias:e,params:t})=>({alias:e,description:t.description,interval:t.interval,timeout:t.timeout}))}var ho=new a("_system.cron",{stores:[ze]});function wo(e){let t=[...new Set(e)],o=new Map;for(let i of t){let s=i.getChainRoot();o.set(s,s.getChainTail());}let r=[...new Set(o.values())],n=new Map;for(let[i,s]of o){let a=s.getName(),c=n.get(a);if(c!==void 0&&c!==i)throw new Error(`Store collision: multiple unrelated stores use collection name '${a}'. Use .extend() to create a single extension chain instead of independent stores.`);n.set(a,i);}return {storesToInit:t,effectiveStores:r}}var qe=new a("_system.lock",{stores:[H]});var ae=new b$1("_modelenceMigrations",{schema:{version:c.number(),status:c.enum(["completed","failed"]),description:c.string().optional(),output:c.string().optional(),appliedAt:c.date()},indexes:[{key:{version:1},unique:true},{key:{version:1,status:1}}]});async function Je(e,{lockMode:t="acquire"}={}){if(e.length!==0){if(t==="acquire"&&!await G("migrations")){j$2("Another instance is running migrations. Skipping migration run.",{source:"migrations"});return}try{let o=e.map(({version:s})=>s),r=await ae.fetch({version:{$in:o}}),n=new Set(r.map(({version:s})=>s)),i=e.filter(({version:s})=>!n.has(s));if(i.length===0)return;j$2(`Running migrations (${i.length})...`,{source:"migrations"});for(let{version:s,description:a,handler:c}of i){j$2(`Running migration v${s}: ${a}`,{source:"migrations"});try{let d=(await c()||"").toString().trim(),m=15*1024*1024,f=d.length>m?d.slice(0,m)+`
|
|
17
|
+
[Output truncated - exceeded size limit]`:d;await ae.upsertOne({version:s},{$set:{version:s,status:"completed",description:a,output:f,appliedAt:new Date}}),j$2(`Migration v${s} complete`,{source:"migrations"});}catch(l){l instanceof Error&&(await ae.upsertOne({version:s},{$set:{version:s,status:"failed",description:a,output:l.message||"",appliedAt:new Date}}),j$2(`Migration v${s} is failed: ${l.message}`,{source:"migrations"}));}}}finally{t==="acquire"&&await se("migrations");}}}function yo(e){setTimeout(()=>{Je(e).catch(t=>{console.error("Error running migrations:",t);});},0);}var bo=new a("_system.migration",{stores:[ae]});var Eo=new a("_system.rateLimit",{stores:[ie]});async function vo({filePath:e,contentType:t,visibility:o}){return await R("/api/files/upload","POST",{filePath:e,contentType:t,visibility:o})}async function Co(e){await R("/api/files/delete","POST",{filePath:e});}async function So(e){return await R("/api/files/download","POST",{filePath:e})}async function ko(e){return await R("/api/files/url","POST",{filePath:e})}var Ao=new a("_system.files",{queries:{async downloadFile({filePath:e}){return So(e)},async getFileUrl({filePath:e}){return ko(e)}},mutations:{async getUploadUrl({filePath:e,contentType:t,visibility:o}){return vo({filePath:e,contentType:t,visibility:o})},async deleteFile({filePath:e}){return Co(e)}}});function We(e){return e.replace(/[<>&\u2028\u2029]/g,t=>`\\u${t.charCodeAt(0).toString(16).padStart(4,"0")}`)}var ce="./.modelence/build/client".replace(/\\/g,"/"),xo="./.modelence/build/ssr".replace(/\\/g,"/"),Oo="/index.tsx",Nr=/(<div\b[^>]*\bid\s*=\s*["']root["'][^>]*>)\s*<\/div>/i,Ur="</head>",Ke=class{constructor(){this.ssrEnabled=false;this.ssrTransportInstalled=false;this.prodEntryLoaded=false;}enableSsr(){this.ssrEnabled=true;}async init({httpServer:t}){if(this.config=await Fr(this.isDev()?t:void 0,{ssr:this.ssrEnabled}),this.isDev())console.log("Starting Vite dev server..."),this.viteServer=await createServer(this.config);else if(this.ssrEnabled){let o=B.resolve(process.cwd(),xo,"index.mjs");if(!Ee.existsSync(o))throw new Error(`Modelence: SSR is enabled (startApp({ ssr: true })) but the SSR bundle is missing at ${o}.
|
|
18
|
+
|
|
19
|
+
This usually means \`postBuildCommand\` is set in modelence.config.ts, which replaces the default Vite client build (and the SSR build along with it). Either:
|
|
20
|
+
\u2022 remove \`postBuildCommand\` so Modelence builds the SSR bundle, or
|
|
21
|
+
\u2022 remove \`ssr: true\` from startApp() if your custom toolchain handles SSR itself.`)}if(this.ssrEnabled&&!this.ssrTransportInstalled){let{installSsrCallMethodTransport:o}=await import('./transport-4MGQHPZB.js');o(),this.ssrTransportInstalled=true;}}middlewares(){if(this.isDev())return this.viteServer?.middlewares??[];let t=this.ssrEnabled?{index:false}:void 0,o=[U.static(ce,t)];return this.config?.publicDir&&o.push(U.static(this.config.publicDir,t)),o}async handler(t,o){if(this.ssrEnabled&&Tr(t)){if(t.method==="HEAD"){o.setHeader("Content-Type","text/html; charset=utf-8"),o.setHeader("Cache-Control","no-store"),o.status(200).end();return}try{await this.handleSsr(t,o);}catch(r){if(this.isDev()&&this.viteServer&&r instanceof Error&&this.viteServer.ssrFixStacktrace(r),console.error("SSR render error:",{url:t.originalUrl,method:t.method,userAgent:t.get("user-agent"),error:r}),o.headersSent){o.end();return}this.serveStaticShell(o);}return}if(this.ssrEnabled){o.status(404).end();return}this.serveStaticShell(o);}async handleSsr(t,o){let r=await this.getTemplate(t.originalUrl),n=await this.captureSsrSnapshot();if(!n)throw new Error("Modelence SSR is enabled but no SSR snapshot was captured. Make sure 'src/client/index.tsx' calls renderApp(...) from 'modelence/client'.");let[{renderSsrTreeStream:i},{getCallContext:s},a]=await Promise.all([import('./render-CHI3Y7PZ.js'),import('./server-NZQGNLQF.js'),import('./collectCss-4YETFI7P.js')]),c=await s(t,o),l=this.collectCssAssets(a);Dr(o,a.buildEarlyHintsLink(l));let{sessionState:d,pipe:m,getQueryState:f}=await i({callContext:c,loadingElement:n.loadingElement,routesElement:n.routesElement,router:n.router,location:t.originalUrl}),{prelude:v,rootOpenTag:y,epilogue:S}=Ir(r),Y=$r(v,a.renderStylesheetLinks(l));o.setHeader("Content-Type","text/html; charset=utf-8"),o.setHeader("Cache-Control","no-store"),o.status(200),o.write(Y),o.write(`<script id="__MODELENCE_STATE__" type="application/json">${We(d)}</script>`),o.write(y),await m(o),o.write("</div>"),o.write(`<script id="__MODELENCE_QUERY_STATE__" type="application/json">${We(f())}</script>`),o.end(S);}collectCssAssets(t){return this.isDev()?this.viteServer?t.collectDevCssAssets(this.viteServer,Oo):{hrefs:[],source:"dev"}:(this.prodCssAssetsCache||(this.prodCssAssetsCache=t.loadProdCssAssets(ce)),this.prodCssAssetsCache)}async getTemplate(t){if(this.isDev()){let o=B.resolve(process.cwd(),"src/client/index.html"),r=Ee.readFileSync(o,"utf-8");return this.viteServer&&(r=await this.viteServer.transformIndexHtml(t,r)),r}if(!this.prodTemplateCache){let o=B.resolve(process.cwd(),ce,"index.html");this.prodTemplateCache=Ee.readFileSync(o,"utf-8");}return this.prodTemplateCache}async captureSsrSnapshot(){let{_getSsrSnapshot:t}=await import('./renderApp-ZDNATNY6.js');if(this.isDev()){if(!this.viteServer)throw new Error("Vite dev server not initialized");return await this.viteServer.ssrLoadModule(Oo),t()}return this.prodEntryLoaded||(await import(B.resolve(process.cwd(),xo,"index.mjs")),this.prodEntryLoaded=true),t()}serveStaticShell(t){if(this.isDev())try{t.setHeader("Cache-Control","no-store"),t.sendFile("index.html",{root:"./src/client"});}catch(o){console.error("Error serving index.html:",o),t.status(500).send("Internal Server Error");}else t.sendFile("index.html",{root:ce});}isDev(){return process.env.NODE_ENV!=="production"}};function Tr(e){if(e.method!=="GET"&&e.method!=="HEAD")return false;let t=e.get("accept")??"";if(t&&!t.includes("text/html")&&!t.includes("*/*"))return false;let o=(e.path??e.url??"").split("?")[0];if(o.startsWith("/api/"))return false;let r=o.split("/").pop()??"",n=r.lastIndexOf(".");if(n>0){let i=r.slice(n).toLowerCase();if(i!==".html"&&i!==".htm")return false}return true}function Ir(e){let t=e.match(Nr);if(!t||t.index===void 0)throw new Error('SSR template is missing the expected `<div id="root"></div>` placeholder.');let o=e.slice(0,t.index),r=e.slice(t.index+t[0].length);return {prelude:o,rootOpenTag:t[1],epilogue:r}}function $r(e,t){if(!t)return e;let o=e.lastIndexOf(Ur);return o===-1?t+e:e.slice(0,o)+t+e.slice(o)}function Dr(e,t){if(t.length===0)return;let o=e;if(typeof o.writeEarlyHints=="function")try{o.writeEarlyHints({link:t});}catch(r){process.env.NODE_ENV!=="production"&&console.warn("Modelence SSR: writeEarlyHints failed",r);}}async function jr(){let e=process.cwd();try{return (await loadConfigFromFile({command:"serve",mode:"development"},void 0,e))?.config||{}}catch(t){return console.warn("Could not load vite config:",t),{}}}function Hr(e,t){let o=mergeConfig(e,t);if(o.plugins&&Array.isArray(o.plugins)){let r=new Set;o.plugins=o.plugins.flat().filter(n=>{if(!n||typeof n!="object"||Array.isArray(n))return true;let i=n.name;return !i||r.has(i)?false:(r.add(i),true)}).reverse(),o.plugins.reverse();}return o}async function Fr(e,t={}){let o=process.cwd(),r=await jr(),n=[".eslintrc.js",".eslintrc.json",".eslintrc","eslint.config.js",".eslintrc.yml",".eslintrc.yaml"].find(a=>Ee.existsSync(B.join(o,a))),i=[Mr(),Gr()];if(n){let a=(await import('vite-plugin-eslint')).default;i.push(a({failOnError:false,include:["src/**/*.js","src/**/*.jsx","src/**/*.ts","src/**/*.tsx"],cwd:o,overrideConfigFile:B.resolve(o,n)}));}let s=defineConfig({plugins:i,build:{outDir:ce,emptyOutDir:true},server:{middlewareMode:true,hmr:e?{server:e}:void 0},appType:t.ssr?"custom":"spa",root:"./src/client",resolve:{alias:{"@":B.resolve(o,"src").replace(/\\/g,"/")}}});return Hr(s,r)}function Gr(){return {name:"modelence-asset-handler",async transform(e,t){if(/\.(png|jpe?g|gif|svg|mpwebm|ogg|mp3|wav|flac|aac)$/.test(t))return process.env.NODE_ENV==="development",e}}}var ve=new Ke;function Vr(e){return e?e.match(/^\s*"?([^"<]+?)"?\s*<[^>]+>\s*$/)?.[1]?.trim():void 0}function Br(e){if(e)return Array.isArray(e)?e:[e]}function zr(e){return {to:Array.isArray(e.to)?e.to:[e.to],subject:e.subject,html:e.html,text:e.text,fromName:Vr(e.from),replyTo:Br(e.replyTo)}}function qr(e){if(!(e instanceof Error))return new Error("Managed email send failed");let t=e.responseBody,o=t?.error?.code,r=t?.error?.message;return o&&r?new Error(`Managed email rejected (${o}): ${r}`):e}var _o={async sendEmail(e){if(e.cc||e.bcc||e.attachments||e.headers)throw new Error("Modelence managed email does not support cc, bcc, attachments, or custom headers in v1. Configure your own provider (Resend, SES, SMTP) to use these features. See https://docs.modelence.com/email/managed.");try{await R("/api/email/send","POST",zr(e));}catch(t){throw qr(t)}}};var Qe=Object.freeze({});function Po(e){Qe=Object.freeze(Object.assign({},Qe,e));}function Lo(){return Qe}var Ye=Object.freeze({});function Mo(e){Ye=Object.freeze(Object.assign({},Ye,e));}function Ce(){return Ye}async function Qr({modules:e$1=[],roles:t={},defaultRoles:o={},server:r=ve,migrations:n=[],email:i={},auth:s={},security:a={},websocket:c={},ssr:l$1=false}){l$1&&r===ve&&ve.enableSsr(),No.config(),No.config({path:".modelence.env"});let d=!!process.env.MODELENCE_SERVICE_ENDPOINT;cn().then(()=>{}).catch(()=>{});let m=[He,l,ho,bo,Eo,oe,qe,Ao],f=[...m,...e$1];f$1(),Xr(m),Yr(e$1),q(t,o);let v=nn(f);e(v);let y=Zr(f),S=en(f);sn(f),He.rateLimits=je(s.rateLimits);let Y=tn(f);Jt(Y);let{storesToInit:X,effectiveStores:T}=wo(y);if(d){let{configs:Z,environmentId:Ho,appAlias:Fo,environmentAlias:Go,telemetry:Vo}=await to({configSchema:v,cronJobsMetadata:go(),stores:T,roles:t});Ge(Z),g$1({environmentId:Ho,appAlias:Fo,environmentAlias:Go,telemetry:Vo});}else c$1(be(v));if(d&&!i.provider?Me({...i,provider:_o}):Me(i),Ht(s),Po(a),Mo({...c,provider:c.provider||Lt}),$()){await _t();let Z=[...new Set([...X,...T])];an(Z),await rn(T,n);}else yo(n);d&&(await h$1(),no()),fo().catch(console.error),await Uo(r,{combinedModules:f,channels:S});}function Yr(e){for(let t of e){for(let[o,r]of Object.entries(t.queries))v(`${t.name}.${o}`,r);for(let[o,r]of Object.entries(t.mutations))w$1(`${t.name}.${o}`,r);}}function Xr(e){for(let t of e){for(let[o,r]of Object.entries(t.queries))x(`${t.name}.${o}`,r);for(let[o,r]of Object.entries(t.mutations))y(`${t.name}.${o}`,r);}}function Zr(e){return e.flatMap(t=>t.stores)}function en(e){return e.flatMap(t=>t.channels)}function tn(e){return e.flatMap(t=>t.rateLimits)}function on(e,t){console.warn(`Failed to create indexes for store '${e}'. Continuing startup.`,t);}var Xe="migrations";async function rn(e,t){if(!await G(Xe,{lockDuration:a$1.seconds(30),heartbeat:true}))return;let r,n;try{r=e.filter(a=>a.getIndexCreationMode()==="blocking"),n=e.filter(a=>a.getIndexCreationMode()==="background");for(let a of r)await Ze(a,"full");for(let a of n)await Ze(a,"drop-only");}catch(a){throw await se(Xe),a}let i=(async()=>{for(let a of n)await Ze(a,"create-only");})(),s=Je(t,{lockMode:"skip"});Promise.allSettled([i,s]).then(([a,c])=>{a.status==="rejected"&&console.error("Error creating background indexes:",a.reason),c.status==="rejected"&&console.error("Error running migrations:",c.reason);}).finally(async()=>{await se(Xe);});}async function Ze(e,t="full"){let o=e.getName();try{await e.createIndexes(t);}catch(r){on(o,r);}}function nn(e){let t={};for(let o of e)for(let[r,n]of Object.entries(o.configSchema)){let i=`${o.name}.${r}`;if(i in t)throw new Error(`Duplicate config schema key: ${i} (${o.name})`);t[i]=n;}return t}function sn(e){for(let t of e)for(let[o,r]of Object.entries(t.cronJobs))po(`${t.name}.${o}`,r);}function an(e){let t=fe();if(!t)throw new Error("Failed to initialize stores: MongoDB client not initialized");for(let o of e)o.init(t);}async function cn(){if(process.env.MODELENCE_TRACKING_ENABLED!=="false"){let t=process.env.MODELENCE_SERVICE_ENDPOINT??"https://cloud.modelence.com",o=process.env.MODELENCE_ENVIRONMENT_ID,r=await ln(),n=await import('./package-AGSLW64J.js');await fetch(`${t}/api/track/app-start`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({projectName:r.name,version:n.default.version,localHostname:wr.hostname(),environmentId:o})});}}async function ln(){try{let e=B.join(process.cwd(),"package.json"),t=await Jr.readFile(e,"utf-8");return {name:JSON.parse(t).name||"unknown"}}catch{return {name:"unknown"}}}async function To(e){await o.deleteMany({userId:e}),await p.deleteMany({userId:e});}async function un(e){await To(e),await m.updateOne(e,{$set:{status:"disabled",disabledAt:new Date}});}async function mn(e){await To(e),await m.updateOne({_id:e},{$set:{handle:`deleted-${e}-${randomUUID()}`,status:"deleted",deletedAt:new Date,authMethods:{},emails:[]}});}var et=class{constructor(t,o){this.category=t,this.canAccessChannel=o||null;}broadcast(t,o){let r=Ce().provider;if(!r){k$2("Websockets provider should be added to startApp",{});return}r.broadcast({category:this.category,id:t,data:o});}};function pn(e){if(!b().provider)throw new Error("Email provider is not configured, see https://docs.modelence.com/email for more details.");return b().provider?.sendEmail(e)}async function Se(e){return !e||typeof e!="string"?null:e$1(e)}function w(e,t,o){let r=E(),n=e.status(t);if(r.errorComponent)try{let i=r.errorComponent({error:o,statusCode:t});if(i)return n.send(i)}catch(i){console.error("Unhandled error in authConfig.errorComponent:",i);}return n.json({error:o})}async function tt(e,t){let{authToken:o}=await i(t);j$1(e,o),e.status(302),e.redirect("/");}async function gn(e,t,o,r,n){let i=E();try{if(o.status==="disabled"||o.status==="deleted"){w(e,400,"User account is not active.");return}let s={};o.firstName===void 0&&t.firstName&&(s.firstName=t.firstName),o.lastName===void 0&&t.lastName&&(s.lastName=t.lastName),o.avatarUrl===void 0&&t.avatarUrl&&(s.avatarUrl=t.avatarUrl);let a=o;Object.keys(s).length>0&&(await m.updateOne({_id:o._id},{$set:s}),a={...o,...s}),await tt(e,o._id),i.onAfterLogin?.({provider:t.providerName,user:a,session:r,connectionInfo:n}),i.login?.onSuccess?.(a);}catch(s){throw s instanceof Error&&(i.login?.onError?.(s),i.onLoginError?.({provider:t.providerName,error:s,session:r,connectionInfo:n})),s}}async function hn(e,t,o,r,n){let i=E();if((i.oauthAccountLinking??"manual")==="auto"&&t.emailVerified){if(o.status==="disabled"||o.status==="deleted"){w(e,400,"User account is not active.");return}if(!o.emails?.find(c=>c.address.toLowerCase()===t.email.toLowerCase())?.verified){w(e,400,"User with this email already exists. Please log in instead.");return}try{let c={...o.firstName===void 0&&t.firstName&&{firstName:t.firstName},...o.lastName===void 0&&t.lastName&&{lastName:t.lastName},...o.avatarUrl===void 0&&t.avatarUrl&&{avatarUrl:t.avatarUrl}};if(!((await m.updateOne({_id:o._id,status:{$nin:["deleted","disabled"]},$or:[{[`authMethods.${t.providerName}.id`]:{$exists:!1}},{[`authMethods.${t.providerName}.id`]:t.id}]},{$set:{[`authMethods.${t.providerName}.id`]:t.id,...c}})).matchedCount>0)){w(e,400,"User with this email already exists. Please log in instead.");return}await tt(e,o._id);let m$1={...o,...c,authMethods:{...o.authMethods,[t.providerName]:{id:t.id}}};i.onAfterLogin?.({provider:t.providerName,user:m$1,session:r,connectionInfo:n}),i.login?.onSuccess?.(m$1);return}catch(c){throw c instanceof Error&&(i.login?.onError?.(c),i.onLoginError?.({provider:t.providerName,error:c,session:r,connectionInfo:n})),c}}w(e,400,"User with this email already exists. Please log in instead.");}async function wn(e,t,o,r){let n=E();try{let i;if(n.generateHandle){let l=await n.generateHandle({email:t.email,firstName:t.firstName,lastName:t.lastName});i=await j(l,t.email,{throwOnConflict:!1});}else i=await j(void 0,t.email);let s={handle:i,status:"active",emails:[{address:t.email,verified:t.emailVerified}],createdAt:new Date,authMethods:{[t.providerName]:{id:t.id}},...t.firstName!==void 0&&{firstName:t.firstName},...t.lastName!==void 0&&{lastName:t.lastName},...t.avatarUrl!==void 0&&{avatarUrl:t.avatarUrl}},a=await m.insertOne(s);await tt(e,a.insertedId);let c=await m.findOne({_id:a.insertedId},{readPreference:"primary"});c&&(n.onAfterSignup?.({provider:t.providerName,user:c,session:o,connectionInfo:r}),n.signup?.onSuccess?.(c));}catch(i){throw i instanceof Error&&(n.onSignupError?.({provider:t.providerName,error:i,session:o,connectionInfo:r}),n.signup?.onError?.(i)),i}}function K(e){return `${a$2("_system.site.url")}/api/_internal/auth/${e}/callback`}async function ke(e,t,o){let r=await m.findOne({[`authMethods.${o.providerName}.id`]:o.id}),{session:n,connectionInfo:i}=await Q(e,t);if(r)return gn(t,o,r,n,i);if(!o.email){w(t,400,`Email address is required for ${o.providerName} authentication.`);return}let s;try{s=await m.findOne({"emails.address":o.email,status:{$ne:"deleted"}},{collation:{locale:"en",strength:2}});}catch(a){if(a instanceof Error){let c=E();c.onSignupError?.({provider:o.providerName,error:a,session:n,connectionInfo:i}),c.signup?.onError?.(a);}throw a}return s?hn(t,o,s,n,i):wn(t,o,n,i)}function k(e){e.cookie("oauthLinkToken","",{httpOnly:true,maxAge:0,path:"/api/_internal/auth/",sameSite:"lax",secure:process.env.NODE_ENV==="production"});}function W(e){if(e)try{e();}catch(t){console.error("Error executing OAuth hook:",t);}}function Ae(e,t,o){let r=e.query.state,n=e.cookies[o],[i,s,a]=(n||"").split(":");return !r||!n||r!==i?(w(t,400,"Invalid OAuth state - possible CSRF attack"),null):(t.clearCookie(o),{mode:s||"login",...a?{linkedUserId:a}:{}})}async function Re(e,t,o,r){let n=E(),{session:i,connectionInfo:s}=await Q(e,t),a=null;if(r){if(!ObjectId.isValid(r)){k(t),w(t,400,"Invalid OAuth linking state.");return}a=new ObjectId(r);}else a=i?.userId??null;if(!a){k(t),w(t,401,"You must be signed in to link a provider.");return}let c=a;try{let l=`authMethods.${o.providerName}.id`;if((await m.updateOne({_id:c,status:{$nin:["deleted","disabled"]},$or:[{[l]:{$exists:!1}},{[l]:o.id}]},{$set:{[l]:o.id}})).matchedCount===0){let f=await m.findOne({_id:c});if(!f||f.status==="deleted"||f.status==="disabled"){W(()=>n.onOAuthLinkError?.({provider:o.providerName,error:new Error("User account not found or not active"),session:i,connectionInfo:s})),k(t),w(t,400,"User account is not active.");return}let v=f?.authMethods?.[o.providerName]?.id;if(v&&v!==o.id){W(()=>n.onOAuthLinkError?.({provider:o.providerName,error:new Error(`User already has a different ${o.providerName} account linked`),session:i,connectionInfo:s})),k(t),w(t,400,`You have already linked a different ${o.providerName} account.`);return}W(()=>n.onOAuthLinkError?.({provider:o.providerName,error:new Error(`Unexpected OAuth linking state for ${o.providerName}`),session:i,connectionInfo:s})),k(t),w(t,400,`Unable to link ${o.providerName} account.`);return}let m$1=await m.findOne({_id:c},{readPreference:"primary"});m$1&&W(()=>n.onAfterOAuthLink?.({provider:o.providerName,user:m$1,session:i,connectionInfo:s})),k(t),t.status(302).redirect("/");}catch(l){if(l instanceof MongoServerError&&l.code===11e3){W(()=>n.onOAuthLinkError?.({provider:o.providerName,error:l,session:i,connectionInfo:s})),k(t),w(t,400,`This ${o.providerName} account is already linked to a different user.`);return}if(l instanceof Error&&W(()=>n.onOAuthLinkError?.({provider:o.providerName,error:l,session:i,connectionInfo:s})),k(t),!t.headersSent)throw l}}function xe(e){return !e||typeof e!="string"?null:e}async function En(e,t,o,r){let n=await fetch("https://oauth2.googleapis.com/token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({code:e,client_id:t,client_secret:o,redirect_uri:r,grant_type:"authorization_code"})});if(!n.ok)throw new Error(`Failed to exchange code for token: ${n.statusText}`);return n.json()}async function vn(e){let t=await fetch("https://www.googleapis.com/oauth2/v2/userinfo",{headers:{Authorization:`Bearer ${e}`}});if(!t.ok)throw new Error(`Failed to fetch user info: ${t.statusText}`);return t.json()}async function Cn(e,t){let o=xe(e.query.code);if(!o){w(t,400,"Missing authorization code");return}let r=Ae(e,t,"authStateGoogle");if(!r)return;let{mode:n,linkedUserId:i}=r,s=String(a$2("_system.user.auth.google.clientId")),a=String(a$2("_system.user.auth.google.clientSecret")),c=K("google");try{let l=await En(o,s,a,c),d=await vn(l.access_token),m={id:d.id,email:d.email,emailVerified:d.verified_email,providerName:"google",firstName:d.given_name||void 0,lastName:d.family_name||void 0,avatarUrl:d.picture||void 0};n==="link"?await Re(e,t,m,i):await ke(e,t,m);}catch(l){console.error("Google OAuth error:",l),n==="link"&&k(t),w(t,500,"Authentication failed");}}function Sn(){let e=Router(),t=(o,r,n)=>{let i=!!a$2("_system.user.auth.google.enabled"),s=String(a$2("_system.user.auth.google.clientId")),a=String(a$2("_system.user.auth.google.clientSecret"));if(!i||!s||!a){w(r,503,"Google authentication is not configured");return}n();};return e.get("/api/_internal/auth/google",t,async(o,r)=>{let n=String(a$2("_system.user.auth.google.clientId")),i=K("google"),s=randomBytes(32).toString("hex"),a=o.query.mode==="link"?"link":"login",c=null;if(a==="link"&&o.query.linkNonce&&(c=await Se(o.query.linkNonce),!c)){w(r,401,"Invalid or expired link nonce for OAuth linking.");return}let l=c?`${s}:${a}:${c}`:`${s}:${a}`;r.cookie("authStateGoogle",l,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",maxAge:a$1.minutes(10)});let d=new URL("https://accounts.google.com/o/oauth2/v2/auth");d.searchParams.append("client_id",n),d.searchParams.append("redirect_uri",i),d.searchParams.append("response_type","code"),d.searchParams.append("scope","profile email"),d.searchParams.append("access_type","online"),d.searchParams.append("state",s),r.redirect(d.toString());}),e.get("/api/_internal/auth/google/callback",t,Cn),e}var $o=Sn;async function Rn(e,t,o,r){let n=await fetch("https://github.com/login/oauth/access_token",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({client_id:t,client_secret:o,code:e,redirect_uri:r})});if(!n.ok)throw new Error(`Failed to exchange code for token: ${n.statusText}`);return n.json()}async function xn(e){let t=await fetch("https://api.github.com/user",{headers:{Authorization:`Bearer ${e}`,Accept:"application/vnd.github.v3+json"}});if(!t.ok)throw new Error(`Failed to fetch user info: ${t.statusText}`);return t.json()}async function On(e){let t=await fetch("https://api.github.com/user/emails",{headers:{Authorization:`Bearer ${e}`,Accept:"application/vnd.github.v3+json"}});if(!t.ok)throw new Error(`Failed to fetch user emails: ${t.statusText}`);return t.json()}async function _n(e,t){return e.email?e.email:(await On(t)).find(r=>r.primary&&r.verified)?.email??null}async function Pn(e,t){let o=xe(e.query.code);if(!o){w(t,400,"Missing authorization code");return}let r=Ae(e,t,"authStateGithub");if(!r)return;let{mode:n,linkedUserId:i}=r,s=String(a$2("_system.user.auth.github.clientId")),a=String(a$2("_system.user.auth.github.clientSecret")),c=K("github");try{let l=await Rn(o,s,a,c),d=await xn(l.access_token),m=await _n(d,l.access_token);if(!m){n==="link"&&k(t),w(t,400,"Unable to retrieve a primary verified email from GitHub. Please ensure your GitHub account has a verified email set as primary.");return}let f=d.name?d.name.trim().split(/\s+/):[],v=f[0]||void 0,y=f.length>1?f.slice(1).join(" "):void 0,S={id:String(d.id),email:m,emailVerified:!0,providerName:"github",firstName:v,lastName:y,avatarUrl:d.avatar_url||void 0};n==="link"?await Re(e,t,S,i):await ke(e,t,S);}catch(l){console.error("GitHub OAuth error:",l),n==="link"&&k(t),w(t,500,"Authentication failed");}}function Ln(){let e=Router(),t=(o,r,n)=>{let i=!!a$2("_system.user.auth.github.enabled"),s=String(a$2("_system.user.auth.github.clientId")),a=String(a$2("_system.user.auth.github.clientSecret"));if(!i||!s||!a){w(r,503,"GitHub authentication is not configured");return}n();};return e.get("/api/_internal/auth/github",t,async(o,r)=>{let n=String(a$2("_system.user.auth.github.clientId")),i=K("github"),s=a$2("_system.user.auth.github.scopes"),a=s?String(s).split(",").map(v=>v.trim()).join(" "):"user:email",c=randomBytes(32).toString("hex"),l=o.query.mode==="link"?"link":"login",d=null;if(l==="link"&&o.query.linkNonce&&(d=await Se(o.query.linkNonce),!d)){w(r,401,"Invalid or expired link nonce for OAuth linking.");return}let m=d?`${c}:${l}:${d}`:`${c}:${l}`;r.cookie("authStateGithub",m,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",maxAge:a$1.minutes(10)});let f=new URL("https://github.com/login/oauth/authorize");f.searchParams.append("client_id",n),f.searchParams.append("redirect_uri",i),f.searchParams.append("scope",a),f.searchParams.append("state",c),r.redirect(f.toString());}),e.get("/api/_internal/auth/github/callback",t,Pn),e}var Do=Ln;function jo(e,t,o){return async(r,n,i)=>{let s$1=r.headers["x-modelence-auth-token"],a={session:null,user:null};if(typeof s$1=="string"&&$())try{let{session:l,user:d}=await s(s$1);a={session:l,user:d};}catch{}let c=l$1("route",`route:${e.toLowerCase()}:${t}`,{method:e,path:t,query:r.query,body:r.body,params:r.params});try{let l=await o({query:r.query,body:r.body,params:r.params,headers:r.headers,cookies:r.cookies,rawBody:Buffer.isBuffer(r.body)?r.body:void 0,req:r,res:n,next:i},a);c.end(),l&&(n.status(l.status||200),l.redirect&&n.redirect(l.redirect),l.headers&&Object.entries(l.headers).forEach(([d,m])=>{n.setHeader(d,m);}),n.send(l.data));}catch(l){c.end("error"),l instanceof a$4?n.status(l.status).send(l.message):(console.error(`Error in route handler: ${r.path}`),console.error(l),n.status(500).send(String(l)));}}}function Un(e){let t=[];if(!e)return t.push(U.json({limit:"16mb"})),t.push(U.urlencoded({extended:true,limit:"16mb"})),t;if(e.json!==false){let o=typeof e.json=="object"?e.json:{limit:"16mb"};t.push(U.json(o));}if(e.urlencoded!==false){let o=typeof e.urlencoded=="object"?e.urlencoded:{extended:true,limit:"16mb"};t.push(U.urlencoded(o));}if(e.raw){let o=typeof e.raw=="object"?e.raw:{},r={limit:o.limit||"16mb",type:o.type||"*/*"};t.push(U.raw(r));}return t}function Tn(e,t){for(let o of t)for(let r of o.routes){let{path:n,handlers:i,body:s}=r,a=Un(s);Object.entries(i).forEach(([c,l])=>{e[c](n,...a,jo(c,n,l));});}}async function Uo(e,{combinedModules:t,channels:o}){let r=U();r.use(Mn()),r.use(Dn()),Tn(r,t),r.use(U.json({limit:"16mb"})),r.use(U.urlencoded({extended:true,limit:"16mb"})),r.use($o()),r.use(Do()),r.post("/api/_internal/auth/set-link-cookie",async(a,c)=>{let{session:l}=await Q(a,c);if(!l?.userId){c.status(401).json({error:"Not authenticated"});return}c.cookie("oauthLinkToken",l.authToken,{httpOnly:true,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:"/api/_internal/auth/",maxAge:10*60*1e3}),c.json({ok:true});}),r.post("/api/_internal/auth/issue-link-nonce",async(a,c)=>{let{session:l}=await Q(a,c);if(!l?.userId){c.status(401).json({error:"Not authenticated"});return}let d=await d$1(String(l.userId));c.json({nonce:d});}),r.post("/api/_internal/method/:methodName(*)",async(a,c)=>{let l=a.params.methodName,d=await Q(a,c);try{let m=a$3(await z$1(l,a.body.args,d));c.json({data:m,typeMap:b$3(m)});}catch(m){In(c,l,m);}});let n=Nn.createServer(r);await e.init({httpServer:n}),e.middlewares&&r.use(e.middlewares()),r.all("*",(a,c,l)=>{Promise.resolve(e.handler(a,c)).catch(l);}),process.on("unhandledRejection",(a,c)=>{console.error("Unhandled Promise Rejection:"),console.error(a instanceof Error?a.stack:a),console.error("Promise:",c);}),process.on("uncaughtException",a=>{console.error("Uncaught Exception:"),console.error(a.stack),console.trace("Full application stack:");});let i=Ce()?.provider;i&&i.init({httpServer:n,channels:o});let s=process.env.MODELENCE_PORT||process.env.PORT||3e3;n.listen(s,()=>{j$2("Application started",{source:"app"});let a=a$2("_system.site.url")||`http://localhost:${s}`;console.log(`
|
|
22
|
+
Application started on ${a}
|
|
23
|
+
`);});}async function Q(e,t=null){let o=(e.path??e.url??"").split("?")[0],r$1=o.startsWith("/api/_internal/auth/")&&o.endsWith("/callback"),n=e.body??{},i=N.string().nullish().transform(l=>l??null).parse(e.cookies.authToken||(r$1?e.cookies.oauthLinkToken:null)||n.authToken),s$1=N.object({screenWidth:N.number(),screenHeight:N.number(),windowWidth:N.number(),windowHeight:N.number(),pixelRatio:N.number(),orientation:N.string().nullable()}).nullish().parse(n.clientInfo)??{screenWidth:0,screenHeight:0,windowWidth:0,windowHeight:0,pixelRatio:1,orientation:null},a={ip:Hn(e),userAgent:e.get("user-agent"),acceptLanguage:e.get("accept-language"),referrer:e.get("referrer"),baseUrl:jn(e)};if(!!$()){let{session:l,user:d,roles:m}=await s(i);return {clientInfo:s$1,connectionInfo:a,session:l,user:d,roles:m,req:e,res:t}}return {clientInfo:s$1,connectionInfo:a,session:null,user:null,roles:r(),req:e,res:t}}function In(e,t,o){if(o instanceof a$4){o.status>=500&&o.status<600&&console.error(`Error calling ${t}:`,o),o.code&&e.setHeader("X-Modelence-Error-Code",o.code),e.status(o.status).send(o.message);return}if(o instanceof Error&&o?.constructor?.name==="ZodError"&&"errors"in o){let r="";try{r=$n(o);}catch(n){console.error(`Error parsing Zod error in ${t}:`,n),r="Validation failed";}e.status(400).send(r);return}console.error(`Error calling ${t}:`,o),e.status(500).send(o instanceof Error?o.message:String(o));}function $n(e){let t=e.flatten(),o=Object.entries(t.fieldErrors).map(([i,s])=>`${i}: ${(s??[]).join(", ")}`),r=t.formErrors;return [...o,...r].filter(Boolean).join("; ")}function Dn(){let{frameAncestors:e}=Lo(),t=e&&e.length>0,o=t?["'self'",...e].join(" "):"'self'";return (r,n,i)=>{n.setHeader("Content-Security-Policy",`frame-ancestors ${o}`),t||n.setHeader("X-Frame-Options","SAMEORIGIN"),i();}}function jn(e){let t=e.headers["x-forwarded-host"],o=(Array.isArray(t)?t[0]:t?.split(",")[0])?.trim()||e.get("host"),r=e.headers["x-forwarded-proto"];return `${(Array.isArray(r)?r[0]:r?.split(",")[0])?.trim()||e.protocol}://${o}`}function Hn(e){let t=e.headers["x-forwarded-for"];if(t)return (Array.isArray(t)?t[0]:t.split(",")[0]).trim();let o=e.ip||e.socket?.remoteAddress;if(o)return o.startsWith("::ffff:")?o.substring(7):o}
|
|
24
|
+
export{A as a,vo as b,Co as c,So as d,ko as e,Uo as f,Q as g,Qr as h,un as i,mn as j,et as k,pn as l};//# sourceMappingURL=chunk-SI5I2VMN.js.map
|
|
25
|
+
//# sourceMappingURL=chunk-SI5I2VMN.js.map
|