js-dev-tool 1.1.2 → 1.2.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 CHANGED
@@ -21,10 +21,80 @@ To see the help for a specific command:
21
21
  node tools.js -help <command_name>
22
22
  ```
23
23
 
24
+ ## Basic Types
25
+
26
+ > Optional: a small bag of legacy-ish utility types.
27
+ > You probably don’t need this — but if you do, it’s handy.
28
+
29
+ ```ts
30
+ /// <reference types="js-dev-tool/basic-types"/>
31
+ ```
32
+
33
+ ## Related Libraries
34
+
35
+ ### [`literate-regex`](https://www.npmjs.com/package/literate-regex)
36
+
37
+ `literate-regex` was originally developed as part of this project, but it has now been separated into an independent library.
38
+ It allows you to write readable, commented regular expressions and provides powerful type-level normalization.
39
+
24
40
  ## Commands
25
41
 
26
42
  Here is a list of available commands registered in `ToolFunctions`:
27
43
 
44
+ ---
45
+
46
+ ### `rws`
47
+ Records the size of webpack bundles or other files. The name stands for (r)ecord(W)ebpack(S)ize.
48
+ * **Usage:** `jstool -cmd rws -webpack lib/webpack.js -dest "./dev-extras/webpack-size.json"`
49
+
50
+ ---
51
+
52
+ ### `cjbm`
53
+ Converts JavaScript files to browser-compatible modules. The name stands for (C)onvert (J)S to (B)rowser (M)odule.
54
+ * **Usage:** `jstool -cmd cjbm -basePath <source_dir> -targets "['file1.js', 'file2.js']"`
55
+
56
+ ---
57
+
58
+ ### `cmtTrick`
59
+ Toggles "comment tricks" in the code, useful for conditional code execution during development.
60
+ * **Usage:** `jstool -cmd cmtTrick -basePath <source_dir> -targets "['file1.js', 'file2.js']"`
61
+
62
+ ---
63
+
64
+ ### `replace`
65
+ Performs generic string replacement on a set of target files using a regular expression.
66
+ * **Usage:** `jstool -cmd replace [-after <replacement>] -regex "<regex>" [-targets "<path1>,<path2>" | <file1> <file2> ...]`
67
+ * **Note:** It's often better to pass target files as direct arguments instead of using the `-targets` option.
68
+
69
+ ---
70
+
71
+ ### `version`
72
+ Bumps the version number in `package.json` and optionally in other files.
73
+ * **Usage:** `jstool -cmd version [-major | -minor] [-pkgJsons "./package.json,../other/package.json"] [-extras "file.html"]`
74
+ * **Note:** Bumps the patch version by default. Use `-major` or `-minor` to bump those instead.
75
+
76
+ ---
77
+
78
+ ### `minify`
79
+ Minifies JavaScript files using Terser.
80
+ * **Usage:** `jstool -cmd minify -basePath <source_dir> [-test "<regex>"] [-suffix ".min"]`
81
+ * **Note:** `basePath` can be a comma-separated list. The default suffix is `.mini`.
82
+
83
+ ---
84
+
85
+ ### `rmc`
86
+ Removes C-style comments from files.
87
+ * **Usage:** `jstool -cmd rmc -basePath "./dist/cjs,./dist/other" -test "/\\.(js|d\\.ts)$/"`
88
+ * **Note:** Use the `-rmc4ts` flag for special handling of TypeScript comments (e.g., `/// <reference>`).
89
+
90
+ ---
91
+
92
+ ### `zip`
93
+ Creates a zip archive of specified files.
94
+ * **Usage:** `jstool -cmd zip [-comment "the comment"] file1.js file2.js ...`
95
+
96
+ ---
97
+
28
98
  ```bash
29
99
  zip help: jstool -cmd zip [-comment "the comment"] lib/webpack.js lib/type-ids.js
30
100
  rws help: (R)ecord(W)ebpack(S)ize
@@ -42,7 +112,7 @@ cjbm help: (C)onvert (J)S to (B)rowser (M)odule
42
112
  root - Recursively searches for files.
43
113
  This option is useful, but if there are directories that need to be avoided, use the 'basePath' option
44
114
  basePath - can be "<path>,<path>,..." (array type arg)
45
- ext - specifies the module extension for import clauses. default is "js"
115
+ ext - specifies the module extension for import/export clauses. default is "js"
46
116
  test - Any file extension can be specified. (The default is /\.js$/)
47
117
  targets - specify this if you want to apply it only to a specific file.
48
118
  the file specified here should be directly under `basePath`!
@@ -87,61 +157,6 @@ rmc help: $ jstool -cmd rmc [-rmc4ts[:keepBangLine]] -basePath "./dist/cjs,./dis
87
157
 
88
158
  ```
