import type { BookmarkClearResult, BookmarkListResult, BookmarkPrewarmResult, DeleteBatchResult, DeleteResult, IncrementOneResult, IndexCreateResult, InsertBatchResult, InsertManyResult, InsertOneResult, UpdateBatchResult, UpdateResult } from './collection'; import type { SchemaDslRuntime } from 'schema-dsl/runtime'; /** * Runtime-scoped schema-dsl namespace passed to Model schema callbacks. */ export type ModelSchemaDsl = SchemaDslRuntime['s']; /** * Schema DSL transformer function. * @since v1.0.0 */ export type SchemaDSL = (s: ModelSchemaDsl) => unknown; /** * Default value for a model field — either a static value or a factory function. * @template T Field value type * @since v1.0.0 */ export type DefaultValue = T | ((context?: unknown, doc?: unknown) => T); export interface ValidationResult { valid: boolean; errors?: Array<{ field: string; message: string; value?: unknown; }>; data?: unknown; } export interface HookContext { operation: string; collection: string; data?: unknown; filter?: unknown; update?: unknown; result?: unknown; error?: Error; [key: string]: unknown; } export interface ModelConnection { pool?: string; database?: string; } export interface RelationConfig { from: string; localField: string; foreignField: string; single?: boolean; } export interface PopulateConfig { path: string; select?: string | string[]; match?: Record; sort?: Record; limit?: number; skip?: number; /** Maximum nested populate depth for this branch. Defaults to 5. */ maxDepth?: number; populate?: string | PopulateConfig | Array; } export interface VirtualConfig { get: (this: Record) => unknown; set?: (this: Record, value: unknown) => void; } export type ModelAutoIndexOptions = boolean | { /** Enable automatic model index creation. Defaults to true for backward compatibility. */ enabled?: boolean; /** Emit `model-index-error` when automatic index creation fails or conflicts are detected. Defaults to true. */ emitEvents?: boolean; }; export type ModelVersionUpdateManyMode = 'counter' | 'strict' | 'off'; export interface ModelVersionOptions { enabled?: boolean; field?: string; /** * Version handling for updateMany on versioned models. * - counter: native batch update plus version increment; not optimistic locking. * - strict: pre-read IDs/versions and conditionally update each document. * - off: skip version handling for this batch update. */ updateMany?: ModelVersionUpdateManyMode; } export type ModelWriteOptions = Record & { expectedVersion?: number; version?: number; }; export type ModelUpdateManyOptions = ModelWriteOptions & { versionMode?: ModelVersionUpdateManyMode; }; export type ModelStrictUpdateManyResult = UpdateResult & { conflictCount: number; conflictedIds: unknown[]; }; export type ModelIndexSource = 'definition' | 'softDelete'; export interface ModelDeclaredIndex { source: ModelIndexSource; key: unknown; options: Record; name?: string; fingerprint: string; } export interface ModelIndexNamespace { db: string; collection: string; poolName: string; } export interface ModelIndexErrorSummary { name?: string; message: string; code?: unknown; } export interface ModelIndexEnsureExisting { declared: ModelDeclaredIndex; existing: Record; } export interface ModelIndexConflict { declared: ModelDeclaredIndex; existing?: Record; reason: string; } export interface ModelIndexCreated { declared: ModelDeclaredIndex; name?: string; result?: unknown; } export interface ModelIndexFailure { declared: ModelDeclaredIndex; error: ModelIndexErrorSummary; } export interface ModelIndexSkipped { declared: ModelDeclaredIndex; reason: string; } export interface ModelEnsureIndexesOptions { /** Return the index diff without creating missing indexes. */ dryRun?: boolean; /** Throw a MonSQLize `MONGODB_ERROR` when conflicts or creation failures are found. */ throwOnError?: boolean; } export interface ModelEnsureAllIndexesOptions extends ModelEnsureIndexesOptions { /** Limit the operation to specific registered model names. Defaults to all models. */ models?: string[]; /** Optional database scope for models without their own connection override. */ database?: string; /** Optional pool scope for models without their own connection override. */ pool?: string; } export interface ModelIndexEnsureResult { dryRun: boolean; namespace: ModelIndexNamespace; declared: ModelDeclaredIndex[]; existing: ModelIndexEnsureExisting[]; missing: ModelDeclaredIndex[]; created: ModelIndexCreated[]; conflicts: ModelIndexConflict[]; failed: ModelIndexFailure[]; skipped: ModelIndexSkipped[]; } export interface ModelIndexEnsureSummary { dryRun: boolean; models: Array<{ name: string; result: ModelIndexEnsureResult }>; totals: { declared: number; existing: number; missing: number; created: number; conflicts: number; failed: number; skipped: number; }; } /** v1 hooks factory format */ export type V1HooksFactory> = ( model: ModelInstance, ) => { find?: { before?: (ctx: Record, ...args: unknown[]) => unknown; after?: (ctx: Record, result: unknown) => unknown; }; insert?: { before?: (ctx: Record, ...args: unknown[]) => unknown; after?: (ctx: Record, result: unknown) => unknown; }; update?: { before?: (ctx: Record, ...args: unknown[]) => unknown; after?: (ctx: Record, result: unknown) => unknown; }; delete?: { before?: (ctx: Record, ...args: unknown[]) => unknown; after?: (ctx: Record, result: unknown) => unknown; }; }; /** v1 methods factory format */ export type V1MethodsFactory> = ( model: ModelInstance, ) => { instance?: Record, ...args: unknown[]) => unknown>; static?: Record unknown>; }; export interface ModelDefinitionOptions { timestamps?: boolean | { createdAt?: string | boolean; updatedAt?: string | boolean }; validate?: boolean; autoIndex?: ModelAutoIndexOptions; softDelete?: boolean | { enabled?: boolean; field?: string; type?: string; ttl?: number | null; }; version?: boolean | ModelVersionOptions; } export interface ModelDefinition> { /** Actual MongoDB collection name; falls back to `name` and then the `Model.define()` registration name. */ collection?: string; /** Compatibility collection name used by model auto-loading files; `collection` has higher priority. */ name?: string; enums?: Record; schema?: SchemaDSL | Record; defaults?: Record unknown)>; hooks?: | { beforeCreate?: (context: HookContext) => Promise | void; afterCreate?: (context: HookContext) => Promise | void; beforeInsert?: (context: HookContext) => Promise | void; afterInsert?: (context: HookContext) => Promise | void; beforeUpdate?: (context: HookContext) => Promise | void; afterUpdate?: (context: HookContext) => Promise | void; beforeDelete?: (context: HookContext) => Promise | void; afterDelete?: (context: HookContext) => Promise | void; beforeFind?: (context: HookContext) => Promise | void; afterFind?: (context: HookContext) => Promise | void; } | V1HooksFactory; methods?: | Record, ...args: unknown[]) => unknown> | V1MethodsFactory; statics?: Record unknown>; relations?: Record; virtuals?: Record; connection?: ModelConnection; indexes?: Array<{ key: unknown } & Record>; options?: ModelDefinitionOptions; } export interface RegisteredModel> { collectionName: string; definition: ModelDefinition; } export interface ModelScopeOptions { database?: string; pool?: string; } export interface PopulateProxy extends Promise { populate(path: string | PopulateConfig | Array, options?: Partial>): PopulateProxy; exec(): Promise; } type LegacyModelPageInfo = unknown extends TDocument ? any : { hasNext: boolean; hasPrev: boolean; startCursor: string | null; endCursor: string | null; currentPage?: number; }; type LegacyModelTotalsInfo = unknown extends TDocument ? any : import('./collection').TotalsInfo; type LegacyModelSyncTotalsInfo = unknown extends TDocument ? any : (import('./collection').TotalsInfo & { mode: 'sync'; total: number; totalPages: number; }); export type RestoreResult = Pick & Partial; export type ModelDocument = TDocument & Record & { save(): Promise>; remove(): Promise; validate(): Promise; populate(path: string | PopulateConfig | Array): PopulateProxy | null>; toObject(): TDocument & Record; toJSON(): TDocument & Record; }; export interface ModelInstance { readonly collectionName: string; readonly dbName: string; readonly poolName?: string; readonly definition: ModelDefinition; /** Returns namespace metadata for the current model, including instance ID, type, database, and collection. */ getNamespace(): { iid: string; type: 'mongodb'; db: string; collection: string; pool?: string; }; /** Returns the relation config map declared by the current model. */ getRelations(): Record; /** Returns the enum value map declared by the current model. */ getEnums(): Record; /** Returns the underlying native MongoDB Collection for raw operations not wrapped by the framework. */ raw(): unknown; /** * Finds documents matching the query. * @param query Optional filter. * @param options Optional query options such as projection, sort, and limit. * @returns Document array with chainable `.populate()` support. */ find(query?: unknown, options?: unknown): PopulateProxy>>; /** * Finds the first document matching the query. * @param query Optional filter. * @param options Optional query options. * @returns The matching document, or `null` when none is found. */ findOne(query?: unknown, options?: unknown): PopulateProxy | null>; /** * Finds a single document by primary ID, as an ID shortcut for `findOne`. * @param id Document primary key value. * @param options Optional query options. * @returns The matching document, or `null` when none is found. */ findOneById(id: unknown, options?: unknown): PopulateProxy | null>; /** * Finds a single document by primary ID; alias of `findOneById`. * @param id Document primary key value. * @param options Optional query options. * @returns The matching document, or `null` when none is found. */ findById(id: unknown, options?: unknown): PopulateProxy | null>; /** * Finds documents by multiple primary IDs. * @param ids Primary key values. * @param options Optional query options. * @returns Matching documents. */ findByIds(ids: unknown[], options?: unknown): PopulateProxy>>; /** * Finds documents with cursor-based or page-number pagination. * @param options Pagination options including `limit`, `cursor`/`page`, `filter`, and `sort`. * @returns Result object containing items, page information, and optional totals. */ findPage(options: { totals: { mode: 'sync'; } & Record; } & Record): PopulateProxy<{ items: Array>; pageInfo: LegacyModelPageInfo; totals: LegacyModelSyncTotalsInfo; meta?: import('./collection').MetaInfo; }>; findPage(options?: unknown): PopulateProxy<{ items: Array>; pageInfo: LegacyModelPageInfo; totals?: LegacyModelTotalsInfo; meta?: import('./collection').MetaInfo; }>; /** * Finds documents and returns the unpaginated total count. * @param query Optional filter. * @param options Optional query options. * @returns Object containing documents and total count. */ findAndCount(query?: unknown, options?: unknown): PopulateProxy<{ data: Array>; total: number; }>; /** * Counts documents matching the query. * @param query Optional filter. * @param options Optional count options. * @returns Number of matching documents. */ count(query?: unknown, options?: unknown): Promise; /** * Inserts a single document. * @param document Document data to insert. * @param options Optional write options. * @returns Result object containing the inserted ID. */ insertOne(document?: unknown, options?: unknown): Promise; /** * Inserts multiple documents in order, stopping on the first error. * @param documents Documents to insert. * @param options Optional write options. */ insertMany(documents?: unknown[], options?: unknown): Promise; /** * Updates the first document matching the filter. * @param filter Filter. * @param update Update operator document, such as `$set` or `$inc`. * @param options Optional update options. */ updateOne(filter?: unknown, update?: unknown, options?: ModelWriteOptions): Promise; /** * Updates all documents matching the filter. * @param filter Filter. * @param update Update operator document. * @param options Optional update options. */ updateMany(filter?: unknown, update?: unknown, options?: ModelUpdateManyOptions): Promise; /** * Replaces the first document matching the filter with a full replacement document. * @param filter Filter. * @param replacement Full replacement document. * @param options Optional replacement options. */ replaceOne(filter?: unknown, replacement?: unknown, options?: ModelWriteOptions): Promise; /** * Atomically finds and updates one document. * @param filter Filter. * @param update Update operator document. * @param options Optional options such as `returnDocument: 'after'`. * @returns Updated document, or `null` when none is found. */ findOneAndUpdate(filter?: unknown, update?: unknown, options?: ModelWriteOptions): Promise; /** * Atomically finds and replaces one document. * @param filter Filter. * @param replacement Full replacement document. * @param options Optional options. * @returns Replaced document, or `null` when none is found. */ findOneAndReplace(filter?: unknown, replacement?: unknown, options?: ModelWriteOptions): Promise; /** * Atomically finds and deletes one document. * @param filter Filter. * @param options Optional options. * @returns Deleted document, or `null` when none is found. */ findOneAndDelete(filter?: unknown, options?: unknown): Promise; /** * Updates an existing document or inserts one when none matches. * @param filter Filter. * @param update Update operator document. * @param options Optional update options. * @returns Standard `UpdateResult` object. */ upsertOne(filter?: unknown, update?: unknown, options?: unknown): Promise; /** * Atomically increments a field on one matching document. * @param filter Filter. * @param field Field name or field-increment map. * @param increment Increment value used when `field` is a string. * @param options Optional update options. */ incrementOne(filter?: unknown, field?: string | Record, increment?: number, options?: unknown): Promise>; /** * Deletes the first document matching the filter. * @param filter Filter. * @param options Optional delete options. * @returns Standard `DeleteResult` object. */ deleteOne(filter?: unknown, options?: unknown): Promise; /** * Deletes all documents matching the filter. * @param filter Filter. * @param options Optional delete options. * @returns Standard `DeleteResult` object. */ deleteMany(filter?: unknown, options?: unknown): Promise; // soft-delete extended methods /** * Finds matching documents, including soft-deleted documents. * @param query Optional filter. * @param options Optional query options. */ findWithDeleted(query?: unknown, options?: unknown): PopulateProxy>>; /** * Finds only soft-deleted documents. * @param query Optional filter. * @param options Optional query options. */ findOnlyDeleted(query?: unknown, options?: unknown): PopulateProxy>>; /** * Finds the first matching document, including soft-deleted documents. * @param query Optional filter. * @param options Optional query options. * @returns Matching document, or `null` when none is found. */ findOneWithDeleted(query?: unknown, options?: unknown): PopulateProxy | null>; /** * Restores the first soft-deleted document matching the filter. * @param filter Filter. * @param options Optional update options. */ restore(filter?: unknown, options?: unknown): Promise; /** * Restores all soft-deleted documents matching the filter. * @param filter Filter. * @param options Optional update options. */ restoreMany(filter?: unknown, options?: unknown): Promise; /** * Physically deletes the first matching document, bypassing soft-delete. * @param filter Filter. * @param options Optional delete options. * @returns Standard `DeleteResult` object. */ forceDelete(filter?: unknown, options?: unknown): Promise; /** * Physically deletes all matching documents, bypassing soft-delete. * @param filter Filter. * @param options Optional delete options. * @returns Standard `DeleteResult` object. */ forceDeleteMany(filter?: unknown, options?: unknown): Promise; /** * Finds the first matching document from only the soft-deleted set. * @param query Optional filter. * @param options Optional query options. * @returns Matching deleted document, or `null` when none is found. */ findOneOnlyDeleted(query?: unknown, options?: unknown): PopulateProxy | null>; /** * Counts matching documents, including soft-deleted documents. * @param query Optional filter. * @param options Optional count options. */ countWithDeleted(query?: unknown, options?: unknown): Promise; /** * Counts soft-deleted documents matching the query. * @param query Optional filter. * @param options Optional count options. */ countOnlyDeleted(query?: unknown, options?: unknown): Promise; /** * Inserts a large document batch through the write queue. * @param docs Documents to insert. * @param options Optional batch write options. */ insertBatch(docs: unknown[], options?: unknown): Promise; /** * Batch-updates matching documents using `bulkWrite`. * @param filter Filter. * @param update Update operator document. * @param options Optional batch write options. */ updateBatch(filter?: unknown, update?: unknown, options?: unknown): Promise; /** Batch-deletes matching documents. */ deleteBatch(filter?: unknown, options?: unknown): Promise; /** * Creates a single index on the collection. * @param keys Index key specification. * @param options Optional index options such as `unique` or `sparse`. * @returns Index creation result. */ createIndex(keys: unknown, options?: unknown): Promise; /** * Creates multiple indexes. * @param specs Index specifications, each containing `key` and optional index options. * @returns Names of created indexes. */ createIndexes(specs: Array<{ key: unknown; } & Record>): Promise; /** Lists all existing index definitions on the collection. */ listIndexes(): Promise[]>; /** * Compares declared model indexes with the database and optionally creates missing indexes. * Does not drop, rename, or rebuild conflicting indexes. */ ensureIndexes(options?: ModelEnsureIndexesOptions): Promise; /** * Drops the specified index by name. * @param name Index name. */ dropIndex(name: string): Promise; /** Drops all non-`_id` indexes on the collection. */ dropIndexes(): Promise; /** Prewarms cursor pagination bookmark cache. */ prewarmBookmarks(keyDims?: unknown, pages?: number[]): Promise; /** Lists cursor pagination bookmark cache entries. */ listBookmarks(keyDims?: unknown): Promise; /** Clears cursor pagination bookmark cache entries. */ clearBookmarks(keyDims?: unknown): Promise; /** * Gets distinct values for a field from matching documents. * @param key Target field name. * @param query Optional filter. * @param options Optional driver-level options. * @returns Distinct values. */ distinct(key: string, query?: unknown, options?: unknown): Promise; /** * Executes an aggregation pipeline and returns result documents. * @param pipeline Aggregation stages. * @param options Optional aggregation options such as `allowDiskUse`. * @returns Aggregation result documents. */ aggregate(pipeline?: unknown[], options?: unknown): Promise; /** Returns a readable stream for matching query results. */ stream(query?: unknown, options?: unknown): NodeJS.ReadableStream; /** Returns the MongoDB query execution plan. */ explain(query?: unknown, options?: unknown): Promise; /** Manually invalidates read cache for the current model collection. */ invalidate(op?: 'find' | 'findOne' | 'count' | 'findPage' | 'aggregate' | 'distinct'): Promise; /** Drops the collection for the current model. */ dropCollection(): Promise; /** Creates the current collection or a collection with the specified name. */ createCollection(name?: string, options?: Record): Promise; /** Creates a MongoDB view. */ createView(name: string, source: string, pipeline?: unknown[]): Promise; /** Returns index usage statistics. */ indexStats(): Promise; /** Sets the collection JSON Schema validator. */ setValidator(validator: unknown, options?: { validationLevel?: string; validationAction?: string }): Promise<{ ok: number; collection: string }>; /** Sets the collection validation level. */ setValidationLevel(level: 'off' | 'moderate' | 'strict' | string): Promise<{ ok: number; validationLevel: string }>; /** Sets the collection validation action. */ setValidationAction(action: 'error' | 'warn' | string): Promise<{ ok: number; validationAction: string }>; /** Reads the collection validator and validation settings. */ getValidator(): Promise<{ validator: Record | null; validationLevel: string; validationAction: string }>; /** Returns collection storage and index statistics. */ stats(options?: { scale?: number }): Promise<{ ns: string; count: number; size: number; storageSize: number; totalIndexSize: number; nindexes: number; avgObjSize?: number; scaleFactor?: number }>; /** Renames the collection for the current model. */ renameCollection(newName: string, options?: { dropTarget?: boolean }): Promise<{ renamed: boolean; from: string; to: string }>; /** Executes a collMod management command. */ collMod(modifications: Record): Promise>; /** Converts the collection to a capped collection. */ convertToCapped(size: number, options?: { max?: number }): Promise<{ ok: number; collection: string; capped: boolean; size: number }>; /** * Opens a ChangeStream on the collection. * @param pipeline Optional aggregation filter pipeline. * @param options Optional ChangeStream options. * @returns Native MongoDB ChangeStream object. */ watch(pipeline?: unknown[], options?: unknown): import('mongodb').ChangeStream; /** * Validates document data against the model schema definition. * @param document Document to validate. * @returns Validation result containing the `valid` flag and error details. */ validate(document?: unknown): ValidationResult; } export declare class Model { static define>(collectionName: string, definition: ModelDefinition): void; static get>(collectionName: string): RegisteredModel | undefined; static has(collectionName: string): boolean; static list(): string[]; static undefine(collectionName: string): boolean; static redefine>(collectionName: string, definition: ModelDefinition): void; static _clear(): void; }