@e-mc/compress 0.8.10 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -3
- package/README.md +84 -13
- package/index.js +93 -103
- package/package.json +4 -4
package/LICENSE
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
Copyright 2024 An Pham
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
8
|
+
|
|
9
|
+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
10
|
+
|
|
11
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @e-mc/compress
|
|
2
2
|
|
|
3
|
-
* NodeJS
|
|
4
|
-
*
|
|
3
|
+
* NodeJS 16
|
|
4
|
+
* ES2020
|
|
5
5
|
|
|
6
6
|
## General Usage
|
|
7
7
|
|
|
@@ -9,16 +9,16 @@
|
|
|
9
9
|
|
|
10
10
|
## Interface
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
* [View Source](https://www.unpkg.com/@e-mc/types@0.9.1/lib/index.d.ts)
|
|
13
13
|
|
|
14
14
|
```typescript
|
|
15
15
|
import type { CompressLevel } from "./squared";
|
|
16
16
|
|
|
17
17
|
import type { IModule, ModuleConstructor } from "./index";
|
|
18
|
-
import type { BufferResult, CompressFormat, TryFileCompressor
|
|
18
|
+
import type { BufferResult, CompressFormat, TryFileCompressor } from "./compress";
|
|
19
19
|
import type { CompressModule, CompressSettings } from "./settings";
|
|
20
20
|
|
|
21
|
-
import type { WriteStream } from
|
|
21
|
+
import type { WriteStream } from "fs";
|
|
22
22
|
import type { Readable } from "stream";
|
|
23
23
|
import type { BrotliCompress, Gzip } from "zlib";
|
|
24
24
|
|
|
@@ -35,10 +35,12 @@ interface ICompress extends IModule {
|
|
|
35
35
|
createBrotliCompress(file: string | Buffer, options?: CompressLevel): BrotliCompress;
|
|
36
36
|
createWriteStreamAsGzip(file: string | Buffer, output: string, options?: CompressLevel): WriteStream;
|
|
37
37
|
createWriteStreamAsBrotli(file: string | Buffer, output: string, options?: CompressLevel): WriteStream;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
writeGzip(file: string | Buffer, output: string, options?: CompressLevel): Promise<void>;
|
|
39
|
+
writeBrotli(file: string | Buffer, output: string, options?: CompressLevel): Promise<void>;
|
|
40
|
+
tryFile(file: string | Buffer, options: CompressFormat): Promise<BufferResult>;
|
|
41
|
+
tryFile(file: string | Buffer, output: string, options?: CompressFormat): Promise<BufferResult>;
|
|
42
|
+
tryImage(file: string, options: CompressFormat): Promise<BufferResult>;
|
|
43
|
+
tryImage(file: string | Buffer, output: string, options?: CompressFormat): Promise<BufferResult>;
|
|
42
44
|
get settings(): CompressSettings;
|
|
43
45
|
}
|
|
44
46
|
|
|
@@ -49,12 +51,81 @@ interface CompressConstructor extends ModuleConstructor {
|
|
|
49
51
|
}
|
|
50
52
|
```
|
|
51
53
|
|
|
54
|
+
## Settings
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import type { BrotliOptions, ZlibOptions } from "zlib";
|
|
58
|
+
import type { Options as ZopfliOptions } from "node-zopfli";
|
|
59
|
+
|
|
60
|
+
interface CompressModule {
|
|
61
|
+
gzip?: ZlibOptions;
|
|
62
|
+
brotli?: BrotliOptions;
|
|
63
|
+
zopfli?: ZopfliOptions;
|
|
64
|
+
tinify?: {
|
|
65
|
+
api_key?: string;
|
|
66
|
+
proxy?: string;
|
|
67
|
+
};
|
|
68
|
+
settings?: {
|
|
69
|
+
broadcast_id?: string | string[];
|
|
70
|
+
cache?: boolean;
|
|
71
|
+
cache_expires?: number | string;
|
|
72
|
+
gzip_level?: number;
|
|
73
|
+
brotli_quality?: number;
|
|
74
|
+
zopfli_iterations?: number;
|
|
75
|
+
chunk_size?: number | string;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Example usage
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
const Compress = require("@e-mc/compress");
|
|
84
|
+
|
|
85
|
+
const instance = new Compress({
|
|
86
|
+
gzip: {
|
|
87
|
+
memLevel: 1,
|
|
88
|
+
windowBits: 16
|
|
89
|
+
},
|
|
90
|
+
tinify: {
|
|
91
|
+
api_key: "**********"
|
|
92
|
+
},
|
|
93
|
+
settings: {
|
|
94
|
+
gzip_level: 9, // Lowest priority
|
|
95
|
+
brotli_quality: 11,
|
|
96
|
+
chunk_size: "16kb" // All compression types
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
instance.init();
|
|
100
|
+
|
|
101
|
+
const stream = instance.createWriteStreamAsGzip("/tmp/archive.tar", "/path/output/archive.tar.gz", { level: 5, chunkSize: 4 * 1024 }); // Override settings
|
|
102
|
+
stream
|
|
103
|
+
.on("finish", () => console.log("finish"))
|
|
104
|
+
.on("error", err => console.error(err));
|
|
105
|
+
|
|
106
|
+
const options = {
|
|
107
|
+
plugin: "tinify",
|
|
108
|
+
format: "png", // Optional with extension
|
|
109
|
+
timeout: 60 * 1000, // 1m
|
|
110
|
+
options: {
|
|
111
|
+
apiKey: "**********" // Override settings
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
instance.tryImage("/tmp/image.png", "/path/output/compressed.png", options)
|
|
115
|
+
.then(data => {
|
|
116
|
+
console.log(Buffer.byteLength(data));
|
|
117
|
+
})
|
|
118
|
+
.catch(err => console.error(err));
|
|
119
|
+
```
|
|
120
|
+
|
|
52
121
|
## References
|
|
53
122
|
|
|
54
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
55
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
56
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
123
|
+
- https://www.unpkg.com/@e-mc/types@0.9.1/lib/squared.d.ts
|
|
124
|
+
- https://www.unpkg.com/@e-mc/types@0.9.1/lib/compress.d.ts
|
|
125
|
+
- https://www.unpkg.com/@e-mc/types@0.9.1/lib/settings.d.ts
|
|
126
|
+
|
|
127
|
+
* https://www.npmjs.com/package/@types/node
|
|
57
128
|
|
|
58
129
|
## LICENSE
|
|
59
130
|
|
|
60
|
-
|
|
131
|
+
BSD 3-Clause
|
package/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
2
|
const path = require("path");
|
|
4
3
|
const fs = require("fs");
|
|
5
4
|
const stream = require("stream");
|
|
@@ -7,7 +6,6 @@ const zlib = require("zlib");
|
|
|
7
6
|
const wawoff2 = require("wawoff2");
|
|
8
7
|
const { toSfnt, toWoff } = require('woff2sfnt-sfnt2woff');
|
|
9
8
|
const types_1 = require("@e-mc/types");
|
|
10
|
-
const lib_v4_1 = require("@e-mc/module/lib-v4");
|
|
11
9
|
const module_1 = require("@e-mc/module");
|
|
12
10
|
const CACHE_IMAGE = {};
|
|
13
11
|
const CACHE_FONT = {};
|
|
@@ -35,7 +33,7 @@ function setCacheData(index) {
|
|
|
35
33
|
if (TEMP_DIR) {
|
|
36
34
|
if (expires === 0) {
|
|
37
35
|
if (CACHE_INIT.every(value => !value)) {
|
|
38
|
-
module_1.
|
|
36
|
+
module_1.removeDir(TEMP_DIR, true);
|
|
39
37
|
}
|
|
40
38
|
settings.cache_expires = 0;
|
|
41
39
|
}
|
|
@@ -83,7 +81,7 @@ function setCacheData(index) {
|
|
|
83
81
|
}
|
|
84
82
|
const removeFile = (pathname) => fs.unlink(pathname, () => { });
|
|
85
83
|
const checkChunkSize = (value) => typeof value === 'number' && value > 0 && value % 1024 === 0;
|
|
86
|
-
class Compress extends module_1
|
|
84
|
+
class Compress extends module_1 {
|
|
87
85
|
static singleton() {
|
|
88
86
|
if (!SINGLETON_INSTANCE) {
|
|
89
87
|
SINGLETON_INSTANCE = new Compress();
|
|
@@ -115,7 +113,7 @@ class Compress extends module_1.default {
|
|
|
115
113
|
if (zopfli_iterations && (zopfli_iterations = Math.floor(+zopfli_iterations)) > 0) {
|
|
116
114
|
this.level.zopfli = zopfli_iterations;
|
|
117
115
|
}
|
|
118
|
-
if (chunk_size && checkChunkSize(chunk_size = +chunk_size)) {
|
|
116
|
+
if (chunk_size && ((0, types_1.isString)(chunk_size) && checkChunkSize(chunk_size = (0, types_1.formatSize)(chunk_size)) || checkChunkSize(chunk_size = +chunk_size))) {
|
|
119
117
|
this.chunkSize = chunk_size;
|
|
120
118
|
}
|
|
121
119
|
return this;
|
|
@@ -127,8 +125,7 @@ class Compress extends module_1.default {
|
|
|
127
125
|
}
|
|
128
126
|
}
|
|
129
127
|
getLevel(value, fallback) {
|
|
130
|
-
|
|
131
|
-
const result = (_a = this.level[value = value.toLowerCase()]) !== null && _a !== void 0 ? _a : this.level[value = path.extname(value).substring(1)];
|
|
128
|
+
const result = this.level[value = value.toLowerCase()] ?? this.level[value = path.extname(value).substring(1)];
|
|
132
129
|
if (!isNaN(result)) {
|
|
133
130
|
return result;
|
|
134
131
|
}
|
|
@@ -146,7 +143,6 @@ class Compress extends module_1.default {
|
|
|
146
143
|
return file instanceof Buffer ? stream.Readable.from(file) : fs.createReadStream(file);
|
|
147
144
|
}
|
|
148
145
|
createGzip(file, options) {
|
|
149
|
-
var _a, _b, _c;
|
|
150
146
|
let algorithm, level, chunkSize;
|
|
151
147
|
if (options) {
|
|
152
148
|
({ algorithm, level, chunkSize } = options);
|
|
@@ -158,7 +154,7 @@ class Compress extends module_1.default {
|
|
|
158
154
|
zopfli.numiterations = level;
|
|
159
155
|
}
|
|
160
156
|
else {
|
|
161
|
-
|
|
157
|
+
zopfli.numiterations ?? (zopfli.numiterations = this.level.zopfli);
|
|
162
158
|
}
|
|
163
159
|
return this.getReadable(file).pipe(GZIP_ZOPFLI.createGzip(zopfli));
|
|
164
160
|
}
|
|
@@ -170,23 +166,22 @@ class Compress extends module_1.default {
|
|
|
170
166
|
gzip.level = level;
|
|
171
167
|
}
|
|
172
168
|
else {
|
|
173
|
-
|
|
169
|
+
gzip.level ?? (gzip.level = this.level.gz);
|
|
174
170
|
}
|
|
175
171
|
if (checkChunkSize(chunkSize)) {
|
|
176
172
|
gzip.chunkSize = chunkSize;
|
|
177
173
|
}
|
|
178
174
|
else {
|
|
179
|
-
|
|
175
|
+
gzip.chunkSize ?? (gzip.chunkSize = this.chunkSize);
|
|
180
176
|
}
|
|
181
177
|
return this.getReadable(file).pipe(zlib.createGzip(gzip));
|
|
182
178
|
}
|
|
183
179
|
createBrotliCompress(file, options) {
|
|
184
|
-
var _a;
|
|
185
180
|
let level, chunkSize, mimeType;
|
|
186
181
|
if (options) {
|
|
187
182
|
({ level, chunkSize, mimeType } = options);
|
|
188
183
|
}
|
|
189
|
-
const params = { [zlib.constants.BROTLI_PARAM_QUALITY]: level
|
|
184
|
+
const params = { [zlib.constants.BROTLI_PARAM_QUALITY]: level ?? this.level.br };
|
|
190
185
|
let brotli = this.module.brotli;
|
|
191
186
|
if ((0, types_1.isPlainObject)(brotli)) {
|
|
192
187
|
brotli = (0, types_1.isPlainObject)(brotli.params) ? { ...brotli, params: Object.assign(params, brotli.params) } : { ...brotli, params };
|
|
@@ -195,12 +190,16 @@ class Compress extends module_1.default {
|
|
|
195
190
|
brotli = { params };
|
|
196
191
|
}
|
|
197
192
|
params[zlib.constants.BROTLI_PARAM_MODE] = (mimeType || (mimeType = '')).includes('text/') ? zlib.constants.BROTLI_MODE_TEXT : mimeType.includes('font/') ? zlib.constants.BROTLI_MODE_FONT : zlib.constants.BROTLI_MODE_GENERIC;
|
|
198
|
-
|
|
193
|
+
try {
|
|
194
|
+
params[zlib.constants.BROTLI_PARAM_SIZE_HINT] = typeof file === 'string' ? fs.statSync(file).size : Buffer.byteLength(file);
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
}
|
|
199
198
|
if (checkChunkSize(chunkSize)) {
|
|
200
199
|
brotli.chunkSize = chunkSize;
|
|
201
200
|
}
|
|
202
201
|
else {
|
|
203
|
-
|
|
202
|
+
brotli.chunkSize ?? (brotli.chunkSize = this.chunkSize);
|
|
204
203
|
}
|
|
205
204
|
return this.getReadable(file).pipe(zlib.createBrotliCompress(brotli));
|
|
206
205
|
}
|
|
@@ -210,51 +209,56 @@ class Compress extends module_1.default {
|
|
|
210
209
|
createWriteStreamAsBrotli(file, output, options) {
|
|
211
210
|
return this.createBrotliCompress(file, options).pipe(fs.createWriteStream(output));
|
|
212
211
|
}
|
|
213
|
-
async
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
212
|
+
async writeGzip(file, output, options) {
|
|
213
|
+
return new Promise((resolve, reject) => {
|
|
214
|
+
this.createWriteStreamAsGzip(file, output, options)
|
|
215
|
+
.on('finish', resolve)
|
|
216
|
+
.on('error', reject);
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
async writeBrotli(file, output, options) {
|
|
220
|
+
return new Promise((resolve, reject) => {
|
|
221
|
+
this.createWriteStreamAsBrotli(file, output, options)
|
|
222
|
+
.on('finish', resolve)
|
|
223
|
+
.on('error', reject);
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
async tryFile(file, output, options) {
|
|
218
227
|
if ((0, types_1.isObject)(output)) {
|
|
219
|
-
|
|
228
|
+
options = output;
|
|
220
229
|
output = '';
|
|
221
230
|
}
|
|
222
231
|
if (!(0, types_1.isString)(output)) {
|
|
223
232
|
output = typeof file === 'string' ? file : '';
|
|
224
233
|
}
|
|
225
|
-
|
|
226
|
-
const { filename, startTime = process.hrtime(), timeout = 0, sessionId, broadcastId } =
|
|
227
|
-
let format =
|
|
228
|
-
if (!
|
|
229
|
-
return Promise.reject((0, types_1.errorValue)(
|
|
234
|
+
options || (options = {});
|
|
235
|
+
const { filename, startTime = process.hrtime(), timeout = 0, sessionId, broadcastId } = options;
|
|
236
|
+
let format = options.format;
|
|
237
|
+
if (!format) {
|
|
238
|
+
return Promise.reject((0, types_1.errorValue)("Missing option \"format\"", output || filename));
|
|
230
239
|
}
|
|
231
|
-
let hash =
|
|
232
|
-
const cache = this.settings.cache ? !!(hash && (hash = module_1.
|
|
240
|
+
let hash = options.etag;
|
|
241
|
+
const cache = this.settings.cache ? !!(hash && (hash = module_1.asHash(hash)) || Buffer.isBuffer(file) && (hash = module_1.asHash(file))) : false;
|
|
233
242
|
return new Promise((resolve, reject) => {
|
|
234
|
-
var _a;
|
|
235
243
|
let timer = null, aborted;
|
|
236
244
|
const endProcess = (err, data = null, ext, result, fromCache) => {
|
|
237
245
|
if (timer) {
|
|
238
246
|
clearTimeout(timer);
|
|
239
247
|
}
|
|
240
248
|
if (err) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
resolve(null);
|
|
244
|
-
}
|
|
245
|
-
else {
|
|
246
|
-
reject(err);
|
|
247
|
-
}
|
|
249
|
+
reject(err);
|
|
250
|
+
return;
|
|
248
251
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
this.writeTimeProcess(ext || format, (0, types_1.isString)(result) ? path.basename(result) : filename || "Completed", startTime, { type: 8, sessionId, broadcastId });
|
|
252
|
-
}
|
|
253
|
-
if (callback) {
|
|
254
|
-
callback(null, result || data, ext);
|
|
255
|
-
}
|
|
256
|
-
resolve(data);
|
|
252
|
+
if (!fromCache) {
|
|
253
|
+
this.writeTimeProcess(ext || format, (0, types_1.isString)(result) ? path.basename(result) : filename || "Completed", startTime, { type: 8, sessionId, broadcastId });
|
|
257
254
|
}
|
|
255
|
+
if (result) {
|
|
256
|
+
options.outFile = result;
|
|
257
|
+
}
|
|
258
|
+
if (ext) {
|
|
259
|
+
options.outExt = ext;
|
|
260
|
+
}
|
|
261
|
+
resolve(data);
|
|
258
262
|
};
|
|
259
263
|
const startProcess = (compressing) => {
|
|
260
264
|
if (timeout > 0) {
|
|
@@ -284,7 +288,7 @@ class Compress extends module_1.default {
|
|
|
284
288
|
if (cache) {
|
|
285
289
|
const pathname = path.join(from, ext);
|
|
286
290
|
let tempFont;
|
|
287
|
-
if (TEMP_DIR && module_1.
|
|
291
|
+
if (TEMP_DIR && module_1.createDir(tempFont = path.join(TEMP_DIR, pathname))) {
|
|
288
292
|
tempFont = path.join(tempFont, hash);
|
|
289
293
|
}
|
|
290
294
|
else {
|
|
@@ -304,7 +308,7 @@ class Compress extends module_1.default {
|
|
|
304
308
|
const cacheKey = from + `_${to}_` + hash;
|
|
305
309
|
const tempFont = CACHE_FONT[cacheKey];
|
|
306
310
|
if (tempFont) {
|
|
307
|
-
if (module_1.
|
|
311
|
+
if (module_1.isPath(tempFont[0])) {
|
|
308
312
|
try {
|
|
309
313
|
const data = fs.readFileSync(tempFont[0]);
|
|
310
314
|
let pathname;
|
|
@@ -315,7 +319,7 @@ class Compress extends module_1.default {
|
|
|
315
319
|
else {
|
|
316
320
|
endProcess(null, data, to, '', true);
|
|
317
321
|
}
|
|
318
|
-
this.formatMessage(8, from, [pathname ? path.basename(pathname) : "Completed" + ` -> font/${to}`, 'cache'], tempFont[1].toLocaleString(), { ...module_1.
|
|
322
|
+
this.formatMessage(8, from, [pathname ? path.basename(pathname) : "Completed" + ` -> font/${to}`, 'cache'], tempFont[1].toLocaleString(), { ...module_1.LOG_STYLE_NOTICE, hintBold: true, sessionId, broadcastId });
|
|
319
323
|
return true;
|
|
320
324
|
}
|
|
321
325
|
catch {
|
|
@@ -326,7 +330,7 @@ class Compress extends module_1.default {
|
|
|
326
330
|
return false;
|
|
327
331
|
}
|
|
328
332
|
};
|
|
329
|
-
const errorResponse = (font) => endProcess((0, types_1.errorValue)(
|
|
333
|
+
const errorResponse = (font) => endProcess((0, types_1.errorValue)("Unsupported MIME", (font ? font.mime : "Unknown") + ': ' + (output || filename || "Unknown")));
|
|
330
334
|
const data = Buffer.isBuffer(file) ? file : fs.readFileSync(file);
|
|
331
335
|
switch (format = format.toLowerCase()) {
|
|
332
336
|
case 'gz':
|
|
@@ -334,11 +338,11 @@ class Compress extends module_1.default {
|
|
|
334
338
|
startProcess(true);
|
|
335
339
|
let transform, chunks;
|
|
336
340
|
if (output) {
|
|
337
|
-
transform = this[format === 'gz' ? 'createWriteStreamAsGzip' : 'createWriteStreamAsBrotli'](data, output,
|
|
341
|
+
transform = this[format === 'gz' ? 'createWriteStreamAsGzip' : 'createWriteStreamAsBrotli'](data, output, options);
|
|
338
342
|
}
|
|
339
343
|
else {
|
|
340
344
|
chunks = [];
|
|
341
|
-
transform = this[format === 'gz' ? 'createGzip' : 'createBrotliCompress'](data,
|
|
345
|
+
transform = this[format === 'gz' ? 'createGzip' : 'createBrotliCompress'](data, options).on('data', chunk => chunks.push(chunk));
|
|
342
346
|
}
|
|
343
347
|
transform
|
|
344
348
|
.on('finish', () => {
|
|
@@ -359,8 +363,8 @@ class Compress extends module_1.default {
|
|
|
359
363
|
}
|
|
360
364
|
startProcess(false);
|
|
361
365
|
const checkResult = (result, from) => {
|
|
362
|
-
module_1.
|
|
363
|
-
switch (font
|
|
366
|
+
module_1.resolveMime(result).then(font => {
|
|
367
|
+
switch (font?.mime) {
|
|
364
368
|
case "font/ttf":
|
|
365
369
|
case "font/otf":
|
|
366
370
|
writeFont(result, font.ext, from);
|
|
@@ -371,9 +375,9 @@ class Compress extends module_1.default {
|
|
|
371
375
|
}
|
|
372
376
|
});
|
|
373
377
|
};
|
|
374
|
-
module_1.
|
|
378
|
+
module_1.resolveMime(data).then(font => {
|
|
375
379
|
try {
|
|
376
|
-
switch (font
|
|
380
|
+
switch (font?.mime) {
|
|
377
381
|
case "font/woff":
|
|
378
382
|
if (cache) {
|
|
379
383
|
CACHE_FONTFROM[hash] = 'woff';
|
|
@@ -403,8 +407,8 @@ class Compress extends module_1.default {
|
|
|
403
407
|
return;
|
|
404
408
|
}
|
|
405
409
|
const checkResult = (result, mimeType, from) => {
|
|
406
|
-
module_1.
|
|
407
|
-
if (
|
|
410
|
+
module_1.resolveMime(result).then(font => {
|
|
411
|
+
if (font?.mime === mimeType) {
|
|
408
412
|
writeFont(result, font.ext, from);
|
|
409
413
|
}
|
|
410
414
|
else {
|
|
@@ -413,9 +417,9 @@ class Compress extends module_1.default {
|
|
|
413
417
|
});
|
|
414
418
|
};
|
|
415
419
|
startProcess(true);
|
|
416
|
-
module_1.
|
|
420
|
+
module_1.resolveMime(data).then(font => {
|
|
417
421
|
try {
|
|
418
|
-
switch (font
|
|
422
|
+
switch (font?.mime) {
|
|
419
423
|
case "font/ttf":
|
|
420
424
|
if (cache) {
|
|
421
425
|
CACHE_FONTFROM[hash] = 'ttf';
|
|
@@ -440,11 +444,11 @@ class Compress extends module_1.default {
|
|
|
440
444
|
break;
|
|
441
445
|
}
|
|
442
446
|
default: {
|
|
443
|
-
const compressor =
|
|
447
|
+
const compressor = this.compressors[format]?.bind(this);
|
|
444
448
|
if (typeof compressor === 'function') {
|
|
445
449
|
startProcess(true);
|
|
446
450
|
if (compressor.toString().startsWith('async')) {
|
|
447
|
-
compressor.call(this, file, output,
|
|
451
|
+
compressor.call(this, file, output, options)
|
|
448
452
|
.then(result => {
|
|
449
453
|
if (typeof result === 'string') {
|
|
450
454
|
endProcess(null, null, format, result);
|
|
@@ -453,14 +457,14 @@ class Compress extends module_1.default {
|
|
|
453
457
|
endProcess(null, result, format);
|
|
454
458
|
}
|
|
455
459
|
})
|
|
456
|
-
.catch(err => endProcess(err));
|
|
460
|
+
.catch((err) => endProcess(err));
|
|
457
461
|
}
|
|
458
462
|
else {
|
|
459
|
-
compressor.call(this, file, output,
|
|
463
|
+
compressor.call(this, file, output, options, endProcess);
|
|
460
464
|
}
|
|
461
465
|
}
|
|
462
466
|
else {
|
|
463
|
-
throw (0, types_1.errorValue)(
|
|
467
|
+
throw (0, types_1.errorValue)("Missing compression plugin", format);
|
|
464
468
|
}
|
|
465
469
|
break;
|
|
466
470
|
}
|
|
@@ -471,39 +475,28 @@ class Compress extends module_1.default {
|
|
|
471
475
|
}
|
|
472
476
|
});
|
|
473
477
|
}
|
|
474
|
-
async tryImage(file, output,
|
|
475
|
-
if (typeof config === 'function') {
|
|
476
|
-
callback = config;
|
|
477
|
-
config = undefined;
|
|
478
|
-
}
|
|
478
|
+
async tryImage(file, output, options) {
|
|
479
479
|
if ((0, types_1.isObject)(output)) {
|
|
480
|
-
|
|
480
|
+
options = output;
|
|
481
481
|
output = '';
|
|
482
482
|
}
|
|
483
483
|
else {
|
|
484
|
-
|
|
484
|
+
options || (options = {});
|
|
485
485
|
}
|
|
486
|
-
const { plugin =
|
|
486
|
+
const { plugin = "tinify", filename, startTime = process.hrtime(), timeout = 0, proxyUrl, sessionId, broadcastId } = options;
|
|
487
487
|
if (!(0, types_1.isString)(output)) {
|
|
488
488
|
output = typeof file === 'string' ? file : '';
|
|
489
489
|
}
|
|
490
|
-
const ext = output ? path.extname(output).substring(1) :
|
|
491
|
-
const format =
|
|
490
|
+
const ext = output ? path.extname(output).substring(1) : options.format || "Unknown";
|
|
491
|
+
const format = options.format || ext;
|
|
492
492
|
return new Promise((resolve, reject) => {
|
|
493
|
-
var _a, _b;
|
|
494
493
|
let timer = null, hash, cacheKey, aborted, apiKey;
|
|
495
494
|
const failed = (err) => {
|
|
496
495
|
aborted = true;
|
|
497
496
|
if (timer) {
|
|
498
497
|
clearTimeout(timer);
|
|
499
498
|
}
|
|
500
|
-
|
|
501
|
-
callback(err, null);
|
|
502
|
-
resolve(null);
|
|
503
|
-
}
|
|
504
|
-
else {
|
|
505
|
-
reject(err);
|
|
506
|
-
}
|
|
499
|
+
reject(err);
|
|
507
500
|
};
|
|
508
501
|
const success = (result, ctime) => {
|
|
509
502
|
if (aborted) {
|
|
@@ -513,21 +506,22 @@ class Compress extends module_1.default {
|
|
|
513
506
|
clearTimeout(timer);
|
|
514
507
|
}
|
|
515
508
|
const complete = (err) => {
|
|
509
|
+
if (err) {
|
|
510
|
+
reject(err);
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
516
513
|
const value = output ? path.basename(output) : filename || (0, types_1.isString)(file) && path.basename(file);
|
|
517
514
|
const status = value ? plugin + ' -> ' + value : "Completed";
|
|
518
515
|
if (ctime) {
|
|
519
|
-
this.formatMessage(8, value ? path.extname(value).substring(1) : '', [status, 'cache'], ctime.toLocaleString(), { ...module_1.
|
|
516
|
+
this.formatMessage(8, value ? path.extname(value).substring(1) : '', [status, 'cache'], ctime.toLocaleString(), { ...module_1.LOG_STYLE_NOTICE, hintBold: true, sessionId, broadcastId });
|
|
520
517
|
}
|
|
521
518
|
else {
|
|
522
519
|
this.writeTimeProcess(ext, status, startTime, { type: 8, sessionId, broadcastId });
|
|
523
520
|
}
|
|
524
|
-
if (callback) {
|
|
525
|
-
callback(err, result);
|
|
526
|
-
}
|
|
527
521
|
resolve(result);
|
|
528
522
|
if (!ctime && hash && cacheKey && TEMP_DIR) {
|
|
529
523
|
const pathname = path.join(TEMP_DIR, plugin, hash);
|
|
530
|
-
if (module_1.
|
|
524
|
+
if (module_1.createDir(pathname)) {
|
|
531
525
|
fs.writeFile(path.join(pathname, cacheKey), result, error => {
|
|
532
526
|
var _a, _b;
|
|
533
527
|
if (!error) {
|
|
@@ -545,29 +539,29 @@ class Compress extends module_1.default {
|
|
|
545
539
|
}
|
|
546
540
|
};
|
|
547
541
|
const getFormat = () => output ? path.basename(output) : ext;
|
|
548
|
-
if (plugin ===
|
|
542
|
+
if (plugin === "tinify") {
|
|
549
543
|
switch (format) {
|
|
550
544
|
case 'png':
|
|
551
545
|
case 'jpg':
|
|
552
546
|
case 'jpeg':
|
|
553
547
|
case 'webp':
|
|
554
|
-
apiKey =
|
|
548
|
+
apiKey = options.options?.apiKey || (module_1.enabled("process.env.apply") ? process.env.TINIFY_KEY : '');
|
|
555
549
|
break;
|
|
556
550
|
default:
|
|
557
|
-
failed((0, types_1.errorMessage)(plugin,
|
|
551
|
+
failed((0, types_1.errorMessage)(plugin, "Unsupported MIME", format));
|
|
558
552
|
return;
|
|
559
553
|
}
|
|
560
|
-
if (!
|
|
554
|
+
if (!apiKey) {
|
|
561
555
|
failed((0, types_1.errorMessage)(plugin, 'Missing API key'));
|
|
562
556
|
return;
|
|
563
557
|
}
|
|
564
|
-
switch (module_1.
|
|
558
|
+
switch (module_1.lookupMime(ext)) {
|
|
565
559
|
case "image/jpeg":
|
|
566
560
|
case "image/png":
|
|
567
561
|
case "image/webp":
|
|
568
562
|
break;
|
|
569
563
|
default:
|
|
570
|
-
failed((0, types_1.errorMessage)(plugin,
|
|
564
|
+
failed((0, types_1.errorMessage)(plugin, "Unsupported MIME", getFormat()));
|
|
571
565
|
return;
|
|
572
566
|
}
|
|
573
567
|
}
|
|
@@ -582,9 +576,9 @@ class Compress extends module_1.default {
|
|
|
582
576
|
if (this.settings.cache && setCacheData.call(this, 1)) {
|
|
583
577
|
let stored;
|
|
584
578
|
try {
|
|
585
|
-
stored = (CACHE_IMAGE[plugin] || (CACHE_IMAGE[plugin] = {}))[hash = module_1.
|
|
586
|
-
cacheKey = module_1.
|
|
587
|
-
const ctime = stored
|
|
579
|
+
stored = (CACHE_IMAGE[plugin] || (CACHE_IMAGE[plugin] = {}))[hash = module_1.asHash(data)];
|
|
580
|
+
cacheKey = module_1.asHash(plugin + ':' + (apiKey ? format + apiKey : module_1.asString(options) || 'unknown'), 'md5');
|
|
581
|
+
const ctime = stored?.[cacheKey];
|
|
588
582
|
if (ctime) {
|
|
589
583
|
success(fs.readFileSync(path.join(TEMP_DIR, plugin, hash, cacheKey)), ctime);
|
|
590
584
|
return;
|
|
@@ -601,7 +595,7 @@ class Compress extends module_1.default {
|
|
|
601
595
|
timer = setTimeout(() => failed((0, types_1.errorMessage)(plugin, "Timeout was exceeded")), timeout);
|
|
602
596
|
}
|
|
603
597
|
if (apiKey) {
|
|
604
|
-
const apiProxy = proxyUrl && (typeof proxyUrl === 'function' ? proxyUrl("https://api.tinify.com") : proxyUrl) ||
|
|
598
|
+
const apiProxy = proxyUrl && (typeof proxyUrl === 'function' ? proxyUrl("https://api.tinify.com") : proxyUrl) || this.module.tinify?.proxy || module_1.enabled("process.env.apply") && process.env.TINIFY_PROXY || '';
|
|
605
599
|
const key = apiKey + apiProxy;
|
|
606
600
|
let tinypng = CACHE_TINIFY[key];
|
|
607
601
|
const validate = () => {
|
|
@@ -647,12 +641,12 @@ class Compress extends module_1.default {
|
|
|
647
641
|
else {
|
|
648
642
|
try {
|
|
649
643
|
const transform = require(plugin);
|
|
650
|
-
transform(options)(data).then(result => {
|
|
644
|
+
transform(options.options)(data).then(result => {
|
|
651
645
|
if (result !== data) {
|
|
652
646
|
success(result);
|
|
653
647
|
}
|
|
654
648
|
else {
|
|
655
|
-
failed((0, types_1.errorMessage)(plugin,
|
|
649
|
+
failed((0, types_1.errorMessage)(plugin, "Unsupported MIME", getFormat()));
|
|
656
650
|
}
|
|
657
651
|
});
|
|
658
652
|
}
|
|
@@ -667,9 +661,5 @@ class Compress extends module_1.default {
|
|
|
667
661
|
return (_a = this.module).settings || (_a.settings = {});
|
|
668
662
|
}
|
|
669
663
|
}
|
|
670
|
-
exports.default = Compress;
|
|
671
664
|
|
|
672
|
-
|
|
673
|
-
module.exports = exports.default;
|
|
674
|
-
module.exports.default = exports.default;
|
|
675
|
-
}
|
|
665
|
+
module.exports = Compress;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e-mc/compress",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "Compress constructor for E-mc.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
"name": "An Pham",
|
|
21
21
|
"email": "anpham6@gmail.com"
|
|
22
22
|
},
|
|
23
|
-
"license": "
|
|
23
|
+
"license": "BSD 3-Clause",
|
|
24
24
|
"homepage": "https://github.com/anpham6/e-mc#readme",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@e-mc/module": "0.
|
|
27
|
-
"@e-mc/types": "0.
|
|
26
|
+
"@e-mc/module": "0.9.1",
|
|
27
|
+
"@e-mc/types": "0.9.1",
|
|
28
28
|
"tinify": "^1.7.1",
|
|
29
29
|
"wawoff2": "^2.0.1",
|
|
30
30
|
"woff2sfnt-sfnt2woff": "^1.0.0"
|