89
159
 
90
- ---
91
-
92
- ### `zip`
93
- Creates a zip archive of specified files.
94
- * **Usage:** `jstool -cmd zip [-comment "the comment"] file1.js file2.js ...`
95
-
96
- ---
97
-
98
- ### `rws`
99
- Records the size of webpack bundles or other files. The name stands for (r)ecord(W)ebpack(S)ize.
100
- * **Usage:** `jstool -cmd rws -webpack lib/webpack.js -dest "./dev-extras/webpack-size.json"`
101
-
102
- ---
103
-
104
- ### `cjbm`
105
- Converts JavaScript files to browser-compatible modules. The name stands for (C)onvert (J)S to (B)rowser (M)odule.
106
- * **Usage:** `jstool -cmd cjbm -basePath <source_dir> -targets "['file1.js', 'file2.js']"`
107
-
108
- ---
109
-
110
- ### `cmtTrick`
111
- Toggles "comment tricks" in the code, useful for conditional code execution during development.
112
- * **Usage:** `jstool -cmd cmtTrick -basePath <source_dir> -targets "['file1.js', 'file2.js']"`
113
-
114
- ---
115
-
116
- ### `replace`
117
- Performs generic string replacement on a set of target files using a regular expression.
118
- * **Usage:** `jstool -cmd replace [-after <replacement>] -regex "<regex>" [-targets "<path1>,<path2>" | <file1> <file2> ...]`
119
- * **Note:** It's often better to pass target files as direct arguments instead of using the `-targets` option.
120
-
121
- ---
122
-
123
- ### `version`
124
- Bumps the version number in `package.json` and optionally in other files.
125
- * **Usage:** `jstool -cmd version [-major | -minor] [-pkgJsons "./package.json,../other/package.json"] [-extras "file.html"]`
126
- * **Note:** Bumps the patch version by default. Use `-major` or `-minor` to bump those instead.
127
-
128
- ---
129
-
130
- ### `minify`
131
- Minifies JavaScript files using Terser.
132
- * **Usage:** `jstool -cmd minify -basePath <source_dir> [-test "<regex>"] [-suffix ".min"]`
133
- * **Note:** `basePath` can be a comma-separated list. The default suffix is `.mini`.
134
-
135
- ---
136
-
137
- ### `rmc`
138
- Removes C-style comments from files.
139
- * **Usage:** `jstool -cmd rmc -basePath "./dist/cjs,./dist/other" -test "/\\.(js|d\\.ts)$/"`
140
- * **Note:** Use the `-rmc4ts` flag for special handling of TypeScript comments (e.g., `/// <reference>`).
141
-
142
- ---
143
-
144
-
145
160
  ## 📜 License
146
161
 
147
162
  Released under the MIT License.
package/basic-types.d.ts CHANGED
@@ -22,7 +22,7 @@ type TBD<T> = T | undefined;
22
22
  * + 2 character shorten
23
23
  */
24
24
  type TBC<T> = T | null;
25
- type DecideType<T> = T extends infer P? P : T;
25
+ type Maybe<T> = T | null | undefined;
26
26
  /**
27
27
  * T is falsy then return A, trusy then B
28
28
  *
@@ -50,14 +50,12 @@ type DecideType<T> = T extends infer P? P : T;
50
50
  * @date 20/03/31
51
51
  */
52
52
  type Conditional<T, A, B> = void extends T ? A : T extends (void | false | undefined) ? A : B;
53
- type BasicIterator<T> = Iterator<T, T, T>;
54
53
  /**
55
54
  * Remove readonly
56
55
  */
