monastery 1.30.4 → 1.31.3
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 +23 -0
- package/changelog.md +0 -0
- package/lib/model-crud.js +30 -15
- package/lib/model-validate.js +2 -2
- package/lib/model.js +1 -0
- package/package.json +10 -9
- package/test/blacklisting.js +4 -4
- package/test/crud.js +137 -91
- package/test/model.js +8 -8
- package/test/populate.js +3 -3
- package/test/util.js +2 -2
- package/test/validate.js +16 -14
- package/test/virtuals.js +2 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
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
|
+
|
|
5
|
+
### 1.31.3 (2022-02-15)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* _callAfterFind bug ([e62472c](https://github.com/boycce/monastery/commit/e62472c191119135839b6d9e42b7f060bc7a508d))
|
|
11
|
+
* .eslintrc.json ([5362585](https://github.com/boycce/monastery/commit/53625857bbf798db97eddad9385799cb1ded97e2))
|
|
12
|
+
* docs ([d8f4e15](https://github.com/boycce/monastery/commit/d8f4e15913f672295cc118fda11ec23a412b4c62))
|
|
13
|
+
* docs ([1a5118e](https://github.com/boycce/monastery/commit/1a5118e4b389b55d30bf987991b59638b11613a9))
|
|
14
|
+
* docs ([564572c](https://github.com/boycce/monastery/commit/564572ce33dfb35fdd131e81d1dcc655f024b26e))
|
|
15
|
+
* docs ([12d37d3](https://github.com/boycce/monastery/commit/12d37d3b2d0b5ec577f9ed4deb9c929c8ea52a36))
|
|
16
|
+
* docs and nav links ([0eabcf0](https://github.com/boycce/monastery/commit/0eabcf0cd9a119a6ab1a07b92634e316995a2a83))
|
|
17
|
+
* model-crud ([d421709](https://github.com/boycce/monastery/commit/d421709a70e6611c78e049e98268153c9bafae6d))
|
|
18
|
+
* normalise afterFind ([0ab7f43](https://github.com/boycce/monastery/commit/0ab7f43f25b599e07d9ae751dc3bac8550e53c24))
|
|
19
|
+
* normalised rule arguments and context ([6ba48da](https://github.com/boycce/monastery/commit/6ba48da3b9c643620cebf5442e60bd0318d6780f))
|
|
20
|
+
* package scripts ([f7935af](https://github.com/boycce/monastery/commit/f7935afb0181ddb3e397bf804b34c841589dfcf0))
|
|
21
|
+
* semver ([6f14909](https://github.com/boycce/monastery/commit/6f14909f4405cf26dc04a8603cc3bac232b96798))
|
|
22
|
+
* standard-version ([f553b08](https://github.com/boycce/monastery/commit/f553b08445eb7dd2e85f6bb447e2bb0bc38dda34))
|
|
23
|
+
* util bug, updated tests ([bec1887](https://github.com/boycce/monastery/commit/bec1887f56cb8582b606a066c913c191362a61b0))
|
package/changelog.md
ADDED
|
File without changes
|
package/lib/model-crud.js
CHANGED
|
@@ -21,14 +21,14 @@ module.exports = {
|
|
|
21
21
|
opts = opts || {}
|
|
22
22
|
opts.insert = true
|
|
23
23
|
opts.model = this
|
|
24
|
-
let
|
|
24
|
+
let req = opts.req
|
|
25
|
+
let data = opts.data = util.isDefined(opts.data)? opts.data : util.isDefined((req||{}).body) ? req.body : {}
|
|
25
26
|
let options = util.omit(opts, [
|
|
26
27
|
'data', 'insert', 'model', 'respond', 'validateUndefined', 'skipValidation', 'blacklist'
|
|
27
28
|
])
|
|
28
29
|
if (cb && !util.isFunction(cb)) {
|
|
29
30
|
throw new Error(`The callback passed to ${this.name}.insert() is not a function`)
|
|
30
31
|
}
|
|
31
|
-
|
|
32
32
|
return util.parseData(data).then(data => {
|
|
33
33
|
opts.data = data
|
|
34
34
|
return this.validate(data, { ...opts })
|
|
@@ -124,12 +124,16 @@ module.exports = {
|
|
|
124
124
|
} else {
|
|
125
125
|
let modelName = (path.split('.').reduce((o,i) => o[i], this.fields) ||{}).model
|
|
126
126
|
if (!modelName) {
|
|
127
|
-
this.error(
|
|
128
|
-
|
|
127
|
+
this.error(
|
|
128
|
+
`The field "${path}" passed to populate is not of type model. You would ` +
|
|
129
|
+
'need to add the field option e.g. { model: \'comment\' } in your schema.'
|
|
130
|
+
)
|
|
129
131
|
continue
|
|
130
132
|
} else if (!this.manager.model[modelName]) {
|
|
131
|
-
this.error(
|
|
132
|
-
|
|
133
|
+
this.error(
|
|
134
|
+
`The field's model defined in your schema does not exist: ${path}: ` +
|
|
135
|
+
`{ model: "${modelName}" }`
|
|
136
|
+
)
|
|
133
137
|
continue
|
|
134
138
|
}
|
|
135
139
|
// Populate model (convert array into document & create lookup)
|
|
@@ -212,7 +216,8 @@ module.exports = {
|
|
|
212
216
|
opts = this._queryObject(opts)
|
|
213
217
|
opts.update = true
|
|
214
218
|
opts.model = this
|
|
215
|
-
|
|
219
|
+
let req = opts.req
|
|
220
|
+
data = opts.data = util.isDefined(opts.data)? opts.data : util.isDefined((req||{}).body) ? req.body : undefined
|
|
216
221
|
operators = util.pluck(opts, [/^\$/])
|
|
217
222
|
// Operation options
|
|
218
223
|
options = util.omit(opts, ['data', 'query', 'respond', 'validateUndefined', 'skipValidation', 'blacklist'])
|
|
@@ -224,23 +229,32 @@ module.exports = {
|
|
|
224
229
|
let order = (options.sort.match(/:(-?[0-9])/) || [])[1]
|
|
225
230
|
options.sort = { [name]: parseInt(order || 1) }
|
|
226
231
|
}
|
|
227
|
-
if (operators['$set'] && data) {
|
|
228
|
-
throw new Error(`Please only pass options.$set or options.data to ${this.name}.update()`)
|
|
229
|
-
}
|
|
230
232
|
util.parseData(data).then(d => resolve(d))
|
|
231
233
|
|
|
232
234
|
}).then(data => {
|
|
233
235
|
opts.data = data
|
|
234
|
-
if (util.
|
|
236
|
+
if (util.isDefined(data)) return this.validate(data, { ...opts })
|
|
237
|
+
else return Promise.resolve(data)
|
|
235
238
|
|
|
236
239
|
}).then(data => {
|
|
237
|
-
if (util.
|
|
238
|
-
throw new Error(`No valid data passed to ${this.name}.update()`)
|
|
240
|
+
if (util.isDefined(data) && (!data || util.isEmpty(data))) {
|
|
241
|
+
throw new Error(`No valid data passed to ${this.name}.update({ data: .. })`)
|
|
242
|
+
}
|
|
243
|
+
if (!util.isDefined(data) && util.isEmpty(operators)) {
|
|
244
|
+
throw new Error(`Please pass an update operator to ${this.name}.update(), e.g. data, $unset, etc`)
|
|
239
245
|
}
|
|
240
246
|
return util.runSeries(this.beforeUpdate.map(f => f.bind(opts, data||{}))).then(() => data)
|
|
241
247
|
|
|
242
248
|
}).then(data => {
|
|
243
|
-
if (data
|
|
249
|
+
if (data && operators['$set']) {
|
|
250
|
+
this.warn(`'$set' fields take precedence over the data fields for \`${this.name}.update()\``)
|
|
251
|
+
}
|
|
252
|
+
if (data || operators['$set']) {
|
|
253
|
+
operators['$set'] = {
|
|
254
|
+
...data,
|
|
255
|
+
...(operators['$set'] || {}),
|
|
256
|
+
}
|
|
257
|
+
}
|
|
244
258
|
return this._update(opts.query, operators, options).then(output => {
|
|
245
259
|
if (!output.n) return null
|
|
246
260
|
let response = Object.assign(Object.create({ _output: output }), operators['$set']||{})
|
|
@@ -377,7 +391,8 @@ module.exports = {
|
|
|
377
391
|
if (!this._pathInProjection(pathWithoutArrays, projection, true)) return
|
|
378
392
|
// Ignore default
|
|
379
393
|
let value = util.isFunction(schema.default)? schema.default(this.manager) : schema.default
|
|
380
|
-
|
|
394
|
+
// console.log(item.dataRef)
|
|
395
|
+
util.setDeepValue(item.dataRef, path.replace(/\.0(\.|$)/g, '.$$$1'), value, true, false, true)
|
|
381
396
|
})
|
|
382
397
|
}
|
|
383
398
|
// Collect all of the model's afterFind hooks
|
package/lib/model-validate.js
CHANGED
|
@@ -140,7 +140,7 @@ module.exports = {
|
|
|
140
140
|
let value = util.isArray(fields)? data : (data||{})[fieldName]
|
|
141
141
|
let indexOrFieldName = util.isArray(fields)? i : fieldName
|
|
142
142
|
let path2 = `${path}.${indexOrFieldName}`.replace(/^\./, '')
|
|
143
|
-
let path3 = path2.replace(/(^|\.)[0-9]+(\.|$)/, '$2') // no
|
|
143
|
+
let path3 = path2.replace(/(^|\.)[0-9]+(\.|$)/, '$2') // no numerical keys, e.g. pets.1.name
|
|
144
144
|
let isType = 'is' + util.ucFirst(schema.type)
|
|
145
145
|
let isTypeRule = this.rules[isType] || rules[isType]
|
|
146
146
|
|
|
@@ -162,7 +162,7 @@ module.exports = {
|
|
|
162
162
|
if (opts.update && schema.insertOnly) return
|
|
163
163
|
// Ignore virtual fields
|
|
164
164
|
if (schema.virtual) return
|
|
165
|
-
// Type cast the value if tryParse is
|
|
165
|
+
// Type cast the value if tryParse is available, .e.g. isInteger.tryParse
|
|
166
166
|
if (isTypeRule && util.isFunction(isTypeRule.tryParse)) {
|
|
167
167
|
value = isTypeRule.tryParse.call(dataRoot, value, fieldName, this)
|
|
168
168
|
}
|
package/lib/model.js
CHANGED
|
@@ -36,6 +36,7 @@ let Model = module.exports = function(name, opts, manager) {
|
|
|
36
36
|
beforeValidate: opts.beforeValidate || [],
|
|
37
37
|
error: manager.error,
|
|
38
38
|
info: manager.info,
|
|
39
|
+
warn: manager.warn,
|
|
39
40
|
insertBL: opts.insertBL || [],
|
|
40
41
|
fields: { ...(util.deepCopy(opts.fields) || {}) },
|
|
41
42
|
findBL: opts.findBL || ['password'],
|
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.31.3",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": "github:boycce/monastery",
|
|
8
8
|
"homepage": "https://boycce.github.io/monastery/",
|
|
@@ -17,14 +17,15 @@
|
|
|
17
17
|
"mongo odm"
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
|
-
"minor": "standard-version --release-as minor && npm publish",
|
|
21
|
-
"patch": "standard-version && npm publish",
|
|
22
|
-
"test": "npm run lint && jest",
|
|
23
|
-
"test-one-example": "jest -t images",
|
|
24
20
|
"dev": "npm run lint & DEBUG=-monastery:info jest --watchAll --runInBand --verbose=false",
|
|
25
|
-
"lint": "eslint ./lib ./plugins ./test",
|
|
26
21
|
"docs": "cd docs && bundle exec jekyll serve --livereload --livereload-port 4001",
|
|
27
|
-
"
|
|
22
|
+
"lint": "eslint ./lib ./plugins ./test",
|
|
23
|
+
"mong": "nodemon resources/mong.js",
|
|
24
|
+
"minor": "standard-version --release-as minor && npm publish",
|
|
25
|
+
"patch": "standard-version --release-as patch && npm publish",
|
|
26
|
+
"release": "standard-version && npm publish",
|
|
27
|
+
"test": "npm run lint && jest",
|
|
28
|
+
"test-one-example": "jest -t images"
|
|
28
29
|
},
|
|
29
30
|
"dependencies": {
|
|
30
31
|
"aws-sdk": "2.1062.0",
|
|
@@ -48,8 +49,8 @@
|
|
|
48
49
|
"releaseCommitMessageFormat": "{{currentTag}}",
|
|
49
50
|
"sign": true,
|
|
50
51
|
"skip": {
|
|
51
|
-
"changelog":
|
|
52
|
-
"tag":
|
|
52
|
+
"changelog": false,
|
|
53
|
+
"tag": false
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
}
|
package/test/blacklisting.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module.exports = function(monastery, opendb) {
|
|
2
2
|
|
|
3
|
-
test('
|
|
3
|
+
test('find blacklisting', async () => {
|
|
4
4
|
// Setup
|
|
5
5
|
let db = (await opendb(null)).db
|
|
6
6
|
let bird = db.model('bird', {
|
|
@@ -152,7 +152,7 @@ module.exports = function(monastery, opendb) {
|
|
|
152
152
|
db.close()
|
|
153
153
|
})
|
|
154
154
|
|
|
155
|
-
test('
|
|
155
|
+
test('find blacklisting (default fields)', async () => {
|
|
156
156
|
// Setup
|
|
157
157
|
let db = (await opendb(null)).db
|
|
158
158
|
let user = db.model('user', {
|
|
@@ -223,7 +223,7 @@ module.exports = function(monastery, opendb) {
|
|
|
223
223
|
db.close()
|
|
224
224
|
})
|
|
225
225
|
|
|
226
|
-
test('
|
|
226
|
+
test('find blacklisting (populate)', async () => {
|
|
227
227
|
// Setup
|
|
228
228
|
let db = (await opendb(null)).db
|
|
229
229
|
let bird = db.model('bird', {
|
|
@@ -305,7 +305,7 @@ module.exports = function(monastery, opendb) {
|
|
|
305
305
|
db.close()
|
|
306
306
|
})
|
|
307
307
|
|
|
308
|
-
test('
|
|
308
|
+
test('insert update blacklisting (validate)', async () => {
|
|
309
309
|
// Setup
|
|
310
310
|
let db = (await opendb(null)).db
|
|
311
311
|
let user = db.model('user', {
|
package/test/crud.js
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
module.exports = function(monastery, opendb) {
|
|
4
4
|
|
|
5
|
-
test('
|
|
5
|
+
test('basic operator calls', async () => {
|
|
6
6
|
let db = (await opendb(null)).db
|
|
7
7
|
let user = db.model('user', {
|
|
8
|
-
fields: {
|
|
9
|
-
|
|
8
|
+
fields: {
|
|
9
|
+
name: { type: 'string' },
|
|
10
|
+
},
|
|
10
11
|
})
|
|
11
12
|
|
|
12
13
|
// Insert one
|
|
@@ -79,60 +80,6 @@ module.exports = function(monastery, opendb) {
|
|
|
79
80
|
let findOne3 = await user.findOne(inserted2[0]._id.toString())
|
|
80
81
|
expect(findOne3).toEqual({ _id: inserted2[0]._id, name: 'Martin Luther1' })
|
|
81
82
|
|
|
82
|
-
// Update
|
|
83
|
-
let update = await user.update({
|
|
84
|
-
query: inserted._id,
|
|
85
|
-
data: { name: 'Martin Luther2' }
|
|
86
|
-
})
|
|
87
|
-
expect(update).toEqual({
|
|
88
|
-
name: 'Martin Luther2'
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
// Update (no/empty data object)
|
|
92
|
-
await expect(user.update({ query: inserted._id, data: {}}))
|
|
93
|
-
.rejects.toThrow('No valid data passed to user.update()')
|
|
94
|
-
|
|
95
|
-
await expect(user.update({ query: inserted._id }))
|
|
96
|
-
.rejects.toThrow('No valid data passed to user.update()')
|
|
97
|
-
|
|
98
|
-
// Update (no/empty data object, but has update operators
|
|
99
|
-
await expect(user.update({ query: inserted._id, $set: { name: 'bruce' }}))
|
|
100
|
-
.resolves.toEqual({ name: 'bruce' })
|
|
101
|
-
|
|
102
|
-
await expect(user.update({ query: inserted._id, $pull: { name: 'bruce' }}))
|
|
103
|
-
.rejects.toThrow('Cannot apply $pull to a non-array value') // gets passed no valid data check
|
|
104
|
-
|
|
105
|
-
// Update (data & $set)
|
|
106
|
-
await expect(user.update({ query: inserted._id, data: {}, $set: { name: 'bruce' }}))
|
|
107
|
-
.rejects.toThrow('Please only pass options.$set or options.data to user.update()')
|
|
108
|
-
|
|
109
|
-
// Update (with operators. Make sure beforeValidate isn't called)
|
|
110
|
-
var beforeValidateHookCalled = false
|
|
111
|
-
await user.update({ query: inserted._id, data: { name: 'bruce' }})
|
|
112
|
-
expect(beforeValidateHookCalled).toEqual(true)
|
|
113
|
-
beforeValidateHookCalled = false
|
|
114
|
-
await user.update({ query: inserted._id, $set: { name: 'bruce' }})
|
|
115
|
-
expect(beforeValidateHookCalled).toEqual(false)
|
|
116
|
-
|
|
117
|
-
// Update multiple
|
|
118
|
-
await user.update({
|
|
119
|
-
query: { _id: { $in: [inserted2[0]._id, inserted2[1]._id] }},
|
|
120
|
-
data: { name: 'Martin Luther3' },
|
|
121
|
-
multi: true
|
|
122
|
-
})
|
|
123
|
-
let findUpdated2 = await user.find({
|
|
124
|
-
query: { _id: { $in: [inserted2[0]._id, inserted2[1]._id] }}
|
|
125
|
-
})
|
|
126
|
-
expect(findUpdated2).toEqual([
|
|
127
|
-
{
|
|
128
|
-
_id: expect.any(Object),
|
|
129
|
-
name: 'Martin Luther3'
|
|
130
|
-
}, {
|
|
131
|
-
_id: expect.any(Object),
|
|
132
|
-
name: 'Martin Luther3'
|
|
133
|
-
}
|
|
134
|
-
])
|
|
135
|
-
|
|
136
83
|
// Remove
|
|
137
84
|
let remove = await user.remove({ query: inserted._id })
|
|
138
85
|
expect(remove.result).toEqual({ n: 1, ok: 1 })
|
|
@@ -140,7 +87,7 @@ module.exports = function(monastery, opendb) {
|
|
|
140
87
|
db.close()
|
|
141
88
|
})
|
|
142
89
|
|
|
143
|
-
test('
|
|
90
|
+
test('insert defaults', async () => {
|
|
144
91
|
let db = (await opendb(null, { defaultObjects: true, serverSelectionTimeoutMS: 2000 })).db
|
|
145
92
|
let db2 = (await opendb(null, { useMilliseconds: true, serverSelectionTimeoutMS: 2000 })).db
|
|
146
93
|
let user = db.model('user', { fields: {
|
|
@@ -194,6 +141,65 @@ module.exports = function(monastery, opendb) {
|
|
|
194
141
|
db2.close()
|
|
195
142
|
})
|
|
196
143
|
|
|
144
|
+
test('update basics', async () => {
|
|
145
|
+
let db = (await opendb(null)).db
|
|
146
|
+
let user = db.model('user', {
|
|
147
|
+
fields: {
|
|
148
|
+
name: { type: 'string' },
|
|
149
|
+
},
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
// Insert
|
|
153
|
+
let inserted = await user.insert({ data: { name: 'Martin Luther' }})
|
|
154
|
+
expect(inserted).toEqual({
|
|
155
|
+
_id: expect.any(Object),
|
|
156
|
+
name: 'Martin Luther'
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
// Insert multiple
|
|
160
|
+
let inserted2 = await user.insert({ data: [{ name: 'Martin Luther1' }, { name: 'Martin Luther2' }]})
|
|
161
|
+
expect(inserted2).toEqual([
|
|
162
|
+
{
|
|
163
|
+
_id: expect.any(Object),
|
|
164
|
+
name: 'Martin Luther1'
|
|
165
|
+
}, {
|
|
166
|
+
_id: expect.any(Object),
|
|
167
|
+
name: 'Martin Luther2'
|
|
168
|
+
}
|
|
169
|
+
])
|
|
170
|
+
|
|
171
|
+
// Update
|
|
172
|
+
await expect(user.update({ query: inserted._id, data: { name: 'Martin Luther2' }}))
|
|
173
|
+
.resolves.toEqual({ name: 'Martin Luther2' })
|
|
174
|
+
|
|
175
|
+
// Update (no/empty data object)
|
|
176
|
+
await expect(user.update({ query: inserted._id, data: {}}))
|
|
177
|
+
.rejects.toThrow('No valid data passed to user.update({ data: .. })')
|
|
178
|
+
|
|
179
|
+
await expect(user.update({ query: inserted._id }))
|
|
180
|
+
.rejects.toThrow('Please pass an update operator to user.update(), e.g. data, $unset, etc')
|
|
181
|
+
|
|
182
|
+
// Update multiple
|
|
183
|
+
await user.update({
|
|
184
|
+
query: { _id: { $in: [inserted2[0]._id, inserted2[1]._id] }},
|
|
185
|
+
data: { name: 'Martin Luther3' },
|
|
186
|
+
multi: true
|
|
187
|
+
})
|
|
188
|
+
let findUpdated2 = await user.find({
|
|
189
|
+
query: { _id: { $in: [inserted2[0]._id, inserted2[1]._id] }}
|
|
190
|
+
})
|
|
191
|
+
expect(findUpdated2).toEqual([
|
|
192
|
+
{
|
|
193
|
+
_id: expect.any(Object),
|
|
194
|
+
name: 'Martin Luther3'
|
|
195
|
+
}, {
|
|
196
|
+
_id: expect.any(Object),
|
|
197
|
+
name: 'Martin Luther3'
|
|
198
|
+
}
|
|
199
|
+
])
|
|
200
|
+
db.close()
|
|
201
|
+
})
|
|
202
|
+
|
|
197
203
|
test('update defaults', async () => {
|
|
198
204
|
let db = (await opendb(null, { useMilliseconds: true, serverSelectionTimeoutMS: 2000 })).db
|
|
199
205
|
let user = db.model('user', {
|
|
@@ -235,7 +241,7 @@ module.exports = function(monastery, opendb) {
|
|
|
235
241
|
query: inserted._id,
|
|
236
242
|
data: {},
|
|
237
243
|
timestamps: false
|
|
238
|
-
})).rejects.toThrow('No valid data passed to user.update()')
|
|
244
|
+
})).rejects.toThrow('No valid data passed to user.update({ data: .. })')
|
|
239
245
|
|
|
240
246
|
// UpdatedAt override (wont work)
|
|
241
247
|
let updated4 = await user.update({
|
|
@@ -255,7 +261,51 @@ module.exports = function(monastery, opendb) {
|
|
|
255
261
|
db.close()
|
|
256
262
|
})
|
|
257
263
|
|
|
258
|
-
test('
|
|
264
|
+
test('update operators', async () => {
|
|
265
|
+
let db = (await opendb(null)).db
|
|
266
|
+
let user = db.model('userOperators', {
|
|
267
|
+
fields: {
|
|
268
|
+
name: { type: 'string', minLength: 5 },
|
|
269
|
+
age: { type: 'number' },
|
|
270
|
+
},
|
|
271
|
+
beforeValidate: [(data, next) => { beforeValidateHookCalled = true; next() }]
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
let inserted = await user.insert({
|
|
275
|
+
data: { name: 'Bruce', age: 12 }
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
// No data object, but has another update operators
|
|
279
|
+
await expect(user.update({ query: inserted._id, $set: { name: 'bruce' }}))
|
|
280
|
+
.resolves.toEqual({ name: 'bruce' })
|
|
281
|
+
|
|
282
|
+
// Mixing data and $set, and $set skips validation (minLength)
|
|
283
|
+
await expect(user.update({ query: inserted._id, data: { name: 'bruce2', age: 12 }, $set: { name: 'john' }}))
|
|
284
|
+
.resolves.toEqual({ age: 12, name: 'john' })
|
|
285
|
+
|
|
286
|
+
// Two operators
|
|
287
|
+
await user.update({ query: inserted._id, $set: { name: 'john' }, $unset: { age: 1 }})
|
|
288
|
+
await expect(user.findOne({ query: inserted._id })).resolves.toEqual({
|
|
289
|
+
_id: expect.any(Object),
|
|
290
|
+
name: 'john',
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
// $pull on a non array (also gets passed no valid data check)
|
|
294
|
+
await expect(user.update({ query: inserted._id, $pull: { name: 'bruce' }}))
|
|
295
|
+
.rejects.toThrow('Cannot apply $pull to a non-array value')
|
|
296
|
+
|
|
297
|
+
// Non-data operators don't call beforeValidate
|
|
298
|
+
var beforeValidateHookCalled = false
|
|
299
|
+
await user.update({ query: inserted._id, data: { name: 'bruce' }})
|
|
300
|
+
expect(beforeValidateHookCalled).toEqual(true)
|
|
301
|
+
beforeValidateHookCalled = false
|
|
302
|
+
await user.update({ query: inserted._id, $set: { name: 'bruce' }})
|
|
303
|
+
expect(beforeValidateHookCalled).toEqual(false)
|
|
304
|
+
|
|
305
|
+
db.close()
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
test('insert with id casting', async () => {
|
|
259
309
|
let db = (await opendb(null)).db
|
|
260
310
|
db.model('company', { fields: {
|
|
261
311
|
name: { type: 'string' }
|
|
@@ -279,56 +329,52 @@ module.exports = function(monastery, opendb) {
|
|
|
279
329
|
db.close()
|
|
280
330
|
})
|
|
281
331
|
|
|
282
|
-
test('
|
|
332
|
+
test('find default field population', async () => {
|
|
283
333
|
let db = (await opendb(null)).db
|
|
284
334
|
let user = db.model('user', {
|
|
285
335
|
fields: {
|
|
286
|
-
name: { type: 'string'},
|
|
287
|
-
addresses: [{ city: { type: 'string' }, country: { type: 'string' }}],
|
|
336
|
+
name: { type: 'string', default: 'Martin Luther' },
|
|
337
|
+
addresses: [{ city: { type: 'string' }, country: { type: 'string', default: 'Germany' } }],
|
|
338
|
+
address: { country: { type: 'string', default: 'Germany' }},
|
|
288
339
|
pet: { dog: { model: 'dog' }},
|
|
289
340
|
dogs: [{ model: 'dog' }], // virtual association
|
|
290
341
|
}
|
|
291
342
|
})
|
|
292
343
|
let dog = db.model('dog', {
|
|
293
344
|
fields: {
|
|
294
|
-
name: { type: 'string' },
|
|
345
|
+
name: { type: 'string', default: 'Scruff' },
|
|
295
346
|
user: { model: 'user' }
|
|
296
347
|
}
|
|
297
348
|
})
|
|
298
349
|
|
|
299
|
-
//
|
|
300
|
-
let
|
|
301
|
-
let
|
|
350
|
+
// Default field doesn't override null
|
|
351
|
+
let nulldoc1 = await dog.insert({ data: { name: null }})
|
|
352
|
+
let nullfind1 = await dog.findOne({ query: nulldoc1._id })
|
|
353
|
+
expect(nullfind1).toEqual({ _id: nulldoc1._id, name: null })
|
|
354
|
+
|
|
355
|
+
// Default field doesn't override empty string
|
|
356
|
+
let nulldoc2 = await dog.insert({ data: { name: '' }})
|
|
357
|
+
let nullfind2 = await dog.findOne({ query: nulldoc2._id })
|
|
358
|
+
expect(nullfind2).toEqual({ _id: nulldoc2._id, name: '' })
|
|
359
|
+
|
|
360
|
+
// Default field overrides undefined
|
|
361
|
+
let nulldoc3 = await dog.insert({ data: { name: undefined }})
|
|
362
|
+
let nullfind3 = await dog.findOne({ query: nulldoc3._id })
|
|
363
|
+
expect(nullfind3).toEqual({ _id: nullfind3._id, name: 'Scruff' })
|
|
364
|
+
|
|
365
|
+
// Default field population test
|
|
366
|
+
// Note that addresses.1.country shouldn't be overriden
|
|
367
|
+
// Insert documents (without defaults)
|
|
368
|
+
let inserted = await dog._insert({})
|
|
369
|
+
let inserted2 = await user._insert({
|
|
302
370
|
addresses: [
|
|
303
371
|
{ city: 'Frankfurt' },
|
|
304
372
|
{ city: 'Christchurch', country: 'New Zealand' }
|
|
305
373
|
],
|
|
306
374
|
pet: { dog: inserted._id }
|
|
307
|
-
}})
|
|
308
|
-
await dog.update({
|
|
309
|
-
query: inserted._id,
|
|
310
|
-
data: { user: inserted2._id }
|
|
311
375
|
})
|
|
376
|
+
await dog._update(inserted._id, { $set: { user: inserted2._id }})
|
|
312
377
|
|
|
313
|
-
// Update models
|
|
314
|
-
db.model('user', {
|
|
315
|
-
fields: {
|
|
316
|
-
name: { type: 'string', default: 'Martin Luther' },
|
|
317
|
-
addresses: [{ city: { type: 'string' }, country: { type: 'string', default: 'Germany' } }],
|
|
318
|
-
address: { country: { type: 'string', default: 'Germany' }},
|
|
319
|
-
pet: { dog: { model: 'dog' }},
|
|
320
|
-
dogs: [{ model: 'dog' }], // virtual association
|
|
321
|
-
}
|
|
322
|
-
})
|
|
323
|
-
db.model('dog', {
|
|
324
|
-
fields: {
|
|
325
|
-
name: { type: 'string', default: 'Scruff' },
|
|
326
|
-
user: { model: 'user' }
|
|
327
|
-
}
|
|
328
|
-
})
|
|
329
|
-
|
|
330
|
-
// Default field population test
|
|
331
|
-
// Note that addresses.1.country shouldn't be overriden
|
|
332
378
|
let find1 = await user.findOne({
|
|
333
379
|
query: inserted2._id,
|
|
334
380
|
populate: ['pet.dog', {
|
|
@@ -369,7 +415,7 @@ module.exports = function(monastery, opendb) {
|
|
|
369
415
|
db.close()
|
|
370
416
|
})
|
|
371
417
|
|
|
372
|
-
test('
|
|
418
|
+
test('hooks', async () => {
|
|
373
419
|
let db = (await opendb(null)).db
|
|
374
420
|
let user = db.model('user', {
|
|
375
421
|
fields: {
|
package/test/model.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module.exports = function(monastery, opendb) {
|
|
2
2
|
|
|
3
|
-
test('
|
|
3
|
+
test('model setup', async () => {
|
|
4
4
|
// Setup
|
|
5
5
|
let db = (await opendb(false)).db
|
|
6
6
|
let user = db.model('user', { fields: {
|
|
@@ -68,7 +68,7 @@ module.exports = function(monastery, opendb) {
|
|
|
68
68
|
))
|
|
69
69
|
})
|
|
70
70
|
|
|
71
|
-
test('
|
|
71
|
+
test('model setup with default fields', async () => {
|
|
72
72
|
// Setup
|
|
73
73
|
let db = (await opendb(false, { defaultObjects: true })).db
|
|
74
74
|
|
|
@@ -90,7 +90,7 @@ module.exports = function(monastery, opendb) {
|
|
|
90
90
|
})
|
|
91
91
|
})
|
|
92
92
|
|
|
93
|
-
test('
|
|
93
|
+
test('model setup with default objects', async () => {
|
|
94
94
|
// Setup
|
|
95
95
|
let db = (await opendb(false, { defaultObjects: true })).db
|
|
96
96
|
let user = db.model('user', { fields: {
|
|
@@ -115,7 +115,7 @@ module.exports = function(monastery, opendb) {
|
|
|
115
115
|
})
|
|
116
116
|
})
|
|
117
117
|
|
|
118
|
-
test('
|
|
118
|
+
test('model indexes', async () => {
|
|
119
119
|
// Setup: Need to test different types of indexes
|
|
120
120
|
let db = (await opendb(null)).db
|
|
121
121
|
// Setup: Drop previously tested collections
|
|
@@ -189,7 +189,7 @@ module.exports = function(monastery, opendb) {
|
|
|
189
189
|
db.close()
|
|
190
190
|
})
|
|
191
191
|
|
|
192
|
-
test('
|
|
192
|
+
test('model subdocument indexes', async () => {
|
|
193
193
|
// Setup: Need to test different types of indexes
|
|
194
194
|
let db = (await opendb(null)).db
|
|
195
195
|
// Setup: Drop previously tested collections
|
|
@@ -234,7 +234,7 @@ module.exports = function(monastery, opendb) {
|
|
|
234
234
|
db.close()
|
|
235
235
|
})
|
|
236
236
|
|
|
237
|
-
test('
|
|
237
|
+
test('model array indexes', async () => {
|
|
238
238
|
// Setup: Need to test different types of indexes
|
|
239
239
|
let db = (await opendb(null)).db
|
|
240
240
|
// Setup: Drop previously tested collections
|
|
@@ -279,7 +279,7 @@ module.exports = function(monastery, opendb) {
|
|
|
279
279
|
db.close()
|
|
280
280
|
})
|
|
281
281
|
|
|
282
|
-
test('
|
|
282
|
+
test('model 2dsphere indexes', async () => {
|
|
283
283
|
// Setup. The tested model needs to be unique as race condition issue arises when the same model
|
|
284
284
|
// with text indexes are setup at the same time
|
|
285
285
|
let db = (await opendb(null)).db
|
|
@@ -339,7 +339,7 @@ module.exports = function(monastery, opendb) {
|
|
|
339
339
|
db.close()
|
|
340
340
|
})
|
|
341
341
|
|
|
342
|
-
test('
|
|
342
|
+
test('model findBL findBLProject', async () => {
|
|
343
343
|
let db = (await opendb(null)).db
|
|
344
344
|
db.model('bird', { fields: {
|
|
345
345
|
name: { type: 'string' }
|
package/test/populate.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module.exports = function(monastery, opendb) {
|
|
2
2
|
|
|
3
|
-
test('
|
|
3
|
+
test('model populate', async () => {
|
|
4
4
|
// Setup
|
|
5
5
|
let db = (await opendb(null)).db
|
|
6
6
|
let bird = db.model('bird', { fields: {
|
|
@@ -82,7 +82,7 @@ module.exports = function(monastery, opendb) {
|
|
|
82
82
|
db.close()
|
|
83
83
|
})
|
|
84
84
|
|
|
85
|
-
test('
|
|
85
|
+
test('model populate type=any', async () => {
|
|
86
86
|
let db = (await opendb(null)).db
|
|
87
87
|
db.model('company', { fields: {
|
|
88
88
|
address: { type: 'any' }
|
|
@@ -132,7 +132,7 @@ module.exports = function(monastery, opendb) {
|
|
|
132
132
|
db.close()
|
|
133
133
|
})
|
|
134
134
|
|
|
135
|
-
test('
|
|
135
|
+
test('model populate or blacklisting via $lookup', async () => {
|
|
136
136
|
// Setup
|
|
137
137
|
let db = (await opendb(null)).db
|
|
138
138
|
let user = db.model('user', {
|
package/test/util.js
CHANGED
|
@@ -2,7 +2,7 @@ let util = require('../lib/util')
|
|
|
2
2
|
|
|
3
3
|
module.exports = function(monastery, opendb) {
|
|
4
4
|
|
|
5
|
-
test('
|
|
5
|
+
test('utilities formdata', async () => {
|
|
6
6
|
expect(await util.parseFormData({
|
|
7
7
|
'name': 'Martin',
|
|
8
8
|
'pets[]': '',
|
|
@@ -31,7 +31,7 @@ module.exports = function(monastery, opendb) {
|
|
|
31
31
|
.toEqual('Array items in bracket notation need array indexes "users[][\'name\']", e.g. users[0][name]')
|
|
32
32
|
})
|
|
33
33
|
|
|
34
|
-
test('
|
|
34
|
+
test('utilities isId', async () => {
|
|
35
35
|
let db = (await opendb(false)).db
|
|
36
36
|
expect(db.isId('')).toEqual(false)
|
|
37
37
|
expect(db.isId(1234)).toEqual(false)
|
package/test/validate.js
CHANGED
|
@@ -61,8 +61,10 @@ module.exports = function(monastery, opendb) {
|
|
|
61
61
|
|
|
62
62
|
// Type error (number)
|
|
63
63
|
let usernum = db.model('usernum', { fields: { amount: { type: 'number', required: true }}})
|
|
64
|
+
let usernum2 = db.model('usernum2', { fields: { amount: { type: 'number' }}})
|
|
64
65
|
await expect(usernum.validate({ amount: 0 })).resolves.toEqual({ amount: 0 })
|
|
65
66
|
await expect(usernum.validate({ amount: '0' })).resolves.toEqual({ amount: 0 })
|
|
67
|
+
await expect(usernum2.validate({ amount: '' })).resolves.toEqual({ amount: null })
|
|
66
68
|
await expect(usernum.validate({ amount: undefined }, { validateUndefined: false })).resolves.toEqual({})
|
|
67
69
|
await expect(usernum.validate({ amount: false })).rejects.toEqual([{
|
|
68
70
|
status: '400',
|
|
@@ -116,7 +118,7 @@ module.exports = function(monastery, opendb) {
|
|
|
116
118
|
})
|
|
117
119
|
})
|
|
118
120
|
|
|
119
|
-
test('
|
|
121
|
+
test('validation subdocument errors', async () => {
|
|
120
122
|
// Setup
|
|
121
123
|
let db = (await opendb(false)).db
|
|
122
124
|
let user = db.model('user', { fields: {
|
|
@@ -243,7 +245,7 @@ module.exports = function(monastery, opendb) {
|
|
|
243
245
|
})
|
|
244
246
|
})
|
|
245
247
|
|
|
246
|
-
test('
|
|
248
|
+
test('validation array errors', async () => {
|
|
247
249
|
// Setup
|
|
248
250
|
let db = (await opendb(false)).db
|
|
249
251
|
let user = db.model('user', { fields: {
|
|
@@ -307,7 +309,7 @@ module.exports = function(monastery, opendb) {
|
|
|
307
309
|
.rejects.toContainEqual(error)
|
|
308
310
|
})
|
|
309
311
|
|
|
310
|
-
test('
|
|
312
|
+
test('validation getMostSpecificKeyMatchingPath', async () => {
|
|
311
313
|
let fn = validate._getMostSpecificKeyMatchingPath
|
|
312
314
|
let mock = {
|
|
313
315
|
'cats.name': true,
|
|
@@ -339,7 +341,7 @@ module.exports = function(monastery, opendb) {
|
|
|
339
341
|
expect(fn(mock, 'gulls.1')).toEqual('gulls.$')
|
|
340
342
|
})
|
|
341
343
|
|
|
342
|
-
test('
|
|
344
|
+
test('validation default messages', async () => {
|
|
343
345
|
// Setup
|
|
344
346
|
let db = (await opendb(false)).db
|
|
345
347
|
let user = db.model('user', {
|
|
@@ -391,7 +393,7 @@ module.exports = function(monastery, opendb) {
|
|
|
391
393
|
})
|
|
392
394
|
})
|
|
393
395
|
|
|
394
|
-
test('
|
|
396
|
+
test('validation custom messages', async () => {
|
|
395
397
|
// Setup
|
|
396
398
|
// Todo: Setup testing for array array subdocument field messages
|
|
397
399
|
let db = (await opendb(false)).db
|
|
@@ -433,7 +435,7 @@ module.exports = function(monastery, opendb) {
|
|
|
433
435
|
})
|
|
434
436
|
})
|
|
435
437
|
|
|
436
|
-
test('
|
|
438
|
+
test('validation custom messages for arrays', async () => {
|
|
437
439
|
// Setup
|
|
438
440
|
// Todo: Setup testing for array array subdocument field messages
|
|
439
441
|
let db = (await opendb(false)).db
|
|
@@ -550,7 +552,7 @@ module.exports = function(monastery, opendb) {
|
|
|
550
552
|
})
|
|
551
553
|
})
|
|
552
554
|
|
|
553
|
-
test('
|
|
555
|
+
test('validation custom rules', async () => {
|
|
554
556
|
// Setup
|
|
555
557
|
let db = (await opendb(false)).db
|
|
556
558
|
let user = db.model('user', {
|
|
@@ -636,7 +638,7 @@ module.exports = function(monastery, opendb) {
|
|
|
636
638
|
}])
|
|
637
639
|
})
|
|
638
640
|
|
|
639
|
-
test('
|
|
641
|
+
test('validated data', async () => {
|
|
640
642
|
// Setup
|
|
641
643
|
let db = (await opendb(false)).db
|
|
642
644
|
let fields = {
|
|
@@ -694,7 +696,7 @@ module.exports = function(monastery, opendb) {
|
|
|
694
696
|
.resolves.toEqual({ animals: { dogs: [{}] }})
|
|
695
697
|
})
|
|
696
698
|
|
|
697
|
-
test('
|
|
699
|
+
test('schema options', async () => {
|
|
698
700
|
// Setup
|
|
699
701
|
let db = (await opendb(false)).db
|
|
700
702
|
let user = db.model('user', { fields: {
|
|
@@ -735,7 +737,7 @@ module.exports = function(monastery, opendb) {
|
|
|
735
737
|
})
|
|
736
738
|
})
|
|
737
739
|
|
|
738
|
-
test('
|
|
740
|
+
test('schema default rules', async () => {
|
|
739
741
|
// Setup
|
|
740
742
|
let db = (await opendb(false)).db
|
|
741
743
|
let user = db.model('user', { fields: {
|
|
@@ -816,7 +818,7 @@ module.exports = function(monastery, opendb) {
|
|
|
816
818
|
await expect(user.validate({ amount: 'bad' })).rejects.toContainEqual(mock2)
|
|
817
819
|
})
|
|
818
820
|
|
|
819
|
-
test('
|
|
821
|
+
test('schema default objects', async () => {
|
|
820
822
|
let db = (await opendb(null, {
|
|
821
823
|
timestamps: false,
|
|
822
824
|
defaultObjects: true,
|
|
@@ -842,7 +844,7 @@ module.exports = function(monastery, opendb) {
|
|
|
842
844
|
db.close()
|
|
843
845
|
})
|
|
844
846
|
|
|
845
|
-
test('
|
|
847
|
+
test('schema nullObjects', async () => {
|
|
846
848
|
let db = (await opendb(null, {
|
|
847
849
|
timestamps: false,
|
|
848
850
|
nullObjects: true,
|
|
@@ -868,7 +870,7 @@ module.exports = function(monastery, opendb) {
|
|
|
868
870
|
db.close()
|
|
869
871
|
})
|
|
870
872
|
|
|
871
|
-
test('
|
|
873
|
+
test('validation options', async () => {
|
|
872
874
|
let db = (await opendb(false)).db
|
|
873
875
|
let user = db.model('user', { fields: {
|
|
874
876
|
name: { type: 'string', required: true }
|
|
@@ -953,7 +955,7 @@ module.exports = function(monastery, opendb) {
|
|
|
953
955
|
})
|
|
954
956
|
})
|
|
955
957
|
|
|
956
|
-
test('
|
|
958
|
+
test('validation hooks', async () => {
|
|
957
959
|
let db = (await opendb(null)).db
|
|
958
960
|
let user = db.model('user', {
|
|
959
961
|
fields: {
|
package/test/virtuals.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module.exports = function(monastery, opendb) {
|
|
2
2
|
|
|
3
|
-
test('
|
|
3
|
+
test('virtuals', async () => {
|
|
4
4
|
// Setup
|
|
5
5
|
let db = (await opendb(null)).db
|
|
6
6
|
// Test model setup
|
|
@@ -147,7 +147,7 @@ module.exports = function(monastery, opendb) {
|
|
|
147
147
|
db.close()
|
|
148
148
|
})
|
|
149
149
|
|
|
150
|
-
test('
|
|
150
|
+
test('insert update virtuals (validate)', async () => {
|
|
151
151
|
// Setup
|
|
152
152
|
let db = (await opendb(null)).db
|
|
153
153
|
let user = db.model('user', {
|