UNPKG

@typegoose/typegoose

Version:

Define Mongoose models using TypeScript classes

690 lines • 53.1 kB
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.allVirtualoptions = void 0;
exports.isPrimitive = isPrimitive;
exports.isAnRefType = isAnRefType;
exports.isObject = isObject;
exports.isNumber = isNumber;
exports.isString = isString;
exports.getCachedSchema = getCachedSchema;
exports.getClass = getClass;
exports.isWithStringValidate = isWithStringValidate;
exports.isWithStringTransform = isWithStringTransform;
exports.isWithNumberValidate = isWithNumberValidate;
exports.isWithEnumValidate = isWithEnumValidate;
exports.isWithVirtualPOP = isWithVirtualPOP;
exports.includesAllVirtualPOP = includesAllVirtualPOP;
exports.assignMetadata = assignMetadata;
exports.mergeMetadata = mergeMetadata;
exports.mergeSchemaOptions = mergeSchemaOptions;
exports.getRightTarget = getRightTarget;
exports.getName = getName;
exports.isNotDefined = isNotDefined;
exports.mapArrayOptions = mapArrayOptions;
exports.mapOptions = mapOptions;
exports.isTypeMeantToBeArray = isTypeMeantToBeArray;
exports.warnMixed = warnMixed;
exports.isNullOrUndefined = isNullOrUndefined;
exports.getMergedModelOptions = getMergedModelOptions;
exports.createArrayFromDimensions = createArrayFromDimensions;
exports.assertion = assertion;
exports.assertionIsClass = assertionIsClass;
exports.getType = getType;
exports.isConstructor = isConstructor;
exports.warnNotCorrectTypeOptions = warnNotCorrectTypeOptions;
exports.warnNotMatchingExisting = warnNotMatchingExisting;
exports.toStringNoFail = toStringNoFail;
exports.mapModelOptionsToNaming = mapModelOptionsToNaming;
exports.isGlobalCachingEnabled = isGlobalCachingEnabled;
exports.isCachingEnabled = isCachingEnabled;
const tslib_1 = require("tslib");
const lodash_1 = tslib_1.__importDefault(require("lodash"));
const mongoose_1 = tslib_1.__importDefault(require("mongoose"));
const logSettings_1 = require("../logSettings");
const constants_1 = require("./constants");
const data_1 = require("./data");
const errors_1 = require("./errors");
/**
 * Returns true, if the type is included in mongoose.Schema.Types
 * @param Type The Type to test
 * @returns true, if it includes it
 */
function isPrimitive(Type) {
    if (typeof Type?.name === 'string') {
        // try to match "Type.name" with all the Property Names of "mongoose.Schema.Types"
        // (like "String" with "mongoose.Schema.Types.String")
        return (Object.getOwnPropertyNames(mongoose_1.default.Schema.Types).includes(Type.name) ||
            // try to match "Type.name" with all "mongoose.Schema.Types.*.name"
            // (like "SchemaString" with "mongoose.Schema.Types.String.name")
            Object.values(mongoose_1.default.Schema.Types).findIndex((v) => v.name === Type.name) >= 0);
    }
    return false;
}
/**
 * Returns true, if the type is included in mongoose.Schema.Types except the aliases
 * @param Type The Type to test
 * @returns true, if it includes it
 */
function isAnRefType(Type) {
    if (typeof Type?.name === 'string') {
        // Note: this is not done "once" because types can be added as custom types
        const tmp = Object.getOwnPropertyNames(mongoose_1.default.Schema.Types).filter((x) => {
            switch (x) {
                case 'Oid':
                case 'Bool':
                case 'Object':
                case 'Boolean':
                    return false;
                default:
                    return true;
            }
        });
        // try to match "Type.name" with all the Property Names of "mongoose.Schema.Types" except the ones with aliases
        // (like "String" with "mongoose.Schema.Types.String")
        return (tmp.includes(Type.name) ||
            // try to match "Type.name" with all "mongoose.Schema.Types.*.name"
            // (like "SchemaString" with "mongoose.Schema.Types.String.name")
            Object.values(mongoose_1.default.Schema.Types).findIndex((v) => v.name === Type.name) >= 0);
    }
    return false;
}
/**
 * Returns true, if it is an Object
 * Looks down the prototype chain, unless "once" is set to "true"
 * @param Type The Type to test
 * @param once Set to not loop down the prototype chain, default "false"
 * @returns true, if it is an Object
 */
