monastery 3.2.1 → 3.4.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/.eslintrc.json +1 -1
- package/changelog.md +4 -0
- package/docs/manager/index.md +5 -4
- package/docs/readme.md +4 -2
- package/lib/index.js +15 -3
- package/lib/model-crud.js +128 -88
- package/lib/model-validate.js +131 -97
- package/lib/model.js +15 -0
- package/lib/util.js +101 -72
- package/package.json +1 -1
- package/test/crud.js +240 -44
- package/test/util.js +237 -22
- package/test/validate.js +87 -3
package/test/validate.js
CHANGED
|
@@ -300,7 +300,7 @@ test('validation subdocument errors', async () => {
|
|
|
300
300
|
])
|
|
301
301
|
)
|
|
302
302
|
|
|
303
|
-
// Insert:
|
|
303
|
+
// Insert: Required subdocument property is ignored with a parent/grandparent specificed
|
|
304
304
|
await expect(user.validate({ animals: {} }, { validateUndefined: false })).resolves.toEqual({
|
|
305
305
|
animals: {},
|
|
306
306
|
})
|
|
@@ -1181,8 +1181,85 @@ test('validation option validateUndefined', async () => {
|
|
|
1181
1181
|
.resolves.toEqual({ names: [{}] })
|
|
1182
1182
|
})
|
|
1183
1183
|
|
|
1184
|
-
test('validation
|
|
1185
|
-
|
|
1184
|
+
test('validation update dot notation', async () => {
|
|
1185
|
+
// Only updates the fields that are passed in the data object, similar to $set. They don't
|
|
1186
|
+
// remove subdocument fields that are not present in the data object.
|
|
1187
|
+
const user = db.model('user_partialUpdate1', {
|
|
1188
|
+
fields: {
|
|
1189
|
+
name: { type: 'string' },
|
|
1190
|
+
address: {
|
|
1191
|
+
city: { type: 'string' },
|
|
1192
|
+
country: { type: 'string' },
|
|
1193
|
+
},
|
|
1194
|
+
},
|
|
1195
|
+
})
|
|
1196
|
+
const user2 = db.model('user_partialUpdate2', {
|
|
1197
|
+
fields: {
|
|
1198
|
+
name: { type: 'string' },
|
|
1199
|
+
address: {
|
|
1200
|
+
city: { type: 'string' },
|
|
1201
|
+
country: { type: 'string', required: true },
|
|
1202
|
+
},
|
|
1203
|
+
books: [{
|
|
1204
|
+
title: { type: 'string', required: true },
|
|
1205
|
+
pages: {
|
|
1206
|
+
count: { type: 'number', required: true },
|
|
1207
|
+
},
|
|
1208
|
+
}],
|
|
1209
|
+
},
|
|
1210
|
+
})
|
|
1211
|
+
|
|
1212
|
+
// Partial validate
|
|
1213
|
+
const validated1 = await user.validate({
|
|
1214
|
+
'address.city': 'Berlin2',
|
|
1215
|
+
'address': { city: 'Berlin' }, // preserved
|
|
1216
|
+
})
|
|
1217
|
+
expect(validated1).toEqual({
|
|
1218
|
+
'address': { city: 'Berlin' },
|
|
1219
|
+
'address.city': 'Berlin2',
|
|
1220
|
+
})
|
|
1221
|
+
|
|
1222
|
+
/// { partialUpdate: true }
|
|
1223
|
+
|
|
1224
|
+
// Order of fields, normal objects are ordered first
|
|
1225
|
+
expect(Object.keys(validated1)).toEqual(['address', 'address.city'])
|
|
1226
|
+
|
|
1227
|
+
// validate (update) throws required error for deep field (as normal)
|
|
1228
|
+
await expect(user2.validate({ 'address': { city: 'Berlin' }}, { update: true }))
|
|
1229
|
+
.rejects.toEqual(expect.any(Array))
|
|
1230
|
+
|
|
1231
|
+
// validate (update) works with dot notatation paths
|
|
1232
|
+
await expect(user2.validate({ 'address.city': 'Berlin2' }, { update: true }))
|
|
1233
|
+
.resolves.toEqual({ 'address.city': 'Berlin2' })
|
|
1234
|
+
|
|
1235
|
+
// validate (insert) still throws required errors, even with dot notatation paths
|
|
1236
|
+
await expect(user2.validate({ 'address.city': 'Berlin2' }))
|
|
1237
|
+
.rejects.toEqual(expect.any(Array))
|
|
1238
|
+
|
|
1239
|
+
// validate (update) works with dot notation array paths, and validates data
|
|
1240
|
+
await expect(user2.validate({ 'books.0.pages.count': '1' }, { update: true }))
|
|
1241
|
+
.resolves.toEqual({ 'books.0.pages.count': 1 })
|
|
1242
|
+
|
|
1243
|
+
// validate (update) works with positional array paths
|
|
1244
|
+
await expect(user2.validate({ 'books.$.pages.count': '2' }, { update: true }))
|
|
1245
|
+
.resolves.toEqual({ 'books.$.pages.count': 2 })
|
|
1246
|
+
|
|
1247
|
+
// Non-field dot notation paths removed
|
|
1248
|
+
await expect(user2.validate({ 'books.0.badfield': 2 }, { update: true }))
|
|
1249
|
+
.resolves.toEqual({})
|
|
1250
|
+
|
|
1251
|
+
// validate (update) should continue on throwing validation errors for dot notation array paths with subdocument values
|
|
1252
|
+
await expect(user2.validate({ 'books.$.pages': {} }, { update: true }))
|
|
1253
|
+
.rejects.toEqual([{
|
|
1254
|
+
'detail': 'This field is required.',
|
|
1255
|
+
'meta': { 'detailLong': undefined, 'field': 'count', 'model': 'user_partialUpdate2', 'rule': 'required' },
|
|
1256
|
+
'status': '400',
|
|
1257
|
+
'title': 'books.$.pages.count',
|
|
1258
|
+
}])
|
|
1259
|
+
})
|
|
1260
|
+
|
|
1261
|
+
test('validation hooks and option skipHooks', async () => {
|
|
1262
|
+
let user = db.model('user_validation_hooks', {
|
|
1186
1263
|
fields: {
|
|
1187
1264
|
first: { type: 'string'},
|
|
1188
1265
|
last: { type: 'string'},
|
|
@@ -1204,6 +1281,7 @@ test('validation hooks', async () => {
|
|
|
1204
1281
|
// Catch validate (a)synchronous errors thrown in function or through `next(err)`
|
|
1205
1282
|
await expect(user.validate({ first: '' })).rejects.toThrow('beforeValidate error 1..')
|
|
1206
1283
|
await expect(user.validate({ first: 'Martin' })).rejects.toThrow('beforeValidate error 2..')
|
|
1284
|
+
await expect(user.validate({ first: 'Martin' }, { skipHooks: true })).resolves.toEqual({ first: 'Martin' })
|
|
1207
1285
|
await expect(user.validate({ first: 'Martin', last: 'Luther' })).resolves.toEqual({
|
|
1208
1286
|
first: 'Martin',
|
|
1209
1287
|
last: 'Luther',
|
|
@@ -1212,6 +1290,10 @@ test('validation hooks', async () => {
|
|
|
1212
1290
|
// Catch insert (a)synchronous errors thrown in function or through `next(err)`
|
|
1213
1291
|
await expect(user.insert({ data: { first: '' } })).rejects.toThrow('beforeValidate error 1..')
|
|
1214
1292
|
await expect(user.insert({ data: { first: 'Martin' } })).rejects.toThrow('beforeValidate error 2..')
|
|
1293
|
+
await expect(user.insert({ data: { first: 'Martin' }, skipHooks: true })).resolves.toEqual({
|
|
1294
|
+
_id: expect.any(Object),
|
|
1295
|
+
first: 'Martin',
|
|
1296
|
+
})
|
|
1215
1297
|
await expect(user.insert({ data: { first: 'Martin', last: 'Luther' } })).resolves.toEqual({
|
|
1216
1298
|
_id: expect.any(Object),
|
|
1217
1299
|
first: 'Martin',
|
|
@@ -1223,6 +1305,8 @@ test('validation hooks', async () => {
|
|
|
1223
1305
|
.rejects.toThrow('beforeValidate error 1..')
|
|
1224
1306
|
await expect(user.update({ query: userDoc._id, data: { first: 'Martin' } }))
|
|
1225
1307
|
.rejects.toThrow('beforeValidate error 2..')
|
|
1308
|
+
await expect(user.update({ query: userDoc._id, data: { first: 'Martin' }, skipHooks: true }))
|
|
1309
|
+
.resolves.toEqual({ first: 'Martin' })
|
|
1226
1310
|
await expect(user.update({ query: userDoc._id, data: { first: 'Martin', last: 'Luther' } }))
|
|
1227
1311
|
.resolves.toEqual({
|
|
1228
1312
|
first: 'Martin',
|