Image Plugin

To use the default image plugin shipped with monastery, you need to use the options below when initialising a manager

  let db = monastery('localhost/mydb', {
    imagePlugin: {
      awsAcl: 'public-read', // default
      awsBucket: 'your-bucket-name',
      awsRegion: undefined, // e.g. 'ap-southeast-2'
      awsAccessKeyId: 'your-key-here',
      awsSecretAccessKey: 'your-key-here',
      filesize: undefined, // default (max filesize in bytes)
      formats: ['bmp', 'gif', 'jpg', 'jpeg', 'png', 'tiff'], // default (use 'any' to allow all extensions)
      getSignedUrl: false, // default (get a S3 signed url after `model.find()`, can be defined per request)
      path: (uid, basename, ext, file) => `/full/${uid}.${ext}`, // default
      metadata: {},
      // Any s3 upload param, which takes precedence over the params above
      // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property)
      params: {},
      // Called after each file is uploaded to S3, before DB update, see "afterUploadBeforeUpdate" below
      afterUploadBeforeUpdate: [ async (ctx) => {} ],
      // Called after each file is uploaded to S3, after DB update, see "afterUploadAfterUpdate" below
      afterUploadAfterUpdate: [ async (ctx) => {} ],
    }
  })

Then in your model definition, e.g.

let user = db.model('user', {
  fields: {
    logo:  {
      type: 'image',
      // ...any imagePlugin option, excluding awsAccessKeyId and awsSecretAccessKey
    },
    logos: [{
      type: 'image',
      // ...any imagePlugin option, excluding awsAccessKeyId and awsSecretAccessKey
    }],
  }
})

Then when inserting or updating a document you need to set options.files to an object containing your parsed files, express-fileupload works great with an express setup, e.g.

user.update({
  query: id,
  data: req.body,
  files: req.files || {}
})

Updating documents

When updating a document with options.files, you need to make sure to always include previously uploaded file objects in options.data otherwise these will be removed automatically from your S3 bucket (via a comparsion check against your previous document).

You can reuse the image objects (e.g. { bucket, data, uid, ... }) for other file field values on the same document. You can’t however copy image objects across documents and collections.

You can skip all file processing by not defining options.files. A nice way to sepearte file and non-file updates is by appending ?files=true to your API route calls, e.g.

user.update({
  query: id,
  data: req.body,
  files: req.query.files? req.files : undefined
})

File types

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

…to be continued

Image sizes

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. https://github.com/boycce/s3-lambda-thumbnail-generator

You can override the function’s default image sizes via the metadata option globally in the manager options, or per file:

// Per file
let user = db.model('user', {
  fields: {
    logo:  {
      type: 'image',
      metadata: { small: '*x300', medium: '*x800', large: '*x1200' },
    },
  }
}

afterUploadBeforeUpdate

Same pattern as Operation hooks (e.g. afterUpdate): an array of functions defined on imagePlugin.afterUploadBeforeUpdate = [ ... ], run in order. Each runs once per successfuly uploaded S3 file, after the image object is set on data, but before the document is updated. Rejecting prevents the document update.

One argument ctx:

  • model: model instance
  • data: the same document payload passed through insert/update validation (already contains the new image at inputPath)
  • image: stored descriptor (bucket, path, uid, filename, filesize, date, …)
  • file: parsed upload (name, size, data, ext, …)
  • imageField: resolved field settings for this path (formats, overrides, fullPath, …)
  • inputPath: dot path for this upload, e.g. logo, photos.0
  • query: operation query
  • create: true when the flow is tied to an insert
  • multi: multi flag from the operation
  • test: second argument passed to addImages (true when using test/dry behaviour)
  • s3Result: AWS upload.done() result when not in test mode; otherwise undefined

afterUploadAfterUpdate

Same as afterUploadBeforeUpdate, but runs after the document has been updated in the DB. Does not fire in test mode.

ctx is identical to afterUploadBeforeUpdate, minus test, plus:

  • updateResult: return value from model._update() after saving image data to the document