@datatruck/cli 0.17.2 → 0.19.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.
Files changed (55) hide show
  1. package/Action/BackupAction.js +4 -2
  2. package/Action/BackupSessionsAction.js +2 -0
  3. package/Action/CleanCacheAction.js +1 -0
  4. package/Action/ConfigAction.js +1 -0
  5. package/Action/InitAction.js +2 -0
  6. package/Action/PruneAction.js +2 -0
  7. package/Action/RestoreAction.js +4 -2
  8. package/Action/RestoreSessionsAction.js +2 -0
  9. package/Action/SnapshotsAction.js +2 -0
  10. package/Command/CommandAbstract.js +2 -0
  11. package/Entity/BackupSessionEntity.js +5 -2
  12. package/Entity/BackupSessionRepositoryEntity.js +5 -2
  13. package/Entity/BackupSessionTaskEntity.js +4 -2
  14. package/Entity/CrudEntityAbstract.js +3 -0
  15. package/Entity/RestoreSessionEntity.js +4 -2
  16. package/Entity/RestoreSessionRepositoryEntity.js +5 -2
  17. package/Entity/RestoreSessionTaskEntity.js +4 -2
  18. package/Entity/StateEntityAbstract.js +5 -0
  19. package/Factory/CommandFactory.js +1 -1
  20. package/JsonSchema/DefinitionEnum.js +1 -1
  21. package/Repository/DatatruckRepository.d.ts +8 -14
  22. package/Repository/DatatruckRepository.js +115 -298
  23. package/Repository/GitRepository.js +1 -1
  24. package/Repository/RepositoryAbstract.js +4 -2
  25. package/Repository/ResticRepository.js +2 -1
  26. package/SessionDriver/ConsoleSessionDriver.js +9 -5
  27. package/SessionDriver/SessionDriverAbstract.js +3 -2
  28. package/SessionDriver/SqliteSessionDriver.js +2 -4
  29. package/SessionManager/BackupSessionManager.js +3 -6
  30. package/SessionManager/RestoreSessionManager.js +3 -6
  31. package/SessionManager/SessionManagerAbstract.js +4 -0
  32. package/Task/GitTask.js +1 -0
  33. package/Task/MariadbTask.d.ts +11 -0
  34. package/Task/MariadbTask.js +234 -51
  35. package/Task/MssqlTask.js +2 -1
  36. package/Task/ScriptTask.js +1 -0
  37. package/Task/SqlDumpTaskAbstract.js +1 -0
  38. package/Task/TaskAbstract.js +2 -1
  39. package/config.schema.json +67 -37
  40. package/index.d.ts +1 -0
  41. package/index.js +1 -0
  42. package/package.json +10 -9
  43. package/utils/DataFormat.js +1 -0
  44. package/utils/Git.js +1 -0
  45. package/utils/ObjectVault.js +3 -5
  46. package/utils/Restic.js +1 -0
  47. package/utils/datatruck/config.d.ts +1 -1
  48. package/utils/fs.d.ts +17 -2
  49. package/utils/fs.js +58 -7
  50. package/utils/process.d.ts +55 -3
  51. package/utils/process.js +159 -19
  52. package/utils/tar.d.ts +32 -0
  53. package/utils/tar.js +92 -0
  54. package/utils/zip.d.ts +0 -97
  55. package/utils/zip.js +0 -238
