@janiscommerce/sls-api-upload

6.0.0 • Public • Published

sls-api-upload

Build Status Coverage Status npm version

This package contains several modules to handle upload files, list it, or delete it for Janis APIs.

Installation

npm install @janiscommerce/sls-api-upload

🔧 Configuration

ENV variables

JANIS_SERVICE_NAME (required): The name of the service that will be use to create the path when saving the file into the S3 through the Storage Microservice.

Content

In this package, you can found several modules to create APIs to manage files, uploads, delete or get them.

Every Module can be customize.

Common Validation

Some APIs Modules offers some custom validation for specfics features such as file size, or file type, but everyone has a common validation hook.

postValidateHook()

In order to add some custom validations you can use re-write this method, can be async, if fails the status-code is setted to 400 by default. If it exist, executes after validate() and before process().

class MyApiUpload extends SlsApiUpload {

	// ... other code
	postValidateHook() {

		if(!Controller.isValidData(this.data))
			throw new Error('Invalid Data');
	}
};

BaseFileModel

This Module allows you to create a Model for file-data document.

This Class extends from @janiscommerce/model

Model Example

'use strict';

const { BaseFileModel } = require('@janiscommerce/sls-api-upload');

class FileModel extends BaseFileModel {

	static get table() {
		return 'your_table_files';
	}

	static get fields() {
		return {
			...super.fields,
			productId: true
		};
	}
}

Getters

The following getters can be used to customize and validate your BaseFileModel.

static get table()

Optional

Default: "files"

This is used to indicate the name of the files table/collection

static get table() {
	return 'your_table_files';
}

static get fields()

Optional

Default:

{
	id: true,
	path: true,
	size: true,
	name: true,
	type: true,
	dateCreated: true
}

This is used to indicate the fields of the files table/collection

static get fields() {
	return {
		...super.fields,
		productId: true
	};
}

SlsApiFileGetCredentials

This Module allows you to create an API to get the credentials to upload multiples Document.

This Class extends from @janiscommerce/api

API Example

// in src/api/{entity}/file-get-credentials/list.js
'use strict';

const { SlsApiFileGetCredentials } = require('@janiscommerce/sls-api-upload');

class MyApiRelation extends SlsApiFileGetCredentials {

	get entity() {
		return 'entityName';
	}
}

get entity()

Required

This is used to indicate the entity name, it will be use in the file path when it's saved

get entity() {
	return 'entityName';
}

get fileExpiration()

Optional

Allows you to set a custom expiration for the file. Possible values: oneDay | tendays | month | never

get fileExpiration() {
	return 'oneDay';
}

Request Data

This API has the following required request data:

  • fileName: (string) The file name to upload to S3. It's required if fileNames its not sended.
  • fileNames: (array) List of file names to upload to S3. It's required if fileName its not sended.
  • expiration: (string) The name and extension of the file.

Request filenames data example

{
	"fileNames": ["front-image.png"],
	"expiration": 120
}

Response

This API response with status-code 201 and id if success to Save the file data Document.

// status-code 201
{
	"fileNames": {
		"front-image.png": {
			"url": "https://s3.amazonaws.com/janis-storage-service-prod",
			"fields": {
				"Content-Type": "image/png",
				"key": "cdn/files/defaultClient/9ea2lbLalrQrjkoWqyJ5gOsJGBtzbml1.png",
				"bucket": "janis-storage-service-beta",
				"X-Amz-Algorithm": "AWS4-HMAC-SHA256",
				"X-Amz-Credential": "ASIASJHJMNZZ5MVD5YHU/20230112/us-east-1/s3/aws4_request",
				"X-Amz-Date": "20230112T114452Z",
				"X-Amz-Security-Token": "IQoJb3JpZ2luX2VjEGQaCXVzLWVhc3QtMSJGMEQCIHJFEKy124C1P0svU5z3M/szk8tN92pSnn5uR=",
				"Policy": "eyJleHBpcmF0aW9uIjoiMjAyMy0wMS0xMlQxMTo0NTo1MloiLCJjb25kaXRpb124IjpbWyJjb250ZW50LWxlbmd0aC1y",
				"X-Amz-Signature": "c9b0e78d8b166847c2583383ac5da48e92e95501ed2991058e5a1244c1514aba"
			}
		}
	}
}

Request filename data example

{
	"fileName": "front-image.png",
	"expiration": 120
}

Response

This API response with status-code 201 and id if success to Save the file data Document.

