@e-mc/compress 0.3.2 → 0.3.3

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.
Files changed (4) hide show
  1. package/LICENSE +10 -10
  2. package/index.d.ts +4 -4
  3. package/index.js +99 -55
  4. package/package.json +3 -3
package/LICENSE CHANGED
@@ -1,11 +1,11 @@
1
- Copyright 2023 An Pham
2
-
3
- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
-
5
- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
-
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
-
1
+ Copyright 2023 An Pham
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
+
5
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
+
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
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/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { CompressConstructor } from '../types/lib';
2
-
3
- declare const Compress: CompressConstructor;
4
-
1
+ import type { CompressConstructor } from '../types/lib';
2
+
3
+ declare const Compress: CompressConstructor;
4
+
5
5
  export = Compress;
package/index.js CHANGED
@@ -9,12 +9,13 @@ const { toSfnt, toWoff } = require('woff2sfnt-sfnt2woff');
9
9
  const types_1 = require("../types");
10
10
  const lib_v4_1 = require("../module/lib-v4");
11
11
  const module_1 = require("../module");
12
+ const CACHE_IMAGE = {};
12
13
  const CACHE_FONT = {};
13
14
  const CACHE_FONTFROM = {};
14
15
  const CACHE_FONTTO = {};
16
+ const CACHE_INIT = [false, false];
15
17
  const CACHE_TINIFY = {};
16
18
  let SINGLETON_INSTANCE;
17
- let CACHE_INIT = false;
18
19
  let TEMP_DIR = '';
