monastery 1.41.1 → 1.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +4 -0
- package/docs/manager/index.md +6 -3
- package/docs/manager/models.md +2 -2
- package/docs/readme.md +5 -2
- package/lib/index.js +10 -2
- package/lib/model-crud.js +4 -0
- package/lib/model-validate.js +6 -0
- package/lib/model.js +13 -7
- package/package.json +1 -1
- package/test/blacklisting.js +20 -4
- package/test/model.js +13 -3
- package/test/monk.js +2 -2
- package/test/validate.js +5 -0
package/changelog.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
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.42.0](https://github.com/boycce/monastery/compare/1.41.2...1.42.0) (2023-10-09)
|
|
6
|
+
|
|
7
|
+
### [1.41.2](https://github.com/boycce/monastery/compare/1.41.1...1.41.2) (2023-10-04)
|
|
8
|
+
|
|
5
9
|
### [1.41.1](https://github.com/boycce/monastery/compare/1.41.0...1.41.1) (2023-04-17)
|
|
6
10
|
|
|
7
11
|
## [1.41.0](https://github.com/boycce/monastery/compare/1.40.5...1.41.0) (2023-04-16)
|
package/docs/manager/index.md
CHANGED
|
@@ -30,15 +30,18 @@ A monk manager instance with additional Monastery methods, i.e. `model` `models`
|
|
|
30
30
|
### Example
|
|
31
31
|
|
|
32
32
|
```js
|
|
33
|
-
|
|
33
|
+
import monastery from 'monastery'
|
|
34
|
+
const db = monastery('localhost/mydb', options)
|
|
34
35
|
```
|
|
35
36
|
|
|
36
37
|
```js
|
|
37
|
-
|
|
38
|
+
import monastery from 'monastery'
|
|
39
|
+
const db = monastery('localhost/mydb,192.168.1.1') // replica set
|
|
38
40
|
```
|
|
39
41
|
|
|
40
42
|
```js
|
|
41
|
-
|
|
43
|
+
import monastery from 'monastery'
|
|
44
|
+
monastery('localhost/mydb,192.168.1.1').then((db) => {
|
|
42
45
|
// db is the connected instance of the Manager
|
|
43
46
|
}).catch((err) => {
|
|
44
47
|
// error connecting to the database
|
package/docs/manager/models.md
CHANGED
|
@@ -9,7 +9,7 @@ Setup model definitions from a folder location
|
|
|
9
9
|
|
|
10
10
|
### Arguments
|
|
11
11
|
|
|
12
|
-
`path` *(string)*: path to model definitions, the filenames are used as the corresponding model name.
|
|
12
|
+
`path` *(string)*: path to model definitions, the filenames are used as the corresponding model name. Make sure the model definition is exported as the default
|
|
13
13
|
|
|
14
14
|
### Returns
|
|
15
15
|
|
|
@@ -23,7 +23,7 @@ db.model.{model-name}
|
|
|
23
23
|
|
|
24
24
|
```js
|
|
25
25
|
// ./models/user.js
|
|
26
|
-
export default {
|
|
26
|
+
export default { // Make sure the model definition is exported as the default
|
|
27
27
|
fields: {
|
|
28
28
|
name: { type: 'string', required: true },
|
|
29
29
|
email: { type: 'email', required: true, index: 'unique' }
|
package/docs/readme.md
CHANGED
|
@@ -24,9 +24,11 @@ $ npm install --save monastery
|
|
|
24
24
|
## Usage
|
|
25
25
|
|
|
26
26
|
```javascript
|
|
27
|
+
import monastery from 'monastery'
|
|
28
|
+
|
|
27
29
|
// Initialise a monastery manager
|
|
28
|
-
const db =
|
|
29
|
-
// const db =
|
|
30
|
+
const db = monastery('localhost/mydb')
|
|
31
|
+
// const db = monastery('user:pass@localhost:port/mydb')
|
|
30
32
|
|
|
31
33
|
// Define a model
|
|
32
34
|
db.model('user', {
|
|
@@ -101,6 +103,7 @@ Coming soon...
|
|
|
101
103
|
- Split away from Monk (unless updated)
|
|
102
104
|
- Add a warning if an invalid model is referenced in jthe schema
|
|
103
105
|
- Remove leading forward slashes from custom image paths (AWS adds this as a seperate folder)
|
|
106
|
+
- double check await db.model.remove({ query: idfromparam }) doesnt cause issues for null, undefined or '', but continue to allow {}
|
|
104
107
|
|
|
105
108
|
## Versions
|
|
106
109
|
|
package/lib/index.js
CHANGED
|
@@ -93,9 +93,17 @@ let models = async function(pathname, waitForIndexes) {
|
|
|
93
93
|
}
|
|
94
94
|
let filenames = fs.readdirSync(pathname)
|
|
95
95
|
for (let filename of filenames) {
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
// Ignore folders
|
|
97
|
+
if (!filename.match(/\.[cm]?js$/)) continue
|
|
98
98
|
let name = filename.replace('.js', '')
|
|
99
|
+
let filepath = path.join(pathname, filename)
|
|
100
|
+
// We can't use require() here since we need to be able to import both CJS and ES6 modules
|
|
101
|
+
let definition = (await import(filepath))?.default
|
|
102
|
+
// When a commonJS project uses babel (e.g. `nodemon -r @babel/register`, similar to `-r esm`), import()
|
|
103
|
+
// will return ES6 model definitions in another nested `default` object
|
|
104
|
+
if (definition?.default) definition = definition.default
|
|
105
|
+
if (!definition) throw new Error(`The model definition for '${name}' must export a default object`)
|
|
106
|
+
// Wait for indexes to be created?
|
|
99
107
|
if (waitForIndexes) out[name] = await this.model(name, { ...definition, waitForIndexes })
|
|
100
108
|
else out[name] = this.model(name, definition)
|
|
101
109
|
}
|
package/lib/model-crud.js
CHANGED
|
@@ -25,9 +25,13 @@ module.exports = {
|
|
|
25
25
|
try {
|
|
26
26
|
opts = await this._queryObject(opts, 'insert')
|
|
27
27
|
|
|
28
|
+
// console.log(11, opts.data )
|
|
29
|
+
|
|
28
30
|
// Validate
|
|
29
31
|
let data = await this.validate(opts.data || {}, opts) // was { ...opts }
|
|
30
32
|
|
|
33
|
+
// console.log(22, data)
|
|
34
|
+
|
|
31
35
|
// Insert
|
|
32
36
|
await util.runSeries(this.beforeInsert.map(f => f.bind(opts, data)))
|
|
33
37
|
let response = await this._insert(data, util.omit(opts, this._queryOptions))
|
package/lib/model-validate.js
CHANGED
|
@@ -108,6 +108,8 @@ module.exports = {
|
|
|
108
108
|
let data2 = util.isArray(fields)? [] : {}
|
|
109
109
|
let timestamps = util.isDefined(opts.timestamps)? opts.timestamps : this.manager.timestamps
|
|
110
110
|
|
|
111
|
+
// console.log(8888, fields)
|
|
112
|
+
|
|
111
113
|
util.forEach(util.forceArray(data), function(data, i) {
|
|
112
114
|
util.forEach(fields, function(field, fieldName) {
|
|
113
115
|
let verrors = []
|
|
@@ -131,8 +133,11 @@ module.exports = {
|
|
|
131
133
|
}
|
|
132
134
|
}
|
|
133
135
|
|
|
136
|
+
// console.log(333,path3)
|
|
137
|
+
|
|
134
138
|
// Ignore blacklisted
|
|
135
139
|
if (this._pathBlacklisted(path3, opts.projectionValidate) && !schema.defaultOverride) return
|
|
140
|
+
// console.log(444,path3)
|
|
136
141
|
// Ignore insert only
|
|
137
142
|
if (opts.update && schema.insertOnly) return
|
|
138
143
|
// Ignore virtual fields
|
|
@@ -141,6 +146,7 @@ module.exports = {
|
|
|
141
146
|
if (isTypeRule && util.isFunction(isTypeRule.tryParse)) {
|
|
142
147
|
value = isTypeRule.tryParse.call(dataRoot, value, fieldName, this)
|
|
143
148
|
}
|
|
149
|
+
// console.log(555,path3)
|
|
144
150
|
|
|
145
151
|
// Schema field (ignore object/array schemas)
|
|
146
152
|
if (util.isSchema(field) && fieldName !== 'schema') {
|
package/lib/model.js
CHANGED
|
@@ -14,16 +14,18 @@ let Model = module.exports = function(name, opts, manager) {
|
|
|
14
14
|
*/
|
|
15
15
|
if (!(this instanceof Model)) {
|
|
16
16
|
return new Model(name, opts, this)
|
|
17
|
-
|
|
18
17
|
} else if (!name) {
|
|
19
18
|
throw 'No model name defined'
|
|
20
|
-
|
|
21
19
|
} else if (name.match(/^_/)) {
|
|
22
20
|
throw 'Model names cannot start with an underscore'
|
|
21
|
+
} else if (!opts) {
|
|
22
|
+
throw `No model definition passed for "${name}"`
|
|
23
|
+
} else if (!opts.fields) {
|
|
24
|
+
throw `We couldn't find ${name}.fields in the model definition, the model maybe setup `
|
|
25
|
+
+ `or exported incorrectly:\n${JSON.stringify(opts, null, 2)}`
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
// Add schema options
|
|
26
|
-
opts = opts || {}
|
|
27
29
|
Object.assign(this, {
|
|
28
30
|
...(opts.methods || {}),
|
|
29
31
|
afterFind: opts.afterFind || [],
|
|
@@ -37,14 +39,14 @@ let Model = module.exports = function(name, opts, manager) {
|
|
|
37
39
|
error: manager.error,
|
|
38
40
|
info: manager.info,
|
|
39
41
|
warn: manager.warn,
|
|
40
|
-
insertBL: opts.insertBL || [],
|
|
42
|
+
insertBL: opts.insertBL || ['_id'],
|
|
41
43
|
fields: { ...(util.deepCopy(opts.fields) || {}) },
|
|
42
44
|
findBL: opts.findBL || ['password'],
|
|
43
45
|
manager: manager,
|
|
44
46
|
messages: opts.messages || {},
|
|
45
47
|
name: name,
|
|
46
48
|
rules: { ...(opts.rules || {}) },
|
|
47
|
-
updateBL: opts.updateBL || [],
|
|
49
|
+
updateBL: opts.updateBL || ['_id'],
|
|
48
50
|
})
|
|
49
51
|
|
|
50
52
|
// Run before model hooks
|
|
@@ -69,7 +71,7 @@ let Model = module.exports = function(name, opts, manager) {
|
|
|
69
71
|
}, this)
|
|
70
72
|
|
|
71
73
|
// Extend default fields with passed in fields and check for invalid fields
|
|
72
|
-
this._setupFields(this.fields = Object.assign({}, this.
|
|
74
|
+
this._setupFields(this.fields = Object.assign({}, this._defaultFields, this.fields))
|
|
73
75
|
this.fieldsFlattened = this._getFieldsFlattened(this.fields, '') // test output?
|
|
74
76
|
|
|
75
77
|
// Extend model with monk collection queries
|
|
@@ -319,7 +321,11 @@ Model.prototype._setupIndexes = function(fields, opts={}) {
|
|
|
319
321
|
}
|
|
320
322
|
}
|
|
321
323
|
|
|
322
|
-
Model.prototype.
|
|
324
|
+
Model.prototype._defaultFields = {
|
|
325
|
+
_id: {
|
|
326
|
+
insertOnly: true,
|
|
327
|
+
type: 'id'
|
|
328
|
+
},
|
|
323
329
|
createdAt: {
|
|
324
330
|
default: function(fieldName, model) {
|
|
325
331
|
return model.manager.useMilliseconds? Date.now() : Math.floor(Date.now() / 1000)
|
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.42.0",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": "github:boycce/monastery",
|
|
8
8
|
"homepage": "https://boycce.github.io/monastery/",
|
package/test/blacklisting.js
CHANGED
|
@@ -339,7 +339,7 @@ module.exports = function(monastery, opendb) {
|
|
|
339
339
|
db.close()
|
|
340
340
|
})
|
|
341
341
|
|
|
342
|
-
test('insert
|
|
342
|
+
test('insert blacklisting (validate)', async () => {
|
|
343
343
|
// Setup
|
|
344
344
|
let db = (await opendb(null)).db
|
|
345
345
|
let user = db.model('user', {
|
|
@@ -365,15 +365,21 @@ module.exports = function(monastery, opendb) {
|
|
|
365
365
|
}
|
|
366
366
|
},
|
|
367
367
|
insertBL: [
|
|
368
|
+
'_id', // default
|
|
368
369
|
'dog',
|
|
369
370
|
'animals.cat',
|
|
370
371
|
'pets.age',
|
|
371
372
|
'hiddenPets',
|
|
372
373
|
'hiddenList',
|
|
373
374
|
'deep.deep2.deep3'
|
|
374
|
-
]
|
|
375
|
+
],
|
|
376
|
+
updateBL: [
|
|
377
|
+
'_id' // default
|
|
378
|
+
],
|
|
375
379
|
})
|
|
380
|
+
let doc1Id = db.id()
|
|
376
381
|
let doc1 = {
|
|
382
|
+
_id: doc1Id,
|
|
377
383
|
list: [44, 54],
|
|
378
384
|
dog: 'Bruce',
|
|
379
385
|
pet: 'Freddy',
|
|
@@ -409,9 +415,10 @@ module.exports = function(monastery, opendb) {
|
|
|
409
415
|
}
|
|
410
416
|
})
|
|
411
417
|
|
|
412
|
-
// Custom blacklist (remove and add to the current schema blacklist)
|
|
418
|
+
// Custom insert blacklist (remove and add to the current schema blacklist)
|
|
413
419
|
let user2 = await user.validate(doc1, {
|
|
414
420
|
blacklist: [
|
|
421
|
+
'-_id',
|
|
415
422
|
'-dog',
|
|
416
423
|
'-animals.dog', // wrong property
|
|
417
424
|
'pets.name',
|
|
@@ -421,6 +428,7 @@ module.exports = function(monastery, opendb) {
|
|
|
421
428
|
})
|
|
422
429
|
let customBlacklist
|
|
423
430
|
expect(user2).toEqual((customBlacklist = {
|
|
431
|
+
_id: doc1Id,
|
|
424
432
|
list: [44, 54],
|
|
425
433
|
dog: 'Bruce',
|
|
426
434
|
pet: 'Freddy',
|
|
@@ -440,7 +448,7 @@ module.exports = function(monastery, opendb) {
|
|
|
440
448
|
|
|
441
449
|
// Blacklist string
|
|
442
450
|
let user3 = await user.validate(doc1, {
|
|
443
|
-
blacklist: '-dog -animals.dog pets.name -hiddenList -deep'
|
|
451
|
+
blacklist: '-_id -dog -animals.dog pets.name -hiddenList -deep'
|
|
444
452
|
})
|
|
445
453
|
expect(user3).toEqual(customBlacklist)
|
|
446
454
|
|
|
@@ -467,6 +475,14 @@ module.exports = function(monastery, opendb) {
|
|
|
467
475
|
}
|
|
468
476
|
}
|
|
469
477
|
})
|
|
478
|
+
|
|
479
|
+
// double check that _id.insertOnly is working
|
|
480
|
+
let user6 = await user.validate(doc1, { update: true, blacklist: false })
|
|
481
|
+
expect(user6).toEqual({
|
|
482
|
+
...doc1,
|
|
483
|
+
_id: undefined,
|
|
484
|
+
})
|
|
485
|
+
|
|
470
486
|
db.close()
|
|
471
487
|
})
|
|
472
488
|
|
package/test/model.js
CHANGED
|
@@ -13,7 +13,12 @@ module.exports = function(monastery, opendb) {
|
|
|
13
13
|
}})
|
|
14
14
|
|
|
15
15
|
// no fields defined
|
|
16
|
-
expect(db.model('user2').fields).toEqual({
|
|
16
|
+
expect(db.model('user2', { fields: {} }).fields).toEqual({
|
|
17
|
+
_id: {
|
|
18
|
+
insertOnly: true,
|
|
19
|
+
isId: true,
|
|
20
|
+
type: 'id',
|
|
21
|
+
},
|
|
17
22
|
createdAt: {
|
|
18
23
|
default: expect.any(Function),
|
|
19
24
|
insertOnly: true,
|
|
@@ -73,7 +78,12 @@ module.exports = function(monastery, opendb) {
|
|
|
73
78
|
let db = (await opendb(false, { defaultObjects: true })).db
|
|
74
79
|
|
|
75
80
|
// Default fields
|
|
76
|
-
expect(db.model('user2').fields).toEqual({
|
|
81
|
+
expect(db.model('user2', { fields: {} }).fields).toEqual({
|
|
82
|
+
_id: {
|
|
83
|
+
insertOnly: true,
|
|
84
|
+
isId: true,
|
|
85
|
+
type: 'id',
|
|
86
|
+
},
|
|
77
87
|
createdAt: {
|
|
78
88
|
default: expect.any(Function),
|
|
79
89
|
insertOnly: true,
|
|
@@ -195,7 +205,7 @@ module.exports = function(monastery, opendb) {
|
|
|
195
205
|
}
|
|
196
206
|
|
|
197
207
|
// Unique & text index (after model initialisation, in serial)
|
|
198
|
-
let userIndexRawModel = db.model('userIndexRaw', {})
|
|
208
|
+
let userIndexRawModel = db.model('userIndexRaw', {fields: {}})
|
|
199
209
|
await userIndexRawModel._setupIndexes({
|
|
200
210
|
email: { type: 'string', index: 'unique' },
|
|
201
211
|
})
|
package/test/monk.js
CHANGED
|
@@ -4,8 +4,8 @@ module.exports = function(monastery, opendb) {
|
|
|
4
4
|
// Setup
|
|
5
5
|
let db = (await opendb(false)).db
|
|
6
6
|
let monkdb = require('monk')(':badconnection', () => {})
|
|
7
|
-
db.model('user', {})
|
|
8
|
-
let modelNamedConnected = db.model('connected', {})
|
|
7
|
+
db.model('user', { fields: {} })
|
|
8
|
+
let modelNamedConnected = db.model('connected', { fields: {} })
|
|
9
9
|
|
|
10
10
|
// Any of our monastery properties already exist on the manager?
|
|
11
11
|
for (let name of ['connected', 'debug', 'log', 'model', 'models']) {
|
package/test/validate.js
CHANGED
|
@@ -765,6 +765,11 @@ module.exports = function(monastery, opendb) {
|
|
|
765
765
|
// Subdocument -> array -> subdocument data (empty)
|
|
766
766
|
await expect(user.validate({ animals: { dogs: [{}] }}))
|
|
767
767
|
.resolves.toEqual({ animals: { dogs: [{}] }})
|
|
768
|
+
|
|
769
|
+
// _id is blacklisted by default
|
|
770
|
+
let id = db.id()
|
|
771
|
+
await expect(user.validate({ _id: id })).resolves.toEqual({})
|
|
772
|
+
await expect(user.validate({ _id: id }, { update: true })).resolves.toEqual({})
|
|
768
773
|
})
|
|
769
774
|
|
|
770
775
|
test('schema options', async () => {
|