57
56
  type Writable<T> = {
58
57
  -readonly [P in keyof T]: T[P];
59
58
  };
60
- type JsonValueTypes = string | number | boolean | object | Array<number | string | boolean | object>;
61
59
  /**
62
60
  * pickup public fields and methods from `typescript` class.
63
61
  *
@@ -75,84 +73,13 @@ type JsonValueTypes = string | number | boolean | object | Array<number | string
75
73
  type InterfaceType<T> = {
76
74
  [P in keyof T]: T[P];
77
75
  };
78
- type TStdFunction<R = any> = (...args: any[]) => R;
79
- /**
80
- * mark a specific property as `required`
81
- */
82
- type RequireThese<T, K extends keyof T> = T & Required<Pick<T, K>>;
83
- /**
84
- * pick any `property` as excludes
85
- */
86
- type ExcludePick<T, K extends keyof T> = Exclude<Pick<T, K>, T>;
87
- /**
88
- * pick any `property` as required
89
- */
90
- type RequiredPick<T, K extends keyof T> = Required<Pick<T, K>>;
91
- /**
92
- * pick any `property` as partial
93
- */
94
- type PartialPick<T, K extends keyof T> = Partial<Pick<T, K>>;
95
- /**
96
- * NOTE: can use ts builtin `Omit` instead
97
- */
98
- type Flip<T, K extends keyof T> = {
99
- [P in Exclude<keyof T, K>]: T[P];
100
- };
101
- /**
102
- *
103
- * @date 2019/8/19
104
- * @see Parameters
105
- */
106
- type RequiredParameters<TFunction extends (...args: any) => any> = Required<
107
- Parameters<TFunction>
108
- >;
76
+ type Prettify<T> = { [K in keyof T]: T[K] } & {};
77
+ type Constructor<T> = new (...args: any[]) => T;
109
78
  type PickProperties<P, T> = { [K in keyof T]-?: T[K] extends P ? K : never }[keyof T];
110
79
  type PickNumberProperties<T> = PickProperties<number, T>;
111
80
  type PickStringProperties<T> = PickProperties<string, T>;
112
81
  type NonFunctionPropertyNames<T> = { [K in keyof T]-?: T[K] extends Function ? never : K }[keyof T];
113
82
  type NonFunctionProperties<T> = Pick<T, NonFunctionPropertyNames<T>>;
114
- /**
115
- * extract () => number | string functoin names from T
116
- */
117
- type NorSFunctions<T> = { [K in keyof T]: T[K] extends (() => number | string) ? K : never }[keyof T];
118
- type Unpacked<T> =
119
- T extends Array<infer U> ? U :
120
- T extends (...args: any[]) => infer U ? U :
121
- T extends Promise<infer U> ? U :
122
- T;
123
- /**
124
- * cannot apply to parameter required function. (?)
125
- */
126
- type SimpleUnpack<T> = T extends (...args: any[]) => infer U ? U :
127
- T extends Promise<infer U> ? U :
128
- T;
129
- /**
130
- * usage:
131
- * ```
132
- * async function some(): Promise<string> {
133
- * return "OK";
134
- * };
135
- * type RT = UnpackReturnType<typeof some>;
136
- *
137
- * ```
138
- */
139
- type UnpackReturnType<T extends (...args: any[]) => any> = Unpacked<ReturnType<T>>;
140
- /**
141
- * http query parameter types. (maybe not enough.
142
- */
143
- type QueryValueTypes = string | number | boolean | Date;
144
- /**
145
- * means can convert to Date object.
146
- */
147
- type DateString = string;
148
- /**
149
- * document.querySelector etc
150
- */
151
- type TQuerySelector = string;
152
- type NumberMap<T> = {
153
- [index: number]: T;
154
- };
155
- type UndefableStringMap<T> = TBD<Record<string, T>>;
156
83
  /**
157
84
  * for lazy assign class.
158
85
  */
@@ -165,27 +92,6 @@ interface ITypedCtor<T> extends TypedCtor<T> {}
165
92
  * Array.sort etc...
166
93
  */
167
94
  declare type TComparator<T> = (a: T, b: T) => number;