19
20
  const GZIP_ZOPFLI = (function () {
20
21
  try {
@@ -24,52 +25,61 @@ const GZIP_ZOPFLI = (function () {
24
25
  }
25
26
  return null;
26
27
  })();
27
- function setCacheData() {
28
- if (!CACHE_INIT) {
29
- TEMP_DIR = this.getTempDir({ moduleDir: true, createDir: true, increment: 5 });
30
- const settings = this.settings;
31
- const expires = (0, types_1.parseExpires)(settings.cache_expires || 0);
28
+ function setCacheData(index) {
29
+ if (CACHE_INIT[index]) {
30
+ return true;
31
+ }
32
+ TEMP_DIR || (TEMP_DIR = this.getTempDir({ moduleDir: true, createDir: true, increment: 5 }));
33
+ const settings = this.settings;
34
+ const expires = (0, types_1.parseExpires)(settings.cache_expires || 0);
35
+ if (TEMP_DIR) {
32
36
  if (expires === 0) {
33
- settings.cache_expires = 0;
34
- }
35
- if (TEMP_DIR) {
36
- if (expires === 0) {
37
+ if (CACHE_INIT.every(value => !value)) {
37
38
  module_1.default.removeDir(TEMP_DIR, true);
38
39
  }
39
- else {
40
- const current = Date.now();
41
- (function recurse(paths) {
42
- const srcDir = path.join(TEMP_DIR, ...paths);
43
- try {
44
- fs.readdirSync(srcDir, { withFileTypes: true }).forEach(item => {
45
- const filename = item.name;
46
- if (item.isFile()) {
47
- const pathname = path.join(srcDir, filename);
40
+ settings.cache_expires = 0;
41
+ }
42
+ else {
43
+ const current = Date.now();
44
+ (function recurse(paths) {
45
+ const srcDir = path.join(TEMP_DIR, ...paths);
46
+ try {
47
+ fs.readdirSync(srcDir, { withFileTypes: true }).forEach(item => {
48
+ var _a, _b, _c;
49
+ const filename = item.name;
50
+ if (item.isFile()) {
51
+ const pathname = path.join(srcDir, filename);
52
+ if (paths.length === 2) {
48
53
  try {
49
- if (fs.lstatSync(pathname).atimeMs + expires > current) {
50
- CACHE_FONT[paths.concat(filename).join('_')] = pathname;
51
- CACHE_FONTFROM[filename] = paths[0];
52
- CACHE_FONTTO[filename] = paths[1];
54
+ const stat = fs.lstatSync(pathname);
55
+ if (stat.atimeMs + expires > current) {
56
+ if (index === 0 /* CACHE_TYPE.FONT */) {
57
+ CACHE_FONT[paths.concat(filename).join('_')] = [pathname, stat.ctime];
58
+ CACHE_FONTFROM[filename] = paths[0];
59
+ CACHE_FONTTO[filename] = paths[1];
60
+ }
61
+ else {
62
+ ((_b = (CACHE_IMAGE[_a = paths[0]] || (CACHE_IMAGE[_a] = {})))[_c = paths[1]] || (_b[_c] = {}))[filename] = stat.ctime;
63
+ }
53
64
  return;
54
65
  }
55
66
  }
56
67
  catch {
57
68
  }
58
- removeFile(pathname);
59
69
  }
60
- else if (item.isDirectory()) {
61
- recurse(paths.concat(filename));
62
- }
63
- });
64
- }
65
- catch {
66
- }
67
- })([]);
68
- }
70
+ removeFile(pathname);
71
+ }
72
+ else if (item.isDirectory()) {
73
+ recurse(paths.concat(filename));
74
+ }
75
+ });
76
+ }
77
+ catch {
78
+ }
79
+ })([]);
69
80
  }
70
- CACHE_INIT = true;
71
81
  }
72
- return true;
82
+ return CACHE_INIT[index] = true;
73
83
  }
74
84
  const removeFile = (pathname) => fs.unlink(pathname, () => { });
75
85
  const checkChunkSize = (value) => typeof value === 'number' && value > 0 && value % 1024 === 0;
@@ -278,7 +288,7 @@ class Compress extends module_1.default {
278
288
  }
279
289
  fs.writeFile(tempFont, data, err => {
280
290
  if (!err) {
281
- CACHE_FONT[from + '_' + ext + '_' + hash] = tempFont;
291
+ CACHE_FONT[from + '_' + ext + '_' + hash] = [tempFont, new Date()];
282
292
  CACHE_FONTTO[hash] = ext;
283
293
  }
284
294
  });
@@ -286,13 +296,13 @@ class Compress extends module_1.default {
286
296
  };
287
297
  const hasFont = () => {
288
298
  let from, to;
289
- if (cache && (CACHE_INIT || setCacheData.call(this)) && (from = CACHE_FONTFROM[hash]) && (to = CACHE_FONTTO[hash])) {
299
+ if (cache && (CACHE_INIT[0] || setCacheData.call(this, 0 /* CACHE_TYPE.FONT */)) && (from = CACHE_FONTFROM[hash]) && (to = CACHE_FONTTO[hash])) {
290
300
  const cacheKey = from + `_${to}_` + hash;
291
301
  const tempFont = CACHE_FONT[cacheKey];
292
302
  if (tempFont) {
293
- if (module_1.default.isPath(tempFont)) {
303
+ if (module_1.default.isPath(tempFont[0])) {
294
304
  try {
295
- const data = fs.readFileSync(tempFont);
305
+ const data = fs.readFileSync(tempFont[0]);
296
306
  let pathname;
297
307
  if (output) {
298
308
  fs.writeFileSync(pathname = (0, types_1.renameExt)(output, to), data);
@@ -301,7 +311,7 @@ class Compress extends module_1.default {
301
311
  else {
302
312
  endProcess(null, data, to, '', true);
303
313
  }
304
- this.formatMessage(8 /* LOG_TYPE.COMPRESS */, from, [pathname ? path.basename(pathname) : `Completed -> font/${to}`, 'cache'], tempFont, { ...module_1.default.LOG_STYLE_NOTICE, hintBold: true, sessionId, broadcastId });
314
+ this.formatMessage(8 /* LOG_TYPE.COMPRESS */, from, [pathname ? path.basename(pathname) : `Completed -> font/${to}`, 'cache'], tempFont[1].toLocaleString(), { ...module_1.default.LOG_STYLE_NOTICE, hintBold: true, sessionId, broadcastId });
305
315
  return true;
306
316
  }
307
317
  catch {
@@ -469,15 +479,14 @@ class Compress extends module_1.default {
469
479
  else {
470
480
  config || (config = {});
471
481
  }
472
- const { plugin = 'tinify', filename, startTime = process.hrtime(), timeout = 0, proxyUrl, sessionId, broadcastId } = config;
482
+ const { plugin = 'tinify', filename, startTime = process.hrtime(), timeout = 0, proxyUrl, options, sessionId, broadcastId } = config;
473
483
  if (!(0, types_1.isString)(output)) {
474
484
  output = typeof file === 'string' ? file : '';
475
485
  }
476
486
  const ext = output ? path.extname(output).substring(1) : config.format || "Unknown" /* ERR_MESSAGE.UNKNOWN */;
477
487
  const format = config.format || ext;
478
- this.formatMessage(8 /* LOG_TYPE.COMPRESS */, ext, ['Compressing image...', plugin], filename || output, { titleColor: 'magenta', sessionId, broadcastId });
479
488
  return new Promise((resolve, reject) => {
480
- let timer = null, aborted, apiKey;
489
+ let timer = null, hash, cacheKey, aborted, apiKey;
481
490
  const failed = (err) => {
482
491
  aborted = true;
483
492
  if (timer) {
@@ -491,7 +500,7 @@ class Compress extends module_1.default {
491
500
  reject(err);
492
501
  }
493
502
  };
494
- const success = (result) => {
503
+ const success = (result, ctime) => {
495
504
  if (aborted) {
496
505
  return;
497
506
  }
@@ -499,12 +508,29 @@ class Compress extends module_1.default {
499
508
  clearTimeout(timer);
500
509
  }
501
510
  const complete = (err) => {
502
- const value = output ? path.basename(output) : filename;
503
- this.writeTimeProcess(ext, value ? plugin + '@' + value : 'Completed', startTime, { type: 8 /* LOG_TYPE.COMPRESS */, sessionId, broadcastId });
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 /* LOG_TYPE.COMPRESS */, value ? path.extname(value).substring(1) : '', [status, 'cache'], ctime.toLocaleString(), { ...module_1.default.LOG_STYLE_NOTICE, hintBold: true, sessionId, broadcastId });
515
+ }
516
+ else {
517
+ this.writeTimeProcess(ext, status, startTime, { type: 8 /* LOG_TYPE.COMPRESS */, sessionId, broadcastId });
518
+ }
504
519
  if (callback) {
505
520
  callback(err, result);
506
521
  }
507
522
  resolve(result);
523
+ if (!ctime && hash && cacheKey && TEMP_DIR) {
524
+ const pathname = path.join(TEMP_DIR, plugin, hash);
525
+ if (module_1.default.createDir(pathname)) {
526
+ fs.writeFile(path.join(pathname, cacheKey), result, error => {
527
+ var _a, _b;
528
+ if (!error) {
529
+ ((_a = (CACHE_IMAGE[plugin] || (CACHE_IMAGE[plugin] = {})))[_b = hash] || (_a[_b] = {}))[cacheKey] = new Date();
530
+ }
531
+ });
532
+ }
533
+ }
508
534
  };
509
535
  if (output) {
510
536
  fs.writeFile(output, result, err => complete(err));
@@ -540,9 +566,6 @@ class Compress extends module_1.default {
540
566
  return;
541
567
  }
542
568
  }
543
- if (timeout > 0) {
544
- timer = setTimeout(() => failed((0, types_1.errorMessage)(plugin, "Timeout was exceeded" /* ERR_MESSAGE.TIMEOUT */)), timeout);
545
- }
546
569
  let data;
547
570
  try {
548
571
  data = Buffer.isBuffer(file) ? file : fs.readFileSync(file);
@@ -551,10 +574,31 @@ class Compress extends module_1.default {
551
574
  failed(err);
552
575
  return;
553
576
  }
577
+ if (this.settings.cache && setCacheData.call(this, 1 /* CACHE_TYPE.IMAGE */)) {
578
+ let stored;
579
+ try {
580
+ stored = (CACHE_IMAGE[plugin] || (CACHE_IMAGE[plugin] = {}))[hash = module_1.default.asHash(data)];
581
+ cacheKey = module_1.default.asHash(plugin + ':' + (apiKey ? format + apiKey : module_1.default.asString(options) || 'unknown'), 'md5');
582
+ const ctime = stored?.[cacheKey];
583
+ if (ctime) {
584
+ success(fs.readFileSync(path.join(TEMP_DIR, plugin, hash, cacheKey)), ctime);
585
+ return;
586
+ }
587
+ }
588
+ catch {
589
+ if (stored && cacheKey) {
590
+ delete stored[cacheKey];
591
+ }
592
+ }
593
+ }
594
+ this.formatMessage(8 /* LOG_TYPE.COMPRESS */, ext, ['Compressing image...', plugin], filename || output, { titleColor: 'magenta', sessionId, broadcastId });
595
+ if (timeout > 0) {
596
+ timer = setTimeout(() => failed((0, types_1.errorMessage)(plugin, "Timeout was exceeded" /* ERR_MESSAGE.TIMEOUT */)), timeout);
597
+ }
554
598
  if (apiKey) {
555
599
  const apiProxy = proxyUrl && (typeof proxyUrl === 'function' ? proxyUrl("https://api.tinify.com" /* VALUES.TINIFY_API_ENDPOINT */) : proxyUrl) || this.module.tinify?.proxy || module_1.default.enabled("process.env.apply" /* KEY_NAME.PROCESS_ENV_APPLY */) && process.env.TINIFY_PROXY || '';
556
- const cacheKey = apiKey + apiProxy;
557
- let tinypng = CACHE_TINIFY[cacheKey];
600
+ const key = apiKey + apiProxy;
601
+ let tinypng = CACHE_TINIFY[key];
558
602
  const validate = () => {
559
603
  tinypng = require('tinify');
560
604
  tinypng.key = apiKey;
@@ -564,11 +608,11 @@ class Compress extends module_1.default {
564
608
  tinypng.validate(err => {
565
609
  if (!err) {
566
610
  fromBuffer();
567
- CACHE_TINIFY[cacheKey] = tinypng;
611
+ CACHE_TINIFY[key] = tinypng;
568
612
  }
569
613
  else {
570
614
  if (err instanceof tinypng.AccountError) {
571
- delete CACHE_TINIFY[cacheKey];
615
+ delete CACHE_TINIFY[key];
572
616
  }
573
617
  failed(err);
574
618
  }
@@ -580,7 +624,7 @@ class Compress extends module_1.default {
580
624
  success(result);
581
625
  }
582
626
  else if (cache) {
583
- delete CACHE_TINIFY[cacheKey];
627
+ delete CACHE_TINIFY[key];
584
628
  validate();
585
629
  }
586
630
  else {
@@ -598,7 +642,7 @@ class Compress extends module_1.default {
598
642
  else {
599
643
  try {
600
644
  const transform = require(plugin);
601
- transform(config.options)(data).then(result => {
645
+ transform(options)(data).then(result => {
602
646
  if (result !== data) {
603
647
  success(result);
604
648
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e-mc/compress",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Compress constructor for E-mc.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -23,8 +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.3.2",
27
- "@e-mc/types": "0.3.2",
26
+ "@e-mc/module": "0.3.3",
27
+ "@e-mc/types": "0.3.3",
28
28
  "tinify": "^1.7.1",
29
29
  "wawoff2": "^2.0.1",
30
30
  "woff2sfnt-sfnt2woff": "^1.0.0"