// status-code 201
{
	"url": "https://s3.amazonaws.com/janis-storage-service-prod",
	"fields": {
		"Content-Type": "image/png",
		"key": "cdn/files/defaultClient/9ea2lbLalrQrjkoWqyJ5gOsJGBtzbml1.png",
		"bucket": "janis-storage-service-beta",
		"X-Amz-Algorithm": "AWS4-HMAC-SHA256",
		"X-Amz-Credential": "ASIASJHJMNZZ5MVD5YHU/20230112/us-east-1/s3/aws4_request",
		"X-Amz-Date": "20230112T114452Z",
		"X-Amz-Security-Token": "IQoJb3JpZ2luX2VjEGQaCXVzLWVhc3QtMSJGMEQCIHJFEKy124C1P0svU5z3M/szk8tN92pSnn5uR=",
		"Policy": "eyJleHBpcmF0aW9uIjoiMjAyMy0wMS0xMlQxMTo0NTo1MloiLCJjb25kaXRpb124IjpbWyJjb250ZW50LWxlbmd0aC1y",
		"X-Amz-Signature": "c9b0e78d8b166847c2583383ac5da48e92e95501ed2991058e5a1244c1514aba"
	}
}

get model()

Optional

This is used to indicate the Model class that should be used to save the file relationship

const FileModel = require('../models/your-file-model');

get model() {
	return FileModel;
}

SlsApiFileRelation

This Module allows you to create an API to create a Document with the file data in the Database Collection.

This Class extends from @janiscommerce/api

API Example

// in src/api/{entity}/file/post.js
'use strict';

const { SlsApiFileRelation } = require('@janiscommerce/sls-api-upload');

class MyApiRelation extends SlsApiFileRelation {

	get entityIdField() {
		return 'productId';
	}
}

Request Data

This API has the following required request data:

  • filename: (string) The name and extension of the file.
  • filesSource: (string) The full key of the file stored in S3.
  • fileExpiration: (string) The expiration of the file stored in S3.

Request data example

{
	"fileName": "front-image.png",
	"fileSource": "files/images/1f368ddd-97b6-4076-ba63-9e0a71273aac.png",
	"fileExpiration": "month"
}

Response

This API response with status-code 201 and id if success to Save the file data Document.

// status-code 201
{
	"id": "5e866d89fc33220011108188"
}

get model()

Optional

This is used to indicate the Model class that should be used to save the file relationship

const FileModel = require('../models/your-file-model');

get model() {
	return FileModel;
}

get entityIdField()

Required

This is used to indicate the field name where the related entity ID should be saved

	...
	get entityIdField() {
		return 'productId';
	}
	...

get customFieldsStruct()

Optional

This is used to indicate more fields to be validated from the request and saved with the relationship.

get customFieldsStruct() {
	return {
		myRelationshipCustomField: 'string',
		myOptionalRelationshipCustomField: 'string?'
	};
}

Request data example;

{
	"fileName": "image.png",
	"fileSource": "files/images/1f368ddd-97b6-4076-ba63-9e0a71273aac.png",
	"myRelationshipCustomField": "theValue"
}

get fileExpiration()

Optional

Allows you to set a custom expiration for the file. Possible values: oneDay | tendays | month | never

get fileExpiration() {
	return 'oneDay';
}

Hooks

This module has 2 Hooks:

postSaveHook(id, dataFormatted)

This hooks is async and execute after save the document. You can used it to emit an Event, invoke a Lambda function, create an extra Log, make a Request or whatever you need to the do after save.

 postSaveHook(id, itemFormatted) {
	return Invoker.call('ItemNotify', { id, ...itemFormatted});
}

Format

The object is created with the following fields:

  • name: the filename, example: front-image.png
  • path: the relative path in S3 Bucket, example files/images/1f368ddd-97b6-4076-ba63-9e0a71273aac.png
  • mimeType: the file full type, example: ìmage/png
  • type: the simplified type, example image
  • size: the file size in Bytes, example: 1000

But if you have more fields, or you can add any others, you can use a custom Format method

format(extraFileData)

It's async and received the extra file data (if you added customFieldsStruct).

format({ myRelationshipCustomField, myOptionalRelationshipCustomField }) {
	return {
		relations: {
			default: myRelationshipCustomField,
			optional: myOptionalRelationshipCustomField
		},
		lucky: Math.random() * 1000
	};
}

And final document saved in database would be:

{
	path: 'files/images/1f368ddd-97b6-4076-ba63-9e0a71273aac.png',
	name: 'front-image.png',
	mimeType: 'image/png',
	type: 'image',
	size: 10000,
	relations: {
		default: 'stuff',
		optional: 'accesory'
	},
	lucky: 667
}

SlsApiFileList