168
- declare const enum ETypeOf {
169
- VBigInt = "bigint",
170
- VBool = "boolean",
171
- VFn = "function",
172
- VNum = "number",
173
- VO = "object",
174
- VS = "string",
175
- VSym = "symbol",
176
- VUndef = "undefined"
177
- }
178
- declare namespace ETypeOf {
179
- export type Values = "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined";
180
- export type Bi = bigint;
181
- export type B = boolean;
182
- export type F = Function;
183
- export type N = number;
184
- export type O = object;
185
- export type S = string;
186
- export type Sym = symbol;
187
- export type U = undefined;
188
- }
189
95
  /**
190
96
  * Generates all combinations of the string S. The order of characters does not matter.
191
97
  * @template S - The target string type
package/lib/zlibjs.d.ts CHANGED
@@ -18,17 +18,32 @@
18
18
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
19
19
  */
20
20
  declare interface IUnzip {
21
- new(data: Uint8Array): this;
22
- getFilenames(): string[];
23
- decompress(entry: string): Uint8Array;
21
+ new(data: Uint8Array): this;
22
+ getFilenames(): string[];
23
+ decompress(entry: string): Uint8Array;
24
+ getCommentAsString(): string;
25
+ getFileHeader(index: number): {
24
26
  getCommentAsString(): string;
25
- getFileHeader(index: number): {
26
- getCommentAsString(): string;
27
- };
27
+ };
28
28
  }
29
- declare namespace Zlib {
30
- const Unzip: IUnzip;
29
+ declare type TZipOption = {
30
+ filename: Uint8Array;
31
+ comment: Uint8Array;
32
+ compressionMethod: number;
33
+ os: number;
34
+ };
35
+ declare interface IZip {
36
+ new(): this;
37
+ addFile(data: Uint8Array, opt: TZipOption): void;
38
+ compress(): Uint8Array;
39
+ CompressionMethod: {
40
+ STORE: 0; DEFLATE: 8;
41
+ };
42
+ OperatingSystem: {
43
+ MSDOS: 0; UNIX: 3; MACINTOSH: 7;
44
+ }
31
45
  }
32
- interface Window {
33
- Zlib: typeof Zlib;
46
+ declare namespace Zlib {
47
+ const Unzip: IUnzip;
48
+ const Zip: IZip;
34
49
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-dev-tool",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "bin": {
5
5
  "jstool": "tools.js"
6
6
  },
@@ -27,18 +27,18 @@
27
27
  "import": "./extras/*.js",
28
28
  "require": "./extras/*.js"
29
29
  },
30
+ "./progress": {
31
+ "types": "./progress/index.d.ts",
32
+ "import": "./progress/index.js",
33
+ "require": "./progress/index.js"
34
+ },
30
35
  "./progress/*": {
31
36
  "types": "./progress/*.d.ts",
32
37
  "import": "./progress/*.js",
33
38
  "require": "./progress/*.js"
34
39
  },
35
- "./literate-regex": {
36
- "types": "./literate-regex/dist/index.d.ts",
37
- "import": "./literate-regex/dist/esm/index.mjs",
38
- "require": "./literate-regex/dist/cjs/index.js"
39
- },
40
- "./literate-regex/global": {
41
- "types": "./literate-regex/dist/global.d.ts"
40
+ "./basic-types": {
41
+ "types": "./basic-types.d.ts"
42
42
  }
43
43
  },
44
44
  "repository": {
@@ -63,10 +63,6 @@
63
63
  "lib",
64
64
  "progress",
65
65
  "scripts",
66
- "literate-regex/package.json",
67
- "literate-regex/README.md",
68
- "literate-regex/LICENSE",
69
- "literate-regex/dist",
70
66
  "tool-lib",
71
67
  "./index.js",
72
68
  "./tools.js",
@@ -76,7 +72,6 @@
76
72
  "!unzip.ts",
77
73
  "!scripts/bin",
78
74
  "!publish-version.json",
79
- "!literate-regex/*.d.ts",
80
75
  "!normalize-commit-msg.mjs",
81
76
  "!regex-test.ts",
82
77
  "!extras/npm",
@@ -90,6 +85,7 @@
90
85
  "dependencies": {
91
86
  "colors.ts": "^1.0.20",
92
87
  "fflate": "^0.8.2",
88
+ "literate-regex": "^0.5.1",
93
89
  "mini-semaphore": "^1.4.4",
94
90
  "replace": "^1.2.2",
95
91
  "rm-cstyle-cmts": "^3.3.26",
package/tool-lib/cjbm.js CHANGED
@@ -14,13 +14,8 @@ const fs = require("fs");
14
14
  const path = require("path");
15
15
  const {
16
16
  compilePCREStyleRegExpLiteral,
17
- } = require("../literate-regex");
17
+ } = require("literate-regex");
18
18
  const RE_TEXT = `/
19
- # DEVNOTE: [.\/] において、js では "/" に escape は必要ないが、pcre の場合 pattern error になる都合上 escape している
20
- # NOTE: PCRE(regex101.com) での検証時は pattern error 回避のため line comment assertion を (?<!\/\/|\/\/\s)(?:(?<!@)import|export) とすること
21
- # line comment の import("...") を正しく除外するには: (?<!\s*\/\/+.*?)(?:(?<!@)import|export)
22
- # NOTE: multiline comment の import statement 誤検出を回避するため、multiline comment の検出を行うようにした. (match count 45, 内 5 は multiline comment[non capture group])
23
- # regex101.com では、line comment assertion (?<!\/\/|\/\/\s) により、48 (3 つは意図しない検出)
24
19
  (?:
25
20
  (?:^\\s*?\\/\\*+?[\\s\\S]*?\\*\\/)|
26
21
  (?<!\\s*\\/\\/+.*?)(?:(?<!@)import|export)
@@ -59,7 +54,9 @@ const RE_TEXT = `/
59
54
  */
60
55
  const reImportExportDetection = compilePCREStyleRegExpLiteral(RE_TEXT);
61
56
  /**
62
- * @typedef {XRegex.ReplacerFunctionSignature<typeof reImportExportDetection>} TImportExportDetectRegexReplacer
57
+ * @typedef {typeof reImportExportDetection} TImportExportDetectorRegex
58
+ * @typedef {TImportExportDetectorRegex["types"]["exec"]} TImportExportDetectorRegexExecResult
59
+ * @typedef {XRegex.StringReplacerFunction<TImportExportDetectorRegex>} TImportExportDetectRegexReplacer
63
60
  */
64
61
  /**
65
62
  * Generates a replacer function to update import/export statements with a new file extension.
@@ -5,7 +5,7 @@
5
5
  https://opensource.org/licenses/mit-license.php
6
6
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7
7
  */
8
- /// <reference types="../literate-regex"/>
8
+ /// <reference types="literate-regex"/>
9
9
  /**
10
10
  * @date 2023-10-25
11
11
  */
@@ -28,6 +28,8 @@ module.exports =
28
28
  }
29
29
  }