function isObject(Type, once = false) {
    if (typeof Type?.name === 'string') {
        let prototype = Type.prototype;
        // schemaName is "Mixed", whereas name for ".Types.Mixed" is since mongoose 8.0 "SchemaMixed"
        // so use "schemaName" if it exists and use ".name" as a fallback
        let name = Type?.schemaName ?? Type.name;
        while (name) {
            if (name === 'Object' || name === 'Mixed') {
                return true;
            }
            if (once) {
                break;
            }
            prototype = Object.getPrototypeOf(prototype);
            name = prototype?.constructor.name;
        }
    }
    return false;
}
/**
 * Returns true, if it is an Number
 * @param Type The Type to test
 * @returns true, if it is an Number
 */
function isNumber(Type) {
    const name = Type?.name ?? '';
    return name === 'Number' || name === mongoose_1.default.Schema.Types.Number.name;
}
/**
 * Returns true, if it is an String
 * @param Type The Type to test
 * @returns true, if it is an String
 */
function isString(Type) {
    const name = Type?.name ?? '';
    return name === 'String' || name === mongoose_1.default.Schema.Types.String.name;
}
/**
 * Get or init the Cached Schema
 * @param target The Target to get / init the cached schema
 * @returns The Schema to use
 */
function getCachedSchema(target) {
    let schemaReflectTarget = Reflect.getMetadata(constants_1.DecoratorKeys.CachedSchema, target);
    if (isNullOrUndefined(schemaReflectTarget)) {
        Reflect.defineMetadata(constants_1.DecoratorKeys.CachedSchema, {}, target);
        schemaReflectTarget = Reflect.getMetadata(constants_1.DecoratorKeys.CachedSchema, target);
    }
    else if (isNullOrUndefined(Reflect.getOwnMetadata(constants_1.DecoratorKeys.CachedSchema, target))) {
        // set own metadata and clone object, because otherwise on inheritance it would just modify the base class's object, not its own object
        schemaReflectTarget = { ...schemaReflectTarget };
        Reflect.defineMetadata(constants_1.DecoratorKeys.CachedSchema, schemaReflectTarget, target);
    }
    return schemaReflectTarget;
}
/**
 * Get the Class for a number of inputs
 * @param input The Input to fetch the class from
 */
function getClass(input) {
    assertion(isGlobalCachingEnabled(), () => new errors_1.CacheDisabledError('getClass'));
    if (typeof input === 'string') {
        return data_1.constructors.get(input);
    }
    if (typeof input?.typegooseName === 'string') {
        return data_1.constructors.get(input.typegooseName);
    }
    if (typeof input?.typegooseName === 'function') {
        return data_1.constructors.get(input.typegooseName());
    }
    if (typeof input?.constructor?.modelName === 'string') {
        return data_1.constructors.get(input.constructor.modelName);
    }
    throw new errors_1.ResolveTypegooseNameError(input);
}
/**
 * Returns all options found in "options" that are String-validate related
 * @param options The raw Options that may contain the wanted options
 */
function isWithStringValidate(options) {
    return lodash_1.default.intersection(Object.keys(options), ['match', 'minlength', 'maxlength']);
}
/**
 * Returns all options found in "options" that are String-transform related
 * @param options The raw Options
 */
function isWithStringTransform(options) {
    return lodash_1.default.intersection(Object.keys(options), ['lowercase', 'uppercase', 'trim']);
}
/**
 * Returns all options found in "options" that are Number-Validate related
 * @param options The raw Options
 */
