UNPKG

@typegoose/typegoose

Version:

Define Mongoose models using TypeScript classes

158 lines 15.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports._buildSchema = _buildSchema; const tslib_1 = require("tslib"); const mongoose_1 = tslib_1.__importDefault(require("mongoose")); const logSettings_1 = require("../logSettings"); const typegoose_1 = require("../typegoose"); const constants_1 = require("./constants"); const data_1 = require("./data"); const errors_1 = require("./errors"); const processProp_1 = require("./processProp"); const utils_1 = require("./utils"); /** * Internal Schema Builder for Classes * This Function should not be used directly outside of typegoose internals, use "buildSchema" from typegoose.ts directly * @param cl The Class to build a Model from * @param origSch A Schema to clone and extend onto * @param opt Overwrite SchemaOptions (Merged with Decorator Options) * @param isFinalSchema Set if this Schema is the final (top-level) to build, only when "true" are discriminators, hooks, virtuals, etc applied * @param overwriteNaming Overwrite options for name generation * @param extraOptions Extra options to affect what needs to be done * @returns Returns the Build Schema * @private */ function _buildSchema(cl, origSch, opt, isFinalSchema = true, overwriteNaming, extraOptions) { (0, utils_1.assertionIsClass)(cl); const mergedOptions = (0, utils_1.getMergedModelOptions)(opt, cl); const finalName = (0, utils_1.getName)(cl, overwriteNaming); logSettings_1.logger.debug('_buildSchema Called for %s with options:', finalName, mergedOptions); /** Simplify the usage */ const Schema = mongoose_1.default.Schema; const schemaOptions = mergedOptions.schemaOptions ?? {}; const decorators = Reflect.getMetadata(constants_1.DecoratorKeys.PropCache, cl.prototype); if (!(0, utils_1.isNullOrUndefined)(decorators)) { for (const decorator of decorators.values()) { (0, processProp_1.processProp)({ ...decorator, cl: cl, mergedOptions }); } } let sch; { const schemaReflectTarget = (0, utils_1.getCachedSchema)(cl); if (!(origSch instanceof Schema)) { sch = new Schema(schemaReflectTarget, schemaOptions); } else { sch = origSch.clone(); sch.add(schemaReflectTarget); } } sch.loadClass(cl); // in the block below are all the things that need to be done for each class, not just the final schema // for example when using "getOwnMetadata" over "getMetadata" (and having a clone in there) { /** Get Metadata for indices */ const indices = Reflect.getOwnMetadata(constants_1.DecoratorKeys.Index, cl); const buildIndexes = typeof extraOptions?.buildIndexes === 'boolean' ? extraOptions?.buildIndexes : true; if (Array.isArray(indices) && buildIndexes) { for (const index of indices) { logSettings_1.logger.debug('Applying Index:', index); sch.index(index.fields, index.options); } } } { /** Get Metadata for Search Indices */ const searchIndices = Reflect.getOwnMetadata(constants_1.DecoratorKeys.SearchIndex, cl); const buildSearchIndexes = typeof extraOptions?.buildSearchIndexes === 'boolean' ? extraOptions?.buildSearchIndexes : true; if (buildSearchIndexes && Array.isArray(searchIndices)) { for (const index of searchIndices) { logSettings_1.logger.debug('Applying Search Index:', index); sch.searchIndex(index); } } } if (isFinalSchema) { /** Get Metadata for Nested Discriminators */ const disMap = Reflect.getMetadata(constants_1.DecoratorKeys.NestedDiscriminators, cl); if (disMap instanceof Map) { for (const [key, discriminators] of disMap) { logSettings_1.logger.debug('Applying Nested Discriminators for:', key, discriminators); const path = sch.path(key); (0, utils_1.assertion)(!(0, utils_1.isNullOrUndefined)(path), () => new errors_1.PathNotInSchemaError(finalName, key)); (0, utils_1.assertion)(typeof path.discriminator === 'function', () => new errors_1.NoDiscriminatorFunctionError(finalName, key)); for (const { type: child, value: childName } of discriminators) { const childSch = (0, utils_1.getName)(child) === finalName ? sch : (0, typegoose_1.buildSchema)(child); const discriminatorKey = childSch.get('discriminatorKey'); if (!!discriminatorKey && childSch.path(discriminatorKey)) { // skip this check, otherwise "extends DiscriminatorBase" would not be allowed (discriminators cannot have the discriminator key defined multiple times) childSch.paths[discriminatorKey].options.$skipDiscriminatorCheck = true; } path.discriminator((0, utils_1.getName)(child), childSch, childName); } } } // Hooks { /** Get Metadata for PreHooks */ const preHooks = Reflect.getMetadata(constants_1.DecoratorKeys.HooksPre, cl); if (Array.isArray(preHooks)) { // "as any" is used here because mongoose explicitly types out many methods, but the input type (from IHooksArray) is a combination of multiple types preHooks.forEach((obj) => callCorrectSignature(sch, 'pre', obj)); } /** Get Metadata for PreHooks */ const postHooks = Reflect.getMetadata(constants_1.DecoratorKeys.HooksPost, cl); if (Array.isArray(postHooks)) { // "as any" is used here because mongoose explicitly types out many methods, but the input type (from IHooksArray) is a combination of multiple types postHooks.forEach((obj) => callCorrectSignature(sch, 'post', obj)); } } /** Get Metadata for Virtual Populates */ const virtuals = Reflect.getMetadata(constants_1.DecoratorKeys.VirtualPopulate, cl); if (virtuals instanceof Map) { for (const [key, options] of virtuals) { logSettings_1.logger.debug('Applying Virtual Populates:', key, options); sch.virtual(key, options); } } /** Get Metadata for Query Methods */ const queryMethods = Reflect.getMetadata(constants_1.DecoratorKeys.QueryMethod, cl); if (queryMethods instanceof Map) { for (const [funcName, func] of queryMethods) { logSettings_1.logger.debug('Applying Query Method:', funcName, func); sch.query[funcName] = func; } } /** Get Metadata for indices */ const plugins = Reflect.getMetadata(constants_1.DecoratorKeys.Plugins, cl); if (Array.isArray(plugins)) { for (const plugin of plugins) { logSettings_1.logger.debug('Applying Plugin:', plugin); sch.plugin(plugin.mongoosePlugin, plugin.options); } } // this method is to get the typegoose name of the model/class if it is user-handled (like buildSchema, then manually mongoose.model) sch.method('typegooseName', () => { return finalName; }); } if ((0, utils_1.isCachingEnabled)(mergedOptions.options?.disableCaching)) { // add the class to the constructors map data_1.constructors.set(finalName, cl); } return sch; } /** * Helper function to call the correct signature for a given "fnToCall" (pre / post hooks) * @param fnToCall The function to call (sch.pre / sch.post) * @param obj The object to call as arguments with */ function callCorrectSignature(sch, fn, obj) { // we have to bind "sch", otherwise "this" will not be defined in the "pre / post" functions const fnToCall = (fn === 'pre' ? sch.pre : sch.post).bind(sch); if (!(0, utils_1.isNullOrUndefined)(obj.options)) { return fnToCall(obj.methods, obj.options, obj.func); } return fnToCall(obj.methods, obj.func); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZW1hLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ludGVybmFsL3NjaGVtYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQW1DQSxvQ0ErSkM7O0FBbE1ELGdFQUFnQztBQUNoQyxnREFBd0M7QUFDeEMsNENBQTJDO0FBZTNDLDJDQUE0QztBQUM1QyxpQ0FBc0M7QUFDdEMscUNBQThFO0FBQzlFLCtDQUE0QztBQUM1QyxtQ0FBNEk7QUFFNUk7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxTQUFnQixZQUFZLENBQzFCLEVBQUssRUFDTCxPQUE4QixFQUM5QixHQUFtQixFQUNuQixnQkFBeUIsSUFBSSxFQUM3QixlQUFnQyxFQUNoQyxZQUFrQztJQUVsQyxJQUFBLHdCQUFnQixFQUFDLEVBQUUsQ0FBQyxDQUFDO0lBRXJCLE1BQU0sYUFBYSxHQUFHLElBQUEsNkJBQXFCLEVBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRXJELE1BQU0sU0FBUyxHQUFHLElBQUEsZUFBTyxFQUFDLEVBQUUsRUFBRSxlQUFlLENBQUMsQ0FBQztJQUUvQyxvQkFBTSxDQUFDLEtBQUssQ0FBQywwQ0FBMEMsRUFBRSxTQUFTLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFFbkYseUJBQXlCO0lBQ3pCLE1BQU0sTUFBTSxHQUFHLGtCQUFRLENBQUMsTUFBTSxDQUFDO0lBQy9CLE1BQU0sYUFBYSxHQUFHLGFBQWEsQ0FBQyxhQUFhLElBQUksRUFBRSxDQUFDO0lBRXhELE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMseUJBQWEsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBaUMsQ0FBQztJQUU5RyxJQUFJLENBQUMsSUFBQSx5QkFBaUIsRUFBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQ25DLEtBQUssTUFBTSxTQUFTLElBQUksVUFBVSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7WUFDNUMsSUFBQSx5QkFBVyxFQUFDLEVB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