@e-mc/compress 0.12.8 → 0.13.0
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 +11 -8
- package/index.js +170 -103
- package/package.json +3 -3
- package/worker/plugin-image.js +1 -5
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @e-mc/compress
|
|
2
2
|
|
|
3
|
-
* NodeJS 18
|
|
3
|
+
* NodeJS 18.20.5 LTS
|
|
4
4
|
* ES2022
|
|
5
5
|
|
|
6
6
|
## General Usage
|
|
@@ -9,7 +9,7 @@
|
|
|
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.13.0/lib/index.d.ts)
|
|
13
13
|
|
|
14
14
|
```typescript
|
|
15
15
|
import type { IModule, ModuleConstructor } from "./index";
|
|
@@ -32,7 +32,7 @@ interface ICompress extends IModule {
|
|
|
32
32
|
createGzip(file: string | Buffer, options?: CompressLevel): Gzip;
|
|
33
33
|
createBrotliCompress(file: string | Buffer, options?: BrotliCompressLevel): BrotliCompress;
|
|
34
34
|
createWriteStreamAsGzip(file: string | Buffer, output: string, options?: CompressLevel): WriteStream;
|
|
35
|
-
createWriteStreamAsBrotli(file: string | Buffer, output: string, options?:
|
|
35
|
+
createWriteStreamAsBrotli(file: string | Buffer, output: string, options?: BrotliCompressLevel): WriteStream;
|
|
36
36
|
intoGzipStream(output: string, options?: ZlibOptions): WriteStream;
|
|
37
37
|
intoBrotliStream(output: string, options?: BrotliOptions): WriteStream;
|
|
38
38
|
writeGzip(file: string | Buffer, output: string, options?: CompressLevel): Promise<void>;
|
|
@@ -58,7 +58,9 @@ interface CompressConstructor extends ModuleConstructor {
|
|
|
58
58
|
## Settings
|
|
59
59
|
|
|
60
60
|
```typescript
|
|
61
|
-
import type {
|
|
61
|
+
import type { CacheDirAction } from "./settings";
|
|
62
|
+
|
|
63
|
+
import type { BrotliOptions, ZlibOptions } from "node:zlib";
|
|
62
64
|
import type { Options as ZopfliOptions } from "node-zopfli";
|
|
63
65
|
|
|
64
66
|
interface CompressModule {
|
|
@@ -67,7 +69,8 @@ interface CompressModule {
|
|
|
67
69
|
zopfli?: ZopfliOptions;
|
|
68
70
|
settings?: {
|
|
69
71
|
broadcast_id?: string | string[];
|
|
70
|
-
cache?: boolean;
|
|
72
|
+
cache?: boolean | CacheDirAction & { font?: string | number | boolean; image?: string | number | boolean; };
|
|
73
|
+
/** @deprecated cache.expires */
|
|
71
74
|
cache_expires?: number | string;
|
|
72
75
|
gzip_level?: number;
|
|
73
76
|
brotli_quality?: number;
|
|
@@ -120,9 +123,9 @@ instance.tryImage("/tmp/image.png", "/path/output/compressed.png", options)
|
|
|
120
123
|
|
|
121
124
|
## References
|
|
122
125
|
|
|
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.
|
|
126
|
+
- https://www.unpkg.com/@e-mc/types@0.13.0/lib/squared.d.ts
|
|
127
|
+
- https://www.unpkg.com/@e-mc/types@0.13.0/lib/compress.d.ts
|
|
128
|
+
- https://www.unpkg.com/@e-mc/types@0.13.0/lib/settings.d.ts
|
|
126
129
|
|
|
127
130
|
* https://www.npmjs.com/package/@types/node
|
|
128
131
|
|
package/index.js
CHANGED
|
@@ -12,13 +12,15 @@ function createWorker(filename) {
|
|
|
12
12
|
return core_1.WorkerChannel.create(path.join(__dirname, 'worker', filename), 'EMC_COMPRESS');
|
|
13
13
|
}
|
|
14
14
|
const SUPPORTED_NODE21 = (0, types_1.supported)(21);
|
|
15
|
-
const CACHE_IMAGE =
|
|
15
|
+
const CACHE_IMAGE = Object.create(null);
|
|
16
16
|
const CACHE_FONT = Object.create(null);
|
|
17
|
-
const CACHE_FONTFROM =
|
|
18
|
-
const CACHE_FONTTO =
|
|
19
|
-
const
|
|
17
|
+
const CACHE_FONTFROM = Object.create(null);
|
|
18
|
+
const CACHE_FONTTO = Object.create(null);
|
|
19
|
+
const CACHE_TEMP = {
|
|
20
|
+
font: undefined,
|
|
21
|
+
image: undefined
|
|
22
|
+
};
|
|
20
23
|
let SINGLETON_INSTANCE;
|
|
21
|
-
let TEMP_DIR = '';
|
|
22
24
|
const WORKER = new core_1.WorkerGroup(parseInt(process.env.EMC_COMPRESS_WORKER_GROUP_MAX || '0'));
|
|
23
25
|
WORKER
|
|
24
26
|
.add('otf', createWorker('sfnt2woff.js'))
|
|
@@ -28,61 +30,6 @@ WORKER
|
|
|
28
30
|
.add('image', createWorker('plugin-image.js'))
|
|
29
31
|
.add('gz', createWorker('system-gzip.js'))
|
|
30
32
|
.add('br', createWorker('system-brotli.js'));
|
|
31
|
-
function setCacheData(instance, index) {
|
|
32
|
-
if (CACHE_INIT[index]) {
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
TEMP_DIR ||= instance.getTempDir({ moduleDir: true, createDir: true, increment: 5 });
|
|
36
|
-
const settings = instance.settings;
|
|
37
|
-
const expires = (0, types_1.parseExpires)(settings.cache_expires || 0);
|
|
38
|
-
if (TEMP_DIR) {
|
|
39
|
-
if (expires === 0) {
|
|
40
|
-
if (CACHE_INIT.every(value => !value)) {
|
|
41
|
-
core_1.Module.removeDir(TEMP_DIR, true);
|
|
42
|
-
}
|
|
43
|
-
settings.cache_expires = 0;
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
const current = Date.now();
|
|
47
|
-
(function recurse(paths) {
|
|
48
|
-
const srcDir = path.join(TEMP_DIR, ...paths);
|
|
49
|
-
try {
|
|
50
|
-
fs.readdirSync(srcDir, { withFileTypes: true }).forEach(item => {
|
|
51
|
-
const filename = item.name;
|
|
52
|
-
if (item.isFile()) {
|
|
53
|
-
const pathname = path.join(srcDir, filename);
|
|
54
|
-
if (paths.length === 2) {
|
|
55
|
-
try {
|
|
56
|
-
const stat = fs.lstatSync(pathname);
|
|
57
|
-
if (stat.atimeMs + expires > current) {
|
|
58
|
-
if (index === 0) {
|
|
59
|
-
CACHE_FONT[paths.concat(filename).join('_')] = [pathname, stat.ctime];
|
|
60
|
-
CACHE_FONTFROM[filename] = paths[0];
|
|
61
|
-
CACHE_FONTTO[filename] = paths[1];
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
((CACHE_IMAGE[paths[0]] ||= {})[paths[1]] ||= {})[filename] = stat.ctime;
|
|
65
|
-
}
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
catch {
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
fs.unlink(pathname, () => { });
|
|
73
|
-
}
|
|
74
|
-
else if (item.isDirectory()) {
|
|
75
|
-
recurse(paths.concat(filename));
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
catch {
|
|
80
|
-
}
|
|
81
|
-
})([]);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return CACHE_INIT[index] = true;
|
|
85
|
-
}
|
|
86
33
|
function getOutputSize(startLength, data, worker) {
|
|
87
34
|
if (startLength === 0 || !data) {
|
|
88
35
|
return worker ? ' (worker)' : '';
|
|
@@ -90,9 +37,28 @@ function getOutputSize(startLength, data, worker) {
|
|
|
90
37
|
const offset = Buffer.byteLength(data) - startLength;
|
|
91
38
|
return ` (${(worker ? 'worker: ' : '') + (offset > 0 ? '+' : '') + (0, types_1.formatSize)(offset)})`;
|
|
92
39
|
}
|
|
40
|
+
function applyBrotliMode(params, value) {
|
|
41
|
+
if (value) {
|
|
42
|
+
if (/\b(?:text\/|javascript|css|json5?|(?:ht|x|ya|to)ml)\b/.test(value)) {
|
|
43
|
+
params[zlib.constants.BROTLI_PARAM_MODE] = zlib.constants.BROTLI_MODE_TEXT;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (value.includes('font/')) {
|
|
47
|
+
params[zlib.constants.BROTLI_PARAM_MODE] = zlib.constants.BROTLI_MODE_FONT;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
params[zlib.constants.BROTLI_PARAM_MODE] ??= zlib.constants.BROTLI_MODE_GENERIC;
|
|
52
|
+
}
|
|
53
|
+
function applyZlibOptions(base, options, ...params) {
|
|
54
|
+
for (const attr of ['flush', 'finishFlush', 'maxOutputLength', 'info'].concat(params)) {
|
|
55
|
+
if (attr in options) {
|
|
56
|
+
base[attr] = options[attr];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
93
60
|
const sanitizePath = (value) => value.replace(/[\\/]/g, '_');
|
|
94
61
|
const getWorkerTimeout = (options, value) => core_1.WorkerGroup.checkTimeout(typeof options.worker === 'number' && options.worker > 0 ? options.worker : value, true);
|
|
95
|
-
const applyBrotliMode = (params, value) => params[zlib.constants.BROTLI_PARAM_MODE] = value.includes('text/') ? zlib.constants.BROTLI_MODE_TEXT : value.includes('font/') ? zlib.constants.BROTLI_MODE_FONT : zlib.constants.BROTLI_MODE_GENERIC;
|
|
96
62
|
class Compress extends core_1.Module {
|
|
97
63
|
module;
|
|
98
64
|
static [kCompress] = true;
|
|
@@ -171,7 +137,7 @@ class Compress extends core_1.Module {
|
|
|
171
137
|
throw (0, types_1.errorValue)("Operation not permitted", file.toString());
|
|
172
138
|
}
|
|
173
139
|
catch (err) {
|
|
174
|
-
if (!options || options.throwsPermission &&
|
|
140
|
+
if (!options || options.throwsPermission && (0, types_1.isErrorCode)(err, 'EACCES') || options.throwsDoesNotExist && (0, types_1.isErrorCode)(err, 'ENOENT')) {
|
|
175
141
|
throw err;
|
|
176
142
|
}
|
|
177
143
|
}
|
|
@@ -198,8 +164,7 @@ class Compress extends core_1.Module {
|
|
|
198
164
|
}
|
|
199
165
|
level = undefined;
|
|
200
166
|
}
|
|
201
|
-
|
|
202
|
-
gzip = (0, types_1.isPlainObject)(gzip) ? { ...gzip } : {};
|
|
167
|
+
const gzip = { ...this.module.gzip };
|
|
203
168
|
if (typeof level === 'number') {
|
|
204
169
|
gzip.level = level;
|
|
205
170
|
}
|
|
@@ -212,33 +177,51 @@ class Compress extends core_1.Module {
|
|
|
212
177
|
else {
|
|
213
178
|
gzip.chunkSize ??= this.chunkSize;
|
|
214
179
|
}
|
|
180
|
+
if (options) {
|
|
181
|
+
applyZlibOptions(gzip, options, 'memLevel', 'strategy', 'windowBits');
|
|
182
|
+
}
|
|
215
183
|
return this.getReadable(file, options).pipe(zlib.createGzip(gzip));
|
|
216
184
|
}
|
|
217
185
|
createBrotliCompress(file, options) {
|
|
218
|
-
let level, chunkSize, mimeType;
|
|
186
|
+
let level, chunkSize, params, mimeType;
|
|
219
187
|
if (options) {
|
|
220
|
-
({ level, chunkSize, mimeType } = options);
|
|
188
|
+
({ level, chunkSize, params, mimeType } = options);
|
|
221
189
|
}
|
|
222
|
-
|
|
190
|
+
params ||= {};
|
|
223
191
|
let brotli = this.module.brotli;
|
|
224
192
|
if ((0, types_1.isPlainObject)(brotli)) {
|
|
225
|
-
|
|
193
|
+
if ((0, types_1.isPlainObject)(brotli.params)) {
|
|
194
|
+
brotli = (0, types_1.cloneObject)(brotli, true);
|
|
195
|
+
params = Object.assign(brotli.params, params);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
brotli = { ...brotli, params };
|
|
199
|
+
}
|
|
226
200
|
}
|
|
227
201
|
else {
|
|
228
202
|
brotli = { params };
|
|
229
203
|
}
|
|
230
|
-
applyBrotliMode(params, mimeType
|
|
204
|
+
applyBrotliMode(params, mimeType);
|
|
231
205
|
try {
|
|
232
206
|
params[zlib.constants.BROTLI_PARAM_SIZE_HINT] = typeof file === 'string' ? fs.statSync(file).size : Buffer.byteLength(file);
|
|
233
207
|
}
|
|
234
208
|
catch {
|
|
235
209
|
}
|
|
210
|
+
if (typeof level === 'number') {
|
|
211
|
+
brotli.params[zlib.constants.BROTLI_PARAM_QUALITY] = level;
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
brotli.params[zlib.constants.BROTLI_PARAM_QUALITY] ??= this.level.br;
|
|
215
|
+
}
|
|
236
216
|
if (!isNaN(chunkSize = (0, types_1.alignSize)(chunkSize, 1))) {
|
|
237
217
|
brotli.chunkSize = chunkSize;
|
|
238
218
|
}
|
|
239
219
|
else {
|
|
240
220
|
brotli.chunkSize ??= this.chunkSize;
|
|
241
221
|
}
|
|
222
|
+
if (options) {
|
|
223
|
+
applyZlibOptions(brotli, options);
|
|
224
|
+
}
|
|
242
225
|
return this.getReadable(file, options).pipe(zlib.createBrotliCompress(brotli));
|
|
243
226
|
}
|
|
244
227
|
createWriteStreamAsGzip(file, output, options) {
|
|
@@ -284,10 +267,9 @@ class Compress extends core_1.Module {
|
|
|
284
267
|
if (!(0, types_1.isString)(format)) {
|
|
285
268
|
return Promise.reject((0, types_1.errorValue)("Missing option \"format\"", output || filename));
|
|
286
269
|
}
|
|
287
|
-
const cache = this.settings.cache ? !!(hash && (hash = core_1.Module.asHash(hash)) || Buffer.isBuffer(file) && (hash = core_1.Module.asHash(file))) : false;
|
|
288
270
|
format = format.toLowerCase();
|
|
289
271
|
return new Promise((resolve, reject) => {
|
|
290
|
-
let timer = null, worker = null, startLength = 0, closed = false;
|
|
272
|
+
let timer = null, worker = null, tempDir = null, startLength = 0, closed = false;
|
|
291
273
|
const endProcess = (err, data = null, ext, result, fromCache) => {
|
|
292
274
|
if (closed) {
|
|
293
275
|
return;
|
|
@@ -300,6 +282,19 @@ class Compress extends core_1.Module {
|
|
|
300
282
|
reject(err);
|
|
301
283
|
return;
|
|
302
284
|
}
|
|
285
|
+
if (typeof ext === 'boolean') {
|
|
286
|
+
fromCache = ext;
|
|
287
|
+
ext = null;
|
|
288
|
+
result = null;
|
|
289
|
+
}
|
|
290
|
+
else if (typeof result === 'boolean') {
|
|
291
|
+
fromCache = result;
|
|
292
|
+
result = null;
|
|
293
|
+
}
|
|
294
|
+
if ((0, types_1.isString)(data)) {
|
|
295
|
+
result = data;
|
|
296
|
+
data = null;
|
|
297
|
+
}
|
|
303
298
|
if (!fromCache) {
|
|
304
299
|
const status = (0, types_1.isString)(result) ? path.basename(result) : filename || "Completed";
|
|
305
300
|
this.writeTimeProcess(ext || format, status + getOutputSize(startLength, data, !!worker), startTime, { type: 8, sessionId: options.sessionId, broadcastId: options.broadcastId });
|
|
@@ -342,10 +337,10 @@ class Compress extends core_1.Module {
|
|
|
342
337
|
else {
|
|
343
338
|
endProcess(null, data, ext);
|
|
344
339
|
}
|
|
345
|
-
if (
|
|
340
|
+
if (tempDir) {
|
|
346
341
|
const pathname = path.join(from, ext);
|
|
347
342
|
let tempFont;
|
|
348
|
-
if (
|
|
343
|
+
if (core_1.Module.createDir(tempFont = path.join(tempDir, pathname))) {
|
|
349
344
|
tempFont = path.join(tempFont, hash);
|
|
350
345
|
}
|
|
351
346
|
else {
|
|
@@ -360,8 +355,23 @@ class Compress extends core_1.Module {
|
|
|
360
355
|
}
|
|
361
356
|
};
|
|
362
357
|
const hasFont = () => {
|
|
363
|
-
|
|
364
|
-
if (
|
|
358
|
+
tempDir = this.#getCacheDir('font');
|
|
359
|
+
if (!tempDir) {
|
|
360
|
+
hash = undefined;
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
363
|
+
if (hash) {
|
|
364
|
+
hash = core_1.Module.asHash(hash);
|
|
365
|
+
}
|
|
366
|
+
else if (Buffer.isBuffer(file)) {
|
|
367
|
+
hash = core_1.Module.asHash(file);
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
const from = CACHE_FONTFROM[hash];
|
|
373
|
+
const to = CACHE_FONTTO[hash];
|
|
374
|
+
if (from && to) {
|
|
365
375
|
const cacheKey = from + `_${to}_` + hash;
|
|
366
376
|
const tempFont = CACHE_FONT[cacheKey];
|
|
367
377
|
if (tempFont) {
|
|
@@ -374,7 +384,7 @@ class Compress extends core_1.Module {
|
|
|
374
384
|
endProcess(null, data, to, pathname, true);
|
|
375
385
|
}
|
|
376
386
|
else {
|
|
377
|
-
endProcess(null, data, to,
|
|
387
|
+
endProcess(null, data, to, true);
|
|
378
388
|
}
|
|
379
389
|
this.formatMessage(8, from, [pathname ? path.basename(pathname) : "Completed" + ` -> font/${to}`, 'cache'], tempFont[1].toLocaleString(), { ...core_1.Module.LOG_STYLE_NOTICE, hintBold: true, sessionId: options.sessionId, broadcastId: options.broadcastId });
|
|
380
390
|
return true;
|
|
@@ -413,13 +423,10 @@ class Compress extends core_1.Module {
|
|
|
413
423
|
}
|
|
414
424
|
else {
|
|
415
425
|
workerOptions.params = { [zlib.constants.BROTLI_PARAM_QUALITY]: options.level ?? this.level.br };
|
|
416
|
-
applyBrotliMode(workerOptions.params, options.mimeType
|
|
426
|
+
applyBrotliMode(workerOptions.params, options.mimeType);
|
|
417
427
|
}
|
|
418
428
|
const endWorker = (result) => {
|
|
419
|
-
if (
|
|
420
|
-
endProcess(null, null, format, result);
|
|
421
|
-
}
|
|
422
|
-
else if (result) {
|
|
429
|
+
if (result) {
|
|
423
430
|
endProcess(null, result, format);
|
|
424
431
|
}
|
|
425
432
|
else {
|
|
@@ -445,7 +452,7 @@ class Compress extends core_1.Module {
|
|
|
445
452
|
}
|
|
446
453
|
transform
|
|
447
454
|
.on('finish', () => {
|
|
448
|
-
endProcess(null, chunks
|
|
455
|
+
endProcess(null, chunks ? Buffer.concat(chunks) : output, format);
|
|
449
456
|
})
|
|
450
457
|
.on('error', (err) => {
|
|
451
458
|
transform.destroy();
|
|
@@ -480,7 +487,7 @@ class Compress extends core_1.Module {
|
|
|
480
487
|
.then(font => {
|
|
481
488
|
switch (font?.mime) {
|
|
482
489
|
case "font/woff":
|
|
483
|
-
if (
|
|
490
|
+
if (hash) {
|
|
484
491
|
CACHE_FONTFROM[hash] = 'woff';
|
|
485
492
|
}
|
|
486
493
|
if (this.hasPermission('worker', options) && (worker = WORKER.get('woff').sendBuffer(data, true, checkResult, 'woff'))) {
|
|
@@ -492,7 +499,7 @@ class Compress extends core_1.Module {
|
|
|
492
499
|
}
|
|
493
500
|
break;
|
|
494
501
|
case "font/woff2":
|
|
495
|
-
if (
|
|
502
|
+
if (hash) {
|
|
496
503
|
CACHE_FONTFROM[hash] = 'woff2';
|
|
497
504
|
}
|
|
498
505
|
if (this.hasPermission('worker', options) && (worker = WORKER.get('woff2').sendBuffer(data, shared, checkResult, 'woff2'))) {
|
|
@@ -500,9 +507,7 @@ class Compress extends core_1.Module {
|
|
|
500
507
|
}
|
|
501
508
|
else {
|
|
502
509
|
startProcess(false);
|
|
503
|
-
void wawoff2.decompress(data).then(woff =>
|
|
504
|
-
checkResult(woff, 'woff2');
|
|
505
|
-
});
|
|
510
|
+
void wawoff2.decompress(data).then(woff => checkResult(woff, 'woff2'));
|
|
506
511
|
}
|
|
507
512
|
break;
|
|
508
513
|
default:
|
|
@@ -538,7 +543,7 @@ class Compress extends core_1.Module {
|
|
|
538
543
|
.then(font => {
|
|
539
544
|
switch (font?.mime) {
|
|
540
545
|
case "font/ttf":
|
|
541
|
-
if (
|
|
546
|
+
if (hash) {
|
|
542
547
|
CACHE_FONTFROM[hash] = 'ttf';
|
|
543
548
|
}
|
|
544
549
|
if (this.hasPermission('worker', options) && (worker = WORKER.get('ttf').sendBuffer(data, shared, checkResult, 'ttf', "font/woff2"))) {
|
|
@@ -546,13 +551,11 @@ class Compress extends core_1.Module {
|
|
|
546
551
|
}
|
|
547
552
|
else {
|
|
548
553
|
startProcess(false);
|
|
549
|
-
void wawoff2.compress(data).then(result =>
|
|
550
|
-
checkResult(result, 'ttf', "font/woff2");
|
|
551
|
-
});
|
|
554
|
+
void wawoff2.compress(data).then(result => checkResult(result, 'ttf', "font/woff2"));
|
|
552
555
|
}
|
|
553
556
|
break;
|
|
554
557
|
case "font/otf":
|
|
555
|
-
if (
|
|
558
|
+
if (hash) {
|
|
556
559
|
CACHE_FONTFROM[hash] = 'otf';
|
|
557
560
|
}
|
|
558
561
|
if (this.hasPermission('worker', options) && (worker = WORKER.get('otf').sendBuffer(data, shared, checkResult, 'otf', "font/woff"))) {
|
|
@@ -580,12 +583,7 @@ class Compress extends core_1.Module {
|
|
|
580
583
|
if (compressor.toString().startsWith('async')) {
|
|
581
584
|
compressor.call(this, data, output, options)
|
|
582
585
|
.then(result => {
|
|
583
|
-
|
|
584
|
-
endProcess(null, null, format, result);
|
|
585
|
-
}
|
|
586
|
-
else {
|
|
587
|
-
endProcess(null, result, format);
|
|
588
|
-
}
|
|
586
|
+
endProcess(null, result, format);
|
|
589
587
|
})
|
|
590
588
|
.catch(endProcess);
|
|
591
589
|
}
|
|
@@ -651,7 +649,7 @@ class Compress extends core_1.Module {
|
|
|
651
649
|
}
|
|
652
650
|
const startLength = Buffer.byteLength(data);
|
|
653
651
|
return new Promise(async (resolve, reject) => {
|
|
654
|
-
let timer = null, hash, cacheKey, closed = false;
|
|
652
|
+
let timer = null, tempDir = null, hash, cacheKey, closed = false;
|
|
655
653
|
const failed = (err) => {
|
|
656
654
|
if (timer) {
|
|
657
655
|
clearTimeout(timer);
|
|
@@ -672,8 +670,8 @@ class Compress extends core_1.Module {
|
|
|
672
670
|
else {
|
|
673
671
|
this.writeTimeProcess(ext, status + getOutputSize(startLength, result, worker), startTime, { type: 8, sessionId: options.sessionId, broadcastId: options.broadcastId });
|
|
674
672
|
}
|
|
675
|
-
if (!ctime && hash
|
|
676
|
-
const pathname = path.join(
|
|
673
|
+
if (!ctime && hash) {
|
|
674
|
+
const pathname = path.join(tempDir, sanitizePath(plugin), hash);
|
|
677
675
|
if (core_1.Module.createDir(pathname)) {
|
|
678
676
|
fs.writeFile(path.join(pathname, cacheKey), result, error => {
|
|
679
677
|
if (!error) {
|
|
@@ -700,7 +698,7 @@ class Compress extends core_1.Module {
|
|
|
700
698
|
complete(null, result, worker, ctime);
|
|
701
699
|
}
|
|
702
700
|
};
|
|
703
|
-
if (
|
|
701
|
+
if (tempDir = this.#getCacheDir('image')) {
|
|
704
702
|
let stored;
|
|
705
703
|
try {
|
|
706
704
|
hash = core_1.Module.asHash(data);
|
|
@@ -708,7 +706,7 @@ class Compress extends core_1.Module {
|
|
|
708
706
|
cacheKey = plugin + (options.options ? ':' + core_1.Module.asHash(core_1.Module.asString(options.options)) : '') + (options.metadata ? ':' + core_1.Module.asHash(core_1.Module.asString(options.metadata)) : '');
|
|
709
707
|
const ctime = stored?.[cacheKey];
|
|
710
708
|
if (ctime) {
|
|
711
|
-
success(fs.readFileSync(path.join(
|
|
709
|
+
success(fs.readFileSync(path.join(tempDir, sanitizePath(plugin), hash, cacheKey)), false, ctime);
|
|
712
710
|
return;
|
|
713
711
|
}
|
|
714
712
|
}
|
|
@@ -775,6 +773,75 @@ class Compress extends core_1.Module {
|
|
|
775
773
|
}
|
|
776
774
|
return false;
|
|
777
775
|
}
|
|
776
|
+
#getCacheDir(type) {
|
|
777
|
+
let tempDir = CACHE_TEMP[type];
|
|
778
|
+
if (tempDir !== undefined) {
|
|
779
|
+
return tempDir;
|
|
780
|
+
}
|
|
781
|
+
const { cache, cache_expires = 0 } = this.settings;
|
|
782
|
+
let expires;
|
|
783
|
+
if ((0, types_1.isPlainObject)(cache)) {
|
|
784
|
+
const value = cache[type];
|
|
785
|
+
if (!cache.enabled || value === false) {
|
|
786
|
+
return CACHE_TEMP[type] = null;
|
|
787
|
+
}
|
|
788
|
+
expires = value !== undefined ? value === true ? 0 : value : cache.expires;
|
|
789
|
+
if (cache.dir && core_1.Module.createDir(tempDir = path.resolve(cache.dir, this.moduleName, type))) {
|
|
790
|
+
this.addLog(5, 'Cache directory: ' + tempDir);
|
|
791
|
+
}
|
|
792
|
+
else {
|
|
793
|
+
tempDir = undefined;
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
else if (cache !== true) {
|
|
797
|
+
return CACHE_TEMP[type] = null;
|
|
798
|
+
}
|
|
799
|
+
expires = (0, types_1.parseExpires)(expires ?? cache_expires);
|
|
800
|
+
tempDir ||= this.getTempDir({ pathname: type, moduleDir: true, createDir: true }) || (0, types_1.getTempDir)(true, this.moduleName, type);
|
|
801
|
+
CACHE_TEMP[type] = tempDir;
|
|
802
|
+
if (expires === 0) {
|
|
803
|
+
core_1.Module.removeDir(tempDir, true);
|
|
804
|
+
}
|
|
805
|
+
else {
|
|
806
|
+
const current = Date.now();
|
|
807
|
+
(function recurse(paths) {
|
|
808
|
+
try {
|
|
809
|
+
const srcDir = path.join(tempDir, ...paths);
|
|
810
|
+
fs.readdirSync(srcDir, { withFileTypes: true }).forEach(item => {
|
|
811
|
+
const filename = item.name;
|
|
812
|
+
if (item.isFile()) {
|
|
813
|
+
const target = path.join(srcDir, filename);
|
|
814
|
+
if (paths.length === 2) {
|
|
815
|
+
try {
|
|
816
|
+
const stat = fs.lstatSync(target);
|
|
817
|
+
if (stat.atimeMs + expires > current) {
|
|
818
|
+
if (type === 'font') {
|
|
819
|
+
CACHE_FONT[paths.concat(filename).join('_')] = [target, stat.ctime];
|
|
820
|
+
CACHE_FONTFROM[filename] = paths[0];
|
|
821
|
+
CACHE_FONTTO[filename] = paths[1];
|
|
822
|
+
}
|
|
823
|
+
else {
|
|
824
|
+
((CACHE_IMAGE[paths[0]] ||= {})[paths[1]] ||= {})[filename] = stat.ctime;
|
|
825
|
+
}
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
catch {
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
fs.unlink(target, () => { });
|
|
833
|
+
}
|
|
834
|
+
else if (item.isDirectory()) {
|
|
835
|
+
recurse(paths.concat(filename));
|
|
836
|
+
}
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
catch {
|
|
840
|
+
}
|
|
841
|
+
})([]);
|
|
842
|
+
}
|
|
843
|
+
return tempDir;
|
|
844
|
+
}
|
|
778
845
|
set chunkSize(value) {
|
|
779
846
|
this.#chunkSize = !isNaN(value = (0, types_1.alignSize)(value, 1)) ? value : undefined;
|
|
780
847
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e-mc/compress",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Compress constructor for E-mc.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"license": "BSD-3-Clause",
|
|
23
23
|
"homepage": "https://github.com/anpham6/e-mc#readme",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@e-mc/core": "0.
|
|
26
|
-
"@e-mc/types": "0.
|
|
25
|
+
"@e-mc/core": "0.13.0",
|
|
26
|
+
"@e-mc/types": "0.13.0",
|
|
27
27
|
"wawoff2": "^2.0.1",
|
|
28
28
|
"woff2sfnt-sfnt2woff": "^1.0.0"
|
|
29
29
|
}
|
package/worker/plugin-image.js
CHANGED
|
@@ -13,7 +13,7 @@ node_worker_threads_1.parentPort.on('message', async (value) => {
|
|
|
13
13
|
catch {
|
|
14
14
|
transform = require(plugin);
|
|
15
15
|
}
|
|
16
|
-
transform(options, metadata)(index_1.asBuffer(data))
|
|
16
|
+
void transform(options, metadata)(index_1.asBuffer(data))
|
|
17
17
|
.then(result => {
|
|
18
18
|
try {
|
|
19
19
|
PORT.postMessage(result, [result.buffer]);
|
|
@@ -21,10 +21,6 @@ node_worker_threads_1.parentPort.on('message', async (value) => {
|
|
|
21
21
|
catch {
|
|
22
22
|
PORT.postMessage(result);
|
|
23
23
|
}
|
|
24
|
-
})
|
|
25
|
-
.catch((err) => {
|
|
26
|
-
console.error(err);
|
|
27
|
-
PORT.postMessage(null);
|
|
28
24
|
});
|
|
29
25
|
}
|
|
30
26
|
catch (err) {
|