monastery 2.0.0 → 2.1.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 CHANGED
@@ -2,6 +2,8 @@
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
+ ## [2.1.0](https://github.com/boycce/monastery/compare/1.42.2...2.1.0) (2024-04-05)
6
+
5
7
  ## [2.0.0](https://github.com/boycce/monastery/compare/1.42.2...2.0.0) (2023-12-06)
6
8
 
7
9
  ### [1.42.2](https://github.com/boycce/monastery/compare/1.42.1...1.42.2) (2023-10-31)
@@ -283,12 +283,12 @@ You are able to define custom error messages for each field rule.
283
283
  }
284
284
  },
285
285
  // Assign custom error messages for arrays
286
+ // e.g. pets = [{ name: { type: 'string' }}]
286
287
  'pets': {
287
288
  minLength: `Please add at least one pet pet group.`
288
289
  },
289
290
  // You can assign custom error messages for all fields on embedded documents in an array
290
- // e.g. pets = [{ name: { type: 'string' }}]
291
- 'pets.name': {
291
+ 'pets.$.name': {
292
292
  required: `Your pet's name needs to be a string.`
293
293
  },
294
294
  // To target a specific array item
@@ -12,6 +12,7 @@ To use the default image plugin shipped with monastery, you need to use the opti
12
12
  imagePlugin: {
13
13
  awsAcl: 'public-read', // default
14
14
  awsBucket: 'your-bucket-name',
15
+ awsRegion: undefined, // required when using getSignedUrl (e.g. 's3-ap-southeast-2')
15
16
  awsAccessKeyId: 'your-key-here',
16
17
  awsSecretAccessKey: 'your-key-here',
17
18
  filesize: undefined, // default (max filesize in bytes)
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": "2.0.0",
5
+ "version": "2.1.0",
6
6
  "license": "MIT",
7
7
  "repository": "github:boycce/monastery",
8
8
  "homepage": "https://boycce.github.io/monastery/",
@@ -26,26 +26,31 @@
26
26
  "patch": "standard-version --release-as patch && npm publish",
27
27
  "release": "standard-version && npm publish && git push --tags",
28
28
  "test": "npm run lint && jest",
29
- "test-one-example": "jest -t images"
29
+ "test-one-example": "jest -t \"images addImages\" --watchAll"
30
30
  },
31
31
  "dependencies": {
32
- "aws-sdk": "2.1062.0",
33
- "debug": "4.1.1",
34
- "file-type": "15.0.0",
32
+ "@aws-sdk/client-s3": "^3.549.0",
33
+ "@aws-sdk/s3-request-presigner": "^3.549.0",
34
+ "debug": "^4.3.4",
35
+ "file-type": "^16.5.4",
35
36
  "monk": "7.3.4",
36
37
  "nanoid": "3.2.0",
37
38
  "validator": "13.7.0"
38
39
  },
39
40
  "devDependencies": {
40
- "body-parser": "1.19.0",
41
+ "body-parser": "^1.20.2",
41
42
  "eslint": "8.7.0",
42
- "express": "4.17.1",
43
- "express-fileupload": "1.2.0",
43
+ "express": "^4.19.2",
44
+ "express-fileupload": "^1.5.0",
44
45
  "jest": "27.4.7",
45
- "nodemon": "2.0.15",
46
+ "nodemon": "^3.1.0",
46
47
  "standard-version": "9.3.2",
47
48
  "supertest": "4.0.2"
48
49
  },
50
+ "engines": {
51
+ "node": ">=14",
52
+ "npm": ">=6"
53
+ },
49
54
  "standard-version": {
50
55
  "infile": "changelog.md",
51
56
  "releaseCommitMessageFormat": "{{currentTag}}",
@@ -1,5 +1,6 @@
1
1
  // requiring: nanoid, file-type, aws-sdk/clients/s3
2
- let util = require('../../lib/util')
2
+ const { getSignedUrl } = require('@aws-sdk/s3-request-presigner')
3
+ const util = require('../../lib/util')
3
4
 
4
5
  let plugin = module.exports = {
5
6
 
@@ -26,6 +27,7 @@ let plugin = module.exports = {
26
27
  this.awsBucket = options.awsBucket
27
28
  this.awsAccessKeyId = options.awsAccessKeyId
28
29
  this.awsSecretAccessKey = options.awsSecretAccessKey
30
+ this.awsRegion = options.awsRegion
29
31
  this.bucketDir = options.bucketDir || 'full' // depreciated > 1.36.2
30
32
  this.filesize = options.filesize
31
33
  this.formats = options.formats || ['bmp', 'gif', 'jpg', 'jpeg', 'png', 'tiff']
@@ -42,10 +44,14 @@ let plugin = module.exports = {
42
44
  }
43
45
 
44
46
  // Create s3 'service' instance (defer require since it takes 120ms to load)
45
- // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property
47
+ // v2: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property
48
+ // v3: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/
49
+ // v3 examples: https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/javascript_s3_code_examples.html
46
50
  manager._getSignedUrl = this._getSignedUrl
47
- this.s3 = () => {
48
- return this._s3 || (this._s3 = new (require('aws-sdk/clients/s3'))({
51
+ this.getS3Client = () => {
52
+ const { S3 } = require('@aws-sdk/client-s3')
53
+ return this._s3Client || (this._s3Client = new S3({
54
+ region: this.awsRegion,
49
55
  credentials: {
50
56
  accessKeyId: this.awsAccessKeyId,
51
57
  secretAccessKey: this.awsSecretAccessKey
@@ -168,7 +174,7 @@ let plugin = module.exports = {
168
174
  plugin._addImageObjectsToData(filesArr.inputPath, data, image)
169
175
  resolve(s3Options)
170
176
  } else {
171
- plugin.s3().upload(s3Options, (err, response) => {
177
+ plugin.getS3Client().upload(s3Options, (err, response) => {
172
178
  if (err) return reject(err)
173
179
  plugin._addImageObjectsToData(filesArr.inputPath, data, image)
174
180
  resolve(s3Options)
@@ -203,7 +209,7 @@ let plugin = module.exports = {
203
209
  * Get signed urls for all image objects in data
204
210
  * @param {object} options - monastery operation options {model, query, files, ..}
205
211
  * @param {object} data
206
- * @return promise(data)
212
+ * @return promise() - mutates data
207
213
  * @this model
208
214
  */
209
215
  // Not wanting signed urls for this operation?
@@ -215,8 +221,9 @@ let plugin = module.exports = {
215
221
  if (options.getSignedUrls
216
222
  || (util.isDefined(imageField.getSignedUrl) ? imageField.getSignedUrl : plugin.getSignedUrl)) {
217
223
  let images = plugin._findImagesInData(doc, imageField, 0, '').filter(o => o.image)
224
+ // todo: we could do this in parallel
218
225
  for (let image of images) {
219
- image.image.signedUrl = plugin._getSignedUrl(image.image.path, 3600, imageField.awsBucket)
226
+ image.image.signedUrl = await plugin._getSignedUrl(image.image.path, 3600, imageField.awsBucket)
220
227
  }
221
228
  }
222
229
  }
@@ -365,7 +372,7 @@ let plugin = module.exports = {
365
372
  // the file doesnt get deleted, we only delete from plugin.awsBucket.
366
373
  if (!unused.length) return
367
374
  await new Promise((resolve, reject) => {
368
- plugin.s3().deleteObjects({
375
+ plugin.getS3Client().deleteObjects({
369
376
  Bucket: plugin.awsBucket,
370
377
  Delete: { Objects: unused }
371
378
  }, (err, data) => {
@@ -571,18 +578,23 @@ let plugin = module.exports = {
571
578
  return list
572
579
  },
573
580
 
574
- _getSignedUrl: (path, expires=3600, bucket) => {
581
+ _getSignedUrl: async (path, expires=3600, bucket) => {
575
582
  /**
576
583
  * @param {string} path - aws file path
577
584
  * @param {number} <expires> - seconds
578
585
  * @param {number} <bucket>
579
- * @see https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property
586
+ * @return {promise} signedUrl
587
+ * @see v2: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property
588
+ * @see v3: https://github.com/aws/aws-sdk-js-v3/blob/main/UPGRADING.md#s3-presigned-url
580
589
  */
581
- let signedUrl = plugin.s3().getSignedUrl('getObject', {
582
- Bucket: bucket || plugin.awsBucket,
583
- Expires: expires,
584
- Key: path,
585
- })
590
+ if (!plugin.awsRegion) {
591
+ throw 'Monastery requires config.awsRegion to be defined when using getSignedUrl\'s'
592
+ }
593
+ const { GetObjectCommand } = require('@aws-sdk/client-s3')
594
+ const params = { Bucket: bucket || plugin.awsBucket, Key: path }
595
+ const command = new GetObjectCommand(params)
596
+ let signedUrl = await getSignedUrl(plugin.getS3Client(), command, { expiresIn: expires })
597
+ // console.log(signedUrl)
586
598
  return signedUrl
587
599
  },
588
600
 
@@ -803,6 +803,7 @@ module.exports = function(monastery, opendb) {
803
803
  awsBucket: 'fake',
804
804
  awsAccessKeyId: 'fake',
805
805
  awsSecretAccessKey: 'fake',
806
+ awsRegion: 's3-ap-southeast-2',
806
807
  getSignedUrl: true,
807
808
  },
808
809
  })).db