This Module allows you to create an API to List file-data documents.

This API extends from @janiscommerce/api-list

API Example

// in src/api/item/file/list.js
'use strict';

const { SlsApiFileDelete } = require('@janiscommerce/sls-api-upload');

class MyApiList extends SlsApiFileList {}

In this example, the List API only can

  • sort and filter by
    • id : file-data document internal ID
    • name : filename
    • dateCreated : strict mode only search by exact Date

Also, every file-data document will NOT have a URL to use it for show it, download it, etc..

Custom Sorting and Filtering

If you need more fields to sort or filter exist 2 optionals getters.

get customSortableFields()

To add more fields to be sortable. Must return an Array of Strings

get customSortableFields() {
	return ['type', 'order'];
}

get customAvailableFilters()

To add more fields to be sortable. Must return an Array of Strings or Object, see more in @janiscommerce/api-list filters.

get customAvailableFilters() {
	return [
		'type',
		{
			name: 'order',
			valueMapper: Number
		}
	];
}

Format

You can format each file-data document and/or the file's URL.

formatFileData(fileData)

To format the file data except file-path

formatFileData({ order, ...fileData }) {
	return {
		...fileData,
		order: `#${order}`
	};
}

Hooks

This module has only one Hook:

SlsApiFileGet

This Module allows you to create an API to get a single file-data document.

This API extends from @janiscommerce/api-get

API Example

// in src/api/item/file/get.js
'use strict';

const { SlsApiFileGet } = require('@janiscommerce/sls-api-upload');

class MyApiGet extends SlsApiFileGet {

}

URL field

This API module always return the file-data document with the url field.

Format

The File-Document can be formatted in the same way as in the SLS-API-List using

Hooks

This module has only one Hook:

SlsApiFileDelete

This Module allows you to create an API to delete a file from S3 Bucket and Database Collection.

This Class extends from @janiscommerce/api

API Example

// in src/api/item/file/delete.js
'use strict';

const { SlsApiFileDelete } = require('@janiscommerce/sls-api-upload');

class MyApiDelete extends SlsApiFileDelete {

	get entityIdField() {
		return 'productId';
	}
}

Getters

The following getters can be used to customize and validate your SlsApiFileDelete.

get model()

Optional

This is used to indicate the Model class that should be used to remove the file relationship

const FileModel = require('../models/your-file-model');

get model() {
	return FileModel;
}

get entityIdField()

Required

This is used to indicate the field name where the related entity ID was saved

get entityIdField() {
	return 'productId';
}

Hooks

This module has two Hooks:

postDeleteHook(itemDeleted)

This hooks is async and execute after delete the document from S3 Bucket. You can used it to emit an Event, invoke a Lambda function, create an extra Log, make a Request or whatever you need to the do after delete it.

 postDeleteHook(itemDeleted) {
	return EventEmitter.emit({
		entity: 'item',
		event: 'deleted',
		client: this.session.clientCode,
		id: itemDeleted.id
	});
}

Serverless Example

This is an example to implement in the serverless configuration.

This Configuration file use this packages @sls-helper and @sls-helper-plugin-janis

[
	[
		"janis.api",
		{
			"path": "/{entityName}/{id}/file",
			"method": "get",
			"methodName": "list",
			"authorizer": "FullAuthorizer",
			"cors": true
		}
	],
	[
		"janis.api",
		{
			"path": "/{entityName}/{id}/file/{fileId}",
			"method": "get",
			"authorizer": "FullAuthorizer",
			"cors": true
		}
	],
	[
		"janis.api",
		{
			"path": "/{entityName}/{id}/file/{fileId}",
			"method": "delete",
			"authorizer": "FullAuthorizer",
			"cors": true
		}
	],
	[
		"janis.api",
		{
			"path": "/{entityName}/{id}/file",
			"method": "post",
			"authorizer": "FullAuthorizer",
			"cors": true,
			"package": {
                "include": ["src/models/file.js", "src/api/{entityName}/file-related/post.js"]
            }
		}
	],
	[
		"janis.api",
		{
			"path": "/{entityName}/{id}/file-get-credentials",
			"method": "get",
			"methodName": "list",
			"authorizer": "FullAuthorizer",
			"cors": true,
			"package": {
                "include": ["src/models/file.js", "src/api/{entityName}/file-related/post.js"]
            }
		}
	]
]

Readme

Keywords

none

Package Sidebar

Install

npm i @janiscommerce/sls-api-upload

Weekly Downloads

105

Version

6.0.0

License

ISC

Unpacked Size

36.4 kB

Total Files

16

Last publish

Collaborators

  • janiscommerce