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 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, custom))
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, custom))
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)) data = await this.validate(opts.data, { ...opts })
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
- // Just peform a normal update if we need to populate a findOneAndUpdate
253
- if (opts.populate && type == 'findOneAndUpdate') type ='update'
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, custom))
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, custom))
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
  }
@@ -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.projection = this._getProjectionFromProject(opts.project)
40
- else opts.projection = this._getProjectionFromBlacklist(opts.update ? 'update' : 'insert', opts.blacklist)
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.projection) && !schema.defaultOverride) return
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.0",
5
+ "version": "1.36.1",
6
6
  "license": "MIT",
7
7
  "repository": "github:boycce/monastery",
8
8
  "homepage": "https://boycce.github.io/monastery/",
@@ -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
- let bird = db.model('bird', {
7
- fields: {
8
- name: { type: 'string' },
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 = monastery('localhost/monastery', {
142
- timestamps: false,
143
- serverSelectionTimeoutMS: 2000,
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
- bird1: { model: 'bird' },
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
- let bird1 = await bird.insert({
186
- data: {
187
- name: 'ponyo',
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
- bird1: bird1._id,
196
- bird2: bird1._id,
197
- bird3: bird1._id,
198
- bird4: bird1._id,
199
- bird5: bird1._id
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
- // Test bird1
205
- expect(await user.findOne({ query: user1._id, populate: ['bird1'] })).toEqual({
206
- ...userData,
207
- _id: user1._id,
208
- bird1: { ...bird1Base, height: 40 },
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
- // Test bird2
211
- expect(await user.findOne({ query: user1._id, populate: ['bird2'] })).toEqual({
212
- ...userData,
213
- _id: user1._id,
214
- bird2: { ...bird1Base, height: 40, wing: { size: 1, sizes: { one: 1, two: 1 }} },
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
- // Test bird3
217
- expect(await user.findOne({ query: user1._id, populate: ['bird3'] })).toEqual({
218
- ...userData,
219
- _id: user1._id,
220
- bird3: { ...bird1Base, name: 'ponyo', wing: { size: 1, sizes: { one: 1, two: 1 }} },
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
- // Test bird4
223
- expect(await user.findOne({ query: user1._id, populate: ['bird4'] })).toEqual({
224
- ...userData,
225
- _id: user1._id,
226
- bird4: { ...bird1Base, name: 'ponyo', height: 40 },
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
- // Test bird5
229
- expect(await user.findOne({ query: user1._id, populate: ['bird5'] })).toEqual({
230
- ...userData,
231
- _id: user1._id,
232
- bird5: { ...bird1Base, name: 'ponyo', height: 40 },
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: ['bird1'] })).toEqual({
122
+ expect(await db.user.findOne({ query: user1._id, blacklist: false, populate: ['bird'] })).toEqual({
236
123
  ...user1,
237
- bird1: { ...bird1Base, height: 40, name: 'ponyo', wing: { size: 1, sizes: { one: 1, two: 1 }} },
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 basics', async () => {
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 basics', async () => {
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 basics', async () => {
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
+ }