@typegoose/typegoose
Version:
Define Mongoose models using TypeScript classes
158 lines • 15.8 kB
JavaScript
"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 });
}
}
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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