package/utils/fs.js CHANGED
@@ -3,8 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.cpy = exports.isNotFoundError = exports.updateFileStats = exports.copyFileWithStreams = exports.waitForClose = exports.writeGitIgnoreList = exports.fastglobToGitIgnore = exports.forEachFile = exports.readDir = exports.checkDir = exports.checkFile = exports.readPartialFile = exports.mkTmpDir = exports.fastFolderSizeAsync = exports.tmpDir = exports.rmTmpDir = exports.isTmpDir = exports.sessionTmpDir = exports.parentTmpDir = exports.existsFile = exports.findFile = exports.parsePackageFile = exports.parseFile = exports.parseFileExtensions = exports.readdirIfExists = exports.writeJSONFile = exports.existsDir = exports.ensureEmptyDir = exports.mkdirIfNotExists = exports.isDirEmpty = exports.isLocalDir = exports.pathIterator = exports.applyPermissions = exports.isEmptyDir = exports.isWSLSystem = void 0;
6
+ exports.createFileScanner = exports.cpy = exports.isNotFoundError = exports.updateFileStats = exports.copyFileWithStreams = exports.waitForClose = exports.writeGitIgnoreList = exports.fastglobToGitIgnore = exports.forEachFile = exports.readDir = exports.checkDir = exports.checkFile = exports.readPartialFile = exports.mkTmpDir = exports.fastFolderSizeAsync = exports.tmpDir = exports.rmTmpDir = exports.isTmpDir = exports.sessionTmpDir = exports.parentTmpDir = exports.existsFile = exports.findFile = exports.parsePackageFile = exports.parseFile = exports.parseFileExtensions = exports.readdirIfExists = exports.writeJSONFile = exports.existsDir = exports.ensureEmptyDir = exports.mkdirIfNotExists = exports.isDirEmpty = exports.isLocalDir = exports.pathIterator = exports.applyPermissions = exports.isEmptyDir = exports.isWSLSystem = void 0;
7
7
  const globalData_1 = __importDefault(require("../globalData"));
8
+ const math_1 = require("./math");
8
9
  const path_1 = require("./path");
9
10
  const async_1 = require("async");
10
11
  const crypto_1 = require("crypto");
@@ -66,12 +67,9 @@ async function isDirEmpty(path) {
66
67
  }
67
68
  exports.isDirEmpty = isDirEmpty;
68
69
  async function mkdirIfNotExists(path) {
69
- try {
70
- await (0, promises_1.mkdir)(path, {
71
- recursive: true,
72
- });
73
- }
74
- catch (e) { }
70
+ await (0, promises_1.mkdir)(path, {
71
+ recursive: true,
72
+ });
75
73
  return path;
76
74
  }
77
75
  exports.mkdirIfNotExists = mkdirIfNotExists;
@@ -458,3 +456,56 @@ async function cpy(options) {
458
456
  return stats;
459
457
  }
460
458
  exports.cpy = cpy;
459
+ async function createFileScanner(options) {
460
+ const object = {
461
+ disposed: false,
462
+ total: 0,
463
+ current: 0,
464
+ progress: async (description, path) => {
465
+ if (object.disposed)
466
+ return;
467
+ if (path)
468
+ object.current++;
469
+ await options.onProgress({
470
+ relative: {
471
+ description,
472
+ payload: path,
473
+ },
474
+ absolute: {
475
+ total: object.total,
476
+ current: object.current,
477
+ percent: (0, math_1.progressPercent)(object.total, object.current),
478
+ },
479
+ });
480
+ },
481
+ end: async () => {
482
+ if (!object.disposed)
483
+ await object.progress("Finished");
484
+ object.disposed = true;
485
+ },
486
+ start: async (cb) => {
487
+ let lastTime = performance.now();
488
+ await object.progress("Scanning files");
489
+ for await (const entry of pathIterator(stream)) {
490
+ if (cb) {
491
+ if (await cb(entry))
492
+ object.total++;
493
+ }
494
+ else {
495
+ object.total++;
496
+ }
497
+ if (lastTime - performance.now() > 500)
498
+ await object.progress("Scanning files");
499
+ }
500
+ await object.progress("Scanned files");
501
+ },
502
+ };
503
+ const stream = fast_glob_1.default.stream(options.glob.include, {
504
+ dot: true,
505
+ markDirectories: true,
506
+ stats: true,
507
+ ...options.glob,
508
+ });
509
+ return object;
510
+ }
511
+ exports.createFileScanner = createFileScanner;
@@ -1,7 +1,9 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
- import { SpawnOptions, ChildProcess } from "child_process";
3
+ /// <reference types="node" />
4
+ import { SpawnOptions, ChildProcess, ChildProcessByStdio } from "child_process";
4
5
  import { ReadStream, WriteStream } from "fs";
