@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,33 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const specialProperties = require('../specialProperties');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
module.exports = function setDottedPath(obj, path, val) {
|
|
7
|
+
if (path.indexOf('.') === -1) {
|
|
8
|
+
if (specialProperties.has(path)) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
obj[path] = val;
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const parts = path.split('.');
|
|
16
|
+
|
|
17
|
+
const last = parts.pop();
|
|
18
|
+
let cur = obj;
|
|
19
|
+
for (const part of parts) {
|
|
20
|
+
if (specialProperties.has(part)) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (cur[part] == null) {
|
|
24
|
+
cur[part] = {};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
cur = cur[part];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!specialProperties.has(last)) {
|
|
31
|
+
cur[last] = val;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports = pluralize;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Pluralization rules.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
exports.pluralization = [
|
|
10
|
+
[/human$/gi, 'humans'],
|
|
11
|
+
[/(m|wom)an$/gi, '$1en'],
|
|
12
|
+
[/(pe)rson$/gi, '$1ople'],
|
|
13
|
+
[/(child)$/gi, '$1ren'],
|
|
14
|
+
[/^(ox)$/gi, '$1en'],
|
|
15
|
+
[/(ax|test)is$/gi, '$1es'],
|
|
16
|
+
[/(octop|cact|foc|fung|nucle)us$/gi, '$1i'],
|
|
17
|
+
[/(alias|status|virus)$/gi, '$1es'],
|
|
18
|
+
[/(bu)s$/gi, '$1ses'],
|
|
19
|
+
[/(buffal|tomat|potat)o$/gi, '$1oes'],
|
|
20
|
+
[/([ti])um$/gi, '$1a'],
|
|
21
|
+
[/sis$/gi, 'ses'],
|
|
22
|
+
[/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
|
|
23
|
+
[/(hive)$/gi, '$1s'],
|
|
24
|
+
[/([^aeiouy]|qu)y$/gi, '$1ies'],
|
|
25
|
+
[/(x|ch|ss|sh)$/gi, '$1es'],
|
|
26
|
+
[/(matr|vert|ind)ix|ex$/gi, '$1ices'],
|
|
27
|
+
[/([m|l])ouse$/gi, '$1ice'],
|
|
28
|
+
[/(kn|w|l)ife$/gi, '$1ives'],
|
|
29
|
+
[/(quiz)$/gi, '$1zes'],
|
|
30
|
+
[/^goose$/i, 'geese'],
|
|
31
|
+
[/s$/gi, 's'],
|
|
32
|
+
[/([^a-z])$/, '$1'],
|
|
33
|
+
[/$/gi, 's']
|
|
34
|
+
];
|
|
35
|
+
const rules = exports.pluralization;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Uncountable words.
|
|
39
|
+
*
|
|
40
|
+
* These words are applied while processing the argument to `toCollectionName`.
|
|
41
|
+
* @api public
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
exports.uncountables = [
|
|
45
|
+
'advice',
|
|
46
|
+
'energy',
|
|
47
|
+
'excretion',
|
|
48
|
+
'digestion',
|
|
49
|
+
'cooperation',
|
|
50
|
+
'health',
|
|
51
|
+
'justice',
|
|
52
|
+
'labour',
|
|
53
|
+
'machinery',
|
|
54
|
+
'equipment',
|
|
55
|
+
'information',
|
|
56
|
+
'pollution',
|
|
57
|
+
'sewage',
|
|
58
|
+
'paper',
|
|
59
|
+
'money',
|
|
60
|
+
'species',
|
|
61
|
+
'series',
|
|
62
|
+
'rain',
|
|
63
|
+
'rice',
|
|
64
|
+
'fish',
|
|
65
|
+
'sheep',
|
|
66
|
+
'moose',
|
|
67
|
+
'deer',
|
|
68
|
+
'news',
|
|
69
|
+
'expertise',
|
|
70
|
+
'status',
|
|
71
|
+
'media'
|
|
72
|
+
];
|
|
73
|
+
const uncountables = exports.uncountables;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Pluralize function.
|
|
77
|
+
*
|
|
78
|
+
* @author TJ Holowaychuk (extracted from _ext.js_)
|
|
79
|
+
* @param {String} string to pluralize
|
|
80
|
+
* @api private
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
function pluralize(str) {
|
|
84
|
+
let found;
|
|
85
|
+
str = str.toLowerCase();
|
|
86
|
+
if (!~uncountables.indexOf(str)) {
|
|
87
|
+
found = rules.filter(function(rule) {
|
|
88
|
+
return str.match(rule[0]);
|
|
89
|
+
});
|
|
90
|
+
if (found[0]) {
|
|
91
|
+
return str.replace(found[0][0], found[0][1]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return str;
|
|
95
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const clone = require('../../helpers/clone');
|
|
4
|
+
const leanPopulateMap = require('./leanPopulateMap');
|
|
5
|
+
const modelSymbol = require('../symbols').modelSymbol;
|
|
6
|
+
const utils = require('../../utils');
|
|
7
|
+
|
|
8
|
+
module.exports = assignRawDocsToIdStructure;
|
|
9
|
+
|
|
10
|
+
const kHasArray = Symbol('mongoose#assignRawDocsToIdStructure#hasArray');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Assign `vals` returned by mongo query to the `rawIds`
|
|
14
|
+
* structure returned from utils.getVals() honoring
|
|
15
|
+
* query sort order if specified by user.
|
|
16
|
+
*
|
|
17
|
+
* This can be optimized.
|
|
18
|
+
*
|
|
19
|
+
* Rules:
|
|
20
|
+
*
|
|
21
|
+
* if the value of the path is not an array, use findOne rules, else find.
|
|
22
|
+
* for findOne the results are assigned directly to doc path (including null results).
|
|
23
|
+
* for find, if user specified sort order, results are assigned directly
|
|
24
|
+
* else documents are put back in original order of array if found in results
|
|
25
|
+
*
|
|
26
|
+
* @param {Array} rawIds
|
|
27
|
+
* @param {Array} resultDocs
|
|
28
|
+
* @param {Array} resultOrder
|
|
29
|
+
* @param {Object} options
|
|
30
|
+
* @param {Boolean} recursed
|
|
31
|
+
* @api private
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, recursed) {
|
|
35
|
+
// honor user specified sort order, unless we're populating a single
|
|
36
|
+
// virtual underneath an array (e.g. populating `employees.mostRecentShift` where
|
|
37
|
+
// `mostRecentShift` is a virtual with `justOne`)
|
|
38
|
+
const newOrder = [];
|
|
39
|
+
const sorting = options.isVirtual && options.justOne && rawIds.length > 1
|
|
40
|
+
? false :
|
|
41
|
+
options.sort && rawIds.length > 1;
|
|
42
|
+
const nullIfNotFound = options.$nullIfNotFound;
|
|
43
|
+
let doc;
|
|
44
|
+
let sid;
|
|
45
|
+
let id;
|
|
46
|
+
|
|
47
|
+
if (utils.isMongooseArray(rawIds)) {
|
|
48
|
+
rawIds = rawIds.__array;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let i = 0;
|
|
52
|
+
const len = rawIds.length;
|
|
53
|
+
|
|
54
|
+
if (sorting && recursed && options[kHasArray] === undefined) {
|
|
55
|
+
options[kHasArray] = false;
|
|
56
|
+
for (const key in resultOrder) {
|
|
57
|
+
if (Array.isArray(resultOrder[key])) {
|
|
58
|
+
options[kHasArray] = true;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
for (i = 0; i < len; ++i) {
|
|
65
|
+
id = rawIds[i];
|
|
66
|
+
|
|
67
|
+
if (Array.isArray(id)) {
|
|
68
|
+
// handle [ [id0, id2], [id3] ]
|
|
69
|
+
assignRawDocsToIdStructure(id, resultDocs, resultOrder, options, true);
|
|
70
|
+
newOrder.push(id);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (id === null && sorting === false) {
|
|
75
|
+
// keep nulls for findOne unless sorting, which always
|
|
76
|
+
// removes them (backward compat)
|
|
77
|
+
newOrder.push(id);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
sid = String(id);
|
|
82
|
+
doc = resultDocs[sid];
|
|
83
|
+
// If user wants separate copies of same doc, use this option
|
|
84
|
+
if (options.clone && doc != null) {
|
|
85
|
+
if (options.lean) {
|
|
86
|
+
const _model = leanPopulateMap.get(doc);
|
|
87
|
+
doc = clone(doc);
|
|
88
|
+
leanPopulateMap.set(doc, _model);
|
|
89
|
+
} else {
|
|
90
|
+
doc = doc.constructor.hydrate(doc._doc);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (recursed) {
|
|
95
|
+
if (doc) {
|
|
96
|
+
if (sorting) {
|
|
97
|
+
const _resultOrder = resultOrder[sid];
|
|
98
|
+
if (options[kHasArray]) {
|
|
99
|
+
// If result arrays, rely on the MongoDB server response for ordering
|
|
100
|
+
newOrder.push(doc);
|
|
101
|
+
} else {
|
|
102
|
+
newOrder[_resultOrder] = doc;
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
newOrder.push(doc);
|
|
106
|
+
}
|
|
107
|
+
} else if (id?.[modelSymbol] != null) {
|
|
108
|
+
newOrder.push(id);
|
|
109
|
+
} else {
|
|
110
|
+
newOrder.push(options.retainNullValues || nullIfNotFound ? null : id);
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
// apply findOne behavior - if document in results, assign, else assign null
|
|
114
|
+
newOrder[i] = doc || null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
rawIds.length = 0;
|
|
119
|
+
if (newOrder.length) {
|
|
120
|
+
// reassign the documents based on corrected order
|
|
121
|
+
|
|
122
|
+
// forEach skips over sparse entries in arrays so we
|
|
123
|
+
// can safely use this to our advantage dealing with sorted
|
|
124
|
+
// result sets too.
|
|
125
|
+
newOrder.forEach(function(doc, i) {
|
|
126
|
+
rawIds[i] = doc;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const MongooseMap = require('../../types/map');
|
|
4
|
+
const SkipPopulateValue = require('./skipPopulateValue');
|
|
5
|
+
const assignRawDocsToIdStructure = require('./assignRawDocsToIdStructure');
|
|
6
|
+
const get = require('../get');
|
|
7
|
+
const getVirtual = require('./getVirtual');
|
|
8
|
+
const leanPopulateMap = require('./leanPopulateMap');
|
|
9
|
+
const lookupLocalFields = require('./lookupLocalFields');
|
|
10
|
+
const markArraySubdocsPopulated = require('./markArraySubdocsPopulated');
|
|
11
|
+
const mpath = require('mpath');
|
|
12
|
+
const sift = require('sift').default;
|
|
13
|
+
const utils = require('../../utils');
|
|
14
|
+
const { populateModelSymbol } = require('../symbols');
|
|
15
|
+
|
|
16
|
+
module.exports = function assignVals(o) {
|
|
17
|
+
// Options that aren't explicitly listed in `populateOptions`
|
|
18
|
+
const userOptions = Object.assign({}, get(o, 'allOptions.options.options'), get(o, 'allOptions.options'));
|
|
19
|
+
// `o.options` contains options explicitly listed in `populateOptions`, like
|
|
20
|
+
// `match` and `limit`.
|
|
21
|
+
const populateOptions = Object.assign({}, o.options, userOptions, {
|
|
22
|
+
justOne: o.justOne,
|
|
23
|
+
isVirtual: o.isVirtual
|
|
24
|
+
});
|
|
25
|
+
populateOptions.$nullIfNotFound = o.isVirtual;
|
|
26
|
+
const populatedModel = o.populatedModel;
|
|
27
|
+
|
|
28
|
+
const originalIds = [].concat(o.rawIds);
|
|
29
|
+
|
|
30
|
+
// replace the original ids in our intermediate _ids structure
|
|
31
|
+
// with the documents found by query
|
|
32
|
+
o.allIds = [].concat(o.allIds);
|
|
33
|
+
assignRawDocsToIdStructure(o.rawIds, o.rawDocs, o.rawOrder, populateOptions);
|
|
34
|
+
|
|
35
|
+
// now update the original documents being populated using the
|
|
36
|
+
// result structure that contains real documents.
|
|
37
|
+
const docs = o.docs;
|
|
38
|
+
const rawIds = o.rawIds;
|
|
39
|
+
const options = o.options;
|
|
40
|
+
const count = o.count && o.isVirtual;
|
|
41
|
+
let i;
|
|
42
|
+
let setValueIndex = 0;
|
|
43
|
+
|
|
44
|
+
function setValue(val) {
|
|
45
|
+
++setValueIndex;
|
|
46
|
+
if (count) {
|
|
47
|
+
return val;
|
|
48
|
+
}
|
|
49
|
+
if (val instanceof SkipPopulateValue) {
|
|
50
|
+
return val.val;
|
|
51
|
+
}
|
|
52
|
+
if (val === void 0) {
|
|
53
|
+
return val;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const _allIds = o.allIds[i];
|
|
57
|
+
|
|
58
|
+
if (o.path.endsWith('.$*')) {
|
|
59
|
+
// Skip maps re: gh-12494
|
|
60
|
+
return valueFilter(val, options, populateOptions, _allIds);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (o.justOne === true && Array.isArray(val)) {
|
|
64
|
+
// Might be an embedded discriminator (re: gh-9244) with multiple models, so make sure to pick the right
|
|
65
|
+
// model before assigning.
|
|
66
|
+
const ret = [];
|
|
67
|
+
for (const doc of val) {
|
|
68
|
+
const _docPopulatedModel = leanPopulateMap.get(doc);
|
|
69
|
+
if (_docPopulatedModel == null || _docPopulatedModel === populatedModel) {
|
|
70
|
+
ret.push(doc);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Since we don't want to have to create a new mongoosearray, make sure to
|
|
74
|
+
// modify the array in place
|
|
75
|
+
while (val.length > ret.length) {
|
|
76
|
+
Array.prototype.pop.apply(val, []);
|
|
77
|
+
}
|
|
78
|
+
for (let i = 0; i < ret.length; ++i) {
|
|
79
|
+
val[i] = ret[i];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return valueFilter(val[0], options, populateOptions, _allIds);
|
|
83
|
+
} else if (o.justOne === false && !Array.isArray(val)) {
|
|
84
|
+
return valueFilter([val], options, populateOptions, _allIds);
|
|
85
|
+
} else if (o.justOne === true && !Array.isArray(val) && Array.isArray(_allIds)) {
|
|
86
|
+
return valueFilter(val, options, populateOptions, val == null ? val : _allIds[setValueIndex - 1]);
|
|
87
|
+
}
|
|
88
|
+
return valueFilter(val, options, populateOptions, _allIds);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
for (i = 0; i < docs.length; ++i) {
|
|
92
|
+
setValueIndex = 0;
|
|
93
|
+
const _path = o.path.endsWith('.$*') ? o.path.slice(0, -3) : o.path;
|
|
94
|
+
const existingVal = mpath.get(_path, docs[i], lookupLocalFields);
|
|
95
|
+
if (existingVal == null && !getVirtual(o.originalModel.schema, _path)) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let valueToSet;
|
|
100
|
+
if (count) {
|
|
101
|
+
valueToSet = numDocs(rawIds[i]);
|
|
102
|
+
} else if (Array.isArray(o.match)) {
|
|
103
|
+
valueToSet = Array.isArray(rawIds[i]) ?
|
|
104
|
+
rawIds[i].filter(v => v == null || sift(o.match[i])(v)) :
|
|
105
|
+
[rawIds[i]].filter(v => v == null || sift(o.match[i])(v))[0];
|
|
106
|
+
} else {
|
|
107
|
+
valueToSet = rawIds[i];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// If we're populating a map, the existing value will be an object, so
|
|
111
|
+
// we need to transform again
|
|
112
|
+
const originalSchema = o.originalModel.schema;
|
|
113
|
+
const isDoc = get(docs[i], '$__', null) != null;
|
|
114
|
+
let isMap = isDoc ?
|
|
115
|
+
existingVal instanceof Map :
|
|
116
|
+
utils.isPOJO(existingVal);
|
|
117
|
+
// If we pass the first check, also make sure the local field's schematype
|
|
118
|
+
// is map (re: gh-6460)
|
|
119
|
+
isMap = isMap && get(originalSchema._getSchema(_path), '$isSchemaMap');
|
|
120
|
+
if (!o.isVirtual && isMap) {
|
|
121
|
+
const _keys = existingVal instanceof Map ?
|
|
122
|
+
Array.from(existingVal.keys()) :
|
|
123
|
+
Object.keys(existingVal);
|
|
124
|
+
valueToSet = valueToSet.reduce((cur, v, i) => {
|
|
125
|
+
cur.set(_keys[i], v);
|
|
126
|
+
return cur;
|
|
127
|
+
}, new Map());
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (isDoc && Array.isArray(valueToSet)) {
|
|
131
|
+
for (const val of valueToSet) {
|
|
132
|
+
if (val?.$__ != null) {
|
|
133
|
+
val.$__.parent = docs[i];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
} else if (isDoc && valueToSet?.$__ != null) {
|
|
137
|
+
valueToSet.$__.parent = docs[i];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (o.isVirtual && isDoc) {
|
|
141
|
+
docs[i].$populated(_path, o.justOne ? originalIds[0] : originalIds, o.allOptions);
|
|
142
|
+
// If virtual populate and doc is already init-ed, need to walk through
|
|
143
|
+
// the actual doc to set rather than setting `_doc` directly
|
|
144
|
+
if (Array.isArray(valueToSet)) {
|
|
145
|
+
valueToSet = valueToSet.map(v => v == null ? void 0 : v);
|
|
146
|
+
}
|
|
147
|
+
mpath.set(
|
|
148
|
+
_path,
|
|
149
|
+
valueToSet,
|
|
150
|
+
docs[i],
|
|
151
|
+
// Handle setting paths underneath maps using $* by converting arrays into maps of values
|
|
152
|
+
function lookup(obj, part, val) {
|
|
153
|
+
if (arguments.length >= 3) {
|
|
154
|
+
obj[part] = val;
|
|
155
|
+
return obj[part];
|
|
156
|
+
}
|
|
157
|
+
if (obj instanceof Map && part === '$*') {
|
|
158
|
+
return [...obj.values()];
|
|
159
|
+
}
|
|
160
|
+
return obj[part];
|
|
161
|
+
},
|
|
162
|
+
setValue,
|
|
163
|
+
false
|
|
164
|
+
);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const parts = _path.split('.');
|
|
169
|
+
let cur = docs[i];
|
|
170
|
+
for (let j = 0; j < parts.length - 1; ++j) {
|
|
171
|
+
// If we get to an array with a dotted path, like `arr.foo`, don't set
|
|
172
|
+
// `foo` on the array.
|
|
173
|
+
if (Array.isArray(cur) && !utils.isArrayIndex(parts[j])) {
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (parts[j] === '$*') {
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (cur[parts[j]] == null) {
|
|
182
|
+
// If nothing to set, avoid creating an unnecessary array. Otherwise
|
|
183
|
+
// we'll end up with a single doc in the array with only defaults.
|
|
184
|
+
// See gh-8342, gh-8455
|
|
185
|
+
const curPath = parts.slice(0, j + 1).join('.');
|
|
186
|
+
const schematype = originalSchema._getSchema(curPath);
|
|
187
|
+
if (valueToSet == null && schematype?.$isMongooseArray) {
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
cur[parts[j]] = {};
|
|
191
|
+
}
|
|
192
|
+
cur = cur[parts[j]];
|
|
193
|
+
// If the property in MongoDB is a primitive, we won't be able to populate
|
|
194
|
+
// the nested path, so skip it. See gh-7545
|
|
195
|
+
if (typeof cur !== 'object') {
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (docs[i].$__) {
|
|
200
|
+
o.allOptions.options[populateModelSymbol] = o.allOptions.model;
|
|
201
|
+
docs[i].$populated(_path, o.unpopulatedValues[i], o.allOptions.options);
|
|
202
|
+
|
|
203
|
+
if (valueToSet?.$__ != null) {
|
|
204
|
+
valueToSet.$__.wasPopulated = { value: o.unpopulatedValues[i] };
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (valueToSet instanceof Map && !valueToSet.$isMongooseMap) {
|
|
208
|
+
valueToSet = new MongooseMap(valueToSet, _path, docs[i], docs[i].schema.path(_path).$__schemaType);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// If lean, need to check that each individual virtual respects
|
|
213
|
+
// `justOne`, because you may have a populated virtual with `justOne`
|
|
214
|
+
// underneath an array. See gh-6867
|
|
215
|
+
mpath.set(_path, valueToSet, docs[i], lookupLocalFields, setValue, false);
|
|
216
|
+
|
|
217
|
+
if (docs[i].$__) {
|
|
218
|
+
markArraySubdocsPopulated(docs[i], [o.allOptions.options]);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
function numDocs(v) {
|
|
224
|
+
if (Array.isArray(v)) {
|
|
225
|
+
// If setting underneath an array of populated subdocs, we may have an
|
|
226
|
+
// array of arrays. See gh-7573
|
|
227
|
+
if (v.some(el => Array.isArray(el) || el === null)) {
|
|
228
|
+
return v.map(el => {
|
|
229
|
+
if (el == null) {
|
|
230
|
+
return 0;
|
|
231
|
+
}
|
|
232
|
+
if (Array.isArray(el)) {
|
|
233
|
+
return el.filter(el => el != null).length;
|
|
234
|
+
}
|
|
235
|
+
return 1;
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
return v.filter(el => el != null).length;
|
|
239
|
+
}
|
|
240
|
+
return v == null ? 0 : 1;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* 1) Apply backwards compatible find/findOne behavior to sub documents
|
|
245
|
+
*
|
|
246
|
+
* find logic:
|
|
247
|
+
* a) filter out non-documents
|
|
248
|
+
* b) remove _id from sub docs when user specified
|
|
249
|
+
*
|
|
250
|
+
* findOne
|
|
251
|
+
* a) if no doc found, set to null
|
|
252
|
+
* b) remove _id from sub docs when user specified
|
|
253
|
+
*
|
|
254
|
+
* 2) Remove _ids when specified by users query.
|
|
255
|
+
*
|
|
256
|
+
* background:
|
|
257
|
+
* _ids are left in the query even when user excludes them so
|
|
258
|
+
* that population mapping can occur.
|
|
259
|
+
* @param {Any} val
|
|
260
|
+
* @param {Object} assignmentOpts
|
|
261
|
+
* @param {Object} populateOptions
|
|
262
|
+
* @param {Function} [populateOptions.transform]
|
|
263
|
+
* @param {Boolean} allIds
|
|
264
|
+
* @api private
|
|
265
|
+
*/
|
|
266
|
+
|
|
267
|
+
function valueFilter(val, assignmentOpts, populateOptions, allIds) {
|
|
268
|
+
const userSpecifiedTransform = typeof populateOptions.transform === 'function';
|
|
269
|
+
const transform = userSpecifiedTransform ? populateOptions.transform : v => v;
|
|
270
|
+
if (Array.isArray(val)) {
|
|
271
|
+
// find logic
|
|
272
|
+
const ret = [];
|
|
273
|
+
const numValues = val.length;
|
|
274
|
+
for (let i = 0; i < numValues; ++i) {
|
|
275
|
+
let subdoc = val[i];
|
|
276
|
+
const _allIds = Array.isArray(allIds) ? allIds[i] : allIds;
|
|
277
|
+
if (!isPopulatedObject(subdoc) && (!populateOptions.retainNullValues || subdoc != null) && !userSpecifiedTransform) {
|
|
278
|
+
continue;
|
|
279
|
+
} else if (!populateOptions.retainNullValues && subdoc == null) {
|
|
280
|
+
continue;
|
|
281
|
+
} else if (userSpecifiedTransform) {
|
|
282
|
+
subdoc = transform(isPopulatedObject(subdoc) ? subdoc : null, _allIds);
|
|
283
|
+
}
|
|
284
|
+
maybeRemoveId(subdoc, assignmentOpts);
|
|
285
|
+
ret.push(subdoc);
|
|
286
|
+
if (assignmentOpts.originalLimit &&
|
|
287
|
+
ret.length >= assignmentOpts.originalLimit) {
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const rLen = ret.length;
|
|
293
|
+
// Since we don't want to have to create a new mongoosearray, make sure to
|
|
294
|
+
// modify the array in place
|
|
295
|
+
while (val.length > rLen) {
|
|
296
|
+
Array.prototype.pop.apply(val, []);
|
|
297
|
+
}
|
|
298
|
+
let i = 0;
|
|
299
|
+
if (utils.isMongooseArray(val)) {
|
|
300
|
+
for (i = 0; i < rLen; ++i) {
|
|
301
|
+
val.set(i, ret[i], true);
|
|
302
|
+
}
|
|
303
|
+
} else {
|
|
304
|
+
for (i = 0; i < rLen; ++i) {
|
|
305
|
+
val[i] = ret[i];
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return val;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// findOne
|
|
312
|
+
if (isPopulatedObject(val) || utils.isPOJO(val)) {
|
|
313
|
+
maybeRemoveId(val, assignmentOpts);
|
|
314
|
+
return transform(val, allIds);
|
|
315
|
+
}
|
|
316
|
+
if (val instanceof Map) {
|
|
317
|
+
return val;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (populateOptions.justOne === false) {
|
|
321
|
+
return [];
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return val == null ? transform(val, allIds) : transform(null, allIds);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Remove _id from `subdoc` if user specified "lean" query option
|
|
329
|
+
* @param {Document} subdoc
|
|
330
|
+
* @param {Object} assignmentOpts
|
|
331
|
+
* @api private
|
|
332
|
+
*/
|
|
333
|
+
|
|
334
|
+
function maybeRemoveId(subdoc, assignmentOpts) {
|
|
335
|
+
if (subdoc != null && assignmentOpts.excludeId) {
|
|
336
|
+
if (typeof subdoc.$__setValue === 'function') {
|
|
337
|
+
delete subdoc._doc._id;
|
|
338
|
+
} else {
|
|
339
|
+
delete subdoc._id;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Determine if `obj` is something we can set a populated path to. Can be a
|
|
346
|
+
* document, a lean document, or an array/map that contains docs.
|
|
347
|
+
* @param {Any} obj
|
|
348
|
+
* @api private
|
|
349
|
+
*/
|
|
350
|
+
|
|
351
|
+
function isPopulatedObject(obj) {
|
|
352
|
+
if (obj == null) {
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return Array.isArray(obj) ||
|
|
357
|
+
obj.$isMongooseMap ||
|
|
358
|
+
obj.$__ != null ||
|
|
359
|
+
leanPopulateMap.has(obj);
|
|
360
|
+
}
|