function isWithNumberValidate(options) {
    return lodash_1.default.intersection(Object.keys(options), ['min', 'max']);
}
/**
 * Returns all options found in "options" that are Enum Related
 * @param options The raw Options
 */
function isWithEnumValidate(options) {
    return lodash_1.default.intersection(Object.keys(options), ['enum']);
}
const virtualOptions = ['localField', 'foreignField'];
/**
 * Check if the "options" contain any Virtual-Populate related options (excluding "ref" by it self)
 * @param options The raw Options
 */
function isWithVirtualPOP(options) {
    return Object.keys(options).some((v) => virtualOptions.includes(v));
}
exports.allVirtualoptions = virtualOptions.slice(0); // copy "virtualOptions" array
exports.allVirtualoptions.push('ref');
/**
 * Check if all Required options for Virtual-Populate are included in "options"
 * @param options The raw Options
 */
function includesAllVirtualPOP(options) {
    return exports.allVirtualoptions.every((v) => Object.keys(options).includes(v));
}
/**
 * Merge "value" with existing Metadata and save it to the class
 * Difference with "mergeMetadata" is that this one DOES save it to the class
 * Overwrites any existing Metadata that is new in "value"
 * @param key Metadata key to read from and assign the new value to
 * @param value Options to merge with
 * @param cl The Class to read and assign the new metadata to
 * @internal
 */
function assignMetadata(key, value, cl) {
    if (isNullOrUndefined(value)) {
        return value;
    }
    const newValue = mergeMetadata(key, value, cl);
    Reflect.defineMetadata(key, newValue, cl);
    return newValue;
}
/**
 * Merge "value" with existing Metadata
 * Difference with "assignMetadata" is that this one DOES NOT save it to the class
 * Overwrites any existing Metadata that is new in "value"
 * @param key Metadata key to read existing metadata from
 * @param value Option to merge with
 * @param cl The Class to read the metadata from
 * @param getOwn Use "getOwnMetadata" isntead of "getMetadata"
 * @returns Returns the merged output, where "value" overwrites existing Metadata values
 * @internal
 */
function mergeMetadata(key, value, cl, getOwn = false) {
    assertion(typeof key === 'string' && key.length > 0, () => new errors_1.StringLengthExpectedError(1, key, getName(cl), 'key'));
    assertionIsClass(cl);
    let classMetadata = (getOwn ? Reflect.getOwnMetadata(key, cl) : Reflect.getMetadata(key, cl)) ?? {};
    // dont inherit some options if the current class does not have its own metadata
    // this is somewhat hacky
    if (key === constants_1.DecoratorKeys.ModelOptions && !Reflect.hasOwnMetadata(key, cl) && 'options' in classMetadata) {
        // this has to be done, because otherwise it will be deleted on the original
        classMetadata = { ...classMetadata };
        classMetadata.options = { ...classMetadata.options };
        // dont inherit "disableLowerIndexes" because that would otherwise be inherited and so disable all indexes if inherited, not just from where it was set
        delete classMetadata?.options?.disableLowerIndexes;
    }
    return mergeObjects(classMetadata, value);
}
/**
 * Merge 2 different objects into a new object, with {@link customMerger} (deep merge).
 * @param src1 Properties overlapping with `src2` will be overwritten by `src2`
 * @param src2 Properties overlapping with `src1` will be overwritten
 */
function mergeObjects(src1, src2) {
    // Please don't remove the other values from the function, even when unused - it is made to be clear what is what
    return lodash_1.default.mergeWith({}, src1, src2, (_objValue, srcValue, ckey) => customMerger(ckey, srcValue));
}
/**
 * Used for lodash customizers (cloneWith, cloneDeepWith, mergeWith)
 * @param key the key of the current object
 * @param val the value of the object that should get returned for "existingMongoose" & "existingConnection"
 */
