@e-mc/compress 0.9.9 → 0.10.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/README.md +10 -14
- package/index.js +182 -163
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -9,13 +9,11 @@
|
|
|
9
9
|
|
|
10
10
|
## Interface
|
|
11
11
|
|
|
12
|
-
* [View Source](https://www.unpkg.com/@e-mc/types@0.
|
|
12
|
+
* [View Source](https://www.unpkg.com/@e-mc/types@0.10.1/lib/index.d.ts)
|
|
13
13
|
|
|
14
14
|
```typescript
|
|
15
|
-
import type { CompressLevel } from "./squared";
|
|
16
|
-
|
|
17
15
|
import type { IModule, ModuleConstructor } from "./index";
|
|
18
|
-
import type { BufferResult, CompressFormat, TryFileCompressor } from "./compress";
|
|
16
|
+
import type { BufferResult, CompressFormat, CompressLevel, ReadableOptions, TryFileCompressor } from "./compress";
|
|
19
17
|
import type { CompressModule, CompressSettings } from "./settings";
|
|
20
18
|
|
|
21
19
|
import type { WriteStream } from "fs";
|
|
@@ -30,7 +28,7 @@ interface ICompress extends IModule {
|
|
|
30
28
|
init(...args: unknown[]): this;
|
|
31
29
|
register(format: string, callback: TryFileCompressor): void;
|
|
32
30
|
getLevel(value: string, fallback?: number): number | undefined;
|
|
33
|
-
getReadable(file: string | URL | Buffer): Readable;
|
|
31
|
+
getReadable(file: string | URL | Buffer, options?: ReadableOptions): Readable;
|
|
34
32
|
createGzip(file: string | Buffer, options?: CompressLevel): Gzip;
|
|
35
33
|
createBrotliCompress(file: string | Buffer, options?: CompressLevel): BrotliCompress;
|
|
36
34
|
createWriteStreamAsGzip(file: string | Buffer, output: string, options?: CompressLevel): WriteStream;
|
|
@@ -41,6 +39,8 @@ interface ICompress extends IModule {
|
|
|
41
39
|
tryFile(file: string | Buffer, output: string, options?: CompressFormat): Promise<BufferResult>;
|
|
42
40
|
tryImage(file: string, options: CompressFormat): Promise<BufferResult>;
|
|
43
41
|
tryImage(file: string | Buffer, output: string, options?: CompressFormat): Promise<BufferResult>;
|
|
42
|
+
set chunkSize(value: number | string | undefined): void;
|
|
43
|
+
get chunkSize(): number | undefined;
|
|
44
44
|
get settings(): CompressSettings;
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -61,10 +61,6 @@ interface CompressModule {
|
|
|
61
61
|
gzip?: ZlibOptions;
|
|
62
62
|
brotli?: BrotliOptions;
|
|
63
63
|
zopfli?: ZopfliOptions;
|
|
64
|
-
tinify?: {
|
|
65
|
-
api_key?: string;
|
|
66
|
-
proxy?: string;
|
|
67
|
-
};
|
|
68
64
|
settings?: {
|
|
69
65
|
broadcast_id?: string | string[];
|
|
70
66
|
cache?: boolean;
|
|
@@ -104,8 +100,8 @@ stream
|
|
|
104
100
|
.on("error", err => console.error(err));
|
|
105
101
|
|
|
106
102
|
const options = {
|
|
107
|
-
plugin: "tinify",
|
|
108
|
-
format: "png", //
|
|
103
|
+
plugin: "@pi-r/tinify",
|
|
104
|
+
format: "png", // Recommended
|
|
109
105
|
timeout: 60 * 1000, // 1m
|
|
110
106
|
options: {
|
|
111
107
|
apiKey: "**********" // Override settings
|
|
@@ -120,9 +116,9 @@ instance.tryImage("/tmp/image.png", "/path/output/compressed.png", options)
|
|
|
120
116
|
|
|
121
117
|
## References
|
|
122
118
|
|
|
123
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
124
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
125
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
119
|
+
- https://www.unpkg.com/@e-mc/types@0.10.1/lib/squared.d.ts
|
|
120
|
+
- https://www.unpkg.com/@e-mc/types@0.10.1/lib/compress.d.ts
|
|
121
|
+
- https://www.unpkg.com/@e-mc/types@0.10.1/lib/settings.d.ts
|
|
126
122
|
|
|
127
123
|
* https://www.npmjs.com/package/@types/node
|
|
128
124
|
|
package/index.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var _a;
|
|
2
3
|
const path = require("path");
|
|
3
4
|
const fs = require("fs");
|
|
4
5
|
const stream = require("stream");
|
|
5
6
|
const zlib = require("zlib");
|
|
6
7
|
const wawoff2 = require("wawoff2");
|
|
7
|
-
const tinify = require("tinify");
|
|
8
|
-
const { toSfnt, toWoff } = require('woff2sfnt-sfnt2woff');
|
|
9
|
-
const types_1 = require("@e-mc/types");
|
|
10
8
|
const module_1 = require("@e-mc/module");
|
|
9
|
+
const types_1 = require("@e-mc/types");
|
|
10
|
+
const { toSfnt, toWoff } = require('woff2sfnt-sfnt2woff');
|
|
11
|
+
const kChunkSize = Symbol('chunkSize');
|
|
11
12
|
const CACHE_IMAGE = {};
|
|
12
13
|
const CACHE_FONT = {};
|
|
13
14
|
const CACHE_FONTFROM = {};
|
|
@@ -20,15 +21,15 @@ const GZIP_ZOPFLI = (function () {
|
|
|
20
21
|
return require('node-zopfli');
|
|
21
22
|
}
|
|
22
23
|
catch {
|
|
24
|
+
return null;
|
|
23
25
|
}
|
|
24
|
-
return null;
|
|
25
26
|
})();
|
|
26
|
-
function setCacheData(index) {
|
|
27
|
+
function setCacheData(instance, index) {
|
|
27
28
|
if (CACHE_INIT[index]) {
|
|
28
29
|
return true;
|
|
29
30
|
}
|
|
30
|
-
TEMP_DIR || (TEMP_DIR =
|
|
31
|
-
const settings =
|
|
31
|
+
TEMP_DIR || (TEMP_DIR = instance.getTempDir({ moduleDir: true, createDir: true, increment: 5 }));
|
|
32
|
+
const settings = instance.settings;
|
|
32
33
|
const expires = (0, types_1.parseExpires)(settings.cache_expires || 0);
|
|
33
34
|
if (TEMP_DIR) {
|
|
34
35
|
if (expires === 0) {
|
|
@@ -43,7 +44,7 @@ function setCacheData(index) {
|
|
|
43
44
|
const srcDir = path.join(TEMP_DIR, ...paths);
|
|
44
45
|
try {
|
|
45
46
|
fs.readdirSync(srcDir, { withFileTypes: true }).forEach(item => {
|
|
46
|
-
var
|
|
47
|
+
var _b, _c, _d;
|
|
47
48
|
const filename = item.name;
|
|
48
49
|
if (item.isFile()) {
|
|
49
50
|
const pathname = path.join(srcDir, filename);
|
|
@@ -57,7 +58,7 @@ function setCacheData(index) {
|
|
|
57
58
|
CACHE_FONTTO[filename] = paths[1];
|
|
58
59
|
}
|
|
59
60
|
else {
|
|
60
|
-
((
|
|
61
|
+
((_c = (CACHE_IMAGE[_b = paths[0]] || (CACHE_IMAGE[_b] = {})))[_d = paths[1]] || (_c[_d] = {}))[filename] = stat.ctime;
|
|
61
62
|
}
|
|
62
63
|
return;
|
|
63
64
|
}
|
|
@@ -79,13 +80,23 @@ function setCacheData(index) {
|
|
|
79
80
|
}
|
|
80
81
|
return CACHE_INIT[index] = true;
|
|
81
82
|
}
|
|
83
|
+
function getOutputSize(startLength, data) {
|
|
84
|
+
if (startLength === 0 || !data) {
|
|
85
|
+
return '';
|
|
86
|
+
}
|
|
87
|
+
const offset = Buffer.byteLength(data) - startLength;
|
|
88
|
+
return ` (${(offset > 0 ? '+' : '') + (0, types_1.formatSize)(offset)})`;
|
|
89
|
+
}
|
|
90
|
+
const sanitizePath = (value) => value.replace(/[\\/]/g, '_');
|
|
82
91
|
class Compress extends module_1 {
|
|
83
92
|
static singleton() {
|
|
84
93
|
if (!SINGLETON_INSTANCE) {
|
|
85
94
|
SINGLETON_INSTANCE = new Compress();
|
|
86
95
|
Object.defineProperty(SINGLETON_INSTANCE, "_logEnabled", { value: false, enumerable: true, writable: false });
|
|
87
96
|
Object.defineProperty(SINGLETON_INSTANCE, "_logFlushed", { value: true, enumerable: true, writable: false });
|
|
88
|
-
Object.defineProperty(SINGLETON_INSTANCE, "host", { set(value) { }, get() {
|
|
97
|
+
Object.defineProperty(SINGLETON_INSTANCE, "host", { set(value) { }, get() {
|
|
98
|
+
return null;
|
|
99
|
+
} });
|
|
89
100
|
}
|
|
90
101
|
return SINGLETON_INSTANCE;
|
|
91
102
|
}
|
|
@@ -99,6 +110,7 @@ class Compress extends module_1 {
|
|
|
99
110
|
};
|
|
100
111
|
this.compressors = {};
|
|
101
112
|
this._moduleName = 'compress';
|
|
113
|
+
this[_a] = undefined;
|
|
102
114
|
}
|
|
103
115
|
init(...args) {
|
|
104
116
|
let { gzip_level, brotli_quality, zopfli_iterations, chunk_size } = (0, types_1.isPlainObject)(args[0]) && args[0].settings || this.settings;
|
|
@@ -111,7 +123,7 @@ class Compress extends module_1 {
|
|
|
111
123
|
if (zopfli_iterations && (zopfli_iterations = Math.floor(+zopfli_iterations)) > 0) {
|
|
112
124
|
this.level.zopfli = zopfli_iterations;
|
|
113
125
|
}
|
|
114
|
-
if (chunk_size
|
|
126
|
+
if (chunk_size !== undefined) {
|
|
115
127
|
this.chunkSize = chunk_size;
|
|
116
128
|
}
|
|
117
129
|
return this;
|
|
@@ -137,8 +149,23 @@ class Compress extends module_1 {
|
|
|
137
149
|
return zlib.constants.BROTLI_DEFAULT_QUALITY;
|
|
138
150
|
}
|
|
139
151
|
}
|
|
140
|
-
getReadable(file) {
|
|
141
|
-
|
|
152
|
+
getReadable(file, options) {
|
|
153
|
+
if (file instanceof Buffer) {
|
|
154
|
+
return stream.Readable.from(file);
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
if (!options?.throwsPermission || this.canRead(file, { ownPermissionOnly: true })) {
|
|
158
|
+
return fs.createReadStream(file);
|
|
159
|
+
}
|
|
160
|
+
options = undefined;
|
|
161
|
+
throw (0, types_1.errorValue)("Operation not permitted", file.toString());
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
if (!options || options.throwsPermission && module_1.isErrorCode(err, 'EACCES') || options.throwsDoesNotExist && module_1.isErrorCode(err, 'ENOENT')) {
|
|
165
|
+
throw err;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return stream.Readable.from(Buffer.alloc(0));
|
|
142
169
|
}
|
|
143
170
|
createGzip(file, options) {
|
|
144
171
|
let algorithm, level, chunkSize;
|
|
@@ -154,7 +181,7 @@ class Compress extends module_1 {
|
|
|
154
181
|
else {
|
|
155
182
|
zopfli.numiterations ?? (zopfli.numiterations = this.level.zopfli);
|
|
156
183
|
}
|
|
157
|
-
return this.getReadable(file).pipe(GZIP_ZOPFLI.createGzip(zopfli));
|
|
184
|
+
return this.getReadable(file, options).pipe(GZIP_ZOPFLI.createGzip(zopfli));
|
|
158
185
|
}
|
|
159
186
|
level = undefined;
|
|
160
187
|
}
|
|
@@ -172,7 +199,7 @@ class Compress extends module_1 {
|
|
|
172
199
|
else {
|
|
173
200
|
gzip.chunkSize ?? (gzip.chunkSize = this.chunkSize);
|
|
174
201
|
}
|
|
175
|
-
return this.getReadable(file).pipe(zlib.createGzip(gzip));
|
|
202
|
+
return this.getReadable(file, options).pipe(zlib.createGzip(gzip));
|
|
176
203
|
}
|
|
177
204
|
createBrotliCompress(file, options) {
|
|
178
205
|
let level, chunkSize, mimeType;
|
|
@@ -199,7 +226,7 @@ class Compress extends module_1 {
|
|
|
199
226
|
else {
|
|
200
227
|
brotli.chunkSize ?? (brotli.chunkSize = this.chunkSize);
|
|
201
228
|
}
|
|
202
|
-
return this.getReadable(file).pipe(zlib.createBrotliCompress(brotli));
|
|
229
|
+
return this.getReadable(file, options).pipe(zlib.createBrotliCompress(brotli));
|
|
203
230
|
}
|
|
204
231
|
createWriteStreamAsGzip(file, output, options) {
|
|
205
232
|
return this.createGzip(file, options).pipe(fs.createWriteStream(output));
|
|
@@ -226,21 +253,18 @@ class Compress extends module_1 {
|
|
|
226
253
|
options = output;
|
|
227
254
|
output = '';
|
|
228
255
|
}
|
|
229
|
-
else {
|
|
230
|
-
options || (options = {});
|
|
231
|
-
}
|
|
232
256
|
if (!(0, types_1.isString)(output)) {
|
|
233
257
|
output = typeof file === 'string' ? file : '';
|
|
234
258
|
}
|
|
259
|
+
options || (options = {});
|
|
235
260
|
const { filename, startTime = process.hrtime(), timeout = 0, sessionId, broadcastId } = options;
|
|
236
|
-
let format = options.format;
|
|
261
|
+
let format = options.format, hash = options.etag;
|
|
237
262
|
if (!format) {
|
|
238
263
|
return Promise.reject((0, types_1.errorValue)("Missing option \"format\"", output || filename));
|
|
239
264
|
}
|
|
240
|
-
let hash = options.etag;
|
|
241
265
|
const cache = this.settings.cache ? !!(hash && (hash = module_1.asHash(hash)) || Buffer.isBuffer(file) && (hash = module_1.asHash(file))) : false;
|
|
242
266
|
return new Promise((resolve, reject) => {
|
|
243
|
-
let timer = null, aborted;
|
|
267
|
+
let timer = null, startLength = 0, aborted;
|
|
244
268
|
const endProcess = (err, data = null, ext, result, fromCache) => {
|
|
245
269
|
if (timer) {
|
|
246
270
|
clearTimeout(timer);
|
|
@@ -250,7 +274,8 @@ class Compress extends module_1 {
|
|
|
250
274
|
return;
|
|
251
275
|
}
|
|
252
276
|
if (!fromCache) {
|
|
253
|
-
|
|
277
|
+
const status = (0, types_1.isString)(result) ? path.basename(result) : filename || "Completed";
|
|
278
|
+
this.writeTimeProcess(ext || format, status + getOutputSize(startLength, data), startTime, { type: 8, sessionId, broadcastId });
|
|
254
279
|
}
|
|
255
280
|
if (result) {
|
|
256
281
|
options.outFile = result;
|
|
@@ -304,7 +329,7 @@ class Compress extends module_1 {
|
|
|
304
329
|
};
|
|
305
330
|
const hasFont = () => {
|
|
306
331
|
let from, to;
|
|
307
|
-
if (cache && (CACHE_INIT[0] || setCacheData
|
|
332
|
+
if (cache && (CACHE_INIT[0] || setCacheData(this, 0)) && (from = CACHE_FONTFROM[hash]) && (to = CACHE_FONTTO[hash])) {
|
|
308
333
|
const cacheKey = from + `_${to}_` + hash;
|
|
309
334
|
const tempFont = CACHE_FONT[cacheKey];
|
|
310
335
|
if (tempFont) {
|
|
@@ -330,8 +355,11 @@ class Compress extends module_1 {
|
|
|
330
355
|
return false;
|
|
331
356
|
}
|
|
332
357
|
};
|
|
333
|
-
const errorResponse = (font) =>
|
|
358
|
+
const errorResponse = (font) => {
|
|
359
|
+
endProcess((0, types_1.errorValue)("Unsupported MIME", (font?.mime || "Unknown") + ': ' + (output || filename || "Unknown")));
|
|
360
|
+
};
|
|
334
361
|
const data = Buffer.isBuffer(file) ? file : fs.readFileSync(file);
|
|
362
|
+
startLength = Buffer.byteLength(data);
|
|
335
363
|
switch (format = format.toLowerCase()) {
|
|
336
364
|
case 'gz':
|
|
337
365
|
case 'br': {
|
|
@@ -342,7 +370,10 @@ class Compress extends module_1 {
|
|
|
342
370
|
}
|
|
343
371
|
else {
|
|
344
372
|
chunks = [];
|
|
345
|
-
transform = this[format === 'gz' ? 'createGzip' : 'createBrotliCompress'](data, options)
|
|
373
|
+
transform = this[format === 'gz' ? 'createGzip' : 'createBrotliCompress'](data, options);
|
|
374
|
+
transform.on('data', chunk => {
|
|
375
|
+
chunks.push(chunk);
|
|
376
|
+
});
|
|
346
377
|
}
|
|
347
378
|
transform
|
|
348
379
|
.on('finish', () => {
|
|
@@ -363,7 +394,7 @@ class Compress extends module_1 {
|
|
|
363
394
|
}
|
|
364
395
|
startProcess(false);
|
|
365
396
|
const checkResult = (result, from) => {
|
|
366
|
-
module_1.resolveMime(result).then(font => {
|
|
397
|
+
void module_1.resolveMime(result).then(font => {
|
|
367
398
|
switch (font?.mime) {
|
|
368
399
|
case "font/ttf":
|
|
369
400
|
case "font/otf":
|
|
@@ -375,7 +406,7 @@ class Compress extends module_1 {
|
|
|
375
406
|
}
|
|
376
407
|
});
|
|
377
408
|
};
|
|
378
|
-
module_1.resolveMime(data)
|
|
409
|
+
void module_1.resolveMime(data)
|
|
379
410
|
.then(font => {
|
|
380
411
|
switch (font?.mime) {
|
|
381
412
|
case "font/woff":
|
|
@@ -388,16 +419,16 @@ class Compress extends module_1 {
|
|
|
388
419
|
if (cache) {
|
|
389
420
|
CACHE_FONTFROM[hash] = 'woff2';
|
|
390
421
|
}
|
|
391
|
-
wawoff2.decompress(data).then(woff =>
|
|
422
|
+
void wawoff2.decompress(data).then(woff => {
|
|
423
|
+
checkResult(woff, 'woff2');
|
|
424
|
+
});
|
|
392
425
|
break;
|
|
393
426
|
default:
|
|
394
427
|
errorResponse(font);
|
|
395
428
|
break;
|
|
396
429
|
}
|
|
397
430
|
})
|
|
398
|
-
.catch(
|
|
399
|
-
endProcess(err);
|
|
400
|
-
});
|
|
431
|
+
.catch(endProcess);
|
|
401
432
|
break;
|
|
402
433
|
}
|
|
403
434
|
case 'woff':
|
|
@@ -406,7 +437,7 @@ class Compress extends module_1 {
|
|
|
406
437
|
return;
|
|
407
438
|
}
|
|
408
439
|
const checkResult = (result, mimeType, from) => {
|
|
409
|
-
module_1.resolveMime(result).then(font => {
|
|
440
|
+
void module_1.resolveMime(result).then(font => {
|
|
410
441
|
if (font?.mime === mimeType) {
|
|
411
442
|
writeFont(result, font.ext, from);
|
|
412
443
|
}
|
|
@@ -416,14 +447,16 @@ class Compress extends module_1 {
|
|
|
416
447
|
});
|
|
417
448
|
};
|
|
418
449
|
startProcess(true);
|
|
419
|
-
module_1.resolveMime(data)
|
|
450
|
+
void module_1.resolveMime(data)
|
|
420
451
|
.then(font => {
|
|
421
452
|
switch (font?.mime) {
|
|
422
453
|
case "font/ttf":
|
|
423
454
|
if (cache) {
|
|
424
455
|
CACHE_FONTFROM[hash] = 'ttf';
|
|
425
456
|
}
|
|
426
|
-
wawoff2.compress(data).then(result =>
|
|
457
|
+
void wawoff2.compress(data).then(result => {
|
|
458
|
+
checkResult(result, "font/woff2", 'ttf');
|
|
459
|
+
});
|
|
427
460
|
break;
|
|
428
461
|
case "font/otf":
|
|
429
462
|
if (cache) {
|
|
@@ -436,33 +469,29 @@ class Compress extends module_1 {
|
|
|
436
469
|
break;
|
|
437
470
|
}
|
|
438
471
|
})
|
|
439
|
-
.catch(
|
|
440
|
-
endProcess(err);
|
|
441
|
-
});
|
|
472
|
+
.catch(endProcess);
|
|
442
473
|
break;
|
|
443
474
|
}
|
|
444
475
|
default: {
|
|
445
476
|
const compressor = this.compressors[format]?.bind(this);
|
|
446
|
-
if (typeof compressor
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
compressor.call(this, file, output, options, endProcess);
|
|
462
|
-
}
|
|
477
|
+
if (typeof compressor !== 'function') {
|
|
478
|
+
throw (0, types_1.errorValue)("Missing compression plugin", format);
|
|
479
|
+
}
|
|
480
|
+
startProcess(true);
|
|
481
|
+
if (compressor.toString().startsWith('async')) {
|
|
482
|
+
compressor.call(this, file, output, options)
|
|
483
|
+
.then(result => {
|
|
484
|
+
if (typeof result === 'string') {
|
|
485
|
+
endProcess(null, null, format, result);
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
endProcess(null, result, format);
|
|
489
|
+
}
|
|
490
|
+
})
|
|
491
|
+
.catch(endProcess);
|
|
463
492
|
}
|
|
464
493
|
else {
|
|
465
|
-
|
|
494
|
+
void compressor.call(this, file, output, options, endProcess);
|
|
466
495
|
}
|
|
467
496
|
break;
|
|
468
497
|
}
|
|
@@ -481,14 +510,42 @@ class Compress extends module_1 {
|
|
|
481
510
|
else {
|
|
482
511
|
options || (options = {});
|
|
483
512
|
}
|
|
484
|
-
const {
|
|
513
|
+
const { filename, startTime = process.hrtime(), timeout = 0, sessionId, broadcastId } = options;
|
|
514
|
+
let plugin = options.plugin;
|
|
515
|
+
if ((0, types_1.isString)(plugin)) {
|
|
516
|
+
if (types_1.IMPORT_MAP[plugin]) {
|
|
517
|
+
plugin = types_1.IMPORT_MAP[plugin];
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
else {
|
|
521
|
+
return Promise.reject();
|
|
522
|
+
}
|
|
485
523
|
if (!(0, types_1.isString)(output)) {
|
|
486
524
|
output = typeof file === 'string' ? file : '';
|
|
487
525
|
}
|
|
488
526
|
const ext = output ? path.extname(output).substring(1) : options.format || "Unknown";
|
|
489
|
-
const
|
|
490
|
-
|
|
491
|
-
|
|
527
|
+
const getFormat = () => output ? path.basename(output) : ext;
|
|
528
|
+
let data;
|
|
529
|
+
if (Buffer.isBuffer(file)) {
|
|
530
|
+
data = file;
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
try {
|
|
534
|
+
data = fs.readFileSync(file);
|
|
535
|
+
}
|
|
536
|
+
catch (err) {
|
|
537
|
+
return Promise.reject(err);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
if (!options.mimeType) {
|
|
541
|
+
const out = await module_1.resolveMime(data);
|
|
542
|
+
if (out) {
|
|
543
|
+
options.mimeType = out.mime;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
const startLength = Buffer.byteLength(data);
|
|
547
|
+
return new Promise(async (resolve, reject) => {
|
|
548
|
+
let timer = null, hash, cacheKey, aborted;
|
|
492
549
|
const failed = (err) => {
|
|
493
550
|
aborted = true;
|
|
494
551
|
if (timer) {
|
|
@@ -496,6 +553,32 @@ class Compress extends module_1 {
|
|
|
496
553
|
}
|
|
497
554
|
reject(err);
|
|
498
555
|
};
|
|
556
|
+
const complete = (err, result, ctime) => {
|
|
557
|
+
if (err) {
|
|
558
|
+
reject(err);
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
const value = output ? path.basename(output) : filename || (0, types_1.isString)(file) && path.basename(file);
|
|
562
|
+
const status = value ? plugin + ': ' + value : "Completed";
|
|
563
|
+
if (ctime) {
|
|
564
|
+
this.formatMessage(8, value ? path.extname(value).substring(1) : '', [status, 'cache'], ctime.toLocaleString(), { ...module_1.LOG_STYLE_NOTICE, hintBold: true, sessionId, broadcastId });
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
this.writeTimeProcess(ext, status + getOutputSize(startLength, result), startTime, { type: 8, sessionId, broadcastId });
|
|
568
|
+
}
|
|
569
|
+
if (!ctime && hash && cacheKey && TEMP_DIR) {
|
|
570
|
+
const pathname = path.join(TEMP_DIR, sanitizePath(plugin), hash);
|
|
571
|
+
if (module_1.createDir(pathname)) {
|
|
572
|
+
fs.writeFile(path.join(pathname, cacheKey), result, error => {
|
|
573
|
+
var _b, _c;
|
|
574
|
+
if (!error) {
|
|
575
|
+
((_b = (CACHE_IMAGE[plugin] || (CACHE_IMAGE[plugin] = {})))[_c = hash] || (_b[_c] = {}))[cacheKey] = new Date();
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
resolve(result);
|
|
581
|
+
};
|
|
499
582
|
const success = (result, ctime) => {
|
|
500
583
|
if (aborted) {
|
|
501
584
|
return;
|
|
@@ -503,137 +586,73 @@ class Compress extends module_1 {
|
|
|
503
586
|
if (timer) {
|
|
504
587
|
clearTimeout(timer);
|
|
505
588
|
}
|
|
506
|
-
const complete = (err) => {
|
|
507
|
-
if (err) {
|
|
508
|
-
reject(err);
|
|
509
|
-
return;
|
|
510
|
-
}
|
|
511
|
-
const value = output ? path.basename(output) : filename || (0, types_1.isString)(file) && path.basename(file);
|
|
512
|
-
const status = value ? plugin + ' -> ' + value : "Completed";
|
|
513
|
-
if (ctime) {
|
|
514
|
-
this.formatMessage(8, value ? path.extname(value).substring(1) : '', [status, 'cache'], ctime.toLocaleString(), { ...module_1.LOG_STYLE_NOTICE, hintBold: true, sessionId, broadcastId });
|
|
515
|
-
}
|
|
516
|
-
else {
|
|
517
|
-
this.writeTimeProcess(ext, status, startTime, { type: 8, sessionId, broadcastId });
|
|
518
|
-
}
|
|
519
|
-
if (!ctime && hash && cacheKey && TEMP_DIR) {
|
|
520
|
-
const pathname = path.join(TEMP_DIR, plugin, hash);
|
|
521
|
-
if (module_1.createDir(pathname)) {
|
|
522
|
-
fs.writeFile(path.join(pathname, cacheKey), result, error => {
|
|
523
|
-
var _a, _b;
|
|
524
|
-
if (!error) {
|
|
525
|
-
((_a = (CACHE_IMAGE[plugin] || (CACHE_IMAGE[plugin] = {})))[_b = hash] || (_a[_b] = {}))[cacheKey] = new Date();
|
|
526
|
-
}
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
resolve(result);
|
|
531
|
-
};
|
|
532
589
|
if (output) {
|
|
533
|
-
fs.writeFile(output, result, err =>
|
|
590
|
+
fs.writeFile(output, result, err => {
|
|
591
|
+
complete(err, result, ctime);
|
|
592
|
+
});
|
|
534
593
|
}
|
|
535
594
|
else {
|
|
536
|
-
complete(null);
|
|
595
|
+
complete(null, result, ctime);
|
|
537
596
|
}
|
|
538
597
|
};
|
|
539
|
-
|
|
540
|
-
if (plugin === "tinify") {
|
|
541
|
-
switch (format) {
|
|
542
|
-
case 'png':
|
|
543
|
-
case 'jpg':
|
|
544
|
-
case 'jpeg':
|
|
545
|
-
case 'webp':
|
|
546
|
-
apiKey = options.options?.apiKey || (module_1.enabled("process.env.apply") ? process.env.TINIFY_KEY : '');
|
|
547
|
-
break;
|
|
548
|
-
default:
|
|
549
|
-
failed((0, types_1.errorMessage)(plugin, "Unsupported MIME", format));
|
|
550
|
-
return;
|
|
551
|
-
}
|
|
552
|
-
if (!apiKey) {
|
|
553
|
-
failed((0, types_1.errorMessage)(plugin, 'Missing API key'));
|
|
554
|
-
return;
|
|
555
|
-
}
|
|
556
|
-
switch (module_1.lookupMime(ext)) {
|
|
557
|
-
case "image/jpeg":
|
|
558
|
-
case "image/png":
|
|
559
|
-
case "image/webp":
|
|
560
|
-
break;
|
|
561
|
-
default:
|
|
562
|
-
failed((0, types_1.errorMessage)(plugin, "Unsupported MIME", getFormat()));
|
|
563
|
-
return;
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
let data;
|
|
567
|
-
try {
|
|
568
|
-
data = Buffer.isBuffer(file) ? file : fs.readFileSync(file);
|
|
569
|
-
}
|
|
570
|
-
catch (err) {
|
|
571
|
-
failed(err);
|
|
572
|
-
return;
|
|
573
|
-
}
|
|
574
|
-
if (this.settings.cache && setCacheData.call(this, 1)) {
|
|
598
|
+
if (this.settings.cache && setCacheData(this, 1)) {
|
|
575
599
|
let stored;
|
|
576
600
|
try {
|
|
577
|
-
|
|
578
|
-
|
|
601
|
+
hash = module_1.asHash(data);
|
|
602
|
+
stored = (CACHE_IMAGE[plugin] || (CACHE_IMAGE[plugin] = {}))[hash];
|
|
603
|
+
cacheKey = plugin + ((0, types_1.isPlainObject)(options.options) ? ':' + module_1.asHash(module_1.asString(options.options), 'md5') : '');
|
|
579
604
|
const ctime = stored?.[cacheKey];
|
|
580
605
|
if (ctime) {
|
|
581
|
-
success(fs.readFileSync(path.join(TEMP_DIR, plugin, hash, cacheKey)), ctime);
|
|
606
|
+
success(fs.readFileSync(path.join(TEMP_DIR, sanitizePath(plugin), hash, cacheKey)), ctime);
|
|
582
607
|
return;
|
|
583
608
|
}
|
|
584
609
|
}
|
|
585
610
|
catch {
|
|
611
|
+
hash = undefined;
|
|
586
612
|
if (stored && cacheKey) {
|
|
587
613
|
delete stored[cacheKey];
|
|
588
614
|
}
|
|
589
615
|
}
|
|
590
616
|
}
|
|
591
617
|
this.formatMessage(8, ext, ['Compressing image...', plugin], filename || output, { titleColor: 'magenta', sessionId, broadcastId });
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
618
|
+
try {
|
|
619
|
+
let transform;
|
|
620
|
+
try {
|
|
621
|
+
transform = require(plugin);
|
|
622
|
+
}
|
|
623
|
+
catch {
|
|
624
|
+
transform = await (0, types_1.importESM)(plugin, true);
|
|
625
|
+
}
|
|
626
|
+
const out = transform.call(this, options.options, options.mimeType);
|
|
627
|
+
if (timeout > 0) {
|
|
628
|
+
timer = setTimeout(() => {
|
|
629
|
+
failed((0, types_1.errorMessage)(plugin, "Timeout was exceeded"));
|
|
630
|
+
}, timeout);
|
|
631
|
+
}
|
|
632
|
+
void out(data).then(result => {
|
|
633
|
+
if (result !== data) {
|
|
634
|
+
success(result);
|
|
609
635
|
}
|
|
610
636
|
else {
|
|
611
|
-
failed(
|
|
637
|
+
failed((0, types_1.errorMessage)(plugin, "Unsupported MIME", getFormat()));
|
|
612
638
|
}
|
|
613
639
|
});
|
|
614
640
|
}
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
const transform = require(plugin);
|
|
618
|
-
transform(options.options)(data).then(result => {
|
|
619
|
-
if (result !== data) {
|
|
620
|
-
success(result);
|
|
621
|
-
}
|
|
622
|
-
else {
|
|
623
|
-
failed((0, types_1.errorMessage)(plugin, "Unsupported MIME", getFormat()));
|
|
624
|
-
}
|
|
625
|
-
});
|
|
626
|
-
}
|
|
627
|
-
catch (err) {
|
|
628
|
-
failed(err);
|
|
629
|
-
}
|
|
641
|
+
catch (err) {
|
|
642
|
+
failed(err);
|
|
630
643
|
}
|
|
631
644
|
});
|
|
632
645
|
}
|
|
646
|
+
set chunkSize(value) {
|
|
647
|
+
this[kChunkSize] = !isNaN(value = (0, types_1.alignSize)(value, 1)) ? value : NaN;
|
|
648
|
+
}
|
|
649
|
+
get chunkSize() {
|
|
650
|
+
return this[kChunkSize];
|
|
651
|
+
}
|
|
633
652
|
get settings() {
|
|
634
|
-
var
|
|
635
|
-
return (
|
|
653
|
+
var _b;
|
|
654
|
+
return (_b = this.module).settings || (_b.settings = {});
|
|
636
655
|
}
|
|
637
656
|
}
|
|
638
|
-
|
|
657
|
+
_a = kChunkSize;
|
|
639
658
|
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.10.1",
|
|
4
4
|
"description": "Compress constructor for E-mc.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -23,9 +23,8 @@
|
|
|
23
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.
|
|
28
|
-
"tinify": "^1.7.1",
|
|
26
|
+
"@e-mc/module": "0.10.1",
|
|
27
|
+
"@e-mc/types": "0.10.1",
|
|
29
28
|
"wawoff2": "^2.0.1",
|
|
30
29
|
"woff2sfnt-sfnt2woff": "^1.0.0"
|
|
31
30
|
}
|