Skip to content

Commit 81bbdff

Browse files
committed
fix: added utility for file format resolver.
1 parent 4a16d64 commit 81bbdff

25 files changed

+482
-30
lines changed
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* File Format Exception Class.
3+
*
4+
* @author Joshua Clifford Reyes <[email protected]>
5+
*/
6+
export declare class FileFormatException extends Error {
7+
constructor(message: string);
8+
static extensionIsNotSupported(): FileFormatException;
9+
static extensionAndMimeTypeIsNotEqual(): FileFormatException;
10+
}

dist/Exception/FileFormatException.js

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"use strict";
2+
/*
3+
* This file is part of the Image Squeezer.
4+
*
5+
* (c) Joshua Clifford Reyes <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
Object.defineProperty(exports, "__esModule", { value: true });
11+
/**
12+
* File Format Exception Class.
13+
*
14+
* @author Joshua Clifford Reyes <[email protected]>
15+
*/
16+
class FileFormatException extends Error {
17+
constructor(message) {
18+
super(message);
19+
this.name = 'FileFormatException';
20+
}
21+
static extensionIsNotSupported() {
22+
return new FileFormatException('The current file extension is not supported. Use only png, jpg, or jpeg.');
23+
}
24+
static extensionAndMimeTypeIsNotEqual() {
25+
return new FileFormatException('The file name extension is not equal to the actual file content mime type.');
26+
}
27+
}
28+
exports.FileFormatException = FileFormatException;

dist/FFMPEGCompression.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ import { ImageSqueezerCommon } from './ImageSqueezerCommon';
66
*/
77
export declare class FFMPEGCompression extends ImageSqueezerCommon {
88
constructor();
9+
protected validate(): void;
910
protected command(): string;
1011
}

dist/FFMPEGCompression.js

+11
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
1313
Object.defineProperty(exports, "__esModule", { value: true });
1414
const image_size_1 = __importDefault(require("image-size"));
1515
const ImageSqueezerCommon_1 = require("./ImageSqueezerCommon");
16+
const FileFormatResolver_1 = require("./Utility/FileFormatResolver");
1617
/**
1718
* FFMPEG Compression Class.
1819
*
@@ -24,6 +25,16 @@ class FFMPEGCompression extends ImageSqueezerCommon_1.ImageSqueezerCommon {
2425
this.setSubClassType('ffmpeg-compression');
2526
this.setBin('ffmpeg');
2627
}
28+
validate() {
29+
let allowedExtensionMimeType = {
30+
'jpg': 'image/jpeg',
31+
'jpeg': 'image/jpeg',
32+
'png': 'image/png'
33+
};
34+
let fileFormatResolver = new FileFormatResolver_1.FileFormatResolver(allowedExtensionMimeType);
35+
fileFormatResolver.setSourceFilePath(this.sourceFilePath);
36+
fileFormatResolver.validate();
37+
}
2738
command() {
2839
let imageDimensions = image_size_1.default(this.sourceFilePath);
2940
return this.bin + ' -y -i ' +

dist/ImageSqueezerCommon.d.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export declare class ImageSqueezerCommon {
1818
protected isAllowedEmptyOutputFilePath: boolean;
1919
protected isExecuteChildProcess: boolean;
2020
load(): void;
21-
verifySupportedOperatingSystem(): void;
21+
private verifySupportedOperatingSystem;
2222
setOperatingSystem(operatingSystem: string): void;
2323
protected getOperatingSystem(): string;
2424
protected setSubClassType(subClassType: string): void;
@@ -30,17 +30,22 @@ export declare class ImageSqueezerCommon {
3030
getCommandStatement(): string;
3131
disableChildProcessExecution(): void;
3232
build(): void;
33-
compress(): Promise<boolean>;
33+
/**
34+
* This is an abstract, hook, or no-op class method.
35+
* The subclass is expected to override this method.
36+
*/
37+
protected validate(): void;
3438
protected transferSouceFilePathToOutputFilePath(): void;
3539
protected validateRequiredProperties(): void;
3640
protected handleOutputFilePath(): string;
3741
protected generateTemporaryOutputFilePath(): string;
3842
private renameCommandWithCompatibilityChecking;
3943
protected escapeShellArg(arg: string): string;
40-
protected executeChildProcess(): Promise<boolean>;
4144
/**
4245
* This is an abstract or no-op class method.
4346
* The subclass is expected to override this method.
4447
*/
4548
protected command(): string;
49+
compress(): Promise<boolean>;
50+
protected executeChildProcess(): Promise<boolean>;
4651
}

dist/ImageSqueezerCommon.js

