@lykmapipo/mongoose-common 0.39.0 → 0.40.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.
@@ -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;