UNPKG

4.24 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.DefinitionsFactory = void 0;
4const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
5const mongoose = require("mongoose");
6const type_metadata_storage_1 = require("../storages/type-metadata.storage");
7const BUILT_IN_TYPES = [
8 Boolean,
9 Number,
10 String,
11 Map,
12 Date,
13 Buffer,
14 BigInt,
15];
16class DefinitionsFactory {
17 static createForClass(target) {
18 if (!target) {
19 throw new Error(`Target class "${target}" passed in to the "DefinitionsFactory#createForClass()" method is "undefined".`);
20 }
21 let schemaDefinition = {};
22 let parent = target;
23 while (!(0, shared_utils_1.isUndefined)(parent.prototype)) {
24 if (parent === Function.prototype) {
25 break;
26 }
27 const schemaMetadata = type_metadata_storage_1.TypeMetadataStorage.getSchemaMetadataByTarget(parent);
28 if (!schemaMetadata) {
29 parent = Object.getPrototypeOf(parent);
30 continue;
31 }
32 schemaMetadata.properties?.forEach((item) => {
33 const options = this.inspectTypeDefinition(item.options);
34 this.inspectRef(item.options);
35 schemaDefinition = {
36 [item.propertyKey]: options,
37 ...schemaDefinition,
38 };
39 });
40 parent = Object.getPrototypeOf(parent);
41 }
42 return schemaDefinition;
43 }
44 static inspectTypeDefinition(optionsOrType) {
45 if (typeof optionsOrType === 'function') {
46 if (this.isPrimitive(optionsOrType)) {
47 return optionsOrType;
48 }
49 else if (this.isMongooseSchemaType(optionsOrType)) {
50 return optionsOrType;
51 }
52 const isClass = /^class\s/.test(Function.prototype.toString.call(optionsOrType));
53 optionsOrType = isClass ? optionsOrType : optionsOrType();
54 const schemaDefinition = this.createForClass(optionsOrType);
55 const schemaMetadata = type_metadata_storage_1.TypeMetadataStorage.getSchemaMetadataByTarget(optionsOrType);
56 if (schemaMetadata?.options) {
57 return new mongoose.Schema(schemaDefinition, schemaMetadata.options);
58 }
59 return schemaDefinition;
60 }
61 else if (typeof optionsOrType.type === 'function' || Array.isArray(optionsOrType.type)) {
62 optionsOrType.type = this.inspectTypeDefinition(optionsOrType.type);
63 return optionsOrType;
64 }
65 else if (Array.isArray(optionsOrType)) {
66 return optionsOrType.length > 0
67 ? [this.inspectTypeDefinition(optionsOrType[0])]
68 : optionsOrType;
69 }
70 return optionsOrType;
71 }
72 static inspectRef(optionsOrType) {
73 if (!optionsOrType || typeof optionsOrType !== 'object') {
74 return;
75 }
76 if (typeof optionsOrType?.ref === 'function') {
77 try {
78 const result = optionsOrType.ref();
79 optionsOrType.ref = result?.name ?? result;
80 }
81 catch (err) {
82 if (err instanceof TypeError) {
83 const refClassName = optionsOrType.ref?.name;
84 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}").`);
85 }
86 throw err;
87 }
88 }
89 else if (Array.isArray(optionsOrType.type)) {
90 if (optionsOrType.type.length > 0) {
91 this.inspectRef(optionsOrType.type[0]);
92 }
93 }
94 }
95 static isPrimitive(type) {
96 return BUILT_IN_TYPES.includes(type);
97 }
98 static isMongooseSchemaType(type) {
99 if (!type || !type.prototype) {
100 return false;
101 }
102 const prototype = Object.getPrototypeOf(type.prototype);
103 return prototype && prototype.constructor === mongoose.SchemaType;
104 }
105}
106exports.DefinitionsFactory = DefinitionsFactory;