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 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
 
@@ -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. (`this` will refer to the data object passed in)
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
  },
@@ -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
- params: {}, // upload params (https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property)
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
+ ```
@@ -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](#more-control).
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
  ```
@@ -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 this field name(s)
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
 
@@ -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 this field name(s)
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)*
@@ -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 this field name(s)
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
- - ~~Change ACL default 'public read' to 'private'~~
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.37.3",
5
+ "version": "1.38.2",
6
6
  "license": "MIT",
7
7
  "repository": "github:boycce/monastery",
8
8
  "homepage": "https://boycce.github.io/monastery/",
@@ -1,6 +1,4 @@
1
- let fileType = require('file-type')
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 || 'private' // default
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 = new S3({
50
- credentials: {
51
- accessKeyId: this.awsAccessKeyId,
52
- secretAccessKey: this.awsSecretAccessKey
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
- fileType.fromBuffer(file.data).then(res => {
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', {
@@ -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('private')
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: 'private',
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(user.validate({ names: 'Martin' })).resolves.toEqual({ names: 'Martin' })
854
- await expect(user.validate({ names: 'bad name' })).rejects.toContainEqual({
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',