function customMerger(key, val) {
    if (typeof key !== 'string') {
        return undefined;
    }
    if (/^(existingMongoose|existingConnection)$/.test(key)) {
        return val;
    }
    return undefined;
}
/**
 * Merge only schemaOptions from ModelOptions of the class
 * @param value The value to use
 * @param cl The Class to get the values from
 */
function mergeSchemaOptions(value, cl) {
    return mergeMetadata(constants_1.DecoratorKeys.ModelOptions, { schemaOptions: value }, cl).schemaOptions;
}
/**
 * Tries to return the right target
 * if target.constructor.name is "Function", return "target", otherwise "target.constructor"
 * @param target The target to determine
 */
function getRightTarget(target) {
    return target.constructor?.name === 'Function' ? target : target.constructor;
}
/**
 * Get the Class's final name
 * (combines all available options to generate a name)
 * @param cl The Class to get the name for
 * @param overwriteNaming Overwrite naming options used for generating the name
 */
function getName(cl, overwriteNaming) {
    // this case (cl being undefined / null) can happen when type casting (or type being "any") happened and wanting to throw a Error (and there using "getName" to help)
    // check if input variable is undefined, if it is throw a error (cannot be combined with the error below because of "getRightTarget")
    assertion(!isNullOrUndefined(cl), () => new errors_1.NoValidClassError(cl));
    const ctor = getRightTarget(cl);
    assertion(isConstructor(ctor), () => new errors_1.NoValidClassError(ctor));
    const options = Reflect.getMetadata(constants_1.DecoratorKeys.ModelOptions, ctor) ?? {};
    const baseName = ctor.name;
    const customName = overwriteNaming?.customName ?? options.options?.customName;
    if (typeof customName === 'function') {
        const name = customName(options);
        assertion(typeof name === 'string' && name.length > 0, () => new errors_1.StringLengthExpectedError(1, name, baseName, 'options.customName(function)'));
        return name;
    }
    const automaticName = overwriteNaming?.automaticName ?? options.options?.automaticName;
    if (automaticName) {
        const suffix = customName ?? overwriteNaming?.schemaCollection ?? options.schemaOptions?.collection;
        return !isNullOrUndefined(suffix) ? `${baseName}_${suffix}` : baseName;
    }
    if (isNullOrUndefined(customName)) {
        return baseName;
    }
    assertion(typeof customName === 'string' && customName.length > 0, () => new errors_1.StringLengthExpectedError(1, customName, baseName, 'options.customName'));
    return customName;
}
/**
 * Check if "Type" is a class and if it is already in "schemas"
 * @param Type The Type to check
 */
function isNotDefined(Type) {
    return (typeof Type === 'function' &&
        !isPrimitive(Type) &&
        Type !== Object &&
        isNullOrUndefined(Reflect.getMetadata(constants_1.DecoratorKeys.CachedSchema, Type)));
}
/**
 * Map Options to "inner" & "outer"
 * -> inner: means inner of "type: [{here})"
 * -> outer: means outer of "type: [{}], here"
 *
 * Specific to Arrays
 * @param rawOptions The raw options
 * @param Type The Type of the array
 * @param target The Target class
 * @param pkey Key of the Property
 * @param loggerType Type to use for logging
 * @param extraInner Extra Options to Mad explicitly to "inner"
 */
function mapArrayOptions(rawOptions, Type, target, pkey, modelOptions, loggerType, extraInner) {
    logSettings_1.logger.debug('mapArrayOptions called');
    loggerType = loggerType ?? Type;
    if (!(Type instanceof mongoose_1.default.Schema)) {
        loggerType = Type;
    }
    const dim = rawOptions.dim; // needed, otherwise it will be included (and not removed) in the returnObject
    delete rawOptions.dim;
    const mapped = mapOptions(rawOptions, Type, target, pkey, modelOptions, constants_1.PropType.ARRAY, loggerType);
    /** The Object that gets returned */
    const returnObject = {
        ...mapped.outer,
        type: [
            {
                type: Type,
                ...mapped.inner,
                ...extraInner,
            },
        ],
    };
    rawOptions.dim = dim; // re-add for "createArrayFromDimensions"
    returnObject.type = createArrayFromDimensions(rawOptions, returnObject.type, getName(target), pkey);
    if (loggerType) {
        logSettings_1.logger.debug('(Array) Final mapped Options for Type "%s"', getName(loggerType), returnObject);
    }
    return returnObject;
}
/**
 * Map Options to "inner" & "outer"
 * @param rawOptions The raw options
 * @param Type The Type of the array
 * @param target The Target class
 * @param pkey Key of the Property
 * @param propType Property type for the outer options
 * @param loggerType Type to use for logging
 */