+21-11
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,16 @@ class ImageSqueezerCommon {
7979
this.isExecuteChildProcess = false;
8080
}
8181
build() {
82+
this.validate();
8283
this.transferSouceFilePathToOutputFilePath();
8384
this.validateRequiredProperties();
8485
this.setCommandStatement(this.command());
8586
}
86-
compress() {
87-
return this.executeChildProcess();
88-
}
87+
/**
88+
* This is an abstract, hook, or no-op class method.
89+
* The subclass is expected to override this method.
90+
*/
91+
validate() { }
8992
transferSouceFilePathToOutputFilePath() {
9093
if (this.isAllowedEmptyOutputFilePath) {
9194
this.outputFilePath = this.sourceFilePath;
@@ -108,9 +111,15 @@ class ImageSqueezerCommon {
108111
}
109112
}
110113
generateTemporaryOutputFilePath() {
114+
const FILE_NAME = 0;
115+
const FILE_NAME_EXT = 1;
111116
let filename = path_1.default.basename(this.outputFilePath);
112117
let splittedFilename = filename.split('.');
113-
let newFilename = splittedFilename[0] + '-tmp-' + this.subClassType + '.' + splittedFilename[1];
118+
let newFilename = splittedFilename[FILE_NAME] +
119+
'-tmp-' +
120+
this.subClassType +
121+
'.' +
122+
splittedFilename[FILE_NAME_EXT];
114123
let newBasename = this.escapeShellArg(this.outputFilePath.replace(filename, newFilename));
115124
return newBasename + this.renameCommandWithCompatibilityChecking(newBasename);
116125
}
@@ -130,6 +139,14 @@ class ImageSqueezerCommon {
130139
escapeShellArg(arg) {
131140
return `'${arg.replace(/'/g, `'\\''`)}'`;
132141
}
142+
/**
143+
* This is an abstract or no-op class method.
144+
* The subclass is expected to override this method.
145+
*/
146+
command() { return ''; }
147+
compress() {
148+
return this.executeChildProcess();
149+
}
133150
executeChildProcess() {
134151
if (!this.isExecuteChildProcess) {
135152
return Promise.reject(ImageSqueezerCommon.DISABLED_CHILD_PROC_MSG);
@@ -140,13 +157,6 @@ class ImageSqueezerCommon {
140157
});
141158
});
142159
}
143-
/**
144-
* This is an abstract or no-op class method.
145-
* The subclass is expected to override this method.
146-
*/
147-
command() {
148-
return '';
149-
}
150160
}
151161
ImageSqueezerCommon.WINDOWS_OS = 'win32';
152162
ImageSqueezerCommon.LINUX_OS = 'linux';

dist/ProgressiveJPEG.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ import { ImageSqueezerCommon } from './ImageSqueezerCommon';
66
*/
77
export declare class ProgressiveJPEG extends ImageSqueezerCommon {
88
constructor();
9+
protected validate(): void;
910
protected command(): string;
1011
}

dist/ProgressiveJPEG.js

+11
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010
Object.defineProperty(exports, "__esModule", { value: true });
1111
const ImageSqueezerCommon_1 = require("./ImageSqueezerCommon");
12+
const FileFormatResolver_1 = require("./Utility/FileFormatResolver");
1213
/**
1314
* Progressive JPEG Class.
1415
*
@@ -20,6 +21,16 @@ class ProgressiveJPEG extends ImageSqueezerCommon_1.ImageSqueezerCommon {
2021
this.setSubClassType('progessive-jpeg');
2122
this.setBin('convert');
2223
}
24+
validate() {
25+
let allowedExtensionMimeType = {
26+
'jpg': 'image/jpeg',
27+
'jpeg': 'image/jpeg',
28+
'png': 'image/png'
29+
};
30+
let fileFormatResolver = new FileFormatResolver_1.FileFormatResolver(allowedExtensionMimeType);
31+
fileFormatResolver.setSourceFilePath(this.sourceFilePath);
32+
fileFormatResolver.validate();
33+
}
2334
command() {
2435
return this.bin + ' ' +
2536
this.escapeShellArg(this.sourceFilePath) + ' -interlace plane ' +
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* Extension Mime Type Interface.
3+
*
4+
* @author Joshua Clifford Reyes <[email protected]>
5+
*/
6+
export interface ExtensionMimeTypeInterface {
7+
[key: string]: string;
8+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"use strict";
2+
/*
3+
* This file is part of the Image Squeezer.
4+
*
5+
* (c) Joshua Clifford Reyes <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
Object.defineProperty(exports, "__esModule", { value: true });

dist/Utility/FileFormatResolver.d.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { ExtensionMimeTypeInterface } from './ExtensionMimeTypeInterface';
2+
/**
3+
* File Format Resolver Class.
4+
*
5+
* The primary role of this class is to transform the details
6+
* of a given file path. It can be renaming of file name or changing the file extension, etc.
7+
*
8+
* @author Joshua Clifford Reyes <[email protected]>
9+
*/
10+
export declare class FileFormatResolver {
11+
private allowedExtensionMimeType;
12+
private sourceFilePath;
13+
private fileNameExtension;
14+
private fileTypeDetails;
15+
constructor(allowedExtensionMimeType: ExtensionMimeTypeInterface);
16+
setSourceFilePath(sourceFilePath: string): void;
17+
validate(): void;
18+
private setFileNameExtension;
19+
private setFileTypeDetails;
20+
}

dist/Utility/FileFormatResolver.js

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"use strict";
2+
/*
3+
* This file is part of the Image Squeezer.
4+
*
5+
* (c) Joshua Clifford Reyes <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
var __importDefault = (this && this.__importDefault) || function (mod) {
11+
return (mod && mod.__esModule) ? mod : { "default": mod };
12+
};
13+
Object.defineProperty(exports, "__esModule", { value: true });
14+
const path_1 = __importDefault(require("path"));
15+
const file_type_1 = __importDefault(require("file-type"));
16+
const read_chunk_1 = __importDefault(require("read-chunk"));
17+
const FileFormatException_1 = require("../Exception/FileFormatException");
18+
/**
19+
* File Format Resolver Class.
20+
*
21+
* The primary role of this class is to transform the details
22+
* of a given file path. It can be renaming of file name or changing the file extension, etc.
23+
*
24+
* @author Joshua Clifford Reyes <[email protected]>
25+
*/
26+
class FileFormatResolver {
27+
constructor(allowedExtensionMimeType) {
28+
this.allowedExtensionMimeType = {};
29+
this.sourceFilePath = '';
30+
this.fileNameExtension = '';
31+
this.fileTypeDetails = { ext: '', mime: '' };
32+
this.allowedExtensionMimeType = allowedExtensionMimeType;
33+
}
34+
setSourceFilePath(sourceFilePath) {
35+
this.sourceFilePath = sourceFilePath;
36+
}
37+
validate() {
38+
this.setFileNameExtension();
39+
this.setFileTypeDetails();
40+
if (typeof this.allowedExtensionMimeType[this.fileTypeDetails['ext']] === 'undefined') {
41+
throw FileFormatException_1.FileFormatException.extensionIsNotSupported();
42+
}
43+
if (this.allowedExtensionMimeType[this.fileNameExtension] !== this.fileTypeDetails['mime']) {
44+
throw FileFormatException_1.FileFormatException.extensionAndMimeTypeIsNotEqual();
45+
}
46+
}
47+
setFileNameExtension() {
48+
const FILE_NAME_EXT = 1;
49+
let filename = path_1.default.basename(this.sourceFilePath);
50+
let splittedFilename = filename.split('.');
51+
this.fileNameExtension = splittedFilename[FILE_NAME_EXT];
52+
}
53+
setFileTypeDetails() {
54+
const buffer = read_chunk_1.default.sync(this.sourceFilePath, 0, file_type_1.default.minimumBytes);
55+
let fileTypeDetails = file_type_1.default(buffer);
56+
if (typeof fileTypeDetails !== 'undefined' || fileTypeDetails) {
57+
this.fileTypeDetails['ext'] = fileTypeDetails.ext;
58+
this.fileTypeDetails['mime'] = fileTypeDetails.mime;
59+
}
60+
}
61+
}
62+
exports.FileFormatResolver = FileFormatResolver;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* File Type Details Interface.
3+
*
4+
* @author Joshua Clifford Reyes <[email protected]>
5+
*/
6+
export interface FileTypeDetailsInterface {
7+
ext: string;
8+
mime: string;
9+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"use strict";
2+
/*
3+
* This file is part of the Image Squeezer.
4+
*
5+
* (c) Joshua Clifford Reyes <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
Object.defineProperty(exports, "__esModule", { value: true });

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@
4545
"dependencies": {
4646
"@types/image-size": "^0.7.0",
4747
"@types/node": "^12.0.2",
48+
"file-type": "^11.1.0",
4849
"image-size": "^0.7.4",
50+
"read-chunk": "^3.2.0",
4951
"typescript": "^3.4.5"
5052
},
5153
"config": {

src/Exception/FileFormatException.ts

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* This file is part of the Image Squeezer.
3+
*
4+
* (c) Joshua Clifford Reyes <[email protected]>
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
/**
11+
* File Format Exception Class.
12+
*
13+
* @author Joshua Clifford Reyes <[email protected]>
14+
*/
15+
export class FileFormatException extends Error {
16+
17+
constructor(message: string) {
18+
19+
super(message);
20+
this.name = 'FileFormatException';
21+
}
22+
23+
public static extensionIsNotSupported(): FileFormatException {
24+
25+
return new FileFormatException(
26+
'The current file extension is not supported. Use only png, jpg, or jpeg.'
27+
);
28+
}
29+
30+
public static extensionAndMimeTypeIsNotEqual(): FileFormatException {
31+
32+
return new FileFormatException(
33+
'The file name extension is not equal to the actual file content mime type.'
34+
);
35+
}
36+
}

0 commit comments

Comments
 (0)