@lykmapipo/mongoose-common 0.38.3 → 0.40.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,163 +0,0 @@
1
- 'use strict';
2
-
3
- /* dependencies */
4
- const _ = require('lodash');
5
- const { uniq } = require('@lykmapipo/common');
6
- const mongoose = require('mongoose-valid8');
7
-
8
- /**
9
- * @function isUniqueError
10
- * @name isUniqueError
11
- * @description Check if the given error is a unique mongodb error.
12
- * @param {Object} error valid error object to test.
13
- * @return {Boolean} true if and only if it is an unique error.
14
- * @returns {Object}
15
- * @version 0.2.0
16
- * @since 0.1.0
17
- */
18
- const isUniqueError = (error) => {
19
- return (
20
- error &&
21
- (error.name === 'BulkWriteError' || error.name === 'MongoError') &&
22
- (error.code === 11000 || error.code === 11001) &&
23
- !_.isEmpty(error.message)
24
- );
25
- };
26
-
27
- /**
28
- * @function parseErrorPaths
29
- * @name parseErrorPaths
30
- * @description Parse paths found in unique mongodb error.
31
- * @param {Schema} schema valid mongoose schema.
32
- * @param {Error} error valid mongodb error.
33
- * @return {String[]} found paths in error.
34
- * @version 0.19.0
35
- * @since 0.1.0
36
- */
37
- const parseErrorPaths = (schema, error) => {
38
- // back off if no error message
39
- if (!error.message) {
40
- return [];
41
- }
42
-
43
- // obtain paths from error message
44
- let paths = _.nth(error.message.match(/index: (.+?) dup key:/), 1) || '';
45
- paths = paths.split('$').pop();
46
-
47
- // handle compound unique paths index
48
- paths = [].concat(paths.split('_'));
49
-
50
- // in case for id ensure _id too and compact paths
51
- paths = uniq([
52
- ...paths,
53
- ..._.map(paths, (pathName) => (pathName === 'id' ? '_id' : pathName)),
54
- ]);
55
-
56
- // ensure paths are within schema
57
- paths = _.filter(paths, (pathName) => !_.isEmpty(schema.path(pathName)));
58
-
59
- // return found paths
60
- return paths;
61
- };
62
-
63
- /**
64
- * @function parseErrorValues
65
- * @name parseErrorValues
66
- * @description Parse paths value found in unique mongodb error.
67
- * @param {String[]} paths paths found in unique mongodb error.
68
- * @param {Error} error valid mongodb error.
69
- * @return {String[]} found paths value from error.
70
- * @version 0.19.0
71
- * @since 0.1.0
72
- */
73
- const parseErrorValues = (paths, error) => {
74
- // back off if no error message
75
- if (!error.message) {
76
- return [];
77
- }
78
-
79
- // obtain paths value
80
- let values = _.nth(error.message.match(/dup key: { (.+?) }/), 1) || '';
81
- values = uniq(
82
- [].concat(values.match(/'(.+?)'/g)).concat(values.match(/"(.+?)"/g))
83
- ); // enclosed with quotes
84
- values = values.map((v) => v.replace(/^"(.+?)"$/, '$1')); //double quotes
85
- values = values.map((v) => v.replace(/^'(.+?)'$/, '$1')); //single quotes
86
- values = paths.length === 1 ? [values.join(' ')] : values;
87
-
88
- // return parsed paths values
89
- return values;
90
- };
91
-
92
- /**
93
- * @function handleUniqueError
94
- * @name handleUniqueError
95
- * @description Handle mongodb unique error and transform to mongoose error
96
- * @param {Schema} schema valid mongoose schema
97
- * @version 0.2.0
98
- * @since 0.1.0
99
- */
100
- const handleUniqueError = (schema) => {
101
- const normalizeUniqueError = (error, doc, next) => {
102
- // obtain current instance
103
- const instance = doc || this;
104
-
105
- // continue if is not unique error
106
- if (!isUniqueError(error)) {
107
- return next(error);
108
- }
109
-
110
- // obtain index name
111
- const indexName =
112
- _.nth(error.message.match(/index: (.+?) dup key:/), 1) || '';
113
-
114
- // obtain unique paths from error
115
- const paths = parseErrorPaths(schema, error);
116
-
117
- // obtain paths value from error
118
- const values = parseErrorValues(paths, error);
119
-
120
- // build mongoose validations error bag
121
- if (!_.isEmpty(paths) && !_.isEmpty(values)) {
122
- const errors = {};
123
- _.forEach(paths, (pathName, index) => {
124
- // construct path error properties
125
- let pathValue = _.nth(values, index);
126
- if (_.isFunction(instance.get)) {
127
- pathValue = instance.get(pathName);
128
- }
129
- const props = {
130
- type: 'unique',
131
- path: pathName,
132
- value: pathValue,
133
- message: 'Path `{PATH}` ({VALUE}) is not unique.',
134
- reason: error.message,
135
- index: indexName,
136
- };
137
- // construct path validation error
138
- const pathError = new mongoose.Error.ValidatorError(props);
139
- pathError.index = indexName;
140
- errors[pathName] = pathError;
141
- });
142
-
143
- // build mongoose validation error
144
- error = new mongoose.Error.ValidationError();
145
- error.status = error.status || 400;
146
- error.errors = errors;
147
- }
148
-
149
- // continue with error
150
- next(error);
151
- };
152
-
153
- schema.post('save', normalizeUniqueError);
154
- schema.post('insertMany', normalizeUniqueError);
155
- schema.post('findOneAndReplace', normalizeUniqueError);
156
- schema.post('findOneAndUpdate', normalizeUniqueError);
157
- schema.post('replaceOne', normalizeUniqueError);
158
- schema.post('update', normalizeUniqueError);
159
- schema.post('updateMany', normalizeUniqueError);
160
- schema.post('updateOne', normalizeUniqueError);
161
- };
162
-
163
- module.exports = exports = handleUniqueError;
@@ -1,43 +0,0 @@
1
- 'use strict';
2
-
3
- /* dependencies */
4
- const _ = require('lodash');
5
-
6
- /**
7
- * @function path
8
- * @name path
9
- * @description obtain schema path from model
10
- * @param {Schema} schema valid mongoose schema instance
11
- * @param {String} value valid mongoose model schema path name
12
- * @returns {SchemaType}
13
- * @version 0.1.0
14
- * @since 0.1.0
15
- */
16
- const path = (schema) => {
17
- // register path
18
- const canNotGetPath = !_.isFunction(schema.statics.path);
19
- if (canNotGetPath) {
20
- schema.statics.path = function path(pathName) {
21
- // initalize path
22
- let _path;
23
-
24
- // tokenize path
25
- const paths = _.split(pathName, '.');
26
-
27
- // iterate on schema recursive to get path schema
28
- _.forEach(paths, function getPath(path) {
29
- // obtain schema to resolve path
30
- const _schema = _path ? _path.schema : schema;
31
- _path = _schema && _schema.path ? _schema.path(path) : undefined;
32
- });
33
-
34
- // fall back to direct path
35
- _path = _path || schema.path(pathName);
36
-
37
- // return found path
38
- return _path;
39
- };
40
- }
41
- };
42
-
43
- module.exports = exports = path;