UNPKG

@nestjs/mongoose

Version:

Nest - modern, fast, powerful node.js web framework (@mongoose)

107 lines (106 loc) 4.24 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DefinitionsFactory = void 0; const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); const mongoose = require("mongoose"); const type_metadata_storage_1 = require("../storages/type-metadata.storage"); const BUILT_IN_TYPES = [ Boolean, Number, String, Map, Date, Buffer, BigInt, ]; class DefinitionsFactory { static createForClass(target) { if (!target) { throw new Error(`Target class "${target}" passed in to the "DefinitionsFactory#createForClass()" method is "undefined".`); } let schemaDefinition = {}; let parent = target; while (!(0, shared_utils_1.isUndefined)(parent.prototype)) { if (parent === Function.prototype) { break; } const schemaMetadata = type_metadata_storage_1.TypeMetadataStorage.getSchemaMetadataByTarget(parent); if (!schemaMetadata) { parent = Object.getPrototypeOf(parent); continue; } schemaMetadata.properties?.forEach((item) => { const options = this.inspectTypeDefinition(item.options); this.inspectRef(item.options); schemaDefinition = { [item.propertyKey]: options, ...schemaDefinition, }; }); parent = Object.getPrototypeOf(parent); } return schemaDefinition; } static inspectTypeDefinition(optionsOrType) { if (typeof optionsOrType === 'function') { if (this.isPrimitive(optionsOrType)) { return optionsOrType; } else if (this.isMongooseSchemaType(optionsOrType)) { return optionsOrType; } const isClass = /^class\s/.test(Function.prototype.toString.call(optionsOrType)); optionsOrType = isClass ? optionsOrType : optionsOrType(); const schemaDefinition = this.createForClass(optionsOrType); const schemaMetadata = type_metadata_storage_1.TypeMetadataStorage.getSchemaMetadataByTarget(optionsOrType); if (schemaMetadata?.options) { return new mongoose.Schema(schemaDefinition, schemaMetadata.options); } return schemaDefinition; } else if (typeof optionsOrType.type === 'function' || Array.isArray(optionsOrType.type)) { optionsOrType.type = this.inspectTypeDefinition(optionsOrType.type); return optionsOrType; } else if (Array.isArray(optionsOrType)) { return optionsOrType.length > 0 ? [this.inspectTypeDefinition(optionsOrType[0])] : optionsOrType; } return optionsOrType; } static inspectRef(optionsOrType) { if (!optionsOrType || typeof optionsOrType !== 'object') { return; } if (typeof optionsOrType?.ref === 'function') { try { const result = optionsOrType.ref(); optionsOrType.ref = result?.name ?? result; } catch (err) { if (err instanceof TypeError) { const refClassName = optionsOrType.ref?.name; throw new Error(`Unsupported syntax: Class constructor "${refClassName}" cannot be invoked without 'new'. Make sure to wrap your class reference in an arrow function (for example, "ref: () => ${refClassName}").`); } throw err; } } else if (Array.isArray(optionsOrType.type)) { if (optionsOrType.type.length > 0) { this.inspectRef(optionsOrType.type[0]); } } } static isPrimitive(type) { return BUILT_IN_TYPES.includes(type); } static isMongooseSchemaType(type) { if (!type || !type.prototype) { return false; } const prototype = Object.getPrototypeOf(type.prototype); return prototype && prototype.constructor === mongoose.SchemaType; } } exports.DefinitionsFactory = DefinitionsFactory;