1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports._buildSchema = void 0;
|
4 | const mongoose = require("mongoose");
|
5 | const logSettings_1 = require("../logSettings");
|
6 | const typegoose_1 = require("../typegoose");
|
7 | const constants_1 = require("./constants");
|
8 | const data_1 = require("./data");
|
9 | const errors_1 = require("./errors");
|
10 | const processProp_1 = require("./processProp");
|
11 | const utils_1 = require("./utils");
|
12 | /**
|
13 | * Internal Schema Builder for Classes
|
14 | * This Function should not be used directly outside of typegoose internals, use "buildSchema" from typegoose.ts directly
|
15 | * @param cl The Class to build a Model from
|
16 | * @param origSch A Schema to clone and extend onto
|
17 | * @param opt Overwrite SchemaOptions (Merged with Decorator Options)
|
18 | * @param isFinalSchema Set if this Schema is the final (top-level) to build, only when "true" are discriminators, hooks, virtuals, etc applied
|
19 | * @param overwriteNaming Overwrite options for name generation
|
20 | * @param extraOptions Extra options to affect what needs to be done
|
21 | * @returns Returns the Build Schema
|
22 | * @private
|
23 | */
|
24 | function _buildSchema(cl, origSch, opt, isFinalSchema = true, overwriteNaming, extraOptions) {
|
25 | (0, utils_1.assertionIsClass)(cl);
|
26 | (0, utils_1.assignGlobalModelOptions)(cl); // to ensure global options are applied to the current class
|
27 | // Options sanity check
|
28 | const rawOptions = typeof opt === 'object' ? opt : {};
|
29 | const mergedOptions = rawOptions?.[constants_1.AlreadyMerged] ? rawOptions : (0, utils_1.mergeMetadata)(constants_1.DecoratorKeys.ModelOptions, rawOptions, cl);
|
30 | mergedOptions[constants_1.AlreadyMerged] = true;
|
31 | const finalName = (0, utils_1.getName)(cl, overwriteNaming);
|
32 | logSettings_1.logger.debug('_buildSchema Called for %s with options:', finalName, mergedOptions);
|
33 | /** Simplify the usage */
|
34 | const Schema = mongoose.Schema;
|
35 | const schemaOptions = mergedOptions.schemaOptions ?? {};
|
36 | const decorators = Reflect.getMetadata(constants_1.DecoratorKeys.PropCache, cl.prototype);
|
37 | if (!(0, utils_1.isNullOrUndefined)(decorators)) {
|
38 | for (const decorator of decorators.values()) {
|
39 | (0, processProp_1.processProp)({ ...decorator, cl: cl });
|
40 | }
|
41 | }
|
42 | let sch;
|
43 | {
|
44 | const schemaReflectTarget = (0, utils_1.getCachedSchema)(cl);
|
45 | if (!(origSch instanceof Schema)) {
|
46 | sch = new Schema(schemaReflectTarget, schemaOptions);
|
47 | }
|
48 | else {
|
49 | sch = origSch.clone();
|
50 | sch.add(schemaReflectTarget);
|
51 | }
|
52 | }
|
53 | sch.loadClass(cl);
|
54 | // in the block below are all the things that need to be done for each class, not just the final schema
|
55 | // for example when using "getOwnMetadata" over "getMetadata" (and having a clone in there)
|
56 | {
|
57 | /** Get Metadata for indices */
|
58 | const indices = Reflect.getOwnMetadata(constants_1.DecoratorKeys.Index, cl);
|
59 | const buildIndexes = typeof extraOptions?.buildIndexes === 'boolean' ? extraOptions?.buildIndexes : true;
|
60 | if (Array.isArray(indices) && buildIndexes) {
|
61 | for (const index of indices) {
|
62 | logSettings_1.logger.debug('Applying Index:', index);
|
63 | sch.index(index.fields, index.options);
|
64 | }
|
65 | }
|
66 | }
|
67 | if (isFinalSchema) {
|
68 | /** Get Metadata for Nested Discriminators */
|
69 | const disMap = Reflect.getMetadata(constants_1.DecoratorKeys.NestedDiscriminators, cl);
|
70 | if (disMap instanceof Map) {
|
71 | for (const [key, discriminators] of disMap) {
|
72 | logSettings_1.logger.debug('Applying Nested Discriminators for:', key, discriminators);
|
73 | const path = sch.path(key);
|
74 | (0, utils_1.assertion)(!(0, utils_1.isNullOrUndefined)(path), () => new errors_1.PathNotInSchemaError(finalName, key));
|
75 | (0, utils_1.assertion)(typeof path.discriminator === 'function', () => new errors_1.NoDiscriminatorFunctionError(finalName, key));
|
76 | for (const { type: child, value: childName } of discriminators) {
|
77 | const childSch = (0, utils_1.getName)(child) === finalName ? sch : (0, typegoose_1.buildSchema)(child);
|
78 | const discriminatorKey = childSch.get('discriminatorKey');
|
79 | if (!!discriminatorKey && childSch.path(discriminatorKey)) {
|
80 | // skip this check, otherwise "extends DiscriminatorBase" would not be allowed (discriminators cannot have the discriminator key defined multiple times)
|
81 | childSch.paths[discriminatorKey].options.$skipDiscriminatorCheck = true;
|
82 | }
|
83 | path.discriminator((0, utils_1.getName)(child), childSch, childName);
|
84 | }
|
85 | }
|
86 | }
|
87 | // Hooks
|
88 | {
|
89 | /** Get Metadata for PreHooks */
|
90 | const preHooks = Reflect.getMetadata(constants_1.DecoratorKeys.HooksPre, cl);
|
91 | if (Array.isArray(preHooks)) {
|
92 | // "as any" is used here because mongoose explicitly types out many methods, but the input type (from IHooksArray) is a combination of multiple types
|
93 | preHooks.forEach((obj) => callCorrectSignature(sch, 'pre', obj));
|
94 | }
|
95 | /** Get Metadata for PreHooks */
|
96 | const postHooks = Reflect.getMetadata(constants_1.DecoratorKeys.HooksPost, cl);
|
97 | if (Array.isArray(postHooks)) {
|
98 | // "as any" is used here because mongoose explicitly types out many methods, but the input type (from IHooksArray) is a combination of multiple types
|
99 | postHooks.forEach((obj) => callCorrectSignature(sch, 'post', obj));
|
100 | }
|
101 | }
|
102 | /** Get Metadata for Virtual Populates */
|
103 | const virtuals = Reflect.getMetadata(constants_1.DecoratorKeys.VirtualPopulate, cl);
|
104 | if (virtuals instanceof Map) {
|
105 | for (const [key, options] of virtuals) {
|
106 | logSettings_1.logger.debug('Applying Virtual Populates:', key, options);
|
107 | sch.virtual(key, options);
|
108 | }
|
109 | }
|
110 | /** Get Metadata for Query Methods */
|
111 | const queryMethods = Reflect.getMetadata(constants_1.DecoratorKeys.QueryMethod, cl);
|
112 | if (queryMethods instanceof Map) {
|
113 | for (const [funcName, func] of queryMethods) {
|
114 | logSettings_1.logger.debug('Applying Query Method:', funcName, func);
|
115 | sch.query[funcName] = func;
|
116 | }
|
117 | }
|
118 | /** Get Metadata for indices */
|
119 | const plugins = Reflect.getMetadata(constants_1.DecoratorKeys.Plugins, cl);
|
120 | if (Array.isArray(plugins)) {
|
121 | for (const plugin of plugins) {
|
122 | logSettings_1.logger.debug('Applying Plugin:', plugin);
|
123 | sch.plugin(plugin.mongoosePlugin, plugin.options);
|
124 | }
|
125 | }
|
126 | // this method is to get the typegoose name of the model/class if it is user-handled (like buildSchema, then manually mongoose.model)
|
127 | sch.method('typegooseName', () => {
|
128 | return finalName;
|
129 | });
|
130 | }
|
131 | if ((0, utils_1.isCachingEnabled)(mergedOptions.options?.disableCaching)) {
|
132 | // add the class to the constructors map
|
133 | data_1.constructors.set(finalName, cl);
|
134 | }
|
135 | return sch;
|
136 | }
|
137 | exports._buildSchema = _buildSchema;
|
138 | /**
|
139 | * Helper function to call the correct signature for a given "fnToCall" (pre / post hooks)
|
140 | * @param fnToCall The function to call (sch.pre / sch.post)
|
141 | * @param obj The object to call as arguments with
|
142 | */
|
143 | function callCorrectSignature(sch, fn, obj) {
|
144 | // we have to bind "sch", otherwise "this" will not be defined in the "pre / post" functions
|
145 | const fnToCall = (fn === 'pre' ? sch.pre : sch.post).bind(sch);
|
146 | if (!(0, utils_1.isNullOrUndefined)(obj.options)) {
|
147 | return fnToCall(obj.methods, obj.options, obj.func);
|
148 | }
|
149 | return fnToCall(obj.methods, obj.func);
|
150 | }
|
151 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZW1hLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ludGVybmFsL3NjaGVtYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxxQ0FBcUM7QUFDckMsZ0RBQXdDO0FBQ3hDLDRDQUEyQztBQWMzQywyQ0FBMkQ7QUFDM0QsaUNBQXNDO0FBQ3RDLHFDQUE4RTtBQUM5RSwrQ0FBNEM7QUFDNUMsbUNBU2lCO0FBRWpCOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsU0FBZ0IsWUFBWSxDQUMxQixFQUFLLEVBQ0wsT0FBOEIsRUFDOUIsR0FBbUIsRUFDbkIsZ0JBQXlCLElBQUksRUFDN0IsZUFBZ0MsRUFDaEMsWUFBa0M7SUFFbEMsSUFBQSx3QkFBZ0IsRUFBQyxFQUFFLENBQUMsQ0FBQztJQUVyQixJQUFBLGdDQUF3QixFQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsNERBQTREO0lBRTFGLHVCQUF1QjtJQUN2QixNQUFNLFVBQVUsR0FBRyxPQUFPLEdBQUcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ3RELE1BQU0sYUFBYSxHQUFrQixVQUFVLEVBQUUsQ0FBQyx5QkFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBQSxxQkFBYSxFQUFDLHlCQUFhLENBQUMsWUFBWSxFQUFFLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUMxSSxhQUFhLENBQUMseUJBQWEsQ0FBQyxHQUFHLElBQUksQ0FBQztJQUVwQyxNQUFNLFNBQVMsR0FBRyxJQUFBLGVBQU8sRUFBQyxFQUFFLEVBQUUsZUFBZSxDQUFDLENBQUM7SUFFL0Msb0JBQU0sQ0FBQyxLQUFLLENBQUMsMENBQTBDLEVBQUUsU0FBUyxFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBRW5GLHlCQUF5QjtJQUN6QixNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDO0lBQy9CLE1BQU0sYUFB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 |
\ | No newline at end of file |