monastery 1.36.0 → 1.36.1
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/changelog.md +7 -0
- package/docs/readme.md +2 -2
- package/lib/model-crud.js +32 -20
- package/lib/model-validate.js +3 -3
- package/package.json +1 -1
- package/test/blacklisting.js +132 -177
- package/test/crud.js +4 -4
- package/test/mock/blacklisting.js +122 -0
package/changelog.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [1.36.1](https://github.com/boycce/monastery/compare/1.36.0...1.36.1) (2022-04-16)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* findOneAndUpdate population, blacklisting, etc ([19c4fc9](https://github.com/boycce/monastery/commit/19c4fc96d8c94d9dd68af2a74af693c8dc7a4c17))
|
|
11
|
+
|
|
5
12
|
## [1.36.0](https://github.com/boycce/monastery/compare/1.35.0...1.36.0) (2022-04-15)
|
|
6
13
|
|
|
7
14
|
|
package/docs/readme.md
CHANGED
|
@@ -83,7 +83,7 @@ Coming soon...
|
|
|
83
83
|
|
|
84
84
|
## Roadmap
|
|
85
85
|
|
|
86
|
-
- Add FindOneAndUpdate
|
|
86
|
+
- ~~Add FindOneAndUpdate~~
|
|
87
87
|
- Add before/afterInsertUpdate
|
|
88
88
|
- Bug: Setting an object literal on an ID field ('model') saves successfully
|
|
89
89
|
- Population within array items
|
|
@@ -95,8 +95,8 @@ Coming soon...
|
|
|
95
95
|
- Remove ACL default 'public read'
|
|
96
96
|
- ~~Public db.arrayWithSchema method~~
|
|
97
97
|
- Global after/before hooks
|
|
98
|
-
- Split away from Monk (unless updated)
|
|
99
98
|
- docs: Make the implicit ID query conversion more apparent
|
|
99
|
+
- Split away from Monk (unless updated)
|
|
100
100
|
|
|
101
101
|
## Special Thanks
|
|
102
102
|
|
package/lib/model-crud.js
CHANGED
|
@@ -24,14 +24,13 @@ module.exports = {
|
|
|
24
24
|
}
|
|
25
25
|
try {
|
|
26
26
|
opts = await this._queryObject(opts, 'insert')
|
|
27
|
-
let custom = ['blacklist', 'data', 'insert', 'model', 'respond', 'skipValidation', 'validateUndefined']
|
|
28
27
|
|
|
29
28
|
// Validate
|
|
30
|
-
let data = await this.validate(opts.data || {}, { ...opts }
|
|
29
|
+
let data = await this.validate(opts.data || {}, opts) // was { ...opts }
|
|
31
30
|
|
|
32
31
|
// Insert
|
|
33
32
|
await util.runSeries(this.beforeInsert.map(f => f.bind(opts, data)))
|
|
34
|
-
let response = await this._insert(data, util.omit(opts,
|
|
33
|
+
let response = await this._insert(data, util.omit(opts, this._queryOptions))
|
|
35
34
|
await util.runSeries(this.afterInsert.map(f => f.bind(opts, response)))
|
|
36
35
|
|
|
37
36
|
// Success/error
|
|
@@ -64,9 +63,8 @@ module.exports = {
|
|
|
64
63
|
throw new Error(`The callback passed to ${this.name}.find() is not a function`)
|
|
65
64
|
}
|
|
66
65
|
try {
|
|
67
|
-
opts = await this._queryObject(opts, 'find', one)
|
|
68
|
-
let custom = ['blacklist', 'model', 'one', 'populate', 'project', 'query', 'respond']
|
|
69
66
|
let lookups = []
|
|
67
|
+
opts = await this._queryObject(opts, 'find', one)
|
|
70
68
|
|
|
71
69
|
// Get projection
|
|
72
70
|
if (opts.project) opts.projection = this._getProjectionFromProject(opts.project)
|
|
@@ -80,7 +78,7 @@ module.exports = {
|
|
|
80
78
|
|
|
81
79
|
// Wanting to populate?
|
|
82
80
|
if (!opts.populate) {
|
|
83
|
-
var response = await this[`_find${opts.one? 'One' : ''}`](opts.query, util.omit(opts,
|
|
81
|
+
var response = await this[`_find${opts.one? 'One' : ''}`](opts.query, util.omit(opts, this._queryOptions))
|
|
84
82
|
} else {
|
|
85
83
|
loop: for (let item of opts.populate) {
|
|
86
84
|
let path = util.isObject(item)? item.as : item
|
|
@@ -157,18 +155,14 @@ module.exports = {
|
|
|
157
155
|
* Find and update document(s) with monk, also auto populates
|
|
158
156
|
* @param {object} opts
|
|
159
157
|
* @param {array|string|false} <opts.blacklist> - augment findBL/updateBL, `false` will remove all blacklisting
|
|
160
|
-
* @param {array|string|false} <opts.blacklistFind> - augment findBL, `false` will remove all blacklisting
|
|
161
158
|
* @param {array} <opts.populate> - find population, see docs
|
|
162
159
|
* @param {array|string} <opts.project> - return only these fields, ignores blacklisting
|
|
163
|
-
* @param {array|string} <opts.projectFind> - return only these fields, ignores blacklisting
|
|
164
160
|
* @param {object} <opts.query> - mongodb query object
|
|
165
161
|
* @param {boolean} <opts.respond> - automatically call res.json/error (requires opts.req)
|
|
166
162
|
* @param {any} <any mongodb option>
|
|
167
163
|
*
|
|
168
164
|
* Update options:
|
|
169
165
|
* @param {object|array} opts.data - mongodb document update object(s)
|
|
170
|
-
* @param {array|string|false} <opts.blacklistUpdate> - augment updateBL, `false` will remove all blacklisting
|
|
171
|
-
* @param {array|string} <opts.projectUpdate> - return only these fields, ignores blacklisting
|
|
172
166
|
* @param {array|string|true} <opts.skipValidation> - skip validation for this field name(s)
|
|
173
167
|
* @param {boolean} <opts.timestamps> - whether `updatedAt` is automatically updated
|
|
174
168
|
* @param {array|string|false} <opts.validateUndefined> - validates all 'required' undefined fields, true by
|
|
@@ -228,37 +222,49 @@ module.exports = {
|
|
|
228
222
|
let data = opts.data
|
|
229
223
|
let response = null
|
|
230
224
|
let operators = util.pick(opts, [/^\$/])
|
|
231
|
-
let custom = [
|
|
232
|
-
'blacklist', 'data', 'model', 'one', 'populate', 'project', 'query', 'respond', 'skipValidation',
|
|
233
|
-
'validateUndefined'
|
|
234
|
-
]
|
|
235
225
|
|
|
236
226
|
// Validate
|
|
237
|
-
if (util.isDefined(data))
|
|
227
|
+
if (util.isDefined(data)) {
|
|
228
|
+
data = await this.validate(opts.data, opts) // was {...opts}
|
|
229
|
+
}
|
|
238
230
|
if (!util.isDefined(data) && util.isEmpty(operators)) {
|
|
239
231
|
throw new Error(`Please pass an update operator to ${this.name}.${type}(), e.g. data, $unset, etc`)
|
|
240
232
|
}
|
|
241
233
|
if (util.isDefined(data) && (!data || util.isEmpty(data))) {
|
|
242
234
|
throw new Error(`No valid data passed to ${this.name}.${type}({ data: .. })`)
|
|
243
235
|
}
|
|
236
|
+
|
|
244
237
|
// Hook: beforeUpdate (has access to original, non-validated opts.data)
|
|
245
238
|
await util.runSeries(this.beforeUpdate.map(f => f.bind(opts, data||{})))
|
|
239
|
+
|
|
246
240
|
if (data && operators['$set']) {
|
|
247
241
|
this.warn(`'$set' fields take precedence over the data fields for \`${this.name}.${type}()\``)
|
|
248
242
|
}
|
|
249
243
|
if (data || operators['$set']) {
|
|
250
244
|
operators['$set'] = { ...data, ...(operators['$set'] || {}) }
|
|
251
245
|
}
|
|
252
|
-
|
|
253
|
-
|
|
246
|
+
|
|
247
|
+
// findOneAndUpdate, get 'find' projection
|
|
248
|
+
if (type == 'findOneAndUpdate') {
|
|
249
|
+
if (opts.project) opts.projection = this._getProjectionFromProject(opts.project)
|
|
250
|
+
else opts.projection = this._getProjectionFromBlacklist('find', opts.blacklist)
|
|
251
|
+
// Just peform a normal update if we need to populate a findOneAndUpdate
|
|
252
|
+
if (opts.populate) type = 'update'
|
|
253
|
+
}
|
|
254
|
+
|
|
254
255
|
// Update
|
|
255
|
-
let update = await this['_' + type](opts.query, operators, util.omit(opts,
|
|
256
|
+
let update = await this['_' + type](opts.query, operators, util.omit(opts, this._queryOptions))
|
|
256
257
|
if (type == 'findOneAndUpdate') response = update
|
|
257
258
|
else if (update.n) response = Object.assign(Object.create({ _output: update }), operators['$set']||{})
|
|
258
259
|
|
|
259
260
|
// Hook: afterUpdate (doesn't have access to validated data)
|
|
260
261
|
if (response) await util.runSeries(this.afterUpdate.map(f => f.bind(opts, response)))
|
|
261
262
|
|
|
263
|
+
// Hook: afterFind if findOneAndUpdate
|
|
264
|
+
if (response && type == 'findOneAndUpdate') {
|
|
265
|
+
response = await this._processAfterFind(response, opts.projection, opts)
|
|
266
|
+
}
|
|
267
|
+
|
|
262
268
|
// Success
|
|
263
269
|
if (cb) cb(null, response)
|
|
264
270
|
else if (opts.req && opts.respond) opts.req.res.json(response)
|
|
@@ -288,12 +294,11 @@ module.exports = {
|
|
|
288
294
|
}
|
|
289
295
|
try {
|
|
290
296
|
opts = await this._queryObject(opts, 'remove')
|
|
291
|
-
let custom = ['model', 'query', 'respond']
|
|
292
297
|
if (util.isEmpty(opts.query)) throw new Error('Please specify opts.query')
|
|
293
298
|
|
|
294
299
|
// Remove
|
|
295
300
|
await util.runSeries(this.beforeRemove.map(f => f.bind(opts)))
|
|
296
|
-
let response = await this._remove(opts.query, util.omit(opts,
|
|
301
|
+
let response = await this._remove(opts.query, util.omit(opts, this._queryOptions))
|
|
297
302
|
await util.runSeries(this.afterRemove.map(f => f.bind(response)))
|
|
298
303
|
|
|
299
304
|
// Success
|
|
@@ -626,4 +631,11 @@ module.exports = {
|
|
|
626
631
|
}, this)
|
|
627
632
|
},
|
|
628
633
|
|
|
634
|
+
_queryOptions: [
|
|
635
|
+
// todo: remove type properties
|
|
636
|
+
'blacklist', 'data', 'find', 'findOneAndUpdate', 'insert', 'model', 'one', 'populate', 'project',
|
|
637
|
+
'projectionValidate', 'query', 'remove', 'req', 'respond', 'skipValidation', 'type', 'update',
|
|
638
|
+
'validateUndefined',
|
|
639
|
+
],
|
|
640
|
+
|
|
629
641
|
}
|
package/lib/model-validate.js
CHANGED
|
@@ -36,8 +36,8 @@ module.exports = {
|
|
|
36
36
|
opts.skipValidation = opts.skipValidation === true ? true : util.toArray(opts.skipValidation||[])
|
|
37
37
|
|
|
38
38
|
// Get projection
|
|
39
|
-
if (opts.project) opts.
|
|
40
|
-
else opts.
|
|
39
|
+
if (opts.project) opts.projectionValidate = this._getProjectionFromProject(opts.project)
|
|
40
|
+
else opts.projectionValidate = this._getProjectionFromBlacklist(opts.update ? 'update' : 'insert', opts.blacklist)
|
|
41
41
|
|
|
42
42
|
// Hook: beforeValidate
|
|
43
43
|
await util.runSeries(this.beforeValidate.map(f => f.bind(opts, data)))
|
|
@@ -132,7 +132,7 @@ module.exports = {
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
// Ignore blacklisted
|
|
135
|
-
if (this._pathBlacklisted(path3, opts.
|
|
135
|
+
if (this._pathBlacklisted(path3, opts.projectionValidate) && !schema.defaultOverride) return
|
|
136
136
|
// Ignore insert only
|
|
137
137
|
if (opts.update && schema.insertOnly) return
|
|
138
138
|
// Ignore virtual fields
|
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.36.
|
|
5
|
+
"version": "1.36.1",
|
|
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
|
}
|
package/test/crud.js
CHANGED
|
@@ -145,7 +145,7 @@ module.exports = function(monastery, opendb) {
|
|
|
145
145
|
db2.close()
|
|
146
146
|
})
|
|
147
147
|
|
|
148
|
-
test('update
|
|
148
|
+
test('update general', async () => {
|
|
149
149
|
let db = (await opendb(null)).db
|
|
150
150
|
let user = db.model('user', {
|
|
151
151
|
fields: {
|
|
@@ -423,9 +423,9 @@ module.exports = function(monastery, opendb) {
|
|
|
423
423
|
db.close()
|
|
424
424
|
})
|
|
425
425
|
|
|
426
|
-
test('findOneAndUpdate
|
|
426
|
+
test('findOneAndUpdate general', async () => {
|
|
427
427
|
// todo: test all findOneAndUpdate options
|
|
428
|
-
|
|
428
|
+
// todo: test find & update hooks
|
|
429
429
|
let db = (await opendb(null)).db
|
|
430
430
|
let dog = db.model('dog', {
|
|
431
431
|
fields: {
|
|
@@ -478,7 +478,7 @@ module.exports = function(monastery, opendb) {
|
|
|
478
478
|
db.close()
|
|
479
479
|
})
|
|
480
480
|
|
|
481
|
-
test('remove
|
|
481
|
+
test('remove general', async () => {
|
|
482
482
|
let db = (await opendb(null)).db
|
|
483
483
|
let user = db.model('userRemove', {
|
|
484
484
|
fields: {
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
module.exports.bird = {
|
|
2
|
+
schema: function() {
|
|
3
|
+
return {
|
|
4
|
+
fields: {
|
|
5
|
+
color: { type: 'string', default: 'red' },
|
|
6
|
+
height: { type: 'number' },
|
|
7
|
+
name: { type: 'string' },
|
|
8
|
+
sub: {
|
|
9
|
+
color: { type: 'string', default: 'red' },
|
|
10
|
+
},
|
|
11
|
+
wing: {
|
|
12
|
+
size: { type: 'number' },
|
|
13
|
+
sizes: {
|
|
14
|
+
one: { type: 'number' },
|
|
15
|
+
two: { type: 'number' },
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
findBL: ['wing'],
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
mock: function() {
|
|
23
|
+
return {
|
|
24
|
+
height: 12,
|
|
25
|
+
name: 'Ponyo',
|
|
26
|
+
sub: {},
|
|
27
|
+
wing: { size: 1, sizes: { one: 1, two: 1 }},
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports.user = {
|
|
33
|
+
schema: function() {
|
|
34
|
+
return {
|
|
35
|
+
fields: {
|
|
36
|
+
bird: { model: 'bird' },
|
|
37
|
+
list: [{ type: 'number' }],
|
|
38
|
+
dog: { type: 'string' },
|
|
39
|
+
pet: { type: 'string' },
|
|
40
|
+
pets: [{
|
|
41
|
+
name: { type: 'string'},
|
|
42
|
+
age: { type: 'number'}
|
|
43
|
+
}],
|
|
44
|
+
animals: {
|
|
45
|
+
cat: { type: 'string' },
|
|
46
|
+
dog: { type: 'string' }
|
|
47
|
+
},
|
|
48
|
+
hiddenPets: [{
|
|
49
|
+
name: { type: 'string'}
|
|
50
|
+
}],
|
|
51
|
+
hiddenList: [{ type: 'number'}],
|
|
52
|
+
deep: {
|
|
53
|
+
deep2: {
|
|
54
|
+
deep3: {
|
|
55
|
+
deep4: { type: 'string' }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
deeper: {
|
|
60
|
+
deeper2: {
|
|
61
|
+
deeper3: {
|
|
62
|
+
deeper4: { type: 'string' }
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
deepModel: {
|
|
67
|
+
myBird: { model: 'bird' }
|
|
68
|
+
},
|
|
69
|
+
hiddenDeepModel: {
|
|
70
|
+
myBird: { model: 'bird' }
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
findBL: [
|
|
74
|
+
'dog',
|
|
75
|
+
'animals.cat',
|
|
76
|
+
'pets.age',
|
|
77
|
+
'hiddenPets',
|
|
78
|
+
'hiddenList',
|
|
79
|
+
'deep.deep2.deep3',
|
|
80
|
+
'deeper',
|
|
81
|
+
'hiddenDeepModel',
|
|
82
|
+
],
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
mock: function(bird1) {
|
|
86
|
+
return {
|
|
87
|
+
bird: bird1._id,
|
|
88
|
+
list: [44, 54],
|
|
89
|
+
dog: 'Bruce',
|
|
90
|
+
pet: 'Freddy',
|
|
91
|
+
pets: [{ name: 'Pluto', age: 5 }, { name: 'Milo', age: 4 }],
|
|
92
|
+
animals: {
|
|
93
|
+
cat: 'Ginger',
|
|
94
|
+
dog: 'Max'
|
|
95
|
+
},
|
|
96
|
+
hiddenPets: [{
|
|
97
|
+
name: 'secretPet'
|
|
98
|
+
}],
|
|
99
|
+
hiddenList: [12, 23],
|
|
100
|
+
deep: {
|
|
101
|
+
deep2: {
|
|
102
|
+
deep3: {
|
|
103
|
+
deep4: 'hideme'
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
deeper: {
|
|
108
|
+
deeper2: {
|
|
109
|
+
deeper3: {
|
|
110
|
+
deeper4: 'hideme'
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
deepModel: {
|
|
115
|
+
myBird: bird1._id
|
|
116
|
+
},
|
|
117
|
+
hiddenDeepModel: {
|
|
118
|
+
myBird: bird1._id
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
}
|