monastery 1.28.0 → 1.28.4
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/docs/Gemfile +8 -18
- package/docs/_config.yml +1 -4
- package/docs/readme.md +6 -0
- package/docs/schema.md +4 -4
- package/lib/model.js +17 -14
- package/lib/rules.js +0 -0
- package/package.json +2 -2
- package/test/model.js +61 -12
package/docs/Gemfile
CHANGED
|
@@ -1,20 +1,10 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Old
|
|
2
|
+
# source 'https://rubygems.org'
|
|
3
|
+
# gem 'github-pages', group: :jekyll_plugins
|
|
2
4
|
|
|
3
|
-
#
|
|
5
|
+
# Below pulls the latest remote_theme in development
|
|
4
6
|
source 'https://rubygems.org'
|
|
5
|
-
gem
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
# # Same as github-docs
|
|
11
|
-
# gem "bundler"
|
|
12
|
-
# gem "jekyll", "~> 3.9.0"
|
|
13
|
-
# gem "jekyll-github-metadata", "~> 2.13.0"
|
|
14
|
-
# gem "jekyll-seo-tag", "~> 2.7.1"
|
|
15
|
-
# gem "kramdown-parser-gfm", "~> 1.1.0"
|
|
16
|
-
# gem "github-docs", git: "https://github.com/boycce/github-docs"
|
|
17
|
-
|
|
18
|
-
# group :jekyll_plugins do
|
|
19
|
-
# gem "jekyll-remote-theme", "~> 0.4.2"
|
|
20
|
-
# end
|
|
7
|
+
gem "github-docs", git: "https://github.com/boycce/github-docs"
|
|
8
|
+
group :jekyll_plugins do
|
|
9
|
+
gem "jekyll-remote-theme", "~> 0.4.2"
|
|
10
|
+
end
|
package/docs/_config.yml
CHANGED
|
@@ -2,16 +2,13 @@ remote_theme: boycce/github-docs
|
|
|
2
2
|
title: Monastery
|
|
3
3
|
description: A straight forward MongoDB ODM built upon MonkJS
|
|
4
4
|
github_url: "https://github.com/boycce/monastery"
|
|
5
|
-
basedir: ""
|
|
5
|
+
basedir: "docs"
|
|
6
6
|
|
|
7
7
|
# Aux links for the naviation.
|
|
8
8
|
aux_links:
|
|
9
9
|
"Monastery on GitHub":
|
|
10
10
|
- "//github.com/boycce/monastery"
|
|
11
11
|
|
|
12
|
-
plugins:
|
|
13
|
-
- jekyll-remote-theme
|
|
14
|
-
|
|
15
12
|
defaults:
|
|
16
13
|
-
|
|
17
14
|
scope:
|
package/docs/readme.md
CHANGED
package/docs/schema.md
CHANGED
|
@@ -173,13 +173,13 @@ You are able to define custom validation rules to use. (`this` will refer to the
|
|
|
173
173
|
```js
|
|
174
174
|
schema.rules = {
|
|
175
175
|
// Basic definition
|
|
176
|
-
isGrandMaster: function(value, ruleArgument,
|
|
176
|
+
isGrandMaster: function(value, ruleArgument, path, model) {
|
|
177
177
|
return (value == 'Martin Luther')? true : false
|
|
178
178
|
},
|
|
179
179
|
// Full definition
|
|
180
180
|
isGrandMaster: {
|
|
181
|
-
message: (value, ruleArgument,
|
|
182
|
-
fn: function(value, ruleArgument,
|
|
181
|
+
message: (value, ruleArgument, path, model) => 'Only grand masters are permitted'
|
|
182
|
+
fn: function(value, ruleArgument, path, model) {
|
|
183
183
|
return (value == 'Martin Luther' || this.age > 100)? true : false
|
|
184
184
|
}
|
|
185
185
|
}
|
|
@@ -214,7 +214,7 @@ schema.messages = {
|
|
|
214
214
|
type: 'Sorry, your name needs to be a string'
|
|
215
215
|
},
|
|
216
216
|
'address.city': {
|
|
217
|
-
minLength: (value, ruleArgument,
|
|
217
|
+
minLength: (value, ruleArgument, path, model) => {
|
|
218
218
|
return `Is your city of residence really only ${ruleArgument} characters long?`
|
|
219
219
|
}
|
|
220
220
|
},
|
package/lib/model.js
CHANGED
|
@@ -6,10 +6,11 @@ let validate = require('./model-validate')
|
|
|
6
6
|
let Model = module.exports = function(name, opts, manager) {
|
|
7
7
|
/**
|
|
8
8
|
* Setup a model (aka monk collection)
|
|
9
|
-
* Todo: convert into a promise
|
|
10
9
|
* @param {string} name
|
|
11
10
|
* @param {object} opts - see mongodb colleciton documentation
|
|
12
|
-
* @
|
|
11
|
+
* @param {boolean} opts.waitForIndexes
|
|
12
|
+
* @this model
|
|
13
|
+
* @return Promise(model) | this
|
|
13
14
|
*/
|
|
14
15
|
if (!(this instanceof Model)) {
|
|
15
16
|
return new Model(name, opts, this)
|
|
@@ -25,10 +26,6 @@ let Model = module.exports = function(name, opts, manager) {
|
|
|
25
26
|
opts = opts || {}
|
|
26
27
|
Object.assign(this, {
|
|
27
28
|
...(opts.methods || {}),
|
|
28
|
-
name: name,
|
|
29
|
-
manager: manager,
|
|
30
|
-
error: manager.error,
|
|
31
|
-
info: manager.info,
|
|
32
29
|
afterFind: opts.afterFind || [],
|
|
33
30
|
afterInsert: (opts.afterInsert || []).concat(opts.afterInsertUpdate || []),
|
|
34
31
|
afterUpdate: (opts.afterUpdate || []).concat(opts.afterInsertUpdate || []),
|
|
@@ -37,12 +34,16 @@ let Model = module.exports = function(name, opts, manager) {
|
|
|
37
34
|
beforeUpdate: (opts.beforeUpdate || []).concat(opts.beforeInsertUpdate || []),
|
|
38
35
|
beforeRemove: opts.beforeRemove || [],
|
|
39
36
|
beforeValidate: opts.beforeValidate || [],
|
|
40
|
-
|
|
37
|
+
error: manager.error,
|
|
38
|
+
info: manager.info,
|
|
41
39
|
insertBL: opts.insertBL || [],
|
|
42
|
-
updateBL: opts.updateBL || [],
|
|
43
|
-
messages: opts.messages || {},
|
|
44
40
|
fields: { ...(util.deepCopy(opts.fields) || {}) },
|
|
45
|
-
|
|
41
|
+
findBL: opts.findBL || ['password'],
|
|
42
|
+
manager: manager,
|
|
43
|
+
messages: opts.messages || {},
|
|
44
|
+
name: name,
|
|
45
|
+
rules: { ...(opts.rules || {}) },
|
|
46
|
+
updateBL: opts.updateBL || [],
|
|
46
47
|
})
|
|
47
48
|
|
|
48
49
|
// Run before model hooks
|
|
@@ -94,13 +95,13 @@ let Model = module.exports = function(name, opts, manager) {
|
|
|
94
95
|
// Add model to manager.model
|
|
95
96
|
this.manager.model[name] = this
|
|
96
97
|
|
|
97
|
-
// Ensure field indexes exist in
|
|
98
|
+
// Setup/Ensure field indexes exist in MongoDB
|
|
98
99
|
let errHandler = err => {
|
|
99
100
|
if (err.type == 'info') this.info(err.detail)
|
|
100
101
|
else this.error(err)
|
|
101
102
|
}
|
|
102
|
-
if (opts.
|
|
103
|
-
else this._setupIndexes().catch(errHandler)
|
|
103
|
+
if (opts.waitForIndexes) return this._setupIndexes().catch(errHandler).then(() => this)
|
|
104
|
+
else this._setupIndexes().catch(errHandler) // returns this
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
Model.prototype._getFieldlist = function(fields, path) {
|
|
@@ -243,7 +244,7 @@ Model.prototype._setupIndexes = function(fields) {
|
|
|
243
244
|
* @link https://docs.mongodb.com/manual/reference/command/createIndexes/
|
|
244
245
|
* @link https://mongodb.github.io/node-mongodb-native/2.1/api/Collection.html#createIndexes
|
|
245
246
|
* @param {object} <fields>
|
|
246
|
-
* @return Promise( {array} indexes | {string} error )
|
|
247
|
+
* @return Promise( {array} indexes ensured | {string} error )
|
|
247
248
|
*
|
|
248
249
|
* MongoDB index structures = [
|
|
249
250
|
* true = { name: 'name_1', key: { name: 1 } },
|
|
@@ -267,6 +268,7 @@ Model.prototype._setupIndexes = function(fields) {
|
|
|
267
268
|
|
|
268
269
|
// Find all indexes
|
|
269
270
|
recurseFields(fields || model.fields, '')
|
|
271
|
+
// console.log(2, indexes, fields)
|
|
270
272
|
if (hasTextIndex) indexes.push(textIndex)
|
|
271
273
|
if (!indexes.length) return Promise.resolve([]) // No indexes defined
|
|
272
274
|
|
|
@@ -313,6 +315,7 @@ Model.prototype._setupIndexes = function(fields) {
|
|
|
313
315
|
})
|
|
314
316
|
.then(response => {
|
|
315
317
|
model.info('db index(s) created for ' + model.name)
|
|
318
|
+
return indexes
|
|
316
319
|
})
|
|
317
320
|
|
|
318
321
|
function recurseFields(fields, parentPath) {
|
package/lib/rules.js
CHANGED
|
File without changes
|
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.28.
|
|
5
|
+
"version": "1.28.4",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": "github:boycce/monastery",
|
|
8
8
|
"homepage": "https://boycce.github.io/monastery/",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"aws-sdk": "^2.742.0",
|
|
29
|
-
"debug": "
|
|
29
|
+
"debug": "4.1.1",
|
|
30
30
|
"file-type": "^15.0.0",
|
|
31
31
|
"monk": "^7.3.0",
|
|
32
32
|
"nanoid": "^3.1.12",
|
package/test/model.js
CHANGED
|
@@ -116,27 +116,76 @@ module.exports = function(monastery, opendb) {
|
|
|
116
116
|
})
|
|
117
117
|
|
|
118
118
|
test('Model indexes', async (done) => {
|
|
119
|
-
// Setup
|
|
120
119
|
// Need to test different types of indexes
|
|
121
120
|
let db = (await opendb(null)).db
|
|
122
|
-
let user = db.model('user', {})
|
|
123
|
-
let user2 = db.model('user2', {})
|
|
124
121
|
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
|
|
122
|
+
// Drop previously tested collections
|
|
123
|
+
if ((await db._db.listCollections().toArray()).find(o => o.name == 'userIndexRaw')) {
|
|
124
|
+
await db._db.collection('userIndexRaw').drop()
|
|
125
|
+
}
|
|
126
|
+
if ((await db._db.listCollections().toArray()).find(o => o.name == 'userIndex')) {
|
|
127
|
+
await db._db.collection('userIndex').drop()
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Unique & text index (after model initialisation, in serial)
|
|
131
|
+
let userIndexRawModel = db.model('userIndexRaw', {})
|
|
132
|
+
let setupIndex1 = await userIndexRawModel._setupIndexes({
|
|
133
|
+
email: { type: 'string', index: 'unique' },
|
|
134
|
+
})
|
|
135
|
+
let setupIndex2 = await userIndexRawModel._setupIndexes({
|
|
136
|
+
name: { type: 'string', index: 'text' },
|
|
137
|
+
})
|
|
138
|
+
let indexes = await db._db.collection('userIndexRaw').indexes()
|
|
139
|
+
expect(indexes[0]).toMatchObject({ v: 2, key: { _id: 1 }, name: '_id_' })
|
|
140
|
+
expect(indexes[1]).toMatchObject({ v: 2, unique: true, key: { email: 1 }, name: 'email_1' })
|
|
141
|
+
expect(indexes[2]).toMatchObject({
|
|
142
|
+
v: 2,
|
|
143
|
+
key: { _fts: 'text', _ftsx: 1 },
|
|
144
|
+
name: 'text',
|
|
145
|
+
weights: { name: 1 },
|
|
146
|
+
default_language: 'english',
|
|
147
|
+
language_override: 'language',
|
|
148
|
+
textIndexVersion: 3
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
// Unique & text index
|
|
152
|
+
let userIndexModel = await db.model('userIndex', {
|
|
153
|
+
waitForIndexes: true,
|
|
154
|
+
fields: {
|
|
155
|
+
email: { type: 'string', index: 'unique' },
|
|
156
|
+
name: { type: 'string', index: 'text' },
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
let indexes2 = await db._db.collection('userIndex').indexes()
|
|
161
|
+
expect(indexes2[0]).toMatchObject({ v: 2, key: { _id: 1 }, name: '_id_' })
|
|
162
|
+
expect(indexes2[1]).toMatchObject({ v: 2, unique: true, key: { email: 1 }, name: 'email_1' })
|
|
163
|
+
expect(indexes2[2]).toMatchObject({
|
|
164
|
+
v: 2,
|
|
165
|
+
key: { _fts: 'text', _ftsx: 1 },
|
|
166
|
+
name: 'text',
|
|
167
|
+
weights: { name: 1 },
|
|
168
|
+
default_language: 'english',
|
|
169
|
+
language_override: 'language',
|
|
170
|
+
textIndexVersion: 3
|
|
128
171
|
})
|
|
129
172
|
|
|
130
173
|
// No text index change error, i.e. new Error("Index with name: text already exists with different options")
|
|
131
|
-
await expect(
|
|
174
|
+
await expect(userIndexModel._setupIndexes({
|
|
132
175
|
name: { type: 'string', index: 'text' },
|
|
133
176
|
name2: { type: 'string', index: 'text' }
|
|
134
|
-
})).resolves.toEqual(
|
|
177
|
+
})).resolves.toEqual([{
|
|
178
|
+
"key": { "name": "text", "name2": "text" },
|
|
179
|
+
"name": "text",
|
|
180
|
+
}])
|
|
135
181
|
|
|
136
182
|
// Text index on a different model
|
|
137
|
-
await expect(
|
|
138
|
-
|
|
139
|
-
})).resolves.toEqual(
|
|
183
|
+
await expect(userIndexRawModel._setupIndexes({
|
|
184
|
+
name2: { type: 'string', index: 'text' }
|
|
185
|
+
})).resolves.toEqual([{
|
|
186
|
+
"key": {"name2": "text"},
|
|
187
|
+
"name": "text",
|
|
188
|
+
}])
|
|
140
189
|
|
|
141
190
|
db.close()
|
|
142
191
|
done()
|
|
@@ -147,7 +196,7 @@ module.exports = function(monastery, opendb) {
|
|
|
147
196
|
// with text indexes are setup at the same time
|
|
148
197
|
let db = (await opendb(null)).db
|
|
149
198
|
await db.model('user3', {
|
|
150
|
-
|
|
199
|
+
waitForIndexes: true,
|
|
151
200
|
fields: {
|
|
152
201
|
location: {
|
|
153
202
|
index: '2dsphere',
|