function mapOptions(rawOptions, Type, target, pkey, modelOptions, propType, loggerType) {
    logSettings_1.logger.debug('mapOptions called');
    loggerType = loggerType ?? Type;
    /** The Object that gets returned */
    const ret = {
        inner: {},
        outer: {},
    };
    // if Type is not a Schema, try to convert js type to mongoose type (Object => Mixed)
    if (!(Type instanceof mongoose_1.default.Schema)) {
        // set the loggerType to the js type
        loggerType = Type;
        const loggerTypeName = getName(loggerType);
        if (loggerTypeName in mongoose_1.default.Schema.Types) {
            logSettings_1.logger.info('Converting "%s" to mongoose Type', loggerTypeName);
            Type = mongoose_1.default.Schema.Types[loggerTypeName];
            if (Type === mongoose_1.default.Schema.Types.Mixed) {
                warnMixed(target, pkey, modelOptions);
            }
        }
    }
    if (isNullOrUndefined(loggerType)) {
        logSettings_1.logger.info('mapOptions loggerType is undefined!');
    }
    /** The OptionsConstructor to use */
    let OptionsCTOR = Type?.prototype?.OptionsConstructor;
    if (Type instanceof mongoose_1.default.Schema) {
        OptionsCTOR = mongoose_1.default.Schema.Types.Subdocument.prototype.OptionsConstructor;
    }
    assertion(!isNullOrUndefined(OptionsCTOR), () => new errors_1.InvalidOptionsConstructorError(getName(target), pkey, loggerType));
    const options = Object.assign({}, rawOptions); // for sanity
    // Try to map options to the outer type first, to correctly map things like "default" and "required" on Map & Array
    let OuterOptionsCTOR = undefined;
    if (propType === constants_1.PropType.ARRAY) {
        OuterOptionsCTOR = mongoose_1.default.Schema.Types.Array.prototype.OptionsConstructor;
    }
    else if (propType === constants_1.PropType.MAP) {
        OuterOptionsCTOR = mongoose_1.default.Schema.Types.Map.prototype.OptionsConstructor;
    }
    // test that the OptionsCTOR extends, or is "SchemaTypeOptions"
    // this is necessary due to `class A {}; class B extends A {}; B.prototype instanceof A === true;`
    // but not due to `class A {}; A instanceof A === false;`
    if (OptionsCTOR.prototype instanceof mongoose_1.default.SchemaTypeOptions || OptionsCTOR === mongoose_1.default.SchemaTypeOptions) {
        for (const [key, value] of Object.entries(options)) {
            if (OuterOptionsCTOR && Object.getOwnPropertyNames(OuterOptionsCTOR).includes(key)) {
                ret.outer[key] = value;
            }
            else if (Object.getOwnPropertyNames(OptionsCTOR.prototype).includes(key)) {
                ret.inner[key] = value;
            }
            else {
                ret.outer[key] = value;
            }
        }
    }
    else {
        if (loggerType) {
            logSettings_1.logger.info('The Type "%s" has a property "OptionsConstructor" but it does not extend "SchemaTypeOptions"', getName(loggerType));
        }
        // later options get deleted, but we dont want to actually delete on `options` itself
        ret.outer = Object.assign({}, options);
    }
    if (typeof options?.innerOptions === 'object') {
        delete ret.outer.innerOptions;
        for (const [key, value] of Object.entries(options.innerOptions)) {
            ret.inner[key] = value;
        }
    }
    if (typeof options?.outerOptions === 'object') {
        delete ret.outer.outerOptions;
        for (const [key, value] of Object.entries(options.outerOptions)) {
            ret.outer[key] = value;
        }
    }
    if (loggerType) {
        logSettings_1.logger.debug('Final mapped Options for Type "%s"', getName(loggerType), ret);
    }
    return ret;
}
/**
 * Check if the current Type is meant to be a Array
 * @param rawOptions The raw options
 */
