/// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// import type * as mongoose from 'mongoose'; import type { PropType, Severity } from './internal/constants'; /** * Get the Type of an instance of a Document with Class properties * @example * ```ts * class ClassName { * @prop() * public someProperty: string; * } * const NameModel = getModelForClass(ClassName); * * const doc: DocumentType = await NameModel.create({}); * ``` */ export type DocumentType = mongoose.Document & mongoose.Default__v> & IObjectWithTypegooseFunction; /** * Get the Type of an instance of a SubDocument with Class properties */ export type SubDocumentType = DocumentType & mongoose.Types.Subdocument; /** * Get the Type of an instance of a SubDocument that exists within an array, with Class properties */ export type ArraySubDocumentType = DocumentType & mongoose.Types.ArraySubdocument; /** * Used Internally for ModelTypes */ export type ModelType = mongoose.Model; /** * Any-param Constructor */ export type AnyParamConstructor = new (...args: any) => T; /** * The Type for Models used in typegoose, mostly returned by "getModelForClass" and "addModelToTypegoose" * @example * const Model: ReturnModelType = mongoose.model("YourClass", YourClassSchema); */ export type ReturnModelType, QueryHelpers = BeAnObject> = ModelType, QueryHelpers> & U; /** Generic "Function" type, because typescript does not like using "Function" directly in strict mode */ export type Func = (...args: any[]) => any; /** * The Type of a function to generate a custom model name. */ export type CustomNameFunction = (options: IModelOptions) => string; /** * Defer a reference with a function (or as other projects call it "Forward declaration") * @param type This is just to comply with the common pattern of `type => ActualType` */ export type DeferredFunc = (...args: unknown[]) => T; /** * Dynamic Functions, since mongoose 4.13 * @param doc The Document current document */ export type DynamicStringFunc> = (doc: DocumentType) => string; /** Type to keep the "discriminators" options consistent in types */ export type NestedDiscriminatorsFunction = DeferredFunc<(AnyParamConstructor | DiscriminatorObject)[]>; /** Type for enum "values" */ export type EnumValues = Array | ReadonlyArray | { [path: string | number]: string | number | null; }; /** Type for the enum object with custom message*/ export interface EnumObj { values: EnumValues | DeferredFunc; message?: string; } /** Type for combines {@link EnumValues} and {@link @EnumObj} */ export type EnumCombinedType = EnumValues | EnumObj; /** * This Interface for most properties uses "mongoose.SchemaTypeOptions['']", but for some special (or typegoose custom) options, it is not used * * Example: `index` is directly from mongoose, where as `type` is from typegoose */ export interface BasePropOptions { /** * include this value? * @default true (Implicitly) */ select?: mongoose.SchemaTypeOptions['select']; /** * is this value required? * @default false (Implicitly) */ required?: mongoose.SchemaTypeOptions['required']; /** Only accept Values from the Enum(|Array) */ enum?: EnumCombinedType | DeferredFunc | { values: DeferredFunc; message?: string; }; /** * Add "null" to the enum array * Note: Custom Typegoose Option */ addNullToEnum?: boolean; /** * Set Custom "warnMixed" Severity for a specific property * Overwrites Severity set in "modelOptions" for a specific property * Note: Custom Typegoose Option */ allowMixed?: Severity; /** Give the Property a default Value */ default?: mongoose.SchemaTypeOptions['default']; /** Give a Validator RegExp or Function */ validate?: mongoose.SchemaTypeOptions['validate']; /** * Should this property have a "unique" index? * @link https://docs.mongodb.com/manual/indexes/#unique-indexes */ unique?: mongoose.SchemaTypeOptions['unique']; /** * Should this property have an index? * Note: don't use this if you want to do a compound index * @link https://docs.mongodb.com/manual/indexes */ index?: mongoose.SchemaTypeOptions['index']; /** * Should this property have a "sparse" index? * @link https://docs.mongodb.com/manual/indexes/#sparse-indexes */ sparse?: mongoose.SchemaTypeOptions['sparse']; /** * Should this property have an "expires" index? * @link https://docs.mongodb.com/manual/tutorial/expire-data */ expires?: mongoose.SchemaTypeOptions['expires']; /** * Should this property have a "text" index? * @link https://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-text */ text?: mongoose.SchemaTypeOptions['text']; /** Should subdocuments get their own id? * @default true (Implicitly) */ _id?: mongoose.SchemaTypeOptions['_id']; /** * Set a Setter (Non-Virtual) to pre-process your value * (when using get/set both are required) * Please note that the option `type` is required, if get/set saves a different value than what is defined * @param value The Value that needs to get modified * @returns The Value, but modified OR anything * @example * ```ts * function setHello(val: string): string { * return val.toLowerCase() * } * function getHello(val: string): string { * return val.toUpperCase(); * } * class Dummy { * @prop({ set: setHello, get: getHello }) // many options can be used, like required * public hello: string; * } * ``` */ set?: mongoose.SchemaTypeOptions['set']; /** * Set a Getter (Non-Virtual) to Post-process your value * (when using get/set both are required) * Please note that the option `type` is required, if get/set saves a different value than what is defined * @param value The Value that needs to get modified * @returns The Value, but modified OR anything * @example * ```ts * function setHello(val: string): string { * return val.toLowerCase() * } * function getHello(val: string): string { * return val.toUpperCase(); * } * class Dummy { * @prop({ set: setHello, get: getHello }) // many options can be used, like required * public hello: string; * } * ``` */ get?: mongoose.SchemaTypeOptions['get']; /** * This may be needed if get/set is used * (this sets the type how it is saved to the DB) */ type?: DeferredFunc> | DeferredFunc | unknown; /** * Make a property read-only * @example * ```ts * class SomeClass { * @prop({ immutable: true }) * public someprop: Readonly; * } * ``` */ immutable?: mongoose.SchemaTypeOptions['immutable']; /** * Give the Property an alias in the output * * Note: you should include the alias as a variable in the class, but not with a prop decorator * @example * ```ts * class Dummy { * @prop({ alias: "helloWorld" }) * public hello: string; // normal, with @prop * public helloWorld: string; // is just for type Completion, will not be included in the DB * } * ``` */ alias?: mongoose.SchemaTypeOptions['alias']; /** * This option has only an effect when the plugin `mongoose-autopopulate` is used */ autopopulate?: boolean | Function | KeyStringAny; /** Reference another Document (you should use Ref as Prop type) */ ref?: DeferredFunc | DynamicStringFunc> | string | AnyParamConstructor; /** Take the Path and try to resolve it to a Model */ refPath?: string; /** * Set the Nested Discriminators * * Note: "_id: false" as a prop option doesn't work here * * Note: Custom Typegoose Option */ discriminators?: NestedDiscriminatorsFunction; /** * Use option {@link BasePropOptions.type} * @see https://typegoose.github.io/typegoose/docs/api/decorators/prop#map-options * @see https://typegoose.github.io/typegoose/docs/api/decorators/prop#proptype */ of?: never; /** * If true, uses Mongoose's default `_id` settings. Only allowed for ObjectIds * * Note: Copied from mongoose's "index.d.ts"#SchemaTypeOptions */ auto?: mongoose.SchemaTypeOptions['auto']; /** * The default [subtype](http://bsonspec.org/spec.html) associated with this buffer when it is stored in MongoDB. Only allowed for buffer paths * * Note: Copied from mongoose's "index.d.ts"#SchemaTypeOptions */ subtype?: mongoose.SchemaTypeOptions['subtype']; /** * If `true`, Mongoose will skip gathering indexes on subpaths. Only allowed for subdocuments and subdocument arrays. * * Note: Copied from mongoose's "index.d.ts"#SchemaTypeOptions */ excludeIndexes?: mongoose.SchemaTypeOptions['excludeIndexes']; /** * Define a transform function for this individual schema type. * Only called when calling `toJSON()` or `toObject()`. * * Note: Copied from mongoose's "index.d.ts"#SchemaTypeOptions */ transform?: mongoose.SchemaTypeOptions['transform']; [extra: string]: any; } export interface InnerOuterOptions { /** * Use this to define inner-options * Use this if the auto-mapping is not correct or for plugin options * * Please open a new issue if some option is mismatched or not existing / mapped */ innerOptions?: KeyStringAny; /** * Use this to define outer-options * Use this if the auto-mapping is not correct or for plugin options * * Please open a new issue if some option is mismatched or not existing / mapped */ outerOptions?: KeyStringAny; } /** * Internal type for `utils.mapOptions` * @internal */ export interface MappedInnerOuterOptions { /** * Mapped options for the inner of the Type */ inner: NonNullable; /** * Mapped options for the outer of the type */ outer: NonNullable; } /** Options for Array's */ export interface ArrayPropOptions extends BasePropOptions, InnerOuterOptions { /** * How many dimensions this Array should have * (needs to be higher than 0) * * Note: Custom Typegoose Option * @default 1 */ dim?: number; /** * Set if Non-Array values will be cast to an array * * NOTE: This option currently only really affects "DocumentArray" and not normal arrays, https://github.com/Automattic/mongoose/issues/10398 * @see https://mongoosejs.com/docs/api/schemaarray.html#schemaarray_SchemaArray.options * @example * ```ts * new Model({ array: "string" }); * // will be cast to equal * new Model({ array: ["string"] }); * ``` * @default true */ castNonArrays?: boolean; } /** Options For Map's */ export interface MapPropOptions extends BasePropOptions, InnerOuterOptions { } export interface ValidateNumberOptions { /** Only allow numbers that are higher than this */ min?: mongoose.SchemaTypeOptions['min']; /** Only allow numbers lower than this */ max?: mongoose.SchemaTypeOptions['max']; /** Only allow Values from the enum */ enum?: number[]; } export interface ValidateStringOptions { /** Only allow values that match this RegExp */ match?: mongoose.SchemaTypeOptions['match']; /** Only allow Values from the enum */ enum?: string[]; /** Only allow values that have at least this length */ minlength?: mongoose.SchemaTypeOptions['minlength']; /** Only allow values that have at max this length */ maxlength?: mongoose.SchemaTypeOptions['maxlength']; } export interface TransformStringOptions { /** Should it be lowercased before save? */ lowercase?: mongoose.SchemaTypeOptions['lowercase']; /** Should it be uppercased before save? */ uppercase?: mongoose.SchemaTypeOptions['uppercase']; /** Should it be trimmed before save? */ trim?: mongoose.SchemaTypeOptions['trim']; } export interface VirtualOptions { /** Reference another Document (Ref should be used as property type) */ ref: NonNullable; /** Which property(on the current-Class) to match `foreignField` against */ localField: mongoose.VirtualTypeOptions['localField']; /** Which property(on the ref-Class) to match `localField` against */ foreignField: mongoose.VirtualTypeOptions['foreignField']; /** Return as One Document(true) or as Array(false) */ justOne?: mongoose.VirtualTypeOptions['justOne']; /** Return the number of Documents found instead of the actual Documents */ count?: mongoose.VirtualTypeOptions['count']; /** Extra Query Options */ options?: mongoose.VirtualTypeOptions['options']; /** Match Options */ match?: mongoose.VirtualTypeOptions['match']; /** * If you set this to `true`, Mongoose will call any custom getters you defined on this virtual. * * Note: Copied from mongoose's "index.d.ts"#VirtualTypeOptions */ getters?: mongoose.VirtualTypeOptions['getters']; /** * Add a default `limit` to the `populate()` query. * * Note: Copied from mongoose's "index.d.ts"#VirtualTypeOptions */ limit?: mongoose.VirtualTypeOptions['limit']; /** * Add a default `skip` to the `populate()` query. * * Note: Copied from mongoose's "index.d.ts"#VirtualTypeOptions */ skip?: mongoose.VirtualTypeOptions['skip']; /** * For legacy reasons, `limit` with `populate()` may give incorrect results because it only * executes a single query for every document being populated. If you set `perDocumentLimit`, * Mongoose will ensure correct `limit` per document by executing a separate query for each * document to `populate()`. For example, `.find().populate({ path: 'test', perDocumentLimit: 2 })` * will execute 2 additional queries if `.find()` returns 2 documents. * * Note: Copied from mongoose's "index.d.ts"#VirtualTypeOptions */ perDocumentLimit?: mongoose.VirtualTypeOptions['perDocumentLimit']; [extra: string]: any; } export type PropOptionsForNumber = BasePropOptions & ValidateNumberOptions; export type PropOptionsForString = BasePropOptions & TransformStringOptions & ValidateStringOptions; export type RefType = mongoose.RefType; /** * Reference another Model */ export type Ref : mongoose.Types.ObjectId> = mongoose.PopulatedDoc, RawId>; export interface DiscriminatorObject { /** The Class to use */ type: AnyParamConstructor; /** * The Name to differentiate between other classes * Mongoose JSDOC: [value] the string stored in the `discriminatorKey` property. If not specified, Mongoose uses the `name` parameter. * @default {string} The output of "getName" */ value?: string; } export interface IModelOptions { /** An Existing Mongoose Connection */ existingMongoose?: mongoose.Mongoose; /** Supports all Mongoose's Schema Options */ schemaOptions?: mongoose.SchemaOptions; /** An Existing Connection */ existingConnection?: mongoose.Connection; /** Typegoose Custom Options */ options?: ICustomOptions; } /** Interface for just all naming options */ export interface INamingOptions { /** Same as in {@link ICustomOptions} */ customName?: ICustomOptions['customName']; /** Same as in {@link ICustomOptions} */ automaticName?: ICustomOptions['automaticName']; /** Same as in {@link mongoose.SchemaOptions} */ schemaCollection?: mongoose.SchemaOptions['collection']; } /** Typegoose options, mostly for "modelOptions({ options: ICustomOptions })" */ export interface ICustomOptions { /** * Set the modelName of the class. * If it is a function, the function will be executed. The function will override * "automaticName". If "automaticName" is true and "customName" is a string, it * sets a *suffix* instead of the whole name. * @default schemaOptions.collection */ customName?: string | CustomNameFunction; /** * Enable Automatic Name generation of a model * Example: * class with name of "SomeClass" * and option "collection" of "SC" * * will generate the name of "SomeClass_SC" * @default false */ automaticName?: boolean; /** Allow "mongoose.Schema.Types.Mixed"? */ allowMixed?: Severity; /** * Enable Overwriting of the plugins on the "to-be" discriminator schema with the base schema's * Note: this does not actually "merge plugins", it will overwrite the "to-be" discriminator's plugins with the base schema's * If {@link ICustomOptions.enableMergePlugins} and {@link ICustomOptions.enableMergeHooks} are both "false", then the global plugins will be automatically applied by typegoose, see https://github.com/Automattic/mongoose/issues/12696 * @default false */ enableMergePlugins?: boolean; /** * Enable Merging of Hooks * Note: only hooks that can be matched against each-other can be de-duplicated * If {@link ICustomOptions.enableMergePlugins} and {@link ICustomOptions.enableMergeHooks} are both "false", then the global plugins will be automatically applied by typegoose, see https://github.com/Automattic/mongoose/issues/12696 * @default false */ enableMergeHooks?: boolean; /** * Disable all lower indexes than this class (works like `sch.clone().clearIndexes()`) * * This option DOES NOT get inherited * @default false */ disableLowerIndexes?: boolean; /** * Set the Nested Discriminators on the *base* of the Discriminators * * This option can be used over the prop-option to not have to re-define discriminators if used in multiple classes */ discriminators?: NestedDiscriminatorsFunction; /** * Disable Caching for this Class if defined via `@modelOptions`, or disable caching for the `getModelForClass` / `buildSchema` / `getDiscriminatorModelForClass` * Does NOT overwrite global disabled caching * "undefined" and "false" have the same meaning * @default false */ disableCaching?: boolean; } /** Extra options for "_buildSchema" in "schema.ts" */ export interface IBuildSchemaOptions { /** * Add indexes from this class? * will be "false" when "ICustomOptions.disableLowerIndexes" is "true" for some upper class * @default true */ buildIndexes?: boolean; /** * Add search indexes from this class? * @default true */ buildSearchIndexes?: boolean; } /** Type for the Values stored in the Reflection for Properties */ export interface DecoratedPropertyMetadata { /** Prop Options */ options: KeyStringAny; /** The Target Reflection target for getting metadata from keys */ target: AnyParamConstructor; /** Property name */ key: string | symbol; /** What is it for a prop type? */ propType?: PropType; } export type DecoratedPropertyMetadataMap = Map; /** * Alias of "mongoose.IndexOptions" for convenience */ export type IndexOptions = mongoose.IndexOptions; /** * Type for the Values stored in the Reflection for Indexes * @example * ```ts * const indices: IIndexArray[] = Reflect.getMetadata(DecoratorKeys.Index, target) || []; * ``` */ export interface IIndexArray { fields: KeyStringAny; options?: IndexOptions; } /** * Type for the Values stored in the Reflection for Search Indexes * @example * ```ts * const searchIndices: SearchIndexDescription[] = Reflect.getMetadata(DecoratorKeys.SearchIndex, target) || []; * ``` */ export type SearchIndexDescription = mongoose.SearchIndexDescription; /** * Type for the Values stored in the Reflection for Plugins * @example * ```ts * const plugins: IPluginsArray[] = Array.from(Reflect.getMetadata(DecoratorKeys.Plugins, target) ?? []); * ``` */ export interface IPluginsArray { /** The Plugin Function to add */ mongoosePlugin: Func; /** The Plugin's options, which could be anything because mongoose does not enforce it to be a object */ options: any | undefined; } /** * Type for the Values stored in the Reflection for Virtual Populates * @example * ```ts * const virtuals: VirtualPopulateMap = new Map(Reflect.getMetadata(DecoratorKeys.VirtualPopulate, target.constructor) ?? []); * ``` */ export type VirtualPopulateMap = Map>; /** * Gets the signature (parameters with their types, and the return type) of a function type. * * @description Should be used when defining an interface for a class that uses query methods. * * @example * ```ts * function sendMessage(recipient: string, sender: string, priority: number, retryIfFails: boolean) { * // some logic... * return true; * } * * // Both of the following types will be identical. * type SendMessageType = AsQueryMethod; * type SendMessageManualType = (recipient: string, sender: string, priority: number, retryIfFails: boolean) => boolean; * ``` */ export type AsQueryMethod any> = (...args: Parameters) => ReturnType; /** * Helper type to easily set the `this` type in a QueryHelper function * * @example * function findById(this: QueryHelperThis, id: string) { * return this.findOne({ _id: id }); * } */ export type QueryHelperThis, QueryHelpers, S = DocumentType, QueryHelpers>> = mongoose.QueryWithHelpers>; /** * Type for the Values stored in the Reflection for Query Methods * @example * ```ts * const queryMethods: QueryMethodMap = new Map(Reflect.getMetadata(DecoratorKeys.QueryMethod, target) ?? []); * ``` */ export type QueryMethodMap = Map; /** * Type for the Values stored in the Reflection for Nested Discriminators * @example * ```ts * const disMap: NestedDiscriminatorsMap = new Map(Reflect.getMetadata(DecoratorKeys.NestedDiscriminators, target) ?? []); * ``` */ export type NestedDiscriminatorsMap = Map; /** A Helper type to combine both mongoose Hook Option types */ export type HookOptionsEither = mongoose.SchemaPreOptions | mongoose.SchemaPostOptions; /** * Type for the Values stored in the Reflection for Hooks * @example * ```ts * const postHooks: IHooksArray[] = Array.from(Reflect.getMetadata(DecoratorKeys.HooksPost, target) ?? []); * ``` */ export interface IHooksArray { /** The Function to add as a hooks */ func: Func; /** The Method to where this hook gets triggered */ methods: (string | RegExp)[]; /** * Options for Hooks * @see https://mongoosejs.com/docs/middleware.html#naming */ options?: HookOptionsEither; } export interface IGlobalOptions { /** Typegoose Options */ options?: ICustomOptions; /** Schema Options that should get applied to all models */ schemaOptions?: mongoose.SchemaOptions; /** * Global Options for general Typegoose */ globalOptions?: ITypegooseOptions; } export interface ITypegooseOptions { /** * Option to disable caching globally * completely disables the "constructors" and "models" maps * "false" and "undefined" have the same result of enabling caching * @default false */ disableGlobalCaching?: boolean; } /** Interface describing a Object that has a "typegooseName" Function */ export interface IObjectWithTypegooseFunction { typegooseName(): string; } /** For the types that error that seemingly don't have a prototype */ export interface IPrototype { prototype?: any; } /** A Helper Interface for defining a "key" index of "string" and "value" of "any" */ export type KeyStringAny = Record; /** * The Return Type of "utils.getType" */ export interface GetTypeReturn { type: unknown; dim: number; } /** * This type is for lint error "ban-types" where "{}" would be used * This type is separate from "{@link KeyStringAny}" because it has a different meaning */ export type BeAnObject = Record; /** * This type is for mongoose-specific things where {@link BeAnObject} does not work * see https://github.com/Automattic/mongoose/issues/13094 */ export type BeAnyObject = {}; /** Options used for "processProp" */ export interface ProcessPropOptions extends DecoratedPropertyMetadata { /** The target Class's static version */ cl: AnyParamConstructor; } /** * Get all keys from "T" that are a function * does NOT filter out getters / setters */ export type GetFunctionKeys = { [K in keyof T]: T[K] extends (...args: any) => any ? K : never; }[keyof T]; /** * Remove all properties from "T" that are a function * does NOT filter out getters / setters */ export type FilterOutFunctionKeys = Omit>;