6
+ import { Readable, Writable } from "stream";
5
7
  export type ExecLogSettingsType = {
6
8
  colorize?: boolean;
7
9
  exec?: boolean;
@@ -13,18 +15,22 @@ export type ExecLogSettingsType = {
13
15
  export interface ExecSettingsInterface {
14
16
  exec?: boolean;
15
17
  pipe?: {
16
- stream: WriteStream | ReadStream;
18
+ stream: WriteStream;
17
19
  onWriteProgress?: (data: {
18
20
  totalBytes: number;
19
21
  }) => void;
22
+ } | {
23
+ stream: ReadStream;
20
24
  onReadProgress?: (data: {
21
25
  totalBytes: number;
22
26
  currentBytes: number;
23
27
  progress: number;
24
28
  }) => void;
29
+ } | {
30
+ stream: Readable;
25
31
  };
26
32
  log?: ExecLogSettingsType | boolean;
27
- onSpawn?: (p: ChildProcess) => void;
33
+ onSpawn?: (p: ChildProcess) => any;
28
34
  stdout?: {
29
35
  save?: boolean;
30
36
  parseLines?: boolean;
@@ -49,6 +55,52 @@ export type ExecResultType = {
49
55
  stderr: string;
50
56
  exitCode: number;
51
57
  };
58
+ export type ParseStreamDataOptions<S extends boolean = boolean> = {
59
+ save?: S;
60
+ parseLines?: boolean;
61
+ log?: LogProcessOptions | boolean;
62
+ onData?: (data: string) => void;
63
+ };
64
+ export declare function parseStreamData<S extends boolean>(stream: Readable, options?: ParseStreamDataOptions<S>): Promise<S extends true ? string : undefined>;
65
+ type OnExitCode = OnExitCodeValue | ((code: number) => OnExitCodeValue | void | undefined);
66
+ type OnExitCodeValue = Error | string | number | boolean;
67
+ export declare function waitForClose<O extends boolean, E extends boolean>(p: ChildProcess, options?: {
68
+ strict?: boolean;
69
+ stdout?: O;
70
+ stderr?: E;
71
+ onExitCode?: OnExitCode;
72
+ }): Promise<{
73
+ exitCode: number;
74
+ } & (O extends true ? {
75
+ stdout: string;
76
+ } : {}) & (E extends true ? {
77
+ stderr: string;
78
+ } : {})>;
79
+ export type LogProcessOptions = {
80
+ envNames?: string[];
81
+ env?: Record<string, any>;
82
+ pipe?: Readable | Writable;
83
+ toStderr?: boolean;
84
+ colorize?: boolean;
85
+ };
86
+ export declare function logProcessExec(command: string, argv: any[], options: LogProcessOptions): Promise<void>;
87
+ export type ProcessOptions<O1 extends boolean, O2 extends boolean> = {
88
+ $stdout?: Omit<ParseStreamDataOptions<O1>, "log">;
89
+ $stderr?: Omit<ParseStreamDataOptions<O2>, "log">;
90
+ $onExitCode?: OnExitCode;
91
+ $log?: boolean | {
92
+ exec?: boolean | LogProcessOptions;
93
+ stdout?: boolean | LogProcessOptions;
94
+ stderr?: boolean | LogProcessOptions;
95
+ };
96
+ };
97
+ export declare function createProcess<O1 extends boolean, O2 extends boolean>(command: string, argv?: (string | number)[], options?: SpawnOptions & ProcessOptions<O1, O2>): ChildProcessByStdio<Writable, Readable, Readable> & PromiseLike<{
98
+ exitCode: number;
99
+ } & (O1 extends true ? {
100
+ stdout: string;
101
+ } : {}) & (O2 extends true ? {
102
+ stderr: string;
103
+ } : {})>;
52
104
  export declare function exec(command: string, argv?: string[], options?: SpawnOptions | null, settings?: ExecSettingsInterface): Promise<ExecResultType>;
53
105
  type EventNameType = "exit" | "SIGINT" | "SIGUSR1" | "SIGUSR2" | "SIGTERM" | "uncaughtException";
54
106
  export declare function onExit(cb: (eventName: EventNameType, ...args: any[]) => void): void;
package/utils/process.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.onExit = exports.exec = exports.logExecStderr = exports.logExecStdout = void 0;
6
+ exports.onExit = exports.exec = exports.createProcess = exports.logProcessExec = exports.waitForClose = exports.parseStreamData = exports.logExecStderr = exports.logExecStdout = void 0;
7
7
  const cli_1 = require("./cli");
8
8
  const fs_1 = require("./fs");
9
9
  const math_1 = require("./math");
@@ -12,6 +12,7 @@ const child_process_1 = require("child_process");
12
12
  const fs_2 = require("fs");
13
13
  const promises_1 = require("fs/promises");
14
14
  const readline_1 = require("readline");
15
+ const stream_1 = require("stream");
15
16
  function logExecStdout(input) {
16
17
  let text = input.colorize ? chalk_1.default.grey(input.data) : input.data;
17
18
  if (input.lineSalt)
@@ -23,6 +24,152 @@ function logExecStderr(data, colorize) {
23
24
  process.stdout.write(colorize ? chalk_1.default.red(data) : data);
24
25
  }
25
26
  exports.logExecStderr = logExecStderr;
27
+ function parseStreamData(stream, options = {}) {
28
+ const log = options.log === true ? {} : options.log;
29
+ let result;
30
+ if (options.save)
31
+ result = "";
32
+ return new Promise((resolve, reject) => {
33
+ const lines = options.parseLines;
34
+ const onData = (data) => {
35
+ if (options.onData)
36
+ options.onData(data.toString());
37
+ if (log)
38
+ logExecStdout({
39
+ data: lines ? `${data}\n` : data.toString(),
40
+ stderr: log.toStderr,
41
+ colorize: log.colorize,
42
+ });
43
+ if (options?.save)
44
+ result += data.toString();
45
+ };
46
+ if (lines) {
47
+ const rl = (0, readline_1.createInterface)({
48
+ input: stream,
49
+ });
50
+ rl.on("line", onData).on("close", () => resolve(result));
51
+ }
52
+ else {
53
+ stream
54
+ .on("data", onData)
55
+ .on("error", reject)
56
+ .once("close", () => resolve(result));
57
+ }
58
+ });
59
+ }
60
+ exports.parseStreamData = parseStreamData;
61
+ function waitForClose(p, options = {}) {
62
+ return new Promise((resolve, reject) => {
63
+ let result = {
64
+ exitCode: 1,
65
+ };
66
+ if (options.stdout) {
67
+ result.stdout = "";
68
+ p.stdout.on("data", (data) => (result.stdout += data.toString()));
69
+ }
70
+ p.once("error", reject).once("close", (exitCode) => {
71
+ if (exitCode) {
72
+ let onExitCode = options.onExitCode ?? true;
73
+ if (typeof onExitCode === "function") {
74
+ onExitCode = onExitCode(exitCode);
75
+ }
76
+ if (typeof onExitCode === "string") {
77
+ reject(new Error(onExitCode));
78
+ }
79
+ else if (typeof onExitCode === "number") {
80
+ reject(new Error(`Exit code: ${onExitCode}`));
81
+ }
82
+ else if (onExitCode instanceof Error) {
83
+ reject(onExitCode);
84
+ }
85
+ else if (onExitCode === false) {
86
+ resolve({ ...result, exitCode: exitCode });
87
+ }
88
+ else {
89
+ reject(new Error(`Exit code: ${exitCode}`));
90
+ }
91
+ }
92
+ else {
93
+ resolve({ ...result, exitCode: exitCode });
94
+ }
95
+ });
96
+ });
97
+ }
98
+ exports.waitForClose = waitForClose;
99
+ async function logProcessExec(command, argv, options) {
100
+ const logEnv = options.envNames?.reduce((env, key) => {
101
+ const value = options?.env?.[key];
102
+ if (typeof value !== "undefined")
103
+ env[key] = value;
104
+ return env;
105
+ }, {});
106
+ (0, cli_1.logExec)(command, options.pipe
107
+ ? [
108
+ ...argv,
109
+ options.pipe instanceof stream_1.Readable ? "<" : ">",
110
+ "path" in options.pipe ? String(options.pipe.path) : "[stream]",
111
+ ]
112
+ : argv, logEnv, options.toStderr);
113
+ }
114
+ exports.logProcessExec = logProcessExec;
115
+ function createProcess(command, argv = [], options = {}) {
116
+ const $log = options.$log === true
117
+ ? { exec: {}, stdout: {}, stderr: {} }
118
+ : options.$log || {};
119
+ if ($log.exec)
120
+ logProcessExec(command, argv, $log.exec === true ? {} : $log.exec);
121
+ if (typeof options.cwd === "string") {
122
+ let isDir = false;
123
+ try {
124
+ isDir = (0, fs_2.statSync)(options.cwd).isDirectory();
125
+ }
126
+ catch (error) { }
127
+ if (!isDir)
128
+ throw new Error(`Current working directory does not exist: ${options.cwd}`);
129
+ }
130
+ const handler = (0, child_process_1.spawn)(command, argv.map((v) => (typeof v === "number" ? v.toString() : v)), options ?? {});
131
+ const { $stdout, $stderr, $onExitCode } = options;
132
+ async function exec() {
133
+ const [stdout, stderr, result] = await Promise.all([
134
+ (!!$log.stdout || !!$stdout) &&
135
+ parseStreamData(handler.stdout, {
136
+ log: $log.stdout,
137
+ ...$stdout,
138
+ }),
139
+ (!!$log.stderr || !!$stderr) &&
140
+ parseStreamData(handler.stderr, {
141
+ log: $log.stderr,
142
+ ...$stderr,
143
+ }),
144
+ waitForClose(handler, {
145
+ onExitCode: $onExitCode,
146
+ }),
147
+ ]);
148
+ const endResult = {
149
+ exitCode: result.exitCode,
150
+ };
151
+ if (typeof stdout === "string")
152
+ endResult.stdout = stdout;
153
+ if (typeof stderr === "string")
154
+ endResult.stderr = stderr;
155
+ return endResult;
156
+ }
157
+ const promise = {
158
+ [Symbol.toStringTag]: "process",
159
+ then: function (onfulfilled, onrejected) {
160
+ return exec().then(onfulfilled, onrejected);
161
+ },
162
+ catch: function (onrejected) {
163
+ return exec().catch(onrejected);
164
+ },
165
+ finally: function (onfinally) {
166
+ return exec().finally(onfinally);
167
+ },
168
+ };
169
+ Object.assign(handler, promise);
170
+ return handler;
171
+ }
172
+ exports.createProcess = createProcess;
26
173
  async function exec(command, argv = [], options = null, settings = {}) {
27
174
  const pipe = settings.pipe;
28
175
  let log = {};
@@ -34,23 +181,16 @@ async function exec(command, argv = [], options = null, settings = {}) {
34
181
  }
35
182
  return new Promise(async (resolve, reject) => {
36
183
  if (log.exec) {
37
- const logEnv = log.envNames?.reduce((env, key) => {
38
- const value = options?.env?.[key];
39
- if (typeof value !== "undefined")
40
- env[key] = value;
41
- return env;
42
- }, {});
43
- (0, cli_1.logExec)(command, pipe
44
- ? [
45
- ...argv,
46
- pipe.stream instanceof fs_2.ReadStream ? "<" : ">",
47
- String(pipe.stream.path),
48
- ]
49
- : argv, logEnv, log.allToStderr);
184
+ logProcessExec(command, argv, {
185
+ env: options?.env,
186
+ envNames: log.envNames,
187
+ pipe: pipe?.stream,
188
+ toStderr: log.allToStderr,
189
+ });
50
190
  }
51
191
  if (typeof options?.cwd === "string" && !(await (0, fs_1.checkDir)(options.cwd)))
52
- return reject(new Error(`Current working directory does not exist: ${options.cwd}`));
53
- if (pipe?.onReadProgress && pipe.stream instanceof fs_2.ReadStream) {
192
+ throw new Error(`Current working directory does not exist: ${options.cwd}`);
193
+ if (pipe?.stream instanceof fs_2.ReadStream && "onReadProgress" in pipe) {
54
194
  const fileInfo = await (0, promises_1.stat)(pipe.stream.path);
55
195
  const totalBytes = fileInfo.size;
56
196
  let currentBytes = 0;
@@ -64,7 +204,7 @@ async function exec(command, argv = [], options = null, settings = {}) {
64
204
  });
65
205
  }
66
206
  const p = (0, child_process_1.spawn)(command, argv, options ?? {});
67
- settings.onSpawn?.(p);
207
+ await settings.onSpawn?.(p);
68
208
  let spawnError;
69
209
  const spawnData = {
70
210
  stdout: "",
@@ -121,7 +261,7 @@ async function exec(command, argv = [], options = null, settings = {}) {
121
261
  throw new Error(`stdout is not defined`);
122
262
  if (!p.stderr)
123
263
  throw new Error(`stderr is not defined`);
124
- if (pipe.onWriteProgress) {
264
+ if ("onWriteProgress" in pipe && pipe.onWriteProgress) {
125
265
  let totalBytes = 0;
126
266
  p.stdout.on("data", (chunk) => {
127
267
  totalBytes += chunk.length;
@@ -136,7 +276,7 @@ async function exec(command, argv = [], options = null, settings = {}) {
136
276
  p.stderr.pipe(pipe.stream, { end: false });
137
277
  p.on("close", tryFinish);
138
278
  }
139
- else if (pipe.stream instanceof fs_2.ReadStream) {
279
+ else if (pipe.stream instanceof stream_1.Readable) {
140
280
  if (!p.stdin)
141
281
  throw new Error(`stdin is not defined`);
142
282
  pipe.stream.pipe(p.stdin);
package/utils/tar.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ export type Progress = {
2
+ percent: number;
3
+ current: number;
4
+ total: number;
5
+ };
6
+ export type TarEntry = {
7
+ path: string;
8
+ progress: Progress;
9
+ };
10
+ export interface CreateTarOptions {
11
+ path: string;
12
+ verbose?: boolean;
13
+ output: string;
14
+ include: string[];
15
+ compress?: boolean;
16
+ onEntry?: (entry: TarEntry) => void;
17
+ }
18
+ export interface ExtractOptions {
19
+ input: string;
20
+ output: string;
21
+ verbose?: boolean;
22
+ total?: number;
23
+ onEntry?: (entry: TarEntry) => void;
24
+ }
25
+ export type ListTarOptions = {
26
+ input: string;
27
+ onEntry?: (entry: Pick<TarEntry, "path">) => void;
28
+ verbose?: boolean;
29
+ };
30
+ export declare function listTar(options: ListTarOptions): Promise<number>;
31
+ export declare function createTar(options: CreateTarOptions): Promise<void>;
32
+ export declare function extractTar(options: ExtractOptions): Promise<void>;
package/utils/tar.js ADDED
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.extractTar = exports.createTar = exports.listTar = void 0;
7
+ const cli_1 = require("./cli");
8
+ const fs_1 = require("./fs");
9
+ const math_1 = require("./math");
10
+ const fs_2 = require("fs");
11
+ const promises_1 = require("fs/promises");
12
+ const tar_1 = __importDefault(require("tar"));
13
+ async function listTar(options) {
14
+ if (options.verbose)
15
+ (0, cli_1.logExec)("tar", ["-ztvf", options.input]);
16
+ let total = 0;
17
+ await tar_1.default.list({
18
+ file: options.input,
19
+ onentry(entry) {
20
+ options.onEntry?.({ path: entry.path });
21
+ total++;
22
+ },
23
+ });
24
+ return total;
25
+ }
26
+ exports.listTar = listTar;
27
+ async function createTar(options) {
28
+ if (options.verbose)
29
+ (0, cli_1.logExec)("tar", [
30
+ options.compress ? "-czvf" : "-cvf",
31
+ options.output,
32
+ options.path,
33
+ ]);
34
+ let total = options.include.length;
35
+ if (!total)
36
+ throw new Error("'include' option is empty");
37
+ let current = 0;
38
+ let progressPromise;
39
+ const inStream = tar_1.default.create({
40
+ gzip: options.compress,
41
+ cwd: options.path,
42
+ filter(path) {
43
+ current++;
44
+ options.onEntry?.({
45
+ path: path,
46
+ progress: {
47
+ total,
48
+ current,
49
+ percent: (0, math_1.progressPercent)(total, current),
50
+ },
51
+ });
52
+ return true;
53
+ },
54
+ }, options.include);
55
+ const outStream = (0, fs_2.createWriteStream)(options.output);
56
+ await new Promise((resolve, reject) => {
57
+ inStream.on("error", reject);
58
+ outStream.on("error", reject);
59
+ inStream.pipe(outStream);
60
+ outStream.on("close", resolve);
61
+ });
62
+ await progressPromise;
63
+ }
64
+ exports.createTar = createTar;
65
+ async function extractTar(options) {
66
+ let total = options.total ??
67
+ (await listTar({ input: options.input, verbose: options.verbose }));
68
+ if (options.verbose) {
69
+ (0, cli_1.logExec)("tar", ["-xzvfp", options.input, "-C", options.output]);
70
+ (0, cli_1.logExec)("mkdir", ["-p", options.output]);
71
+ }
72
+ let current = 0;
73
+ await (0, promises_1.mkdir)(options.output, { recursive: true });
74
+ await (0, fs_1.ensureEmptyDir)(options.output);
75
+ await tar_1.default.extract({
76
+ file: options.input,
77
+ cwd: options.output,
78
+ preserveOwner: true,
79
+ onentry(entry) {
80
+ current++;
81
+ options.onEntry?.({
82
+ path: entry.path,
83
+ progress: {
84
+ total,
85
+ current,
86
+ percent: (0, math_1.progressPercent)(total, current),
87
+ },
88
+ });
89
+ },
90
+ });
91
+ }
92
+ exports.extractTar = extractTar;
package/utils/zip.d.ts DELETED
@@ -1,97 +0,0 @@
1
- export interface ZipDataFilterType {
2
- recursive?: boolean;
3
- exclude?: boolean;
4
- patterns: string[];
5
- }
6
- export interface ZipDataType {
7
- command?: string;
8
- path: string;
9
- filter?: (ZipDataFilterType | string)[];
10
- output: string;
11
- deleteOnZip?: boolean;
12
- includeList?: string;
13
- excludeList?: string;
14
- verbose?: boolean;
15
- onProgress?: (data: {
16
- percent: number;
17
- total: number;
18
- current: number;
19
- path?: string;
20
- type?: "start" | "end";
21
- }) => void | Promise<void>;
22
- onStream?: (data: ZipStream) => void | Promise<void>;
23
- }
24
- export interface UnzipDataType {
25
- command?: string;
26
- input: string;
27
- files?: (ZipDataFilterType | string)[];
28
- output: string;
29
- verbose?: boolean;
30
- onProgress?: (data: {
31
- percent: number;
32
- current: number;
33
- path?: string;
34
- type?: "start" | "end";
35
- }) => void | Promise<void>;
36
- onStream?: (data: UnzipStream) => void | Promise<void>;
37
- }
38
- export declare function buildArguments(filters: (ZipDataFilterType | string)[]): string[];
39
- export declare function checkSSEOption(command?: string): Promise<boolean>;
40
- type ListZipStream = {
41
- Path?: string;
42
- Folder?: string;
43
- Size?: string;
44
- "Packed Size"?: string;
45
- Modified?: string;
46
- Created?: string;
47
- Accessed?: string;
48
- Attributes?: string;
49
- Encrypted?: string;
50
- Comment?: string;
51
- CRC?: string;
52
- Method?: string;
53
- Characteristics?: string;
54
- "Host OS"?: string;
55
- Version?: string;
56
- Volume?: string;
57
- Offset?: string;
58
- };
59
- export declare function listZip(data: {
60
- command?: string;
61
- path: string;
62
- onStream: (item: ListZipStream) => Promise<void>;
63
- verbose?: boolean;
64
- }): Promise<void>;
65
- export type ZipStream = {
66
- type: "progress";
67
- data: {
68
- progress: number;
69
- files: number;
70
- path: string;
71
- };
72
- } | {
73
- type: "summary";
74
- data: {
75
- folders: number;
76
- files: number;
77
- };
78
- };
79
- export declare function zip(data: ZipDataType): Promise<{
80
- folders: number;
81
- files: number;
82
- }>;
83
- export type UnzipStream = {
84
- type: "progress";
85
- data: {
86
- percent: number;
87
- files: number;
88
- path: string;
89
- };
90
- };
91
- export declare function unzip(data: UnzipDataType): Promise<{
92
- files: number;
93
- stdout: string;
94
- stderr: string;
95
- exitCode: number;
96
- }>;
97
- export {};