function isTypeMeantToBeArray(rawOptions) {
    // check if the "dim" option exists, if yes the type is meant to be a array in the end
    return !isNullOrUndefined(rawOptions) && !isNullOrUndefined(rawOptions.dim) && typeof rawOptions.dim === 'number' && rawOptions.dim > 0;
}
/**
 * Warn, Error or Allow if an mixed type is set
 * -> this function exists for de-duplication
 * @param target Target Class
 * @param key Property key
 */
function warnMixed(target, key, modelOptions) {
    const name = getName(target);
    const rawOptions = Reflect.getMetadata(constants_1.DecoratorKeys.PropCache, target);
    const setSeverity = rawOptions?.get(key)?.options?.allowMixed ?? modelOptions.options?.allowMixed ?? constants_1.Severity.WARN;
    logSettings_1.logger.debug(`setSeverity for "${name}.${key}" is "${setSeverity}"`);
    switch (setSeverity) {
        default:
        case constants_1.Severity.WARN:
            logSettings_1.logger.warn('Setting "Mixed" for property "%s.%s"\nLook here for how to disable this message: https://typegoose.github.io/typegoose/docs/api/decorators/model-options/#allowmixed', name, key);
            break;
        case constants_1.Severity.ALLOW:
            break;
        case constants_1.Severity.ERROR:
            throw new TypeError(`Setting "Mixed" is not allowed! (${name}, ${key}) [E017]`);
    }
    return; // always return, if "allowMixed" is not "ERROR"
}
/**
 * Check if "val" is "null" to "undefined"
 * This Function exists because since node 4.0.0 the internal util.is* functions got deprecated
 * @param val Any value to test if null or undefined
 */
function isNullOrUndefined(val) {
    return val === null || val === undefined;
}
/**
 * Consistently get the "ModelOptions", merged with.
 *
 * Property (deep) priority list:
 * input "rawOptions" > decorator `ModelOptions` > globalOptions
 * @param rawOptions Options to merge(-overwrite) all previous options
 * @param cl The Class to get / set the ModelOptions on
 * @param getOwn use "getOwnMetadata" instead of "getMetadata"
 * @returns A ModelOptions object
 */
function getMergedModelOptions(rawOptions, cl, getOwn = false) {
    let opt = typeof rawOptions === 'object' ? rawOptions : {};
    // dont skip merging if "getOwn" is "true"
    if (!(opt?.[constants_1.AlreadyMerged] && !getOwn)) {
        opt = mergeMetadata(constants_1.DecoratorKeys.ModelOptions, opt, cl, getOwn);
        logSettings_1.logger.info('Applying global Schema Options to "%s"', getName(cl));
        opt = mergeObjects(lodash_1.default.omit(data_1.globalOptions, 'globalOptions'), opt);
        opt[constants_1.AlreadyMerged] = true;
    }
    return opt;
}
/**
 * Loop over "dimensions" and create an array from that
 * @param rawOptions baseProp's rawOptions
 * @param extra What is actually in the deepest array
 * @param name name of the target for better error logging
 * @param key key of target-key for better error logging
 */
