-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 8b6e376
Showing
18 changed files
with
586 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
name: Release Database Connector Service | ||
on: | ||
push: | ||
tags: | ||
- 'v*' # P | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v1 | ||
- name: Use Node.js | ||
uses: actions/setup-node@v2 | ||
with: | ||
node-version: '16' | ||
- name: Creating 'Release' Directory | ||
run: mkdir -p release/functions | ||
- name: Installing Packages for 'Image Processor' & Creating the Zip | ||
run: cd functions/image_processor/ && npm install --omit=dev && zip -r ../../release/functions/image_processor.zip . | ||
- name: Copying Project Template JSON | ||
run: cp project-template-1.0.0.json release/project-template-1.0.0.json | ||
- name: Creating Zip of Release Folder | ||
run: cd release && zip -r release.zip . | ||
|
||
# - uses: actions/checkout@v2 | ||
- uses: ncipollo/release-action@v1 | ||
with: | ||
artifacts: './release/release.zip' | ||
bodyFile: 'README.md' | ||
token: ${{ secrets.GITHUB_TOKEN }} | ||
tag: ${{ env.RELEASE_VERSION }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
.catalystrc | ||
catalyst.json | ||
**/node_modules | ||
**/package-lock.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
## Image Processor CodeLib Solution | ||
The Image Processor CodeLib solution enables you to resize images to the required dimensions and compress them without distorting the image quality. | ||
|
||
**Note:** You can get more detailed information on the steps to install and configure the Image Processor CodeLib solution from your Catalyst console. You must navigate to the bottom of your Catalyst console where you will find the ***Catalyst CodeLib*** section. You can click on the **Image Processor CodeLib** tile to access the steps. | ||
|
||
|
||
### How does the CodeLib solution work? | ||
|
||
|
||
Upon installing this CodeLib solution, pre-defined Catalyst components specific to the solution will be automatically configured in your project. This includes one [Catalyst Serverless function](https://docs.catalyst.zoho.com/en/serverless/help/functions/introduction/) ([Advanced I/O](https://docs.catalyst.zoho.com/en/serverless/help/functions/advanced-io/)) in **Node.js**. We will also be using the Catalyst SmartBrowz service in this CodeLib solution. | ||
|
||
|
||
|
||
Upon the installation of the CodeLib solution, when you invoke the **/resize** endpoint of the **image_processor([Advanced I/O](https://docs.catalyst.zoho.com/en/serverless/help/functions/advanced-io/))** function as a *cURL* request, the image is resized and rendered as a 2-dimensional object with the height and width provided in the request payload, using the [Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext) and placed in an HTML file. Along with the dimensions, you must also configure the original image path to file in your local system, in the request payload. We will be using the Catalyst SmartBrowz service to connect to a headless Chrome and take a screenshot of the HTML page served in the browser containing the image. We have implemented this using the Puppeteer framework, a popular Node.js library that is used to control the headless browser using the pre-configured commands in Javascript. The screenshot will be provided as the response in the *.png* format. | ||
|
||
You will also need to configure a key named **CODELIB\_SECRET\_KEY** as an [environmental variable ](https://docs.catalyst.zoho.com/en/serverless/help/functions/implementation/#environmental-variables)in the function's code, and pass this in the request header every time you invoke the endpoints of the pre-configured function in the CodeLib solutionThis key allows you to access the Catalyst resources of the CodeLib solution securely. | ||
|
||
Similarly, when you invoke the **/compress** endpoint of the **image_processor([Advanced I/O](https://docs.catalyst.zoho.com/en/serverless/help/functions/advanced-io/))** function as a *cURL* request by configuring the original image file path and level of compression required, the image will be compressed based on the inputs provided in the request payload. | ||
|
||
Similar to the **/resize** endpoint, we have again used the SmartBrowz's [PDF & Screenshot](https://docs.catalyst.zoho.com/en/smartbrowz/help/pdfnscreenshot/introduction/) component to take a screenshot and send its a response in the *.png* format. Also note that, the height and width dimensions of the input image should be 2000\*2000 pixels. If the dimensions are any less than the configured limit, we would automatically resize your image to 2000\*2000 pixels using the [Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext) and then compress the image based on the required compression level using the [**HTMLCanvasElement.toDataURL()**](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL) method of the API. | ||
|
||
**Note:** You can get more detailed information on the steps to install and configure the Image Processor CodeLib solution from the ***Catalyst CodeLib*** section in your Catalyst console. | ||
|
||
### Resources Involved: | ||
|
||
The following Catalyst resources are used as a part of the Image Processor CodeLib solution: | ||
|
||
**1. [Catalyst Serverless Functions](https://docs.catalyst.zoho.com/en/serverless/help/functions/introduction/):** | ||
|
||
This **image_processor([Advanced I/O](https://docs.catalyst.zoho.com/en/serverless/help/functions/advanced-io/)) function** handles the logic to resize and compress the input images, and returns the resized or compressed image as the response in the *.png* format. | ||
|
||
**2. [Catalyst SmartBrowz](https://docs.catalyst.zoho.com/en/smartbrowz/getting-started/introduction/):** | ||
|
||
We have used Catalyst SmartBrowz service in this CodeLib solution to connect to a headless Chrome browser. The images modified using the [Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext) will be in the HTML format. We will input this HTML file to the Puppeteer framework through the SmartBrowz service. This will serve the HTML in a browser webpage and take a screenshot of the updated image using the [PDF & Screenshot component](https://docs.catalyst.zoho.com/en/smartbrowz/help/pdfnscreenshot/introduction/), and return it in the .*png* format. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"deployment": { | ||
"name": "image_processor", | ||
"stack": "node16", | ||
"type": "advancedio", | ||
"env_variables": { | ||
"BROWSER_WS_ENDPOINT": "Your Catalyst SmartBrowz WS endpoint", | ||
"CODELIB_SECRET_KEY": "CODELIB_FAKE_KEY" | ||
} | ||
}, | ||
"execution": { | ||
"main": "index.js" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
class AppConstants { | ||
static NumberRegex = /^[0-9]+$/ | ||
static File = { | ||
MaxSize: 5 * 1000 * 1000 | ||
} | ||
|
||
static Headers = { | ||
CodelibSecretKey: 'catalyst-codelib-secret-key' | ||
} | ||
|
||
static Env = { | ||
CodelibSecretKey: 'CODELIB_SECRET_KEY', | ||
BrowserWSEndpoint: 'BROWSER_WS_ENDPOINT' | ||
} | ||
|
||
static MountingDivID = 'root' | ||
static MaxImageWidth = 2000 | ||
static MaxImageHeight = 2000 | ||
} | ||
|
||
module.exports = AppConstants |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
class AppError extends Error { | ||
statusCode = 500 | ||
|
||
constructor (statusCode, message) { | ||
super() | ||
|
||
this.statusCode = statusCode | ||
this.message = message | ||
} | ||
} | ||
module.exports = AppError |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
const AppError = require('./AppError') | ||
|
||
module.exports = { AppError } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
const { AppError } = require('../errors') | ||
|
||
class ErrorHandler { | ||
processError = (err) => { | ||
if (err instanceof AppError) { | ||
return { | ||
status: 'failure', | ||
statusCode: err.statusCode, | ||
message: err.message | ||
} | ||
} else { | ||
console.log('Error :::', err?.message || err) | ||
return { | ||
status: 'failure', | ||
statusCode: 500, | ||
message: | ||
"We're unable to process your request. Kindly check logs to know more details." | ||
} | ||
} | ||
} | ||
|
||
static getInstance = () => { | ||
return new ErrorHandler() | ||
} | ||
} | ||
module.exports = ErrorHandler |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
const path = require('path') | ||
const multer = require('multer') | ||
|
||
const { AppError } = require('../errors') | ||
const AppConstants = require('../constants') | ||
const { FileService } = require('../services') | ||
|
||
class FileUploadHandler { | ||
#__fields = {} | ||
#__request = null | ||
#__response = null | ||
|
||
constructor (request, response, fields) { | ||
this.#__fields = fields | ||
this.#__request = request | ||
this.#__response = response | ||
} | ||
|
||
handleFileUpload = () => { | ||
const storage = multer.diskStorage({ | ||
destination: FileService.getInstance().getTempDirectory(), | ||
filename: function (__request, file, cb) { | ||
cb(null, Date.now() + path.extname(file.originalname)) | ||
} | ||
}) | ||
const upload = multer({ | ||
storage, | ||
limits: { | ||
fileSize: AppConstants.File.MaxSize | ||
}, | ||
fileFilter: (__request, file, cb) => { | ||
const fileName = path.parse(file.originalname).name | ||
if (!['image/png', 'image/jpg', 'image/jpeg'].includes(file.mimetype)) { | ||
cb( | ||
new AppError( | ||
400, | ||
`${file.fieldname} must be a one of the following formats: jpg,jpeg or png file.` | ||
) | ||
) | ||
} else if (!/^[A-Za-z0-9_-]*$/.test(fileName)) { | ||
cb( | ||
new AppError( | ||
400, | ||
'Invalid value for filename. Filename must contain only alphanumeric characters, underscores and hyphens' | ||
) | ||
) | ||
} else { | ||
cb(null, true) | ||
} | ||
} | ||
}).fields(this.#__fields) | ||
|
||
return new Promise((resolve, reject) => { | ||
upload(this.#__request, this.#__response, (err) => { | ||
if (err) { | ||
if (err instanceof multer.MulterError) { | ||
if (err.code === 'LIMIT_FILE_COUNT') { | ||
reject( | ||
new AppError(400, `${err.field} can contain a single file.`) | ||
) | ||
} else if (err.code === 'LIMIT_FILE_SIZE') { | ||
reject( | ||
new AppError(400, `${err.field} size should not exceed 5 MB.`) | ||
) | ||
} else if (err.code === 'LIMIT_UNEXPECTED_FILE') { | ||
reject( | ||
new AppError( | ||
400, | ||
'file must be named with one of the following values: ' + | ||
this.#__fields.map((field) => field.name) | ||
) | ||
) | ||
} else { | ||
reject(err) | ||
} | ||
} else { | ||
reject(err) | ||
} | ||
} else { | ||
resolve('') | ||
} | ||
}) | ||
}) | ||
} | ||
|
||
static getInstance = (request, response, fields) => { | ||
return new FileUploadHandler(request, response, fields) | ||
} | ||
} | ||
module.exports = FileUploadHandler |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
const ErrorHandler = require('./ErrorHandler') | ||
const FileUploadHandler = require('./FileUploadHandler') | ||
|
||
module.exports = { FileUploadHandler, ErrorHandler } |
Oops, something went wrong.