monastery 1.37.3 → 1.38.2
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 +21 -0
- package/docs/definition/index.md +7 -1
- package/docs/image-plugin.md +22 -1
- package/docs/model/find.md +1 -1
- package/docs/model/insert.md +1 -1
- package/docs/model/update.md +1 -1
- package/docs/model/validate.md +1 -1
- package/docs/readme.md +8 -1
- package/lib/rules.js +13 -14
- package/package.json +1 -1
- package/plugins/images/index.js +24 -20
- package/test/crud.js +39 -0
- package/test/plugin-images.js +11 -3
- package/test/validate.js +6 -3
package/changelog.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
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.38.2](https://github.com/boycce/monastery/compare/1.38.1...1.38.2) (2022-07-31)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* init load time ([2273f11](https://github.com/boycce/monastery/commit/2273f11a654a9cfe05ee15ed682203a8752237d6))
|
|
11
|
+
|
|
12
|
+
### [1.38.1](https://github.com/boycce/monastery/compare/1.38.0...1.38.1) (2022-06-20)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* changed ACL default ([cc92624](https://github.com/boycce/monastery/commit/cc926243728d0752940359fe4ae4a490f21b5750))
|
|
18
|
+
|
|
19
|
+
## [1.38.0](https://github.com/boycce/monastery/compare/1.37.3...1.38.0) (2022-06-17)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
* added options.metadata ([cb4ca43](https://github.com/boycce/monastery/commit/cb4ca43a395c1f90a5e37b8cc95472053e2b3b36))
|
|
25
|
+
|
|
5
26
|
### [1.37.3](https://github.com/boycce/monastery/compare/1.37.2...1.37.3) (2022-06-17)
|
|
6
27
|
|
|
7
28
|
|
package/docs/definition/index.md
CHANGED
|
@@ -212,7 +212,10 @@ Since unique indexes by default don't allow multiple documents with `null`, you
|
|
|
212
212
|
|
|
213
213
|
### Custom field rules
|
|
214
214
|
|
|
215
|
-
You are able to define custom field rules to use.
|
|
215
|
+
You are able to define custom field rules to use.
|
|
216
|
+
|
|
217
|
+
- `this` will refer to the data object passed in
|
|
218
|
+
- by default, custom rules will ignore `undefined` values
|
|
216
219
|
|
|
217
220
|
```js
|
|
218
221
|
{
|
|
@@ -223,6 +226,9 @@ You are able to define custom field rules to use. (`this` will refer to the data
|
|
|
223
226
|
},
|
|
224
227
|
// Full definition
|
|
225
228
|
isGrandMaster: {
|
|
229
|
+
validateUndefined: false, // default
|
|
230
|
+
validateNull: true, // default
|
|
231
|
+
validateEmptyString: true, // default
|
|
226
232
|
message: function(value, ruleArgument, path, model) {
|
|
227
233
|
return 'Only grand masters are permitted'
|
|
228
234
|
},
|
package/docs/image-plugin.md
CHANGED
|
@@ -18,7 +18,10 @@ To use the default image plugin shipped with monastery, you need to use the opti
|
|
|
18
18
|
formats: ['bmp', 'gif', 'jpg', 'jpeg', 'png', 'tiff'], // default (use 'any' to allow all extensions)
|
|
19
19
|
getSignedUrl: false, // default (get a S3 signed url after `model.find()`, can be defined per request)
|
|
20
20
|
path: (uid, basename, ext, file) => `/full/${uid}.${ext}`, // default
|
|
21
|
-
|
|
21
|
+
metadata: {},
|
|
22
|
+
// Any s3 upload param, which takes precedence over the params above
|
|
23
|
+
// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property)
|
|
24
|
+
params: {},
|
|
22
25
|
}
|
|
23
26
|
})
|
|
24
27
|
```
|
|
@@ -65,3 +68,21 @@ user.update({
|
|
|
65
68
|
Due to known limitations, we are not able to verify the contents of non-binary files, only the filename extension (e.g. .txt, .svg) before uploading to S3
|
|
66
69
|
|
|
67
70
|
...to be continued
|
|
71
|
+
|
|
72
|
+
### Image sizes
|
|
73
|
+
|
|
74
|
+
I've put together a AWS Lambda function which you can use to generate small/medium/large image sizes automatically for any new files uploaded to your bucket.
|
|
75
|
+
[https://github.com/boycce/s3-lambda-thumbnail-generator](https://github.com/boycce/s3-lambda-thumbnail-generator#install-bucket)
|
|
76
|
+
|
|
77
|
+
You can override the function's default image sizes via the `metadata` option globally in the manager options, or per file:
|
|
78
|
+
```js
|
|
79
|
+
// Per file
|
|
80
|
+
let user = db.model('user', {
|
|
81
|
+
fields: {
|
|
82
|
+
logo: {
|
|
83
|
+
type: 'image',
|
|
84
|
+
metadata: { small: '*x300', medium: '*x800', large: '*x1200' },
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
package/docs/model/find.md
CHANGED
|
@@ -74,7 +74,7 @@ user.find({ query: {...}, populate: ['myBook'] })
|
|
|
74
74
|
```
|
|
75
75
|
|
|
76
76
|
You can also populate within embedded document fields. Although at this time arrays are not supported,
|
|
77
|
-
you would need to use the [example below](#
|
|
77
|
+
you would need to use the [example below](#populate-multiple-documents-into-virtual-fields).
|
|
78
78
|
```js
|
|
79
79
|
user.find({ query: {...}, populate: ['myBooks.book'] })
|
|
80
80
|
```
|
package/docs/model/insert.md
CHANGED
|
@@ -14,7 +14,7 @@ Validate and insert document(s) in a collection and calls model hooks: `beforeIn
|
|
|
14
14
|
- `data` *(object\|array)* - Data that is validated against the model fields. Key names can be in dot or bracket notation which is handy for HTML FormData.
|
|
15
15
|
- [[`blacklist`](#blacklisting)] *(array\|string\|false)*: augment `definition.insertBL`. `false` will remove all blacklisting
|
|
16
16
|
- [`project`] *(string\|array\|object)*: project these fields, ignores blacklisting
|
|
17
|
-
- [`skipValidation`] (string\|array): skip validation for
|
|
17
|
+
- [`skipValidation`] (string\|array\|boolean): skip validation for these field name(s), or `true` for all fields
|
|
18
18
|
- [`timestamps`] *(boolean)*: whether `createdAt` and `updatedAt` are automatically inserted, defaults to `manager.timestamps`
|
|
19
19
|
- [[`any mongodb option`](http://mongodb.github.io/node-mongodb-native/3.2/api/Collection.html#insert)] *(any)*
|
|
20
20
|
|
package/docs/model/update.md
CHANGED
|
@@ -15,7 +15,7 @@ Update document(s) in a collection and calls model hooks: `beforeUpdate`, `afte
|
|
|
15
15
|
- [`data`](#data) *(object)* - data that's validated against the model fields (always wrapped in `{ $set: .. }`)
|
|
16
16
|
- [[`blacklist`](#blacklisting)]*(array\|string\|false)*: augment `definition.updateBL`. `false` will remove all blacklisting
|
|
17
17
|
- [`project`] *(string\|array\|object)*: project these fields, ignores blacklisting
|
|
18
|
-
- [`skipValidation`] (string\|array): skip validation for
|
|
18
|
+
- [`skipValidation`] (string\|array\|boolean): skip validation for these field name(s), or `true` for all fields
|
|
19
19
|
- [`sort`] *(string\|object\|array)*: same as the mongodb option, but allows for string parsing e.g. 'name', 'name:1'
|
|
20
20
|
- [`timestamps`] *(boolean)*: whether `updatedAt` is automatically updated, defaults to the `manager.timestamps` value
|
|
21
21
|
- [[`any mongodb option`](http://mongodb.github.io/node-mongodb-native/3.2/api/Collection.html#update)] *(any)*
|
package/docs/model/validate.md
CHANGED
|
@@ -14,7 +14,7 @@ Validate a model and calls the model hook: `beforeValidate`
|
|
|
14
14
|
|
|
15
15
|
[`options`] *(object)*
|
|
16
16
|
|
|
17
|
-
- [`skipValidation`] (string\|array): skip validation for
|
|
17
|
+
- [`skipValidation`] (string\|array\/boolean): skip validation for thse field name(s), or `true` for all fields
|
|
18
18
|
- [[`blacklist`](#blacklisting)] *(array\|string\|false)*: augment the model's blacklist. `false` will remove all blacklisting
|
|
19
19
|
- [`project`] *(string\|array\|object)*: project these fields, ignores blacklisting
|
|
20
20
|
- [`timestamps`] *(boolean)*: whether `createdAt` and `updatedAt` are inserted, or `updatedAt` is updated, depending on the `update` value. Defaults to the `manager.timestamps` value
|
package/docs/readme.md
CHANGED
|
@@ -93,12 +93,19 @@ Coming soon...
|
|
|
93
93
|
- ~~Whitelisting a parent will remove any previously blacklisted children~~
|
|
94
94
|
- ~~Blacklist/project works the same across find/insert/update/validate~~
|
|
95
95
|
- Automatic embedded document ids/createdAt/updatedAt fields
|
|
96
|
-
- ~~
|
|
96
|
+
- ~~Ability to change ACL default on the manager~~
|
|
97
97
|
- ~~Public db.arrayWithSchema method~~
|
|
98
98
|
- Global after/before hooks
|
|
99
|
+
- before hooks can receive a data array, remove this
|
|
99
100
|
- docs: Make the implicit ID query conversion more apparent
|
|
100
101
|
- Split away from Monk (unless updated)
|
|
101
102
|
|
|
103
|
+
## Versions
|
|
104
|
+
|
|
105
|
+
- Monk: `v7.3.4`
|
|
106
|
+
- MongoDB NodeJS driver: `v3.2.3` ([compatibility](https://www.mongodb.com/docs/drivers/node/current/compatibility/#compatibility))
|
|
107
|
+
- MongoDB: [`v4.0.0`](https://www.mongodb.com/docs/v4.2/reference/)
|
|
108
|
+
|
|
102
109
|
## Special Thanks
|
|
103
110
|
|
|
104
111
|
[Jerome Gravel-Niquet](https://github.com/jeromegn)
|
package/lib/rules.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Todo: remove stringnums in date/number/integer rules
|
|
2
2
|
let ObjectId = require('mongodb').ObjectId
|
|
3
3
|
let util = require('./util')
|
|
4
|
-
let validator = require('validator')
|
|
5
4
|
|
|
6
5
|
module.exports = {
|
|
7
6
|
|
|
@@ -175,31 +174,31 @@ module.exports = {
|
|
|
175
174
|
},
|
|
176
175
|
isAfter: {
|
|
177
176
|
message: (x, arg) => 'Value was before the configured time (' + arg + ')',
|
|
178
|
-
fn: function(x, arg) { return validator.isAfter(x, arg) }
|
|
177
|
+
fn: function(x, arg) { return require('validator').isAfter(x, arg) }
|
|
179
178
|
},
|
|
180
179
|
isBefore: {
|
|
181
180
|
message: (x, arg) => 'Value was after the configured time (' + arg + ')',
|
|
182
|
-
fn: function(x, arg) { return validator.isBefore(x, arg) }
|
|
181
|
+
fn: function(x, arg) { return require('validator').isBefore(x, arg) }
|
|
183
182
|
},
|
|
184
183
|
isCreditCard: {
|
|
185
184
|
message: 'Value was not a valid credit card.',
|
|
186
|
-
fn: function(x, arg) { return validator.isCreditCard(x, arg) }
|
|
185
|
+
fn: function(x, arg) { return require('validator').isCreditCard(x, arg) }
|
|
187
186
|
},
|
|
188
187
|
isEmail: {
|
|
189
188
|
message: 'Please enter a valid email address.',
|
|
190
|
-
fn: function(x, arg) { return validator.isEmail(x, arg) }
|
|
189
|
+
fn: function(x, arg) { return require('validator').isEmail(x, arg) }
|
|
191
190
|
},
|
|
192
191
|
isHexColor: {
|
|
193
192
|
message: 'Value was not a valid hex color.',
|
|
194
|
-
fn: function(x, arg) { return validator.isHexColor(x, arg) }
|
|
193
|
+
fn: function(x, arg) { return require('validator').isHexColor(x, arg) }
|
|
195
194
|
},
|
|
196
195
|
isIn: {
|
|
197
196
|
message: (x, arg) => 'Value was not in the configured whitelist (' + arg.join(', ') + ')',
|
|
198
|
-
fn: function(x, arg) { return validator.isIn(x, arg) }
|
|
197
|
+
fn: function(x, arg) { return require('validator').isIn(x, arg) }
|
|
199
198
|
},
|
|
200
199
|
isIP: {
|
|
201
200
|
message: 'Value was not a valid IP address.',
|
|
202
|
-
fn: function(x, arg) { return validator.isIP(x, arg) }
|
|
201
|
+
fn: function(x, arg) { return require('validator').isIP(x, arg) }
|
|
203
202
|
},
|
|
204
203
|
isNotEmptyString: {
|
|
205
204
|
validateEmptyString: true,
|
|
@@ -210,15 +209,15 @@ module.exports = {
|
|
|
210
209
|
},
|
|
211
210
|
isNotIn: {
|
|
212
211
|
message: (x, arg) => 'Value was in the configured blacklist (' + arg.join(', ') + ')',
|
|
213
|
-
fn: function(x, arg) { return !validator.isIn(x, arg) }
|
|
212
|
+
fn: function(x, arg) { return !require('validator').isIn(x, arg) }
|
|
214
213
|
},
|
|
215
214
|
isURL: {
|
|
216
215
|
message: 'Value was not a valid URL.',
|
|
217
|
-
fn: function(x, arg) { return validator.isURL(x, arg === true? undefined : arg) }
|
|
216
|
+
fn: function(x, arg) { return require('validator').isURL(x, arg === true? undefined : arg) }
|
|
218
217
|
},
|
|
219
218
|
isUUID: {
|
|
220
219
|
message: 'Value was not a valid UUID.',
|
|
221
|
-
fn: function(x, arg) { return validator.isUUID(x) }
|
|
220
|
+
fn: function(x, arg) { return require('validator').isUUID(x) }
|
|
222
221
|
},
|
|
223
222
|
minLength: {
|
|
224
223
|
message: function(x, arg) {
|
|
@@ -227,7 +226,7 @@ module.exports = {
|
|
|
227
226
|
},
|
|
228
227
|
fn: function(x, arg) {
|
|
229
228
|
if (typeof x !== 'string' && !util.isArray(x)) throw new Error ('Value was not a string or an array.')
|
|
230
|
-
else if (typeof x === 'string') return validator.isLength(x, arg)
|
|
229
|
+
else if (typeof x === 'string') return require('validator').isLength(x, arg)
|
|
231
230
|
else return x.length >= arg
|
|
232
231
|
}
|
|
233
232
|
},
|
|
@@ -238,14 +237,14 @@ module.exports = {
|
|
|
238
237
|
},
|
|
239
238
|
fn: function(x, arg) {
|
|
240
239
|
if (typeof x !== 'string' && !util.isArray(x)) throw new Error ('Value was not a string or an array.')
|
|
241
|
-
else if (typeof x === 'string') return validator.isLength(x, 0, arg)
|
|
240
|
+
else if (typeof x === 'string') return require('validator').isLength(x, 0, arg)
|
|
242
241
|
else return x.length <= arg
|
|
243
242
|
}
|
|
244
243
|
},
|
|
245
244
|
regex: {
|
|
246
245
|
message: (x, arg) => 'Value did not match the configured regular expression (' + arg + ')',
|
|
247
246
|
fn: function(x, arg) {
|
|
248
|
-
if (util.isRegex(arg)) return validator.matches(x, arg)
|
|
247
|
+
if (util.isRegex(arg)) return require('validator').matches(x, arg)
|
|
249
248
|
throw new Error('This rule expects a regular expression to be configured, but instead got the '
|
|
250
249
|
+ typeof arg + ' `' + arg + '`.')
|
|
251
250
|
}
|
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.38.2",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": "github:boycce/monastery",
|
|
8
8
|
"homepage": "https://boycce.github.io/monastery/",
|
package/plugins/images/index.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
let nanoid = require('nanoid')
|
|
3
|
-
let S3 = require('aws-sdk/clients/s3')
|
|
1
|
+
// requiring: nanoid, file-type, aws-sdk/clients/s3
|
|
4
2
|
let util = require('../../lib/util')
|
|
5
3
|
|
|
6
4
|
let plugin = module.exports = {
|
|
@@ -9,7 +7,6 @@ let plugin = module.exports = {
|
|
|
9
7
|
/**
|
|
10
8
|
* Monastery plugin that allows models to automatically process and store uploaded images
|
|
11
9
|
* e.g. fields.avatar: { image: true }
|
|
12
|
-
* e.g. fields.photos: [{ image: true, //sizes: { large: [800, 600], .. } (not implemented) }]
|
|
13
10
|
*
|
|
14
11
|
* Note we cannot accurately test for non binary file-types, e.g. 'txt', 'csv'
|
|
15
12
|
*
|
|
@@ -25,7 +22,7 @@ let plugin = module.exports = {
|
|
|
25
22
|
}
|
|
26
23
|
|
|
27
24
|
// Settings
|
|
28
|
-
this.awsAcl = options.awsAcl || '
|
|
25
|
+
this.awsAcl = options.awsAcl || 'public-read' // default
|
|
29
26
|
this.awsBucket = options.awsBucket
|
|
30
27
|
this.awsAccessKeyId = options.awsAccessKeyId
|
|
31
28
|
this.awsSecretAccessKey = options.awsSecretAccessKey
|
|
@@ -34,6 +31,7 @@ let plugin = module.exports = {
|
|
|
34
31
|
this.formats = options.formats || ['bmp', 'gif', 'jpg', 'jpeg', 'png', 'tiff']
|
|
35
32
|
this.getSignedUrl = options.getSignedUrl
|
|
36
33
|
this.manager = manager
|
|
34
|
+
this.metadata = options.metadata ? util.deepCopy(options.metadata) : undefined,
|
|
37
35
|
this.params = options.params ? util.deepCopy(options.params) : {},
|
|
38
36
|
this.path = options.path || function (uid, basename, ext, file) { return `full/${uid}.${ext}` }
|
|
39
37
|
|
|
@@ -43,15 +41,17 @@ let plugin = module.exports = {
|
|
|
43
41
|
return
|
|
44
42
|
}
|
|
45
43
|
|
|
46
|
-
// Create s3 'service' instance
|
|
44
|
+
// Create s3 'service' instance (defer require since it takes 120ms to load)
|
|
47
45
|
// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property
|
|
48
46
|
manager._getSignedUrl = this._getSignedUrl
|
|
49
|
-
this.s3 =
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
this.s3 = () => {
|
|
48
|
+
return this._s3 || (this._s3 = new (require('aws-sdk/clients/s3'))({
|
|
49
|
+
credentials: {
|
|
50
|
+
accessKeyId: this.awsAccessKeyId,
|
|
51
|
+
secretAccessKey: this.awsSecretAccessKey
|
|
52
|
+
}
|
|
53
|
+
}))
|
|
54
|
+
}
|
|
55
55
|
|
|
56
56
|
// Add before model hook
|
|
57
57
|
manager.beforeModel.push(this.setupModel.bind(this))
|
|
@@ -140,15 +140,15 @@ let plugin = module.exports = {
|
|
|
140
140
|
return Promise.all(files.map(filesArr => {
|
|
141
141
|
return Promise.all(filesArr.map(file => {
|
|
142
142
|
return new Promise((resolve, reject) => {
|
|
143
|
-
let uid = nanoid.nanoid()
|
|
143
|
+
let uid = require('nanoid').nanoid()
|
|
144
144
|
let path = filesArr.imageField.path || plugin.path
|
|
145
145
|
let image = {
|
|
146
146
|
bucket: filesArr.imageField.awsBucket || plugin.awsBucket,
|
|
147
147
|
date: plugin.manager.useMilliseconds? Date.now() : Math.floor(Date.now() / 1000),
|
|
148
148
|
filename: file.name,
|
|
149
149
|
filesize: file.size,
|
|
150
|
+
metadata: filesArr.imageField.metadata || plugin.metadata,
|
|
150
151
|
path: path(uid, file.name, file.ext, file),
|
|
151
|
-
// sizes: ['large', 'medium', 'small'],
|
|
152
152
|
uid: uid,
|
|
153
153
|
}
|
|
154
154
|
let s3Options = {
|
|
@@ -158,6 +158,7 @@ let plugin = module.exports = {
|
|
|
158
158
|
Body: file.data,
|
|
159
159
|
Bucket: image.bucket,
|
|
160
160
|
Key: image.path,
|
|
161
|
+
Metadata: image.metadata,
|
|
161
162
|
...(filesArr.imageField.params || plugin.params),
|
|
162
163
|
}
|
|
163
164
|
plugin.manager.info(
|
|
@@ -167,7 +168,7 @@ let plugin = module.exports = {
|
|
|
167
168
|
plugin._addImageObjectsToData(filesArr.inputPath, data, image)
|
|
168
169
|
resolve(s3Options)
|
|
169
170
|
} else {
|
|
170
|
-
plugin.s3.upload(s3Options, (err, response) => {
|
|
171
|
+
plugin.s3().upload(s3Options, (err, response) => {
|
|
171
172
|
if (err) return reject(err)
|
|
172
173
|
plugin._addImageObjectsToData(filesArr.inputPath, data, image)
|
|
173
174
|
resolve(s3Options)
|
|
@@ -347,11 +348,12 @@ let plugin = module.exports = {
|
|
|
347
348
|
if (useCount[key] > 0) continue
|
|
348
349
|
let pre = preExistingImages.find(o => o.image.uid == key)
|
|
349
350
|
unused.push(
|
|
350
|
-
// original key can have a different extension
|
|
351
|
+
// original key can have a different extension, but always expect generated assets
|
|
352
|
+
// to be in jpg
|
|
351
353
|
{ Key: pre.image.path },
|
|
352
354
|
{ Key: `small/${key}.jpg` },
|
|
353
355
|
{ Key: `medium/${key}.jpg` },
|
|
354
|
-
{ Key: `large/${key}.jpg` }
|
|
356
|
+
{ Key: `large/${key}.jpg` },
|
|
355
357
|
)
|
|
356
358
|
plugin.manager.info(
|
|
357
359
|
`Removing '${pre.image.filename}' from '${pre.image.bucket}/${pre.image.path}'`
|
|
@@ -362,7 +364,7 @@ let plugin = module.exports = {
|
|
|
362
364
|
// the file doesnt get deleted, we only delete from plugin.awsBucket.
|
|
363
365
|
if (!unused.length) return
|
|
364
366
|
await new Promise((resolve, reject) => {
|
|
365
|
-
plugin.s3.deleteObjects({
|
|
367
|
+
plugin.s3().deleteObjects({
|
|
366
368
|
Bucket: plugin.awsBucket,
|
|
367
369
|
Delete: { Objects: unused }
|
|
368
370
|
}, (err, data) => {
|
|
@@ -428,7 +430,7 @@ let plugin = module.exports = {
|
|
|
428
430
|
return Promise.all(validFiles.map(filesArr => {
|
|
429
431
|
return Promise.all(filesArr.map((file, i) => {
|
|
430
432
|
return new Promise((resolve, reject) => {
|
|
431
|
-
|
|
433
|
+
require('file-type').fromBuffer(file.data).then(res => {
|
|
432
434
|
let filesize = filesArr.imageField.filesize || plugin.filesize
|
|
433
435
|
let formats = filesArr.imageField.formats || plugin.formats
|
|
434
436
|
let allowAny = util.inArray(formats, 'any')
|
|
@@ -504,6 +506,7 @@ let plugin = module.exports = {
|
|
|
504
506
|
fullPath: path2,
|
|
505
507
|
fullPathRegex: new RegExp('^' + path2.replace(/\.[0-9]+/g, '.[0-9]+').replace(/\./g, '\\.') + '$'),
|
|
506
508
|
getSignedUrl: field.getSignedUrl,
|
|
509
|
+
metadata: field.metadata ? util.deepCopy(field.metadata) : undefined,
|
|
507
510
|
path: field.path,
|
|
508
511
|
params: field.params ? util.deepCopy(field.params) : undefined,
|
|
509
512
|
})
|
|
@@ -513,6 +516,7 @@ let plugin = module.exports = {
|
|
|
513
516
|
date: { type: 'number' },
|
|
514
517
|
filename: { type: 'string' },
|
|
515
518
|
filesize: { type: 'number' },
|
|
519
|
+
metadata: { type: 'any' },
|
|
516
520
|
path: { type: 'string' },
|
|
517
521
|
schema: { image: true, nullObject: true, isImageObject: true },
|
|
518
522
|
uid: { type: 'string' },
|
|
@@ -573,7 +577,7 @@ let plugin = module.exports = {
|
|
|
573
577
|
* @param {number} <bucket>
|
|
574
578
|
* @see https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property
|
|
575
579
|
*/
|
|
576
|
-
let signedUrl = plugin.s3.getSignedUrl('getObject', {
|
|
580
|
+
let signedUrl = plugin.s3().getSignedUrl('getObject', {
|
|
577
581
|
Bucket: bucket || plugin.awsBucket,
|
|
578
582
|
Expires: expires,
|
|
579
583
|
Key: path,
|
package/test/crud.js
CHANGED
|
@@ -213,6 +213,45 @@ module.exports = function(monastery, opendb) {
|
|
|
213
213
|
db.close()
|
|
214
214
|
})
|
|
215
215
|
|
|
216
|
+
test('update general max', async () => {
|
|
217
|
+
let db = (await opendb(null)).db
|
|
218
|
+
let user = db.model('user', {
|
|
219
|
+
fields: {
|
|
220
|
+
name: { type: 'string' },
|
|
221
|
+
active: { type: 'boolean' },
|
|
222
|
+
},
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
// Insert
|
|
226
|
+
let inserted = await user.insert({ data: { name: 'Martin Luther' }})
|
|
227
|
+
|
|
228
|
+
expect(inserted).toEqual({
|
|
229
|
+
_id: expect.any(Object),
|
|
230
|
+
name: 'Martin Luther',
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
let updatedUser1 = await user.update({
|
|
234
|
+
query: { _id: inserted._id },
|
|
235
|
+
data: { name: 'Martin' },
|
|
236
|
+
blacklist: ['active'],
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
expect(updatedUser1).toEqual({ name: 'Martin' })
|
|
240
|
+
|
|
241
|
+
let updatedUser2 = await user._update(
|
|
242
|
+
{ _id: db.id(inserted._id) },
|
|
243
|
+
{ $set: { name: 'Martin2' }},
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
expect(updatedUser2).toEqual({ n: 1, nModified: 1, ok: 1 })
|
|
248
|
+
|
|
249
|
+
// Mongo connected?
|
|
250
|
+
// Try native updates
|
|
251
|
+
|
|
252
|
+
db.close()
|
|
253
|
+
})
|
|
254
|
+
|
|
216
255
|
test('update defaults', async () => {
|
|
217
256
|
let db = (await opendb(null, { useMilliseconds: true, serverSelectionTimeoutMS: 2000 })).db
|
|
218
257
|
let user = db.model('user', {
|
package/test/plugin-images.js
CHANGED
|
@@ -75,6 +75,7 @@ module.exports = function(monastery, opendb) {
|
|
|
75
75
|
date: { type: 'number', isNumber: true },
|
|
76
76
|
filename: { type: 'string', isString: true },
|
|
77
77
|
filesize: { type: 'number', isNumber: true },
|
|
78
|
+
metadata: { type: 'any', isAny: true },
|
|
78
79
|
path: { type: 'string', isString: true },
|
|
79
80
|
schema: {
|
|
80
81
|
type: 'object', isObject: true, image: true, nullObject: true, default: undefined,
|
|
@@ -641,10 +642,11 @@ module.exports = function(monastery, opendb) {
|
|
|
641
642
|
app.use(upload({ limits: { fileSize: 1000 * 480, files: 10 }}))
|
|
642
643
|
|
|
643
644
|
// Basic tests
|
|
644
|
-
expect(plugin.awsAcl).toEqual('
|
|
645
|
+
expect(plugin.awsAcl).toEqual('public-read')
|
|
645
646
|
expect(plugin.filesize).toEqual(undefined)
|
|
646
647
|
expect(plugin.formats).toEqual(['bmp', 'gif', 'jpg', 'jpeg', 'png', 'tiff'])
|
|
647
648
|
expect(plugin.getSignedUrl).toEqual(undefined)
|
|
649
|
+
expect(plugin.metadata).toEqual(undefined)
|
|
648
650
|
expect(plugin.path).toEqual(expect.any(Function))
|
|
649
651
|
expect(plugin.params).toEqual({})
|
|
650
652
|
|
|
@@ -688,7 +690,7 @@ module.exports = function(monastery, opendb) {
|
|
|
688
690
|
// S3 options
|
|
689
691
|
expect(response[1]).toEqual([
|
|
690
692
|
[{
|
|
691
|
-
ACL: '
|
|
693
|
+
ACL: 'public-read',
|
|
692
694
|
Body: expect.any(Object),
|
|
693
695
|
Bucket: 'fake',
|
|
694
696
|
Key: expect.stringMatching(/^full\/.*png$/),
|
|
@@ -853,7 +855,7 @@ module.exports = function(monastery, opendb) {
|
|
|
853
855
|
db.close()
|
|
854
856
|
})
|
|
855
857
|
|
|
856
|
-
test('images options awsAcl, awsBucket, params, path', async () => {
|
|
858
|
+
test('images options awsAcl, awsBucket, metadata, params, path', async () => {
|
|
857
859
|
let db = (await opendb(null, {
|
|
858
860
|
timestamps: false,
|
|
859
861
|
serverSelectionTimeoutMS: 2000,
|
|
@@ -862,6 +864,7 @@ module.exports = function(monastery, opendb) {
|
|
|
862
864
|
awsBucket: 'fake',
|
|
863
865
|
awsAccessKeyId: 'fake',
|
|
864
866
|
awsSecretAccessKey: 'fake',
|
|
867
|
+
metadata: { small: '*x300' , medium: '*x800', large: '*x1200' },
|
|
865
868
|
params: { ContentLanguage: 'DE'},
|
|
866
869
|
path: (uid, basename, ext, file) => `images/${basename}`,
|
|
867
870
|
}
|
|
@@ -874,6 +877,7 @@ module.exports = function(monastery, opendb) {
|
|
|
874
877
|
type: 'image',
|
|
875
878
|
awsAcl: 'public-read-write',
|
|
876
879
|
awsBucket: 'fake2',
|
|
880
|
+
metadata: { small: '*x100' , medium: '*x400', large: '*x800' },
|
|
877
881
|
params: { ContentLanguage: 'NZ'},
|
|
878
882
|
path: (uid, basename, ext, file) => `images2/${basename}`,
|
|
879
883
|
},
|
|
@@ -904,6 +908,7 @@ module.exports = function(monastery, opendb) {
|
|
|
904
908
|
date: expect.any(Number),
|
|
905
909
|
filename: 'logo.png',
|
|
906
910
|
filesize: expect.any(Number),
|
|
911
|
+
metadata: { small: '*x300' , medium: '*x800', large: '*x1200' },
|
|
907
912
|
path: 'images/logo.png',
|
|
908
913
|
uid: expect.any(String),
|
|
909
914
|
},
|
|
@@ -912,6 +917,7 @@ module.exports = function(monastery, opendb) {
|
|
|
912
917
|
date: expect.any(Number),
|
|
913
918
|
filename: 'logo2.png',
|
|
914
919
|
filesize: expect.any(Number),
|
|
920
|
+
metadata: { small: '*x100' , medium: '*x400', large: '*x800' },
|
|
915
921
|
path: 'images2/logo2.png',
|
|
916
922
|
uid: expect.any(String),
|
|
917
923
|
},
|
|
@@ -924,6 +930,7 @@ module.exports = function(monastery, opendb) {
|
|
|
924
930
|
Bucket: 'fake',
|
|
925
931
|
ContentLanguage: 'DE',
|
|
926
932
|
Key: 'images/logo.png',
|
|
933
|
+
Metadata: { small: '*x300' , medium: '*x800', large: '*x1200' },
|
|
927
934
|
}],
|
|
928
935
|
[{
|
|
929
936
|
ACL: 'public-read-write',
|
|
@@ -931,6 +938,7 @@ module.exports = function(monastery, opendb) {
|
|
|
931
938
|
Bucket: 'fake2',
|
|
932
939
|
ContentLanguage: 'NZ',
|
|
933
940
|
Key: 'images2/logo2.png',
|
|
941
|
+
Metadata: { small: '*x100' , medium: '*x400', large: '*x800' },
|
|
934
942
|
}],
|
|
935
943
|
])
|
|
936
944
|
res.send()
|
package/test/validate.js
CHANGED
|
@@ -816,12 +816,14 @@ module.exports = function(monastery, opendb) {
|
|
|
816
816
|
let user = db.model('user', { fields: {
|
|
817
817
|
name: { type: 'string', minLength: 7 },
|
|
818
818
|
email: { type: 'string', isEmail: true },
|
|
819
|
-
names: { type: 'string', enum: ['Martin', 'Luther'] },
|
|
820
819
|
amount: { type: 'number' },
|
|
821
820
|
}})
|
|
822
821
|
let user2 = db.model('user', { fields: {
|
|
823
822
|
amount: { type: 'number', required: true },
|
|
824
823
|
}})
|
|
824
|
+
let user3 = db.model('user', { fields: {
|
|
825
|
+
names: { type: 'string', enum: ['Martin', 'Luther'], default: 'Martin' },
|
|
826
|
+
}})
|
|
825
827
|
|
|
826
828
|
// MinLength
|
|
827
829
|
await expect(user.validate({ name: 'Martin Luther' })).resolves.toEqual({name: 'Martin Luther'})
|
|
@@ -850,8 +852,9 @@ module.exports = function(monastery, opendb) {
|
|
|
850
852
|
})
|
|
851
853
|
|
|
852
854
|
// Enum
|
|
853
|
-
await expect(
|
|
854
|
-
await expect(
|
|
855
|
+
await expect(user3.validate({})).resolves.toEqual({ names: 'Martin' })
|
|
856
|
+
await expect(user3.validate({ names: 'Luther' })).resolves.toEqual({ names: 'Luther' })
|
|
857
|
+
await expect(user3.validate({ names: 'bad name' })).rejects.toContainEqual({
|
|
855
858
|
detail: 'Invalid enum value',
|
|
856
859
|
status: '400',
|
|
857
860
|
title: 'names',
|