function createArrayFromDimensions(rawOptions, extra, name, key) {
    // dimensions start at 1 (not 0)
    const dim = typeof rawOptions.dim === 'number' ? rawOptions.dim : 1;
    if (dim < 1) {
        throw new RangeError(`"dim" needs to be higher than 0 (${name}.${key}) [E018]`);
    }
    delete rawOptions.dim; // delete this property to not actually put it as an option
    logSettings_1.logger.info('createArrayFromDimensions called with %d dimensions', dim);
    let retArray = Array.isArray(extra) ? extra : [extra];
    // index starts at 1 because "retArray" is already once wrapped in an array
    for (let index = 1; index < dim; index++) {
        retArray = [retArray];
    }
    return retArray;
}
/**
 * Assert a condition, if "false" throw error
 * Note: it is not named "assert" to differentiate between node and jest types
 *
 * Note: "error" can be a function to not execute the constructor when not needed
 * @param cond The Condition to check
 * @param error A Custom Error to throw or a function that returns a Error
 */
function assertion(cond, error) {
    if (!cond) {
        throw typeof error === 'function' ? error() : (error ?? new errors_1.AssertionFallbackError());
    }
}
/**
 * Assert if "val" is an function (constructor for classes)
 * @param val Value to test
 */
function assertionIsClass(val) {
    assertion(isConstructor(val), () => new errors_1.NoValidClassError(val));
}
/**
 * Get Type, if input is an arrow-function, execute it and return the result
 * @param typeOrFunc Function or Type
 * @param returnLastFoundArray Return the last found array (used for something like PropOptions.discriminators)
 */
function getType(typeOrFunc, returnLastFoundArray = false) {
    const returnObject = {
        type: typeOrFunc,
        dim: 0,
    };
    if (typeof returnObject.type === 'function' && !isConstructor(returnObject.type)) {
        returnObject.type = returnObject.type();
    }
    function getDepth() {
        if (returnObject.dim > 100) {
            // this is arbitrary, but why would anyone have more than 10 nested arrays anyway?
            throw new Error('getDepth recursed too much (dim > 100)');
        }
        if (Array.isArray(returnObject.type)) {
            returnObject.dim++;
            if (returnLastFoundArray && !Array.isArray(returnObject.type[0])) {
                return;
            }
            returnObject.type = returnObject.type[0];
            getDepth();
        }
    }
    getDepth();
    logSettings_1.logger.debug('Final getType: dim: %s, type:', returnObject.dim, returnObject.type);
    return returnObject;
}
/**
 * Is the provided input an class with an constructor?
 * @param obj The Value to test
 */
function isConstructor(obj) {
    return (typeof obj === 'function' && !isNullOrUndefined(obj.prototype?.constructor?.name)
    // TODO: maybe change to the following implementation, because it would be more correct, but would involve some refactoring
    // if the js environment is spec-compliant, then the following should always work
    // /^class\s/.test(Function.prototype.toString.call(obj))
    );
}
// /**
//  * Execute util.deprecate or when "process" does not exist use "console.log"
//  * (if "process" does not exist, the codes are not cached, and are always logged again)
//  * This Function is here to try to make typegoose compatible with the browser (see https://github.com/typegoose/typegoose/issues/33)
//  */
// export function deprecate<T extends Function>(fn: T, message: string, code: string): T {
//   if (!isNullOrUndefined(process)) {
//     // eslint-disable-next-line @typescript-eslint/no-var-requires
//     return require('util').deprecate(fn, message, code);
//   }
//   console.log(`[${code}] DeprecationWarning: ${message}`);
//   return fn;
// }
/**
 * Logs an warning if "included > 0" that the options of not the current type are included
 * @param name Name of the Class
 * @param key Name of the Currently Processed key
 * @param type Name of the Expected Type
 * @param extra Extra string to be included
 * @param included Included Options to be listed
 */
function warnNotCorrectTypeOptions(name, key, type, extra, included) {
    // this "if" is in this function to de-duplicate code
    if (included.length > 0) {
        logSettings_1.logger.warn(`Type of "${name}.${key}" is not ${type}, but includes the following ${extra} options [W001]:\n` + `  [${included.join(', ')}]`);
    }
}
/**
 * Logs a warning for Discriminator setting a different "existing*" property than the base
 * @param fromName Name of the Base Model
 * @param clName Name of the Discriminator's class
 * @param property The property defined that does not match
 */
