@nestjs/mongoose
Version:
Nest - modern, fast, powerful node.js web framework (@mongoose)
107 lines (106 loc) • 4.24 kB
JavaScript
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;
;