30
30
  },
31
- help: `jstool -cmd zip [-comment "the comment"] lib/webpack.js lib/type-ids.js`,
31
+ help: `jstool -cmd zip [-comment "the comment"] lib/webpack.js lib/type-ids.js
32
+ It is possible to create zip files with comments
33
+ `,
32
34
  };
33
35
  };
package/tools.js CHANGED
@@ -65,7 +65,6 @@ function getVersionRegex() {
65
65
  * @type {Record<string, TJSToolEntry>}
66
66
  */
67
67
  const ToolFunctions = {
68
- zip: require("./tool-lib/zip-task")(utils),
69
68
  /** (r)ecord(W)ebpack(S)ize */
70
69
  rws: require("./tool-lib/rws")(fs, utils),
71
70
  cjbm: require("./tool-lib/cjbm")(),
@@ -241,39 +240,7 @@ const ToolFunctions = {
241
240
  - In addition to the "rmc4ts" processing, it also preserves line comments that start with "//!".
242
241
  `,
243
242
  },
244
- backup: {
245
- taskName: "backup",
246
- fn() {
247
- // @ts-ignore
248
- const archiver = require("archiver");
249
- const archive = archiver("zip", {
250
- zlib: { level: 9 },
251
- });
252
- const destDir = params.dest || "../tmp";
253
- const projectName = params.projectName || "anonymouse";
254
- const prefix = utils.dateStringForFile(true);
255
- const output = fs.createWriteStream(`${destDir}/${prefix}-${projectName}-backup.zip`)
256
- .on("close", function () {
257
- console.log(archive.pointer() + " total bytes");
258
- console.log(
259
- "archiver has been finalized and the output file descriptor has closed.",
260
- );
261
- })
262
- .on("end", function () {
263
- console.log("Data has been drained");
264
- });
265
- archive.on("progress", (progress) => {
266
- console.log(progress.entries.processed);
267
- });
268
- archive.pipe(output);
269
- archive.glob("{*,*/**/.*,*/**/*,.*,.*/**/*,.*/**/.*}", {
270
- cwd: `${destDir}/${projectName}/`,
271
- });
272
- archive.finalize();
273
- },
274
- help: 'npx cpx "./{*,*/.*,.*,.*/**/*,!(node_modules|lib)/**/!(eve.db*|etag.json)}" ../tmp/my-project -v -u && npx rimraf ../tmp/my-project/node_modules && jstool -cmd backup -projectName my-project\n\
275
- \ \ result zip name form: <date string>-<projectName>-backup.zip',
276
- },
243
+ zip: require("./tool-lib/zip-task")(utils),
277
244
  };
278
245
  /**
279
246
  * @param {TJSToolEntry} entry
package/tsconfig.json CHANGED
@@ -28,7 +28,6 @@
28
28
  "*.d.ts",
29
29
  "./**/*.js",
30
30
  "./**/*.d.ts",
31
- "./literate-regex/*.d.ts",
32
31
  ],
33
32
  "exclude": [
34
33
  "./**/npm-outdated*.js",
package/utils.js CHANGED
@@ -18,6 +18,7 @@
18
18
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
19
19
  */
20
20
  /// <reference types="./basic-types"/>
21
+ /// <reference types="./lib/zlibjs.d.ts"/>
21
22
  // @ts-check
22
23
  const fs = require("fs");
23
24
  const path = require("path");
@@ -209,6 +210,12 @@ function fireReplace(regex, replacement, paths, async = false) {
209
210
  throw new Error(`invalid paths parameter: paths=[${paths}]`);
210
211
  }
211
212
  }
213
+ /** @type {TextEncoder} */
214
+ let _encoder;
215
+ const getEncorder = () => {
216
+ if (!_encoder) _encoder = new TextEncoder();
217
+ return _encoder;
218
+ };
212
219
  /**
213
220
  * create sourceName zip. (using zip.min.js
214
221
  *
@@ -216,13 +223,15 @@ function fireReplace(regex, replacement, paths, async = false) {
216
223
  * @param {string} comment the zip file comment.
217
224
  */
218
225
  function compressScript(scriptPath, comment = "") {
226
+ /** @type {IZip} */
219
227
  // @ts-ignore
220
228
  const zlibZip = require("./lib/zip.min").Zlib.Zip;
221
229
  const zip = new zlibZip();
230
+ const encoder = getEncorder();
222
231
  const scriptBin = fs.readFileSync(scriptPath);
223
232
  zip.addFile(scriptBin, {
224
- filename: stringToByteArray(path.basename(scriptPath)),
225
- comment: stringToByteArray(comment),
233
+ filename: encoder.encode(path.basename(scriptPath)),
234
+ comment: encoder.encode(comment),
226
235
  compressionMethod: zlibZip.CompressionMethod.DEFLATE,
227
236
  os: zlibZip.OperatingSystem.MSDOS,
228
237
  });
@@ -237,16 +246,6 @@ function compressScript(scriptPath, comment = "") {
237
246
  fs.writeFile(output, compressed, (err) => {
238
247
  console.log(`\nzip file created, error: ${err}\n => ${output}`);
239
248
  });
240
- /**
241
- * @param {string} str
242
- */
243
- function stringToByteArray(str) {
244
- const array = new Uint8Array(str.length);
245
- for (let i = 0, il = str.length; i < il; ++i) {
246
- array[i] = str.charCodeAt(i) & 0xff;
247
- }
248
- return array;
249
- }
250
249
  }
251
250
  /**
252
251
  * DEVNOTE: 10/21/2018, 9:15:00 PM - using "archiver" package, this is too fast!.