function warnNotMatchingExisting(fromName, clName, property) {
    logSettings_1.logger.warn(`Property "${property}" was defined on "${clName}", but is different from discriminator base "${fromName}", which is not supported! [W002]`);
}
/**
 * Try to convert input "value" to a String, without it failing
 * @param value The Value to convert to String
 * @returns A String, either "value.toString" or a placeholder
 */
function toStringNoFail(value) {
    try {
        return String(value);
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
    }
    catch (_) {
        return '(Error: Converting value to String failed)';
    }
}
/**
 * Map options from {@link IModelOptions} to {@link INamingOptions}
 * @param options The options to map
 * @returns Always a object, contains mapped options from {@link IModelOptions}
 */
function mapModelOptionsToNaming(options) {
    const mappedNaming = { ...options?.options }; // this copies more than necessary, but works because most of the options are from there
    if (!isNullOrUndefined(options?.schemaOptions?.collection)) {
        mappedNaming.schemaCollection = options?.schemaOptions?.collection;
    }
    return mappedNaming;
}
/**
 * Helper function to check if caching is enabled globally
 * @returns "true" if caching is enabled or "false" if disabled
 */
function isGlobalCachingEnabled() {
    return !(data_1.globalOptions.globalOptions?.disableGlobalCaching === true);
}
/**
 * Helper function to check if caching is enabled globally AND by options
 * @param opt The caching option (from IModelOptions)
 * @returns "true" if caching is enabled or "false" if disabled
 */
function isCachingEnabled(opt) {
    return isGlobalCachingEnabled() && !(opt === true);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW50ZXJuYWwvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBbUNBLGtDQWFDO0FBT0Qsa0NBMEJDO0FBU0QsNEJBb0JDO0FBT0QsNEJBSUM7QUFPRCw0QkFJQztBQU9ELDBDQWFDO0FBTUQsNEJBcUJDO0FBTUQsb0RBRUM7QUFNRCxzREFFQztBQU1ELG9EQUVDO0FBTUQsZ0RBRUM7QUFRRCw0Q0FFQztBQVNELHNEQUVDO0FBV0Qsd0NBU0M7QUFhRCxzQ0FrQkM7QUFpQ0QsZ0RBRUM7QUFPRCx3Q0FFQztBQVFELDBCQXdDQztBQU1ELG9DQU9DO0FBZUQsMENBMENDO0FBV0QsZ0NBa0dDO0FBTUQsb0RBR0M7QUFRRCw4QkF5QkM7QUFPRCw4Q0FFQztBQVlELHNEQWtCQztBQVNELDhEQWtCQztBQVVELDhCQUlDO0FBTUQsNENBRUM7QUFPRCwwQkFnQ0M7QUFNRCxzQ0FPQztBQTBCRCw4REFPQztBQVFELDBEQUlDO0FBT0Qsd0NBT0M7QUFPRCwwREFRQztBQU1ELHdEQUVDO0FBT0QsNENBRUM7O0FBM3pCRCw0REFBNEI7QUFDNUIsZ0VBQWdDO0FBQ2hDLGdEQUF3QztBQWlCeEMsMkNBQStFO0FBQy9FLGlDQUFxRDtBQUNyRCxxQ0FPa0I7QUFFbEI7Ozs7R0FJRztBQUNILFNBQWdCLFdBQVcsQ0FBQyxJQUFTO0lBQ25DLElBQUksT0FBTyxJQUFJLEVBQUUsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQ25DLGtGQUFrRjtRQUNsRixzREFBc0Q7UUFDdEQsT0FBTyxDQUNMLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxrQkFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUNyRSxtRUFBbUU7WUFDbkUsaUVBQWlFO1lBQ2pFLE1BQU0sQ0FBQyxNQUFNLENBQUMsa0JBQVEsQ0FBQyxNQUFNLENBQUMs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