monastery 1.35.0 → 1.36.2
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 +2 -1
- package/.travis.yml +1 -1
- package/changelog.md +32 -1
- package/docs/{schema/rules.md → definition/field-rules.md} +6 -4
- package/docs/definition/index.md +338 -0
- package/docs/image-plugin.md +16 -16
- package/docs/manager/index.md +8 -8
- package/docs/manager/model.md +4 -3
- package/docs/manager/models.md +1 -1
- package/docs/model/find.md +31 -29
- package/docs/model/findOne.md +3 -4
- package/docs/model/findOneAndUpdate.md +42 -0
- package/docs/model/index.md +2 -2
- package/docs/model/insert.md +22 -20
- package/docs/model/remove.md +3 -3
- package/docs/model/update.md +11 -10
- package/docs/model/validate.md +22 -25
- package/docs/readme.md +8 -7
- package/lib/index.js +36 -34
- package/lib/model-crud.js +89 -25
- package/lib/model-validate.js +28 -22
- package/lib/model.js +2 -3
- package/lib/monk-monkey-patches.js +73 -0
- package/lib/util.js +20 -18
- package/package.json +1 -1
- package/test/blacklisting.js +132 -177
- package/test/crud.js +83 -25
- package/test/mock/blacklisting.js +122 -0
- package/test/monk.js +1 -1
- package/test/test.js +2 -0
- package/test/validate.js +33 -3
- package/docs/schema/index.md +0 -313
package/lib/model-validate.js
CHANGED
|
@@ -3,7 +3,7 @@ let rules = require('./rules')
|
|
|
3
3
|
|
|
4
4
|
module.exports = {
|
|
5
5
|
|
|
6
|
-
validate: function(data, opts, cb) {
|
|
6
|
+
validate: async function(data, opts, cb) {
|
|
7
7
|
/**
|
|
8
8
|
* Validates a model
|
|
9
9
|
* @param {object} data
|
|
@@ -22,38 +22,44 @@ module.exports = {
|
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
// Optional cb and opts
|
|
25
|
-
if (util.isFunction(opts)) {
|
|
25
|
+
if (util.isFunction(opts)) {
|
|
26
|
+
cb = opts; opts = undefined
|
|
27
|
+
}
|
|
26
28
|
if (cb && !util.isFunction(cb)) {
|
|
27
29
|
throw new Error(`The callback passed to ${this.name}.validate() is not a function`)
|
|
28
30
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
try {
|
|
32
|
+
data = util.deepCopy(data)
|
|
33
|
+
opts = opts || {}
|
|
34
|
+
opts.update = opts.update || opts.findOneAndUpdate
|
|
35
|
+
opts.insert = !opts.update
|
|
36
|
+
opts.skipValidation = opts.skipValidation === true ? true : util.toArray(opts.skipValidation||[])
|
|
37
|
+
|
|
38
|
+
// Get projection
|
|
39
|
+
if (opts.project) opts.projectionValidate = this._getProjectionFromProject(opts.project)
|
|
40
|
+
else opts.projectionValidate = this._getProjectionFromBlacklist(opts.update ? 'update' : 'insert', opts.blacklist)
|
|
34
41
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
else opts.projection = this._getProjectionFromBlacklist(opts.action, opts.blacklist)
|
|
42
|
+
// Hook: beforeValidate
|
|
43
|
+
await util.runSeries(this.beforeValidate.map(f => f.bind(opts, data)))
|
|
38
44
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return util.toArray(data).map(item => {
|
|
45
|
+
// Recurse and validate fields
|
|
46
|
+
let response = util.toArray(data).map(item => {
|
|
42
47
|
let validated = this._validateFields(item, this.fields, item, opts, '')
|
|
43
48
|
if (validated[0].length) throw validated[0]
|
|
44
49
|
else return validated[1]
|
|
45
50
|
})
|
|
46
51
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
// Single document?
|
|
53
|
+
response = util.isArray(data)? response : response[0]
|
|
54
|
+
|
|
55
|
+
// Success/error
|
|
50
56
|
if (cb) cb(null, response)
|
|
51
57
|
else return Promise.resolve(response)
|
|
52
58
|
|
|
53
|
-
}
|
|
54
|
-
if (cb) cb(
|
|
55
|
-
else throw
|
|
56
|
-
}
|
|
59
|
+
} catch (e) {
|
|
60
|
+
if (cb) cb(e)
|
|
61
|
+
else throw e
|
|
62
|
+
}
|
|
57
63
|
},
|
|
58
64
|
|
|
59
65
|
_getMostSpecificKeyMatchingPath: function(object, path) {
|
|
@@ -126,7 +132,7 @@ module.exports = {
|
|
|
126
132
|
}
|
|
127
133
|
|
|
128
134
|
// Ignore blacklisted
|
|
129
|
-
if (this._pathBlacklisted(path3, opts.
|
|
135
|
+
if (this._pathBlacklisted(path3, opts.projectionValidate) && !schema.defaultOverride) return
|
|
130
136
|
// Ignore insert only
|
|
131
137
|
if (opts.update && schema.insertOnly) return
|
|
132
138
|
// Ignore virtual fields
|
|
@@ -239,7 +245,7 @@ module.exports = {
|
|
|
239
245
|
if (typeof value === 'undefined' && (!validateUndefined || !rule.validateUndefined)) return
|
|
240
246
|
|
|
241
247
|
// Ignore null (if nullObject is set on objects or arrays)
|
|
242
|
-
if (value === null && (field.isObject || field.isArray) && field.nullObject) return
|
|
248
|
+
if (value === null && (field.isObject || field.isArray) && field.nullObject && !rule.validateNull) return
|
|
243
249
|
|
|
244
250
|
// Ignore null
|
|
245
251
|
if (value === null && !(field.isObject || field.isArray) && !rule.validateNull) return
|
package/lib/model.js
CHANGED
|
@@ -72,7 +72,7 @@ let Model = module.exports = function(name, opts, manager) {
|
|
|
72
72
|
this._setupFields(this.fields = Object.assign({}, this._timestampFields, this.fields))
|
|
73
73
|
this.fieldsFlattened = this._getFieldsFlattened(this.fields, '') // test output?
|
|
74
74
|
|
|
75
|
-
// Extend model with monk collection
|
|
75
|
+
// Extend model with monk collection queries
|
|
76
76
|
this._collection = manager.get? manager.get(name, { castIds: false }) : null
|
|
77
77
|
if (!this._collection) {
|
|
78
78
|
this.info('There is no mongodb connection, a lot of the monk/monastery methods will be unavailable')
|
|
@@ -83,8 +83,7 @@ let Model = module.exports = function(name, opts, manager) {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
// Add model to manager
|
|
86
|
-
if (typeof this.manager[name] === 'undefined'
|
|
87
|
-
|| typeof this.manager.model[name] !== 'undefined') {
|
|
86
|
+
if (typeof this.manager[name] === 'undefined' || typeof this.manager.model[name] !== 'undefined') {
|
|
88
87
|
this.manager[name] = this
|
|
89
88
|
} else {
|
|
90
89
|
this.warn(`Your model name '${name}' is conflicting, you are only able to
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
let MongoClient = require('mongodb').MongoClient
|
|
2
|
+
|
|
3
|
+
module.exports.open = function(uri, opts, fn) {
|
|
4
|
+
/*
|
|
5
|
+
* Monkey patch to remove db event listener warnings
|
|
6
|
+
* @todo remove when monk is removed
|
|
7
|
+
* @see https://www.mongodb.com/community/forums/t/node-44612-deprecationwarning-listening-to-events-on-
|
|
8
|
+
the-db-class-has-been-deprecated-and-will-be-removed-in-the-next-major-version/15849/4
|
|
9
|
+
*/
|
|
10
|
+
var STATE = {
|
|
11
|
+
CLOSED: 'closed',
|
|
12
|
+
OPENING: 'opening',
|
|
13
|
+
OPEN: 'open'
|
|
14
|
+
}
|
|
15
|
+
MongoClient.connect(uri, opts, function (err, client) {
|
|
16
|
+
// this = Manager
|
|
17
|
+
if (err) {
|
|
18
|
+
this._state = STATE.CLOSED
|
|
19
|
+
this.emit('error-opening', err)
|
|
20
|
+
} else {
|
|
21
|
+
this._state = STATE.OPEN
|
|
22
|
+
|
|
23
|
+
this._client = client
|
|
24
|
+
this._db = client.db()
|
|
25
|
+
|
|
26
|
+
// set up events
|
|
27
|
+
var self = this
|
|
28
|
+
;['authenticated', 'close', 'error', 'parseError', 'timeout'].forEach(function (eventName) {
|
|
29
|
+
self._client.on(eventName, function (e) {
|
|
30
|
+
self.emit(eventName, e)
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
this.emit('open', this._db)
|
|
35
|
+
}
|
|
36
|
+
if (fn) {
|
|
37
|
+
fn(err, this)
|
|
38
|
+
}
|
|
39
|
+
}.bind(this))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports.findOneAndUpdate = function(query, update, opts, fn) {
|
|
43
|
+
/*
|
|
44
|
+
* Monkey patch to use returnDocument
|
|
45
|
+
* @todo remove when monk is removed
|
|
46
|
+
* @see https://github.com/Automattic/monk/blob/master/lib/collection.js#L265
|
|
47
|
+
*/
|
|
48
|
+
// this = model
|
|
49
|
+
if (typeof opts === 'function') {
|
|
50
|
+
fn = opts
|
|
51
|
+
opts = {}
|
|
52
|
+
}
|
|
53
|
+
return this._dispatch(function findOneAndUpdate(args) {
|
|
54
|
+
var method = 'findOneAndUpdate'
|
|
55
|
+
if (typeof (args.options || {}).returnDocument === 'undefined') {
|
|
56
|
+
args.options.returnDocument = 'after'
|
|
57
|
+
}
|
|
58
|
+
if (args.options.replaceOne | args.options.replace) {
|
|
59
|
+
method = 'findOneAndReplace'
|
|
60
|
+
}
|
|
61
|
+
return args.col[method](args.query, args.update, args.options)
|
|
62
|
+
.then(function (doc) {
|
|
63
|
+
if (doc && typeof doc.value !== 'undefined') {
|
|
64
|
+
return doc.value
|
|
65
|
+
}
|
|
66
|
+
if (doc.ok && doc.lastErrorObject && doc.lastErrorObject.n === 0) {
|
|
67
|
+
return null
|
|
68
|
+
}
|
|
69
|
+
return doc
|
|
70
|
+
})
|
|
71
|
+
})({options: opts, query: query, update: update, callback: fn}, 'findOneAndUpdate')
|
|
72
|
+
}
|
|
73
|
+
|
package/lib/util.js
CHANGED
|
@@ -140,14 +140,13 @@ module.exports = {
|
|
|
140
140
|
return typeof value === 'undefined'
|
|
141
141
|
},
|
|
142
142
|
|
|
143
|
-
omit: function(obj,
|
|
144
|
-
|
|
145
|
-
for (let i
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
target[i] = obj[i]
|
|
143
|
+
omit: function(obj, fields) {
|
|
144
|
+
const shallowCopy = Object.assign({}, obj)
|
|
145
|
+
for (let i=0; i<fields.length; i+=1) {
|
|
146
|
+
const key = fields[i]
|
|
147
|
+
delete shallowCopy[key]
|
|
149
148
|
}
|
|
150
|
-
return
|
|
149
|
+
return shallowCopy
|
|
151
150
|
},
|
|
152
151
|
|
|
153
152
|
parseData: function(obj) {
|
|
@@ -228,21 +227,24 @@ module.exports = {
|
|
|
228
227
|
}
|
|
229
228
|
},
|
|
230
229
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
230
|
+
pick: function(obj, keys) {
|
|
231
|
+
// Similiar to underscore.pick
|
|
232
|
+
// @param {string[] | regex[]} keys
|
|
233
|
+
if (!this.isObject(obj) && !this.isFunction(obj)) return {}
|
|
234
|
+
keys = this.toArray(keys)
|
|
235
|
+
let res = {}
|
|
236
|
+
for (let key of keys) {
|
|
237
|
+
if (this.isString(key) && obj.hasOwnProperty(key)) res[key] = obj[key]
|
|
238
|
+
if (this.isRegex(key)) {
|
|
239
|
+
for (let key2 in obj) {
|
|
240
|
+
if (obj.hasOwnProperty(key2) && key2.match(key)) res[key2] = obj[key2]
|
|
241
|
+
}
|
|
239
242
|
}
|
|
240
|
-
if (match) target[prop] = obj[prop]
|
|
241
243
|
}
|
|
242
|
-
return
|
|
244
|
+
return res
|
|
243
245
|
},
|
|
244
246
|
|
|
245
|
-
removeUndefined: (variable)
|
|
247
|
+
removeUndefined: function(variable) {
|
|
246
248
|
// takes an array or object
|
|
247
249
|
if (Array.isArray(variable)) {
|
|
248
250
|
for (let i=variable.length; i--;) {
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "monastery",
|
|
3
3
|
"description": "⛪ A straight forward MongoDB ODM built around Monk",
|
|
4
4
|
"author": "Ricky Boyce",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.36.2",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": "github:boycce/monastery",
|
|
8
8
|
"homepage": "https://boycce.github.io/monastery/",
|
package/test/blacklisting.js
CHANGED
|
@@ -1,104 +1,25 @@
|
|
|
1
|
+
let bird = require('./mock/blacklisting').bird
|
|
2
|
+
let user = require('./mock/blacklisting').user
|
|
3
|
+
let util = require('../lib/util')
|
|
4
|
+
|
|
1
5
|
module.exports = function(monastery, opendb) {
|
|
2
6
|
|
|
3
7
|
test('find blacklisting basic', async () => {
|
|
4
8
|
// Setup
|
|
5
9
|
let db = (await opendb(null)).db
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
})
|
|
11
|
-
let user = db.model('user', {
|
|
12
|
-
fields: {
|
|
13
|
-
list: [{ type: 'number' }],
|
|
14
|
-
dog: { type: 'string' },
|
|
15
|
-
pet: { type: 'string' },
|
|
16
|
-
pets: [{
|
|
17
|
-
name: { type: 'string'},
|
|
18
|
-
age: { type: 'number'}
|
|
19
|
-
}],
|
|
20
|
-
animals: {
|
|
21
|
-
cat: { type: 'string' },
|
|
22
|
-
dog: { type: 'string' }
|
|
23
|
-
},
|
|
24
|
-
hiddenPets: [{
|
|
25
|
-
name: { type: 'string'}
|
|
26
|
-
}],
|
|
27
|
-
hiddenList: [{ type: 'number'}],
|
|
28
|
-
deep: {
|
|
29
|
-
deep2: {
|
|
30
|
-
deep3: {
|
|
31
|
-
deep4: { type: 'string' }
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
deeper: {
|
|
36
|
-
deeper2: {
|
|
37
|
-
deeper3: {
|
|
38
|
-
deeper4: { type: 'string' }
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
deepModel: {
|
|
43
|
-
myBird: { model: 'bird' }
|
|
44
|
-
},
|
|
45
|
-
hiddenDeepModel: {
|
|
46
|
-
myBird: { model: 'bird' }
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
findBL: [
|
|
50
|
-
'dog',
|
|
51
|
-
'animals.cat',
|
|
52
|
-
'pets.age',
|
|
53
|
-
'hiddenPets',
|
|
54
|
-
'hiddenList',
|
|
55
|
-
'deep.deep2.deep3',
|
|
56
|
-
'deeper',
|
|
57
|
-
'hiddenDeepModel'
|
|
58
|
-
],
|
|
59
|
-
})
|
|
60
|
-
let bird1 = await bird.insert({ data: { name: 'ponyo' }})
|
|
61
|
-
let user1 = await user.insert({ data: {
|
|
62
|
-
list: [44, 54],
|
|
63
|
-
dog: 'Bruce',
|
|
64
|
-
pet: 'Freddy',
|
|
65
|
-
pets: [{ name: 'Pluto', age: 5 }, { name: 'Milo', age: 4 }],
|
|
66
|
-
animals: {
|
|
67
|
-
cat: 'Ginger',
|
|
68
|
-
dog: 'Max'
|
|
69
|
-
},
|
|
70
|
-
hiddenPets: [{
|
|
71
|
-
name: 'secretPet'
|
|
72
|
-
}],
|
|
73
|
-
hiddenList: [12, 23],
|
|
74
|
-
deep: {
|
|
75
|
-
deep2: {
|
|
76
|
-
deep3: {
|
|
77
|
-
deep4: 'hideme'
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
deeper: {
|
|
82
|
-
deeper2: {
|
|
83
|
-
deeper3: {
|
|
84
|
-
deeper4: 'hideme'
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
deepModel: {
|
|
89
|
-
myBird: bird1._id
|
|
90
|
-
},
|
|
91
|
-
hiddenDeepModel: {
|
|
92
|
-
myBird: bird1._id
|
|
93
|
-
}
|
|
94
|
-
}})
|
|
10
|
+
db.model('bird', bird.schema())
|
|
11
|
+
db.model('user', user.schema())
|
|
12
|
+
|
|
13
|
+
let bird1 = await db.bird.insert({ data: bird.mock() })
|
|
14
|
+
let user1 = await db.user.insert({ data: user.mock(bird1) })
|
|
95
15
|
|
|
96
16
|
// initial blacklist
|
|
97
|
-
let find1 = await user.findOne({
|
|
17
|
+
let find1 = await db.user.findOne({
|
|
98
18
|
query: user1._id
|
|
99
19
|
})
|
|
100
20
|
expect(find1).toEqual({
|
|
101
21
|
_id: user1._id,
|
|
22
|
+
bird: bird1._id,
|
|
102
23
|
list: [44, 54],
|
|
103
24
|
pet: 'Freddy',
|
|
104
25
|
pets: [{ name: 'Pluto' }, { name: 'Milo' }],
|
|
@@ -108,13 +29,14 @@ module.exports = function(monastery, opendb) {
|
|
|
108
29
|
})
|
|
109
30
|
|
|
110
31
|
// augmented blacklist
|
|
111
|
-
let find2 = await user.findOne({
|
|
32
|
+
let find2 = await db.user.findOne({
|
|
112
33
|
query: user1._id,
|
|
113
34
|
blacklist: ['pet', 'pet', 'deep', 'deepModel', '-dog', '-animals.cat']
|
|
114
35
|
})
|
|
115
36
|
let customBlacklist
|
|
116
37
|
expect(find2).toEqual((customBlacklist = {
|
|
117
38
|
_id: user1._id,
|
|
39
|
+
bird: bird1._id,
|
|
118
40
|
dog: 'Bruce',
|
|
119
41
|
list: [44, 54],
|
|
120
42
|
pets: [{ name: 'Pluto' }, { name: 'Milo' }],
|
|
@@ -122,119 +44,84 @@ module.exports = function(monastery, opendb) {
|
|
|
122
44
|
}))
|
|
123
45
|
|
|
124
46
|
// blacklist string
|
|
125
|
-
let find3 = await user.findOne({
|
|
47
|
+
let find3 = await db.user.findOne({
|
|
126
48
|
query: user1._id,
|
|
127
49
|
blacklist: 'pet pet deep deepModel -dog -animals.cat'
|
|
128
50
|
})
|
|
129
51
|
expect(find3).toEqual(customBlacklist)
|
|
130
52
|
|
|
131
53
|
// blacklist removal
|
|
132
|
-
let find4 = await user.findOne({ query: user1._id, blacklist: false })
|
|
54
|
+
let find4 = await db.user.findOne({ query: user1._id, blacklist: false })
|
|
133
55
|
expect(find4).toEqual(user1)
|
|
134
56
|
|
|
135
57
|
db.close()
|
|
136
58
|
})
|
|
137
59
|
|
|
138
60
|
test('find blacklisting population', async () => {
|
|
139
|
-
// inprogresss
|
|
140
61
|
// Setup
|
|
141
|
-
let db =
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
})
|
|
145
|
-
let bird = db.model('bird', {
|
|
146
|
-
fields: {
|
|
147
|
-
color: { type: 'string', default: 'red' },
|
|
148
|
-
height: { type: 'number' },
|
|
149
|
-
name: { type: 'string' },
|
|
150
|
-
sub: {
|
|
151
|
-
color: { type: 'string', default: 'red' },
|
|
152
|
-
},
|
|
153
|
-
subs: [{
|
|
154
|
-
color: { type: 'string', default: 'red'},
|
|
155
|
-
}],
|
|
156
|
-
wing: {
|
|
157
|
-
size: { type: 'number' },
|
|
158
|
-
sizes: {
|
|
159
|
-
one: { type: 'number' },
|
|
160
|
-
two: { type: 'number' },
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
|
-
},
|
|
164
|
-
findBL: ['wing']
|
|
165
|
-
})
|
|
166
|
-
let user = db.model('user', {
|
|
62
|
+
let db = (await opendb(null)).db
|
|
63
|
+
db.model('bird', bird.schema())
|
|
64
|
+
db.model('user', {
|
|
167
65
|
fields: {
|
|
168
66
|
dog: { type: 'string' },
|
|
169
|
-
|
|
170
|
-
bird2: { model: 'bird' },
|
|
171
|
-
bird3: { model: 'bird' },
|
|
172
|
-
bird4: { model: 'bird' },
|
|
173
|
-
bird5: { model: 'bird' },
|
|
67
|
+
bird: { model: 'bird' },
|
|
174
68
|
},
|
|
175
|
-
findBL: [
|
|
176
|
-
'bird1.name', // bird1.name & bird1.wing blacklisted
|
|
177
|
-
'-bird2', 'bird2.name', // bird2.name blacklisted
|
|
178
|
-
'bird3.name', '-bird3', 'bird3.height', // bird3.height blacklisted
|
|
179
|
-
'-bird4.wing.sizes.one', '-bird4.wing.size', // ignored
|
|
180
|
-
// bird4.wing.sizes.two blacklisted (expand in future verion)
|
|
181
|
-
'-bird5.wing.sizes.one', // bird5.wing.sizes.one ignored, wing blacklisted
|
|
182
|
-
// bird5.wing.sizes.two, wing.size blacklisted (expand in future verion)
|
|
183
|
-
]
|
|
184
69
|
})
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
height: 40,
|
|
189
|
-
sub: {},
|
|
190
|
-
wing: { size: 1, sizes: { one: 1, two: 1 }}
|
|
191
|
-
}
|
|
192
|
-
})
|
|
193
|
-
let userData = {
|
|
70
|
+
|
|
71
|
+
let bird1 = await db.bird.insert({ data: bird.mock() })
|
|
72
|
+
let user1 = await db.user.insert({ data: {
|
|
194
73
|
dog: 'Bruce',
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
74
|
+
bird: bird1._id,
|
|
75
|
+
}})
|
|
76
|
+
|
|
77
|
+
let bird1Base = {
|
|
78
|
+
_id: bird1._id,
|
|
79
|
+
color: 'red',
|
|
80
|
+
sub: { color: 'red' }
|
|
200
81
|
}
|
|
201
|
-
let user1 = await user.insert({ data: userData })
|
|
202
|
-
let bird1Base = { _id: bird1._id, color: 'red', sub: { color: 'red' }}
|
|
203
82
|
|
|
204
|
-
//
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
83
|
+
// 'bird1.name', // bird1.name & bird1.wing blacklisted
|
|
84
|
+
// '-bird2', 'bird2.name', // bird2.name blacklisted
|
|
85
|
+
// 'bird3.name', '-bird3', 'bird3.height', // bird3.height blacklisted
|
|
86
|
+
// '-bird4.wing.sizes.one', '-bird4.wing.size', // ignored
|
|
87
|
+
// bird4.wing.sizes.two blacklisted (expand in future verion)
|
|
88
|
+
// '-bird5.wing.sizes.one', // bird5.wing.sizes.one ignored, wing blacklisted
|
|
89
|
+
// bird5.wing.sizes.two, wing.size blacklisted (expand in future verion)
|
|
90
|
+
|
|
91
|
+
// test 1
|
|
92
|
+
db.user.findBL = ['bird.name']
|
|
93
|
+
expect(await db.user.findOne({ query: user1._id, populate: ['bird'] })).toEqual({
|
|
94
|
+
...user1,
|
|
95
|
+
bird: { ...bird1Base, height: 12 },
|
|
209
96
|
})
|
|
210
|
-
//
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
97
|
+
// test 2
|
|
98
|
+
db.user.findBL = ['-bird', 'bird.name']
|
|
99
|
+
expect(await db.user.findOne({ query: user1._id, populate: ['bird'] })).toEqual({
|
|
100
|
+
...user1,
|
|
101
|
+
bird: { ...bird1Base, height: 12, wing: { size: 1, sizes: { one: 1, two: 1 }} },
|
|
215
102
|
})
|
|
216
|
-
//
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
103
|
+
// test 3
|
|
104
|
+
db.user.findBL = ['bird.name', '-bird', 'bird.height']
|
|
105
|
+
expect(await db.user.findOne({ query: user1._id, populate: ['bird'] })).toEqual({
|
|
106
|
+
...user1,
|
|
107
|
+
bird: { ...bird1Base, name: 'Ponyo', wing: { size: 1, sizes: { one: 1, two: 1 }} },
|
|
221
108
|
})
|
|
222
|
-
//
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
109
|
+
// test 4
|
|
110
|
+
db.user.findBL = ['-bird.wing.sizes.one', '-bird.wing.size']
|
|
111
|
+
expect(await db.user.findOne({ query: user1._id, populate: ['bird'] })).toEqual({
|
|
112
|
+
...user1,
|
|
113
|
+
bird: { ...bird1Base, name: 'Ponyo', height: 12 },
|
|
227
114
|
})
|
|
228
|
-
//
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
115
|
+
// test 5
|
|
116
|
+
db.user.findBL = ['-bird.wing.sizes.one']
|
|
117
|
+
expect(await db.user.findOne({ query: user1._id, populate: ['bird'] })).toEqual({
|
|
118
|
+
...user1,
|
|
119
|
+
bird: { ...bird1Base, name: 'Ponyo', height: 12 },
|
|
233
120
|
})
|
|
234
121
|
// blacklist removal
|
|
235
|
-
expect(await user.findOne({ query: user1._id, blacklist: false, populate: ['
|
|
122
|
+
expect(await db.user.findOne({ query: user1._id, blacklist: false, populate: ['bird'] })).toEqual({
|
|
236
123
|
...user1,
|
|
237
|
-
|
|
124
|
+
bird: { ...bird1Base, height: 12, name: 'Ponyo', wing: { size: 1, sizes: { one: 1, two: 1 }} },
|
|
238
125
|
})
|
|
239
126
|
|
|
240
127
|
db.close()
|
|
@@ -583,4 +470,72 @@ module.exports = function(monastery, opendb) {
|
|
|
583
470
|
db.close()
|
|
584
471
|
})
|
|
585
472
|
|
|
473
|
+
test('findOneAndUpdate blacklisting general', async () => {
|
|
474
|
+
// todo: test all findOneAndUpdate options
|
|
475
|
+
// todo: test find & update hooks
|
|
476
|
+
let db = (await opendb(null)).db
|
|
477
|
+
db.model('bird', bird.schema())
|
|
478
|
+
db.model('user', user.schema())
|
|
479
|
+
|
|
480
|
+
let bird1 = await db.bird.insert({ data: bird.mock() })
|
|
481
|
+
let user1 = await db.user.insert({ data: user.mock(bird1) })
|
|
482
|
+
|
|
483
|
+
// augmented blacklist
|
|
484
|
+
let find2 = await db.user.findOneAndUpdate({
|
|
485
|
+
query: user1._id,
|
|
486
|
+
data: { dog: 'Bruce2', pet: 'Freddy2' }, // pet shouldn't update
|
|
487
|
+
blacklist: ['pet', 'deep', 'deepModel', '-dog', '-animals.cat'],
|
|
488
|
+
})
|
|
489
|
+
expect(find2).toEqual({
|
|
490
|
+
_id: user1._id,
|
|
491
|
+
bird: bird1._id,
|
|
492
|
+
dog: 'Bruce2',
|
|
493
|
+
list: [44, 54],
|
|
494
|
+
pets: [{ name: 'Pluto' }, { name: 'Milo' }],
|
|
495
|
+
animals: { dog: 'Max', cat: 'Ginger' },
|
|
496
|
+
})
|
|
497
|
+
expect(await db.user.findOne({ query: user1._id, project: ['pet'] })).toEqual({
|
|
498
|
+
_id: user1._id,
|
|
499
|
+
pet: 'Freddy',
|
|
500
|
+
})
|
|
501
|
+
|
|
502
|
+
db.close()
|
|
503
|
+
})
|
|
504
|
+
|
|
505
|
+
test('findOneAndUpdate blacklisting populate', async () => {
|
|
506
|
+
let db = (await opendb(null)).db
|
|
507
|
+
db.model('bird', bird.schema())
|
|
508
|
+
db.model('user', user.schema())
|
|
509
|
+
|
|
510
|
+
let bird1 = await db.bird.insert({ data: bird.mock() })
|
|
511
|
+
let user1 = await db.user.insert({ data: user.mock(bird1) })
|
|
512
|
+
|
|
513
|
+
// augmented blacklist
|
|
514
|
+
let find2 = await db.user.findOneAndUpdate({
|
|
515
|
+
query: user1._id,
|
|
516
|
+
data: { dog: 'Bruce2', pet: 'Freddy2' }, // pet shouldn't update
|
|
517
|
+
blacklist: [
|
|
518
|
+
'pet', 'deep', 'deepModel', '-dog', '-animals.cat',
|
|
519
|
+
'bird.name', '-bird', 'bird.height' // <- populated model
|
|
520
|
+
],
|
|
521
|
+
populate: ['bird'],
|
|
522
|
+
})
|
|
523
|
+
expect(find2).toEqual({
|
|
524
|
+
_id: user1._id,
|
|
525
|
+
bird: {
|
|
526
|
+
...util.omit(bird1, ['height']),
|
|
527
|
+
},
|
|
528
|
+
dog: 'Bruce2',
|
|
529
|
+
list: [44, 54],
|
|
530
|
+
pets: [{ name: 'Pluto' }, { name: 'Milo' }],
|
|
531
|
+
animals: { dog: 'Max', cat: 'Ginger' },
|
|
532
|
+
})
|
|
533
|
+
expect(await db.user.findOne({ query: user1._id, project: ['pet'] })).toEqual({
|
|
534
|
+
_id: user1._id,
|
|
535
|
+
pet: 'Freddy',
|
|
536
|
+
})
|
|
537
|
+
|
|
538
|
+
db.close()
|
|
539
|
+
})
|
|
540
|
+
|
|
586
541
|
}
|