@depup/mongoose 9.1.3-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +22 -0
- package/README.md +397 -0
- package/SECURITY.md +1 -0
- package/eslint.config.mjs +198 -0
- package/index.js +64 -0
- package/lib/aggregate.js +1189 -0
- package/lib/cast/bigint.js +46 -0
- package/lib/cast/boolean.js +32 -0
- package/lib/cast/date.js +41 -0
- package/lib/cast/decimal128.js +39 -0
- package/lib/cast/double.js +50 -0
- package/lib/cast/int32.js +36 -0
- package/lib/cast/number.js +42 -0
- package/lib/cast/objectid.js +29 -0
- package/lib/cast/string.js +37 -0
- package/lib/cast/uuid.js +35 -0
- package/lib/cast.js +436 -0
- package/lib/collection.js +321 -0
- package/lib/connection.js +1855 -0
- package/lib/connectionState.js +26 -0
- package/lib/constants.js +73 -0
- package/lib/cursor/aggregationCursor.js +466 -0
- package/lib/cursor/changeStream.js +198 -0
- package/lib/cursor/queryCursor.js +622 -0
- package/lib/document.js +5521 -0
- package/lib/driver.js +15 -0
- package/lib/drivers/SPEC.md +4 -0
- package/lib/drivers/node-mongodb-native/bulkWriteResult.js +5 -0
- package/lib/drivers/node-mongodb-native/collection.js +393 -0
- package/lib/drivers/node-mongodb-native/connection.js +506 -0
- package/lib/drivers/node-mongodb-native/index.js +10 -0
- package/lib/error/browserMissingSchema.js +29 -0
- package/lib/error/bulkSaveIncompleteError.js +44 -0
- package/lib/error/bulkWriteError.js +41 -0
- package/lib/error/cast.js +158 -0
- package/lib/error/createCollectionsError.js +26 -0
- package/lib/error/divergentArray.js +40 -0
- package/lib/error/eachAsyncMultiError.js +41 -0
- package/lib/error/index.js +237 -0
- package/lib/error/invalidSchemaOption.js +32 -0
- package/lib/error/messages.js +47 -0
- package/lib/error/missingSchema.js +33 -0
- package/lib/error/mongooseError.js +13 -0
- package/lib/error/notFound.js +47 -0
- package/lib/error/objectExpected.js +31 -0
- package/lib/error/objectParameter.js +31 -0
- package/lib/error/overwriteModel.js +31 -0
- package/lib/error/parallelSave.js +33 -0
- package/lib/error/parallelValidate.js +33 -0
- package/lib/error/serverSelection.js +62 -0
- package/lib/error/setOptionError.js +103 -0
- package/lib/error/strict.js +35 -0
- package/lib/error/strictPopulate.js +31 -0
- package/lib/error/syncIndexes.js +30 -0
- package/lib/error/validation.js +97 -0
- package/lib/error/validator.js +100 -0
- package/lib/error/version.js +38 -0
- package/lib/helpers/aggregate/prepareDiscriminatorPipeline.js +39 -0
- package/lib/helpers/aggregate/stringifyFunctionOperators.js +50 -0
- package/lib/helpers/arrayDepth.js +33 -0
- package/lib/helpers/clone.js +204 -0
- package/lib/helpers/common.js +127 -0
- package/lib/helpers/createJSONSchemaTypeDefinition.js +24 -0
- package/lib/helpers/cursor/eachAsync.js +225 -0
- package/lib/helpers/discriminator/applyEmbeddedDiscriminators.js +36 -0
- package/lib/helpers/discriminator/areDiscriminatorValuesEqual.js +16 -0
- package/lib/helpers/discriminator/checkEmbeddedDiscriminatorKeyProjection.js +12 -0
- package/lib/helpers/discriminator/getConstructor.js +29 -0
- package/lib/helpers/discriminator/getDiscriminatorByValue.js +28 -0
- package/lib/helpers/discriminator/getSchemaDiscriminatorByValue.js +27 -0
- package/lib/helpers/discriminator/mergeDiscriminatorSchema.js +91 -0
- package/lib/helpers/document/applyDefaults.js +132 -0
- package/lib/helpers/document/applyTimestamps.js +106 -0
- package/lib/helpers/document/applyVirtuals.js +147 -0
- package/lib/helpers/document/cleanModifiedSubpaths.js +45 -0
- package/lib/helpers/document/compile.js +238 -0
- package/lib/helpers/document/getDeepestSubdocumentForPath.js +38 -0
- package/lib/helpers/document/getEmbeddedDiscriminatorPath.js +53 -0
- package/lib/helpers/document/handleSpreadDoc.js +35 -0
- package/lib/helpers/each.js +25 -0
- package/lib/helpers/error/combinePathErrors.js +22 -0
- package/lib/helpers/firstKey.js +8 -0
- package/lib/helpers/get.js +65 -0
- package/lib/helpers/getConstructorName.js +16 -0
- package/lib/helpers/getDefaultBulkwriteResult.js +18 -0
- package/lib/helpers/getFunctionName.js +10 -0
- package/lib/helpers/immediate.js +16 -0
- package/lib/helpers/indexes/applySchemaCollation.js +13 -0
- package/lib/helpers/indexes/decorateDiscriminatorIndexOptions.js +14 -0
- package/lib/helpers/indexes/getRelatedIndexes.js +63 -0
- package/lib/helpers/indexes/isDefaultIdIndex.js +18 -0
- package/lib/helpers/indexes/isIndexEqual.js +95 -0
- package/lib/helpers/indexes/isIndexSpecEqual.js +32 -0
- package/lib/helpers/indexes/isTextIndex.js +16 -0
- package/lib/helpers/indexes/isTimeseriesIndex.js +16 -0
- package/lib/helpers/isAsyncFunction.js +9 -0
- package/lib/helpers/isBsonType.js +15 -0
- package/lib/helpers/isMongooseObject.js +22 -0
- package/lib/helpers/isObject.js +16 -0
- package/lib/helpers/isPOJO.js +12 -0
- package/lib/helpers/isPromise.js +6 -0
- package/lib/helpers/isSimpleValidator.js +22 -0
- package/lib/helpers/minimize.js +41 -0
- package/lib/helpers/model/applyDefaultsToPOJO.js +52 -0
- package/lib/helpers/model/applyHooks.js +140 -0
- package/lib/helpers/model/applyMethods.js +70 -0
- package/lib/helpers/model/applyStaticHooks.js +33 -0
- package/lib/helpers/model/applyStatics.js +13 -0
- package/lib/helpers/model/castBulkWrite.js +316 -0
- package/lib/helpers/model/decorateBulkWriteResult.js +8 -0
- package/lib/helpers/model/discriminator.js +265 -0
- package/lib/helpers/model/pushNestedArrayPaths.js +15 -0
- package/lib/helpers/omitUndefined.js +20 -0
- package/lib/helpers/once.js +12 -0
- package/lib/helpers/parallelLimit.js +37 -0
- package/lib/helpers/path/parentPaths.js +18 -0
- package/lib/helpers/path/setDottedPath.js +33 -0
- package/lib/helpers/pluralize.js +95 -0
- package/lib/helpers/populate/assignRawDocsToIdStructure.js +129 -0
- package/lib/helpers/populate/assignVals.js +360 -0
- package/lib/helpers/populate/createPopulateQueryFilter.js +97 -0
- package/lib/helpers/populate/getModelsMapForPopulate.js +776 -0
- package/lib/helpers/populate/getSchemaTypes.js +228 -0
- package/lib/helpers/populate/getVirtual.js +103 -0
- package/lib/helpers/populate/leanPopulateMap.js +7 -0
- package/lib/helpers/populate/lookupLocalFields.js +40 -0
- package/lib/helpers/populate/markArraySubdocsPopulated.js +49 -0
- package/lib/helpers/populate/modelNamesFromRefPath.js +66 -0
- package/lib/helpers/populate/removeDeselectedForeignField.js +31 -0
- package/lib/helpers/populate/setPopulatedVirtualValue.js +33 -0
- package/lib/helpers/populate/skipPopulateValue.js +10 -0
- package/lib/helpers/populate/validateRef.js +19 -0
- package/lib/helpers/printJestWarning.js +21 -0
- package/lib/helpers/processConnectionOptions.js +65 -0
- package/lib/helpers/projection/applyProjection.js +83 -0
- package/lib/helpers/projection/hasIncludedChildren.js +41 -0
- package/lib/helpers/projection/isDefiningProjection.js +18 -0
- package/lib/helpers/projection/isExclusive.js +37 -0
- package/lib/helpers/projection/isInclusive.js +39 -0
- package/lib/helpers/projection/isNestedProjection.js +8 -0
- package/lib/helpers/projection/isPathExcluded.js +40 -0
- package/lib/helpers/projection/isPathSelectedInclusive.js +28 -0
- package/lib/helpers/projection/isSubpath.js +14 -0
- package/lib/helpers/projection/parseProjection.js +33 -0
- package/lib/helpers/query/applyGlobalOption.js +29 -0
- package/lib/helpers/query/cast$expr.js +287 -0
- package/lib/helpers/query/castFilterPath.js +54 -0
- package/lib/helpers/query/castUpdate.js +643 -0
- package/lib/helpers/query/getEmbeddedDiscriminatorPath.js +103 -0
- package/lib/helpers/query/handleImmutable.js +44 -0
- package/lib/helpers/query/handleReadPreferenceAliases.js +23 -0
- package/lib/helpers/query/hasDollarKeys.js +23 -0
- package/lib/helpers/query/isOperator.js +14 -0
- package/lib/helpers/query/sanitizeFilter.js +38 -0
- package/lib/helpers/query/sanitizeProjection.js +14 -0
- package/lib/helpers/query/selectPopulatedFields.js +62 -0
- package/lib/helpers/query/trusted.js +13 -0
- package/lib/helpers/query/validOps.js +3 -0
- package/lib/helpers/schema/addAutoId.js +7 -0
- package/lib/helpers/schema/applyBuiltinPlugins.js +12 -0
- package/lib/helpers/schema/applyPlugins.js +55 -0
- package/lib/helpers/schema/applyReadConcern.js +20 -0
- package/lib/helpers/schema/applyWriteConcern.js +39 -0
- package/lib/helpers/schema/cleanPositionalOperators.js +12 -0
- package/lib/helpers/schema/getIndexes.js +171 -0
- package/lib/helpers/schema/getKeysInSchemaOrder.js +28 -0
- package/lib/helpers/schema/getPath.js +43 -0
- package/lib/helpers/schema/getSubdocumentStrictValue.js +32 -0
- package/lib/helpers/schema/handleIdOption.js +20 -0
- package/lib/helpers/schema/handleTimestampOption.js +24 -0
- package/lib/helpers/schema/idGetter.js +34 -0
- package/lib/helpers/schema/merge.js +36 -0
- package/lib/helpers/schematype/handleImmutable.js +50 -0
- package/lib/helpers/setDefaultsOnInsert.js +158 -0
- package/lib/helpers/specialProperties.js +3 -0
- package/lib/helpers/symbols.js +20 -0
- package/lib/helpers/timers.js +3 -0
- package/lib/helpers/timestamps/setDocumentTimestamps.js +26 -0
- package/lib/helpers/timestamps/setupTimestamps.js +116 -0
- package/lib/helpers/topology/allServersUnknown.js +12 -0
- package/lib/helpers/topology/isAtlas.js +31 -0
- package/lib/helpers/topology/isSSLError.js +16 -0
- package/lib/helpers/update/applyTimestampsToChildren.js +193 -0
- package/lib/helpers/update/applyTimestampsToUpdate.js +131 -0
- package/lib/helpers/update/castArrayFilters.js +113 -0
- package/lib/helpers/update/decorateUpdateWithVersionKey.js +35 -0
- package/lib/helpers/update/modifiedPaths.js +33 -0
- package/lib/helpers/update/moveImmutableProperties.js +53 -0
- package/lib/helpers/update/removeUnusedArrayFilters.js +32 -0
- package/lib/helpers/update/updatedPathsByArrayFilter.js +27 -0
- package/lib/helpers/updateValidators.js +193 -0
- package/lib/index.js +17 -0
- package/lib/internal.js +46 -0
- package/lib/model.js +5010 -0
- package/lib/modifiedPathsSnapshot.js +9 -0
- package/lib/mongoose.js +1411 -0
- package/lib/options/populateOptions.js +36 -0
- package/lib/options/propertyOptions.js +8 -0
- package/lib/options/saveOptions.js +16 -0
- package/lib/options/schemaArrayOptions.js +78 -0
- package/lib/options/schemaBufferOptions.js +38 -0
- package/lib/options/schemaDateOptions.js +71 -0
- package/lib/options/schemaDocumentArrayOptions.js +68 -0
- package/lib/options/schemaMapOptions.js +43 -0
- package/lib/options/schemaNumberOptions.js +101 -0
- package/lib/options/schemaObjectIdOptions.js +64 -0
- package/lib/options/schemaStringOptions.js +138 -0
- package/lib/options/schemaSubdocumentOptions.js +66 -0
- package/lib/options/schemaTypeOptions.js +244 -0
- package/lib/options/schemaUnionOptions.js +32 -0
- package/lib/options/virtualOptions.js +164 -0
- package/lib/options.js +17 -0
- package/lib/plugins/index.js +6 -0
- package/lib/plugins/saveSubdocs.js +76 -0
- package/lib/plugins/sharding.js +84 -0
- package/lib/plugins/trackTransaction.js +84 -0
- package/lib/plugins/validateBeforeSave.js +41 -0
- package/lib/query.js +5673 -0
- package/lib/queryHelpers.js +387 -0
- package/lib/schema/array.js +699 -0
- package/lib/schema/bigint.js +282 -0
- package/lib/schema/boolean.js +332 -0
- package/lib/schema/buffer.js +343 -0
- package/lib/schema/date.js +467 -0
- package/lib/schema/decimal128.js +263 -0
- package/lib/schema/documentArray.js +656 -0
- package/lib/schema/documentArrayElement.js +137 -0
- package/lib/schema/double.js +246 -0
- package/lib/schema/index.js +32 -0
- package/lib/schema/int32.js +289 -0
- package/lib/schema/map.js +201 -0
- package/lib/schema/mixed.js +146 -0
- package/lib/schema/number.js +510 -0
- package/lib/schema/objectId.js +333 -0
- package/lib/schema/operators/bitwise.js +38 -0
- package/lib/schema/operators/exists.js +12 -0
- package/lib/schema/operators/geospatial.js +107 -0
- package/lib/schema/operators/helpers.js +32 -0
- package/lib/schema/operators/text.js +39 -0
- package/lib/schema/operators/type.js +20 -0
- package/lib/schema/string.js +733 -0
- package/lib/schema/subdocument.js +436 -0
- package/lib/schema/symbols.js +5 -0
- package/lib/schema/union.js +113 -0
- package/lib/schema/uuid.js +305 -0
- package/lib/schema.js +3226 -0
- package/lib/schemaType.js +1835 -0
- package/lib/stateMachine.js +232 -0
- package/lib/types/array/index.js +119 -0
- package/lib/types/array/isMongooseArray.js +5 -0
- package/lib/types/array/methods/index.js +1095 -0
- package/lib/types/arraySubdocument.js +207 -0
- package/lib/types/buffer.js +294 -0
- package/lib/types/decimal128.js +13 -0
- package/lib/types/documentArray/index.js +113 -0
- package/lib/types/documentArray/isMongooseDocumentArray.js +5 -0
- package/lib/types/documentArray/methods/index.js +415 -0
- package/lib/types/double.js +13 -0
- package/lib/types/index.js +23 -0
- package/lib/types/map.js +419 -0
- package/lib/types/objectid.js +41 -0
- package/lib/types/subdocument.js +464 -0
- package/lib/types/uuid.js +13 -0
- package/lib/utils.js +1054 -0
- package/lib/validOptions.js +42 -0
- package/lib/virtualType.js +204 -0
- package/package.json +148 -0
- package/types/aggregate.d.ts +180 -0
- package/types/augmentations.d.ts +9 -0
- package/types/callback.d.ts +8 -0
- package/types/collection.d.ts +49 -0
- package/types/connection.d.ts +297 -0
- package/types/cursor.d.ts +67 -0
- package/types/document.d.ts +374 -0
- package/types/error.d.ts +143 -0
- package/types/expressions.d.ts +3053 -0
- package/types/helpers.d.ts +32 -0
- package/types/index.d.ts +1056 -0
- package/types/indexes.d.ts +97 -0
- package/types/inferhydrateddoctype.d.ts +115 -0
- package/types/inferrawdoctype.d.ts +135 -0
- package/types/inferschematype.d.ts +337 -0
- package/types/middlewares.d.ts +59 -0
- package/types/models.d.ts +1306 -0
- package/types/mongooseoptions.d.ts +228 -0
- package/types/pipelinestage.d.ts +333 -0
- package/types/populate.d.ts +53 -0
- package/types/query.d.ts +934 -0
- package/types/schemaoptions.d.ts +282 -0
- package/types/schematypes.d.ts +654 -0
- package/types/session.d.ts +32 -0
- package/types/types.d.ts +109 -0
- package/types/utility.d.ts +175 -0
- package/types/validation.d.ts +39 -0
- package/types/virtuals.d.ts +14 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports = function stringifyFunctionOperators(pipeline) {
|
|
4
|
+
if (!Array.isArray(pipeline)) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
for (const stage of pipeline) {
|
|
9
|
+
if (stage == null) {
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const canHaveAccumulator = stage.$group || stage.$bucket || stage.$bucketAuto;
|
|
14
|
+
if (canHaveAccumulator != null) {
|
|
15
|
+
for (const key of Object.keys(canHaveAccumulator)) {
|
|
16
|
+
handleAccumulator(canHaveAccumulator[key]);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const stageType = Object.keys(stage)[0];
|
|
21
|
+
if (stageType && typeof stage[stageType] === 'object') {
|
|
22
|
+
const stageOptions = stage[stageType];
|
|
23
|
+
for (const key of Object.keys(stageOptions)) {
|
|
24
|
+
if (stageOptions[key] != null &&
|
|
25
|
+
stageOptions[key].$function != null &&
|
|
26
|
+
typeof stageOptions[key].$function.body === 'function') {
|
|
27
|
+
stageOptions[key].$function.body = stageOptions[key].$function.body.toString();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (stage.$facet != null) {
|
|
33
|
+
for (const key of Object.keys(stage.$facet)) {
|
|
34
|
+
stringifyFunctionOperators(stage.$facet[key]);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
function handleAccumulator(operator) {
|
|
41
|
+
if (operator == null || operator.$accumulator == null) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
for (const key of ['init', 'accumulate', 'merge', 'finalize']) {
|
|
46
|
+
if (typeof operator.$accumulator[key] === 'function') {
|
|
47
|
+
operator.$accumulator[key] = String(operator.$accumulator[key]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports = arrayDepth;
|
|
4
|
+
|
|
5
|
+
function arrayDepth(arr) {
|
|
6
|
+
if (!Array.isArray(arr)) {
|
|
7
|
+
return { min: 0, max: 0, containsNonArrayItem: true };
|
|
8
|
+
}
|
|
9
|
+
if (arr.length === 0) {
|
|
10
|
+
return { min: 1, max: 1, containsNonArrayItem: false };
|
|
11
|
+
}
|
|
12
|
+
if (arr.length === 1 && !Array.isArray(arr[0])) {
|
|
13
|
+
return { min: 1, max: 1, containsNonArrayItem: false };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const res = arrayDepth(arr[0]);
|
|
17
|
+
|
|
18
|
+
for (let i = 1; i < arr.length; ++i) {
|
|
19
|
+
const _res = arrayDepth(arr[i]);
|
|
20
|
+
if (_res.min < res.min) {
|
|
21
|
+
res.min = _res.min;
|
|
22
|
+
}
|
|
23
|
+
if (_res.max > res.max) {
|
|
24
|
+
res.max = _res.max;
|
|
25
|
+
}
|
|
26
|
+
res.containsNonArrayItem = res.containsNonArrayItem || _res.containsNonArrayItem;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
res.min = res.min + 1;
|
|
30
|
+
res.max = res.max + 1;
|
|
31
|
+
|
|
32
|
+
return res;
|
|
33
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Decimal = require('../types/decimal128');
|
|
4
|
+
const ObjectId = require('../types/objectid');
|
|
5
|
+
const specialProperties = require('./specialProperties');
|
|
6
|
+
const isMongooseObject = require('./isMongooseObject');
|
|
7
|
+
const getFunctionName = require('./getFunctionName');
|
|
8
|
+
const isBsonType = require('./isBsonType');
|
|
9
|
+
const isMongooseArray = require('../types/array/isMongooseArray').isMongooseArray;
|
|
10
|
+
const isObject = require('./isObject');
|
|
11
|
+
const isPOJO = require('./isPOJO');
|
|
12
|
+
const symbols = require('./symbols');
|
|
13
|
+
const trustedSymbol = require('./query/trusted').trustedSymbol;
|
|
14
|
+
const BSON = require('mongodb/lib/bson');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Object clone with Mongoose natives support.
|
|
18
|
+
*
|
|
19
|
+
* If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.
|
|
20
|
+
*
|
|
21
|
+
* Functions and primitives are never cloned.
|
|
22
|
+
*
|
|
23
|
+
* @param {Object} obj the object to clone
|
|
24
|
+
* @param {Object} options
|
|
25
|
+
* @param {Boolean} isArrayChild true if cloning immediately underneath an array. Special case for minimize.
|
|
26
|
+
* @return {Object} the cloned object
|
|
27
|
+
* @api private
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
function clone(obj, options, isArrayChild) {
|
|
31
|
+
if (obj == null) {
|
|
32
|
+
return obj;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (isBsonType(obj, 'Double')) {
|
|
36
|
+
return new BSON.Double(obj.value);
|
|
37
|
+
}
|
|
38
|
+
if (typeof obj === 'number' || typeof obj === 'string' || typeof obj === 'boolean' || typeof obj === 'bigint') {
|
|
39
|
+
return obj;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (Array.isArray(obj)) {
|
|
43
|
+
return cloneArray(obj, options);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (isMongooseObject(obj)) {
|
|
47
|
+
if (options) {
|
|
48
|
+
if (options.retainDocuments && obj.$__ != null) {
|
|
49
|
+
const clonedDoc = obj.$clone();
|
|
50
|
+
if (obj.__index != null) {
|
|
51
|
+
clonedDoc.__index = obj.__index;
|
|
52
|
+
}
|
|
53
|
+
if (obj.__parentArray != null) {
|
|
54
|
+
clonedDoc.__parentArray = obj.__parentArray;
|
|
55
|
+
}
|
|
56
|
+
clonedDoc.$__setParent(options.parentDoc ?? obj.$__parent);
|
|
57
|
+
return clonedDoc;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (isPOJO(obj) && obj.$__ != null && obj._doc != null) {
|
|
62
|
+
return obj._doc;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let ret;
|
|
66
|
+
if (options?.json && typeof obj.toJSON === 'function') {
|
|
67
|
+
ret = obj.toJSON(options);
|
|
68
|
+
} else {
|
|
69
|
+
ret = obj.toObject(options);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return ret;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const objConstructor = obj.constructor;
|
|
76
|
+
|
|
77
|
+
if (objConstructor) {
|
|
78
|
+
switch (getFunctionName(objConstructor)) {
|
|
79
|
+
case 'Object':
|
|
80
|
+
return cloneObject(obj, options, isArrayChild);
|
|
81
|
+
case 'Date':
|
|
82
|
+
return new objConstructor(+obj);
|
|
83
|
+
case 'RegExp':
|
|
84
|
+
return cloneRegExp(obj);
|
|
85
|
+
default:
|
|
86
|
+
// ignore
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (isBsonType(obj, 'ObjectId')) {
|
|
92
|
+
if (options?.flattenObjectIds) {
|
|
93
|
+
return obj.toJSON();
|
|
94
|
+
}
|
|
95
|
+
return new ObjectId(obj.id);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (isBsonType(obj, 'Decimal128')) {
|
|
99
|
+
if (options?.flattenDecimals) {
|
|
100
|
+
return obj.toJSON();
|
|
101
|
+
}
|
|
102
|
+
return Decimal.fromString(obj.toString());
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// object created with Object.create(null)
|
|
106
|
+
if (!objConstructor && isObject(obj)) {
|
|
107
|
+
return cloneObject(obj, options, isArrayChild);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (typeof obj === 'object' && obj[symbols.schemaTypeSymbol]) {
|
|
111
|
+
return obj.clone();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// If we're cloning this object to go into a MongoDB command,
|
|
115
|
+
// and there's a `toBSON()` function, assume this object will be
|
|
116
|
+
// stored as a primitive in MongoDB and doesn't need to be cloned.
|
|
117
|
+
if (options?.bson && typeof obj.toBSON === 'function') {
|
|
118
|
+
return obj;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (typeof obj.valueOf === 'function') {
|
|
122
|
+
return obj.valueOf();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return cloneObject(obj, options, isArrayChild);
|
|
126
|
+
}
|
|
127
|
+
module.exports = clone;
|
|
128
|
+
|
|
129
|
+
/*!
|
|
130
|
+
* ignore
|
|
131
|
+
*/
|
|
132
|
+
|
|
133
|
+
function cloneObject(obj, options, isArrayChild) {
|
|
134
|
+
const minimize = options?.minimize;
|
|
135
|
+
const omitUndefined = options?.omitUndefined;
|
|
136
|
+
const seen = options?._seen;
|
|
137
|
+
const ret = {};
|
|
138
|
+
let hasKeys;
|
|
139
|
+
|
|
140
|
+
if (seen && seen.has(obj)) {
|
|
141
|
+
return seen.get(obj);
|
|
142
|
+
} else if (seen) {
|
|
143
|
+
seen.set(obj, ret);
|
|
144
|
+
}
|
|
145
|
+
if (trustedSymbol in obj && options?.copyTrustedSymbol !== false) {
|
|
146
|
+
ret[trustedSymbol] = obj[trustedSymbol];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const keys = Object.keys(obj);
|
|
150
|
+
const len = keys.length;
|
|
151
|
+
|
|
152
|
+
for (let i = 0; i < len; ++i) {
|
|
153
|
+
const key = keys[i];
|
|
154
|
+
if (specialProperties.has(key)) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Don't pass `isArrayChild` down
|
|
159
|
+
const val = clone(obj[key], options, false);
|
|
160
|
+
|
|
161
|
+
if ((minimize === false || omitUndefined) && typeof val === 'undefined') {
|
|
162
|
+
delete ret[key];
|
|
163
|
+
} else if (minimize !== true || (typeof val !== 'undefined')) {
|
|
164
|
+
hasKeys || (hasKeys = true);
|
|
165
|
+
ret[key] = val;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return minimize && !isArrayChild ? hasKeys && ret : ret;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function cloneArray(arr, options) {
|
|
173
|
+
let i = 0;
|
|
174
|
+
const len = arr.length;
|
|
175
|
+
|
|
176
|
+
let ret = null;
|
|
177
|
+
if (options?.retainDocuments) {
|
|
178
|
+
if (arr.isMongooseDocumentArray) {
|
|
179
|
+
ret = new (arr.$schemaType().schema.base.Types.DocumentArray)([], arr.$path(), arr.$parent(), arr.$schemaType());
|
|
180
|
+
} else if (arr.isMongooseArray) {
|
|
181
|
+
ret = new (arr.$parent().schema.base.Types.Array)([], arr.$path(), arr.$parent(), arr.$schemaType());
|
|
182
|
+
} else {
|
|
183
|
+
ret = new Array(len);
|
|
184
|
+
}
|
|
185
|
+
} else {
|
|
186
|
+
ret = new Array(len);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
arr = isMongooseArray(arr) ? arr.__array : arr;
|
|
190
|
+
for (i = 0; i < len; ++i) {
|
|
191
|
+
ret[i] = clone(arr[i], options, true);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return ret;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function cloneRegExp(regexp) {
|
|
198
|
+
const ret = new RegExp(regexp.source, regexp.flags);
|
|
199
|
+
|
|
200
|
+
if (ret.lastIndex !== regexp.lastIndex) {
|
|
201
|
+
ret.lastIndex = regexp.lastIndex;
|
|
202
|
+
}
|
|
203
|
+
return ret;
|
|
204
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/*!
|
|
4
|
+
* Module dependencies.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const Binary = require('mongodb/lib/bson').Binary;
|
|
8
|
+
const isBsonType = require('./isBsonType');
|
|
9
|
+
const isMongooseObject = require('./isMongooseObject');
|
|
10
|
+
const MongooseError = require('../error');
|
|
11
|
+
const util = require('util');
|
|
12
|
+
|
|
13
|
+
exports.flatten = flatten;
|
|
14
|
+
exports.modifiedPaths = modifiedPaths;
|
|
15
|
+
|
|
16
|
+
/*!
|
|
17
|
+
* ignore
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
function flatten(update, path, options, schema) {
|
|
21
|
+
let keys;
|
|
22
|
+
if (update && isMongooseObject(update) && !Buffer.isBuffer(update)) {
|
|
23
|
+
keys = Object.keys(update.toObject({ transform: false, virtuals: false }) || {});
|
|
24
|
+
} else {
|
|
25
|
+
keys = Object.keys(update || {});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const numKeys = keys.length;
|
|
29
|
+
const result = {};
|
|
30
|
+
path = path ? path + '.' : '';
|
|
31
|
+
|
|
32
|
+
for (let i = 0; i < numKeys; ++i) {
|
|
33
|
+
const key = keys[i];
|
|
34
|
+
const val = update[key];
|
|
35
|
+
result[path + key] = val;
|
|
36
|
+
|
|
37
|
+
// Avoid going into mixed paths if schema is specified
|
|
38
|
+
const keySchema = schema?.path?.(path + key);
|
|
39
|
+
const isNested = schema?.nested?.[path + key];
|
|
40
|
+
if (keySchema?.instance === 'Mixed') continue;
|
|
41
|
+
|
|
42
|
+
if (shouldFlatten(val)) {
|
|
43
|
+
if (options?.skipArrays && Array.isArray(val)) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const flat = flatten(val, path + key, options, schema);
|
|
47
|
+
for (const k in flat) {
|
|
48
|
+
result[k] = flat[k];
|
|
49
|
+
}
|
|
50
|
+
if (Array.isArray(val)) {
|
|
51
|
+
result[path + key] = val;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (isNested) {
|
|
56
|
+
const paths = Object.keys(schema.paths);
|
|
57
|
+
for (const p of paths) {
|
|
58
|
+
if (p.startsWith(path + key + '.') && !Object.hasOwn(result, p)) {
|
|
59
|
+
result[p] = void 0;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/*!
|
|
69
|
+
* ignore
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
function modifiedPaths(update, path, result, recursion = null) {
|
|
73
|
+
if (update == null || typeof update !== 'object') {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (recursion == null) {
|
|
78
|
+
recursion = {
|
|
79
|
+
raw: { update, path },
|
|
80
|
+
trace: new WeakSet()
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (recursion.trace.has(update)) {
|
|
85
|
+
throw new MongooseError(`a circular reference in the update value, updateValue:
|
|
86
|
+
${util.inspect(recursion.raw.update, { showHidden: false, depth: 1 })}
|
|
87
|
+
updatePath: '${recursion.raw.path}'`);
|
|
88
|
+
}
|
|
89
|
+
recursion.trace.add(update);
|
|
90
|
+
|
|
91
|
+
const keys = Object.keys(update || {});
|
|
92
|
+
const numKeys = keys.length;
|
|
93
|
+
result = result || {};
|
|
94
|
+
path = path ? path + '.' : '';
|
|
95
|
+
|
|
96
|
+
for (let i = 0; i < numKeys; ++i) {
|
|
97
|
+
const key = keys[i];
|
|
98
|
+
let val = update[key];
|
|
99
|
+
|
|
100
|
+
const _path = path + key;
|
|
101
|
+
result[_path] = true;
|
|
102
|
+
if (!Buffer.isBuffer(val) && isMongooseObject(val)) {
|
|
103
|
+
val = val.toObject({ transform: false, virtuals: false });
|
|
104
|
+
}
|
|
105
|
+
if (shouldFlatten(val)) {
|
|
106
|
+
modifiedPaths(val, path + key, result, recursion);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
recursion.trace.delete(update);
|
|
110
|
+
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/*!
|
|
115
|
+
* ignore
|
|
116
|
+
*/
|
|
117
|
+
|
|
118
|
+
function shouldFlatten(val) {
|
|
119
|
+
return val &&
|
|
120
|
+
typeof val === 'object' &&
|
|
121
|
+
!(val instanceof Date) &&
|
|
122
|
+
!isBsonType(val, 'ObjectId') &&
|
|
123
|
+
(!Array.isArray(val) || val.length !== 0) &&
|
|
124
|
+
!(val instanceof Buffer) &&
|
|
125
|
+
!isBsonType(val, 'Decimal128') &&
|
|
126
|
+
!(val instanceof Binary);
|
|
127
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Handles creating `{ type: 'object' }` vs `{ bsonType: 'object' }` vs `{ bsonType: ['object', 'null'] }`
|
|
5
|
+
*
|
|
6
|
+
* @param {String} type
|
|
7
|
+
* @param {String} bsonType
|
|
8
|
+
* @param {Boolean} useBsonType
|
|
9
|
+
* @param {Boolean} isRequired
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
module.exports = function createJSONSchemaTypeArray(type, bsonType, useBsonType, isRequired) {
|
|
13
|
+
if (useBsonType) {
|
|
14
|
+
if (isRequired) {
|
|
15
|
+
return { bsonType };
|
|
16
|
+
}
|
|
17
|
+
return { bsonType: [bsonType, 'null'] };
|
|
18
|
+
} else {
|
|
19
|
+
if (isRequired) {
|
|
20
|
+
return { type };
|
|
21
|
+
}
|
|
22
|
+
return { type: [type, 'null'] };
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/*!
|
|
4
|
+
* Module dependencies.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const EachAsyncMultiError = require('../../error/eachAsyncMultiError');
|
|
8
|
+
const immediate = require('../immediate');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Execute `fn` for every document in the cursor. If `fn` returns a promise,
|
|
12
|
+
* will wait for the promise to resolve before iterating on to the next one.
|
|
13
|
+
* Returns a promise that resolves when done.
|
|
14
|
+
*
|
|
15
|
+
* @param {Function} next the thunk to call to get the next document
|
|
16
|
+
* @param {Function} fn
|
|
17
|
+
* @param {Object} options
|
|
18
|
+
* @param {Number} [options.batchSize=null] if set, Mongoose will call `fn` with an array of at most `batchSize` documents, instead of a single document
|
|
19
|
+
* @param {Number} [options.parallel=1] maximum number of `fn` calls that Mongoose will run in parallel
|
|
20
|
+
* @param {AbortSignal} [options.signal] allow cancelling this eachAsync(). Once the abort signal is fired, `eachAsync()` will immediately fulfill the returned promise (or call the callback) and not fetch any more documents.
|
|
21
|
+
* @return {Promise}
|
|
22
|
+
* @api public
|
|
23
|
+
* @method eachAsync
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
module.exports = async function eachAsync(next, fn, options) {
|
|
27
|
+
const parallel = options.parallel || 1;
|
|
28
|
+
const batchSize = options.batchSize;
|
|
29
|
+
const signal = options.signal;
|
|
30
|
+
const continueOnError = options.continueOnError;
|
|
31
|
+
const aggregatedErrors = [];
|
|
32
|
+
const enqueue = asyncQueue();
|
|
33
|
+
|
|
34
|
+
let aborted = false;
|
|
35
|
+
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
if (signal != null) {
|
|
38
|
+
if (signal.aborted) {
|
|
39
|
+
return resolve(null);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
signal.addEventListener('abort', () => {
|
|
43
|
+
aborted = true;
|
|
44
|
+
return resolve(null);
|
|
45
|
+
}, { once: true });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (batchSize != null) {
|
|
49
|
+
if (typeof batchSize !== 'number') {
|
|
50
|
+
throw new TypeError('batchSize must be a number');
|
|
51
|
+
} else if (!Number.isInteger(batchSize)) {
|
|
52
|
+
throw new TypeError('batchSize must be an integer');
|
|
53
|
+
} else if (batchSize < 1) {
|
|
54
|
+
throw new TypeError('batchSize must be at least 1');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
iterate((err, res) => {
|
|
59
|
+
if (err != null) {
|
|
60
|
+
return reject(err);
|
|
61
|
+
}
|
|
62
|
+
resolve(res);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
function iterate(finalCallback) {
|
|
67
|
+
let handleResultsInProgress = 0;
|
|
68
|
+
let currentDocumentIndex = 0;
|
|
69
|
+
|
|
70
|
+
let error = null;
|
|
71
|
+
for (let i = 0; i < parallel; ++i) {
|
|
72
|
+
enqueue(createFetch());
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function createFetch() {
|
|
76
|
+
let documentsBatch = [];
|
|
77
|
+
let drained = false;
|
|
78
|
+
|
|
79
|
+
return fetch;
|
|
80
|
+
|
|
81
|
+
function fetch(done) {
|
|
82
|
+
if (drained || aborted) {
|
|
83
|
+
return done();
|
|
84
|
+
} else if (error) {
|
|
85
|
+
return done();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
next(function(err, doc) {
|
|
89
|
+
if (error != null) {
|
|
90
|
+
return done();
|
|
91
|
+
}
|
|
92
|
+
if (err != null) {
|
|
93
|
+
if (err.name === 'MongoCursorExhaustedError') {
|
|
94
|
+
// We may end up calling `next()` multiple times on an exhausted
|
|
95
|
+
// cursor, which leads to an error. In case cursor is exhausted,
|
|
96
|
+
// just treat it as if the cursor returned no document, which is
|
|
97
|
+
// how a cursor indicates it is exhausted.
|
|
98
|
+
doc = null;
|
|
99
|
+
} else if (continueOnError) {
|
|
100
|
+
aggregatedErrors.push(err);
|
|
101
|
+
} else {
|
|
102
|
+
error = err;
|
|
103
|
+
finalCallback(err);
|
|
104
|
+
return done();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (doc == null) {
|
|
108
|
+
drained = true;
|
|
109
|
+
if (handleResultsInProgress <= 0) {
|
|
110
|
+
const finalErr = continueOnError ?
|
|
111
|
+
createEachAsyncMultiError(aggregatedErrors) :
|
|
112
|
+
error;
|
|
113
|
+
|
|
114
|
+
finalCallback(finalErr);
|
|
115
|
+
} else if (batchSize && documentsBatch.length) {
|
|
116
|
+
handleNextResult(documentsBatch, currentDocumentIndex++, handleNextResultCallBack);
|
|
117
|
+
}
|
|
118
|
+
return done();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
++handleResultsInProgress;
|
|
122
|
+
|
|
123
|
+
// Kick off the subsequent `next()` before handling the result, but
|
|
124
|
+
// make sure we know that we still have a result to handle re: #8422
|
|
125
|
+
immediate(() => done());
|
|
126
|
+
|
|
127
|
+
if (batchSize) {
|
|
128
|
+
documentsBatch.push(doc);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// If the current documents size is less than the provided batch size don't process the documents yet
|
|
132
|
+
if (batchSize && documentsBatch.length !== batchSize) {
|
|
133
|
+
immediate(() => enqueue(fetch));
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const docsToProcess = batchSize ? documentsBatch : doc;
|
|
138
|
+
|
|
139
|
+
function handleNextResultCallBack(err) {
|
|
140
|
+
if (batchSize) {
|
|
141
|
+
handleResultsInProgress -= documentsBatch.length;
|
|
142
|
+
documentsBatch = [];
|
|
143
|
+
} else {
|
|
144
|
+
--handleResultsInProgress;
|
|
145
|
+
}
|
|
146
|
+
if (err != null) {
|
|
147
|
+
if (continueOnError) {
|
|
148
|
+
aggregatedErrors.push(err);
|
|
149
|
+
} else {
|
|
150
|
+
error = err;
|
|
151
|
+
return finalCallback(err);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if ((drained || aborted) && handleResultsInProgress <= 0) {
|
|
155
|
+
const finalErr = continueOnError ?
|
|
156
|
+
createEachAsyncMultiError(aggregatedErrors) :
|
|
157
|
+
error;
|
|
158
|
+
return finalCallback(finalErr);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
immediate(() => enqueue(fetch));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
handleNextResult(docsToProcess, currentDocumentIndex++, handleNextResultCallBack);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function handleNextResult(doc, i, callback) {
|
|
171
|
+
let maybePromise;
|
|
172
|
+
try {
|
|
173
|
+
maybePromise = fn(doc, i);
|
|
174
|
+
} catch (err) {
|
|
175
|
+
return callback(err);
|
|
176
|
+
}
|
|
177
|
+
if (typeof maybePromise?.then === 'function') {
|
|
178
|
+
maybePromise.then(
|
|
179
|
+
function() { callback(null); },
|
|
180
|
+
function(error) {
|
|
181
|
+
callback(error || new Error('`eachAsync()` promise rejected without error'));
|
|
182
|
+
});
|
|
183
|
+
} else {
|
|
184
|
+
callback(null);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// `next()` can only execute one at a time, so make sure we always execute
|
|
190
|
+
// `next()` in series, while still allowing multiple `fn()` instances to run
|
|
191
|
+
// in parallel.
|
|
192
|
+
function asyncQueue() {
|
|
193
|
+
const _queue = [];
|
|
194
|
+
let inProgress = null;
|
|
195
|
+
let id = 0;
|
|
196
|
+
|
|
197
|
+
return function enqueue(fn) {
|
|
198
|
+
if (
|
|
199
|
+
inProgress === null &&
|
|
200
|
+
_queue.length === 0
|
|
201
|
+
) {
|
|
202
|
+
inProgress = id++;
|
|
203
|
+
return fn(_step);
|
|
204
|
+
}
|
|
205
|
+
_queue.push(fn);
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
function _step() {
|
|
209
|
+
if (_queue.length !== 0) {
|
|
210
|
+
inProgress = id++;
|
|
211
|
+
const fn = _queue.shift();
|
|
212
|
+
fn(_step);
|
|
213
|
+
} else {
|
|
214
|
+
inProgress = null;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function createEachAsyncMultiError(aggregatedErrors) {
|
|
220
|
+
if (aggregatedErrors.length === 0) {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return new EachAsyncMultiError(aggregatedErrors);
|
|
225
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports = applyEmbeddedDiscriminators;
|
|
4
|
+
|
|
5
|
+
function applyEmbeddedDiscriminators(schema, seen = new WeakSet(), overwriteExisting = false) {
|
|
6
|
+
if (seen.has(schema)) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
seen.add(schema);
|
|
10
|
+
for (const path of Object.keys(schema.paths)) {
|
|
11
|
+
const schemaType = schema.paths[path];
|
|
12
|
+
if (!schemaType.schema) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
applyEmbeddedDiscriminators(schemaType.schema, seen);
|
|
16
|
+
if (!schemaType.schema._applyDiscriminators) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (schemaType._appliedDiscriminators && !overwriteExisting) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
for (const discriminatorKey of schemaType.schema._applyDiscriminators.keys()) {
|
|
23
|
+
const {
|
|
24
|
+
schema: discriminatorSchema,
|
|
25
|
+
options
|
|
26
|
+
} = schemaType.schema._applyDiscriminators.get(discriminatorKey);
|
|
27
|
+
applyEmbeddedDiscriminators(discriminatorSchema, seen);
|
|
28
|
+
schemaType.discriminator(
|
|
29
|
+
discriminatorKey,
|
|
30
|
+
discriminatorSchema,
|
|
31
|
+
overwriteExisting ? { ...options, overwriteExisting: true } : options
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
schemaType._appliedDiscriminators = true;
|
|
35
|
+
}
|
|
36
|
+
}
|