npm package: @grupojaque/gcs-file
Description: Provides functions to manage files licked to models.
Author: JaqueOSS
Latest version: 1.0.1

# GcsFile
  Provides functions to validate and upload files to Cloud, while managing
  the related models and generating paths.

  This service was developed according to the following
  [documentaition](https://github.com/link_to_git).

## Setup
### Requirements

##### Modules

- [Cloud](https://github.com/link_to_git): Recommended option to manage files in Cloud.

- [Sequelize](https://sequelize.readthedocs.io/en/v3/): ORM

### Initialization

Install with:

``$ npm install @grupojaque/gcs-file``

Import in project:

``GCSFile = require('@grupojaque/gcs-file')(configObject);``

``configObject`` Object with configuration. Explained below

``models`` The models created by Sequelize

When required will return the ``GCSFile`` to be used as explained below.

### Configuration

##### Configuration object

An object with the following data must be provided when the module is imported.


| Key  | Description |
| ---- | ----------- |
| modelFiles | Object with the definitions of the models using files. |
| types | Definition of all the possible types used in the modelFiles descriptions. |
| [tasks](#tasks) | The configured tasks to be used before uploading |
| defaultUploadOptions | Object with default options passed to cloud when uploading |
| storageUrl | Base url for the storage service |
| getBucketName | Function to return the bucket name |
| getPath | Function to return the path given the gcsFile as parameter |
| getCloud | Function to return the cloud object with de functions upload and delete to communicate with cloud |

###### modelFiles

Each key of the object must be the name of the model, the value is an object
containing as keys the names of the attributes which store the file info. This
keys do not contain the prefix. Each attribute configuration must have the
following.

| Key  | Description |
| ---- | ----------- |
| type | String that identifies the type configuration of the file.|
| options | Object with the options of the attribute, used for tasks and procedures. |
| beforeUpload | Array of procedures names that must be called before uploading, this will be done after the procedures defined in the type |

###### types

Each type most have the following attributes. To complete this fields you can
use this [types-list](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Complete_list_of_MIME_types).

| Key  | Description |
| ---- | ----------- |
| mimeType | String to indicate the content MIME type of the file|
| ext | String to indicate the file extension, including the `.` |
| beforeUpload | Array of procedures names that must be called before uploading |

###### tasks

Each of the configured tasks will receive the gcsFile as parameter to use as convinent.
This tasks must be synchronous and can throw a `GCSFileError` if required.
The configured tasks can overwrite the [default tasks](#default-tasks).



You can also find a configuration example file [here](gcsFile.example.js)

##### Other configurations

A module to read files from the request might be necesary.
The functions are expecting ``busboy-body-parser`` to manage this in a middleware
and provide the buffer in the upload.

If using Sails Js the `config\http.js` file must be edited to provide this.

## Usage

### Constructor

##### `new GCSFile(modelInstance, fileName, inputFile, options)`

Creates a new GCSFile object.
- **modelInstance**: Model associated to the file. Must have an attribute called
`has_ + fileName`. This attribute must be a boolean or a boolean array in case
of a gallery.
- **fileName**: Name of the file without extension. If the name has `-` it will be
considered with the first part being the attribute name, and the second the
index (starting in 1) to index the attribute gallery.
- **inputFile**: Input file generated with busboy-body-parser. This is required if
calling the `upload` function.
- **options**: Optional object that can be used in configuration functions,
such as `getPath` or any task.

### Instance functions

##### `upload()`

Runs all the tasks indicated in the `beforeUpload` array, if all are successful,
uploads the inputFile in cloud.
After doing so, updates the corresponding attribute in the model instance.

###### Errors

This function can throw all errors defined in the tasks.

##### `remove()`

Deletes the file from Cloud.
After doing so, updates the corresponding attribute in the model instance.

##### `getFullUrl()`

Gets the full url of the file. If no file uploaded, returns an empty string.

`storageUrl` + `bucketName()` + `getPath()`

### Default tasks
The following tasks are given by default, they can be overwritten in the
configuration file.

##### validateHasUploadedData
Validates that there has been data uploaded.
###### Throws

| status                 | message                   | errorDetail           |
| ---------------------- | --------------------------| --------------------- |
| `unsupportedMediaType` | Media type not supported  | [unsupportedMediaType] |

##### validateExtension
Validates that the file MIME type is one of the accepted mimes.
###### Requires
-  `acceptedMimes`: Array in type options indicating the list of accepted MIMES.
###### Throws

| status                 | message                   | errorDetail           |
| ---------------------- | --------------------------| --------------------- |
| `unsupportedMediaType` | Extension not supported   | [unsupportedExtension, fileName, acceptedMimes]  |

##### encode
If the image uploaded has a different extension than expected, encodes
the image to the `encondigFormat` specified.
###### Requires
-  `encodingFormat`: Format for encoding indicated in the type.
-  `encodingCompresionRate`: Number indicating the compression rate indicated in the type.

##### validateExactDimentions
Validates that the image on the image are the same as those in options.
###### Requires
-  `width`: Key in options configuration for the attribute.
-  `height`: Key in options configuration for the attribute.
###### Throws

| status                 | message                   | errorDetail           |
| ---------------------- | --------------------------| --------------------- |
| `unsupportedMediaType` | Dimensions must be exact  | [unsupportedSize, fileName, expectedH, expectedW] |

##### validateNotBiggerSize
Validates that the image was not trucated.
###### Requires
-  `width`: Key in options configuration for the attribute.
-  `height`: Key in options configuration for the attribute.
###### Throws

| status                 | message                   | errorDetail           |
| ---------------------- | --------------------------| --------------------- |
| `unsupportedMediaType` | Size is too big           | [unsupportedSizeBig, fileName]`  |  

##### validateNotSmallerDimentions
Validates that the image has dimensions bigger than expected .
###### Requires
-  `width`: Key in options configuration for the attribute.
-  `height`: Key in options configuration for the attribute.
###### Throws

| status                 | message                   | errorDetail           |
| ---------------------- | --------------------------| --------------------- |
| `unsupportedMediaType` | Dimentions are too small | [unsupportedSizeSmall, fileName, expectedH, expectedW]  |

##### validateSameProportion
Validates that the image has the same proportion.
###### Requires
-  `width`: Key in options configuration for the attribute.
-  `height`: Key in options configuration for the attribute.
###### Throws

| status                 | message                   | errorDetail           |
| ---------------------- | --------------------------| --------------------- |
| `unsupportedMediaType` | Invalid proportion  | [unsupportedProportion, fileName, expectedH, expectedW]  |


### Errors

All errors in this module will be instances of GCSFileError, which extends
the Error class with the following attributes.

 - `name` GCSFileError.
 - `message`: Message for user in english.
 - `status`: The HTTP status for the error.
 - `errorDetail`: Object with metadata specific for the error translation.

 This errors can be manage by the `ErrorHandler` module by adding the following
  constructor in the module configuration.

  ```javascript
  GCSFileError: function(err, req) {
    return new ErrorHandler(err.status, err.message, null, err.errorDetail);
  }
 ```

## Contributors

- Susana Hahn Martin Lunas [github/susuhahnml](https://github.com/susuhahnml)