@datatruck/cli 0.14.0 → 0.16.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/Action/BackupAction.d.ts +10 -3
- package/Action/BackupAction.js +41 -49
- package/Action/RestoreAction.d.ts +2 -2
- package/Action/RestoreAction.js +8 -16
- package/Command/BackupCommand.js +2 -1
- package/Command/BackupSessionsCommand.js +1 -0
- package/Command/RestoreCommand.js +1 -1
- package/Command/RestoreSessionsCommand.js +1 -0
- package/Entity/StateEntityAbstract.d.ts +2 -5
- package/Error/AppError.d.ts +1 -0
- package/Error/AppError.js +4 -0
- package/Repository/DatatruckRepository.d.ts +1 -0
- package/Repository/DatatruckRepository.js +162 -158
- package/Repository/RepositoryAbstract.d.ts +4 -10
- package/Repository/ResticRepository.js +34 -17
- package/SessionDriver/ConsoleSessionDriver.d.ts +2 -7
- package/SessionDriver/ConsoleSessionDriver.js +51 -24
- package/SessionDriver/SqliteSessionDriver.js +5 -0
- package/SessionManager/BackupSessionManager.d.ts +12 -11
- package/SessionManager/BackupSessionManager.js +20 -5
- package/SessionManager/RestoreSessionManager.d.ts +14 -11
- package/SessionManager/RestoreSessionManager.js +20 -5
- package/SessionManager/SessionManagerAbstract.d.ts +18 -0
- package/SessionManager/SessionManagerAbstract.js +32 -0
- package/Task/GitTask.js +22 -14
- package/Task/MariadbTask.js +9 -4
- package/Task/MysqlDumpTask.d.ts +3 -1
- package/Task/MysqlDumpTask.js +5 -2
- package/Task/PostgresqlDumpTask.d.ts +3 -1
- package/Task/PostgresqlDumpTask.js +2 -2
- package/Task/SqlDumpTaskAbstract.d.ts +3 -1
- package/Task/SqlDumpTaskAbstract.js +55 -13
- package/Task/TaskAbstract.d.ts +3 -9
- package/cli.js +1 -1
- package/migrations/001-initial.sql +6 -30
- package/package.json +1 -1
- package/util/cli-util.d.ts +1 -1
- package/util/cli-util.js +17 -2
- package/util/fs-util.d.ts +10 -1
- package/util/fs-util.js +10 -1
- package/util/process-util.d.ts +3 -0
- package/util/process-util.js +11 -0
- package/util/progress.d.ts +12 -0
- package/util/progress.js +2 -0
- package/util/zip-util.d.ts +23 -5
- package/util/zip-util.js +82 -25
package/cli.js
CHANGED
|
@@ -81,7 +81,7 @@ program.usage("dtt");
|
|
|
81
81
|
program.option("-v,--verbose", "Verbose", (_, previous) => previous + 1, 0);
|
|
82
82
|
program.option("-c,--config <path>", "Config path", process.env["DATATRUCK_CONFIG"] ?? (cwd.endsWith(path_1.sep) ? cwd : `${cwd}${path_1.sep}`));
|
|
83
83
|
program.option("--progress <value>", "Progress type (auto, plain, tty)", "auto");
|
|
84
|
-
program.option("--progress-interval <ms>", "Progress interval");
|
|
84
|
+
program.option("--progress-interval <ms>", "Progress interval", Number, 1000);
|
|
85
85
|
program.option("-o,--output-format <format>", "Output format (json, pjson, yaml, table, custom=$, tpl=name)", "table");
|
|
86
86
|
makeCommand(CommandFactory_1.CommandEnum.config).alias("c");
|
|
87
87
|
makeCommand(CommandFactory_1.CommandEnum.init).alias("i");
|
|
@@ -11,11 +11,7 @@ CREATE TABLE "backup_session" (
|
|
|
11
11
|
"endDate" TEXT,
|
|
12
12
|
"state" TEXT,
|
|
13
13
|
"error" TEXT,
|
|
14
|
-
"
|
|
15
|
-
"progressTotal" INTEGER,
|
|
16
|
-
"progressPercent" INTEGER,
|
|
17
|
-
"progressStep" TEXT,
|
|
18
|
-
"progressStepPercent" INTEGER,
|
|
14
|
+
"progress" TEXT,
|
|
19
15
|
|
|
20
16
|
"snapshotId" TEXT NOT NULL,
|
|
21
17
|
"packageName" TEXT NOT NULL,
|
|
@@ -32,11 +28,7 @@ CREATE TABLE "backup_session_task" (
|
|
|
32
28
|
"endDate" TEXT,
|
|
33
29
|
"state" TEXT,
|
|
34
30
|
"error" TEXT,
|
|
35
|
-
"
|
|
36
|
-
"progressTotal" INTEGER,
|
|
37
|
-
"progressPercent" INTEGER,
|
|
38
|
-
"progressStep" TEXT,
|
|
39
|
-
"progressStepPercent" INTEGER,
|
|
31
|
+
"progress" TEXT,
|
|
40
32
|
|
|
41
33
|
"sessionId" INTEGER NOT NULL,
|
|
42
34
|
"taskName" TEXT NOT NULL
|
|
@@ -51,11 +43,7 @@ CREATE TABLE "backup_session_repository" (
|
|
|
51
43
|
"endDate" TEXT,
|
|
52
44
|
"state" TEXT,
|
|
53
45
|
"error" TEXT,
|
|
54
|
-
"
|
|
55
|
-
"progressTotal" INTEGER,
|
|
56
|
-
"progressPercent" INTEGER,
|
|
57
|
-
"progressStep" TEXT,
|
|
58
|
-
"progressStepPercent" INTEGER,
|
|
46
|
+
"progress" TEXT,
|
|
59
47
|
|
|
60
48
|
"sessionId" INTEGER NOT NULL,
|
|
61
49
|
"repositoryName" TEXT NOT NULL,
|
|
@@ -71,11 +59,7 @@ CREATE TABLE "restore_session" (
|
|
|
71
59
|
"endDate" TEXT,
|
|
72
60
|
"state" TEXT,
|
|
73
61
|
"error" TEXT,
|
|
74
|
-
"
|
|
75
|
-
"progressTotal" INTEGER,
|
|
76
|
-
"progressPercent" INTEGER,
|
|
77
|
-
"progressStep" TEXT,
|
|
78
|
-
"progressStepPercent" INTEGER,
|
|
62
|
+
"progress" TEXT,
|
|
79
63
|
|
|
80
64
|
"snapshotId" TEXT NOT NULL,
|
|
81
65
|
"packageName" TEXT NOT NULL -- ,
|
|
@@ -91,11 +75,7 @@ CREATE TABLE "restore_session_task" (
|
|
|
91
75
|
"endDate" TEXT,
|
|
92
76
|
"state" TEXT,
|
|
93
77
|
"error" TEXT,
|
|
94
|
-
"
|
|
95
|
-
"progressTotal" INTEGER,
|
|
96
|
-
"progressPercent" INTEGER,
|
|
97
|
-
"progressStep" TEXT,
|
|
98
|
-
"progressStepPercent" INTEGER,
|
|
78
|
+
"progress" TEXT,
|
|
99
79
|
|
|
100
80
|
"sessionId" INTEGER NOT NULL,
|
|
101
81
|
"taskName" TEXT NOT NULL
|
|
@@ -110,11 +90,7 @@ CREATE TABLE "restore_session_repository" (
|
|
|
110
90
|
"endDate" TEXT,
|
|
111
91
|
"state" TEXT,
|
|
112
92
|
"error" TEXT,
|
|
113
|
-
"
|
|
114
|
-
"progressTotal" INTEGER,
|
|
115
|
-
"progressPercent" INTEGER,
|
|
116
|
-
"progressStep" TEXT,
|
|
117
|
-
"progressStepPercent" INTEGER,
|
|
93
|
+
"progress" TEXT,
|
|
118
94
|
|
|
119
95
|
"sessionId" INTEGER NOT NULL,
|
|
120
96
|
"repositoryName" TEXT NOT NULL,
|
package/package.json
CHANGED
package/util/cli-util.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export declare const showCursorCommand = "\u001B[?25h";
|
|
|
5
5
|
export declare const clearCommand = "\r\u001B[K";
|
|
6
6
|
export declare const hideCursorCommand = "\u001B[?25l";
|
|
7
7
|
export declare function renderSpinner(counter: number): string;
|
|
8
|
-
export declare function renderProgressBar(progress: number, size?: number): string;
|
|
8
|
+
export declare function renderProgressBar(progress: number, size?: number, subprogress?: number): string;
|
|
9
9
|
export declare function logVars(data: Record<string, any>): void;
|
|
10
10
|
export declare function logExec(command: string, argv?: string[], env?: NodeJS.ProcessEnv, logToStderr?: boolean): void;
|
|
11
11
|
export declare function resultColumn(error: Error | null | string, state?: "started" | "ended"): "❌" | " ? " | "✅";
|
package/util/cli-util.js
CHANGED
|
@@ -20,12 +20,27 @@ function renderSpinner(counter) {
|
|
|
20
20
|
return exports.spinnerChars[counter % (exports.spinnerChars.length - 1)];
|
|
21
21
|
}
|
|
22
22
|
exports.renderSpinner = renderSpinner;
|
|
23
|
-
function renderProgressBar(progress, size = 10) {
|
|
23
|
+
function renderProgressBar(progress, size = 10, subprogress) {
|
|
24
24
|
const completeChar = "\u2588";
|
|
25
25
|
const incompleteChar = "\u2591";
|
|
26
26
|
const completedSize = Math.round((progress * size) / 100);
|
|
27
27
|
const restSize = Math.max(size - completedSize, 0);
|
|
28
|
-
|
|
28
|
+
let result = completeChar.repeat(completedSize) + incompleteChar.repeat(restSize);
|
|
29
|
+
if (typeof subprogress === "number") {
|
|
30
|
+
const subprogressChar = Math.round((subprogress * size) / 100);
|
|
31
|
+
if (subprogressChar === size) {
|
|
32
|
+
result =
|
|
33
|
+
result.slice(0, subprogressChar - 1) +
|
|
34
|
+
chalk_1.default.white(result[Math.max(0, subprogressChar - 1)]);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
result =
|
|
38
|
+
result.slice(0, subprogressChar) +
|
|
39
|
+
chalk_1.default.white(result[Math.max(0, subprogressChar - 1)]) +
|
|
40
|
+
result.slice(subprogressChar + 1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return (0, chalk_2.cyan)(result);
|
|
29
44
|
}
|
|
30
45
|
exports.renderProgressBar = renderProgressBar;
|
|
31
46
|
function logVars(data) {
|
package/util/fs-util.d.ts
CHANGED
|
@@ -73,6 +73,11 @@ export declare function cpy(options: {
|
|
|
73
73
|
*/
|
|
74
74
|
concurrency?: number;
|
|
75
75
|
skipNotFoundError?: boolean;
|
|
76
|
+
onProgress?: (data: {
|
|
77
|
+
current: number;
|
|
78
|
+
path?: string;
|
|
79
|
+
type?: "start" | "end";
|
|
80
|
+
}) => Promise<boolean | void>;
|
|
76
81
|
onPath?: (data: {
|
|
77
82
|
isDir: boolean;
|
|
78
83
|
entryPath: string;
|
|
@@ -84,5 +89,9 @@ export declare function cpy(options: {
|
|
|
84
89
|
dirs: number;
|
|
85
90
|
};
|
|
86
91
|
}) => Promise<boolean | void>;
|
|
87
|
-
}): Promise<
|
|
92
|
+
}): Promise<{
|
|
93
|
+
paths: number;
|
|
94
|
+
files: number;
|
|
95
|
+
dirs: number;
|
|
96
|
+
}>;
|
|
88
97
|
export {};
|
package/util/fs-util.js
CHANGED
|
@@ -162,7 +162,7 @@ function sessionTmpDir() {
|
|
|
162
162
|
exports.sessionTmpDir = sessionTmpDir;
|
|
163
163
|
function tmpDir(prefix, id) {
|
|
164
164
|
if (!id)
|
|
165
|
-
id = (0, crypto_1.
|
|
165
|
+
id = (0, crypto_1.randomUUID)().slice(0, 8);
|
|
166
166
|
return (0, path_1.join)(sessionTmpDir(), `${prefix}-${id}`);
|
|
167
167
|
}
|
|
168
168
|
exports.tmpDir = tmpDir;
|
|
@@ -369,6 +369,10 @@ async function cpy(options) {
|
|
|
369
369
|
else {
|
|
370
370
|
const dir = (0, path_1.dirname)(entryTargetPath);
|
|
371
371
|
await makeRecursiveDir(dir);
|
|
372
|
+
await options.onProgress?.({
|
|
373
|
+
current: stats.files,
|
|
374
|
+
path: entryPath,
|
|
375
|
+
});
|
|
372
376
|
stats.files++;
|
|
373
377
|
// https://github.com/nodejs/node/issues/44261
|
|
374
378
|
if (exports.isWSLSystem) {
|
|
@@ -429,5 +433,10 @@ async function cpy(options) {
|
|
|
429
433
|
},
|
|
430
434
|
});
|
|
431
435
|
}
|
|
436
|
+
await options.onProgress?.({
|
|
437
|
+
current: stats.files,
|
|
438
|
+
type: "end",
|
|
439
|
+
});
|
|
440
|
+
return stats;
|
|
432
441
|
}
|
|
433
442
|
exports.cpy = cpy;
|
package/util/process-util.d.ts
CHANGED
package/util/process-util.js
CHANGED
|
@@ -121,6 +121,17 @@ async function exec(command, argv = [], options = null, settings = {}) {
|
|
|
121
121
|
throw new Error(`stdout is not defined`);
|
|
122
122
|
if (!p.stderr)
|
|
123
123
|
throw new Error(`stderr is not defined`);
|
|
124
|
+
if (pipe.onWriteProgress) {
|
|
125
|
+
let totalBytes = 0;
|
|
126
|
+
p.stdout.on("data", (chunk) => {
|
|
127
|
+
totalBytes += chunk.length;
|
|
128
|
+
pipe.onWriteProgress({ totalBytes });
|
|
129
|
+
});
|
|
130
|
+
p.stderr.on("data", (chunk) => {
|
|
131
|
+
totalBytes += chunk.length;
|
|
132
|
+
pipe.onWriteProgress({ totalBytes });
|
|
133
|
+
});
|
|
134
|
+
}
|
|
124
135
|
p.stdout.pipe(pipe.stream, { end: false });
|
|
125
136
|
p.stderr.pipe(pipe.stream, { end: false });
|
|
126
137
|
p.on("close", tryFinish);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare type ProgressStats = {
|
|
2
|
+
percent?: number;
|
|
3
|
+
total?: number;
|
|
4
|
+
current?: number;
|
|
5
|
+
description?: string;
|
|
6
|
+
payload?: string;
|
|
7
|
+
format?: "amount" | "size";
|
|
8
|
+
};
|
|
9
|
+
export declare type Progress = {
|
|
10
|
+
absolute?: ProgressStats;
|
|
11
|
+
relative?: ProgressStats;
|
|
12
|
+
};
|
package/util/progress.js
ADDED
package/util/zip-util.d.ts
CHANGED
|
@@ -12,7 +12,14 @@ export interface ZipDataType {
|
|
|
12
12
|
includeList?: string;
|
|
13
13
|
excludeList?: string;
|
|
14
14
|
verbose?: boolean;
|
|
15
|
-
|
|
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>;
|
|
16
23
|
}
|
|
17
24
|
export interface UnzipDataType {
|
|
18
25
|
command?: string;
|
|
@@ -20,7 +27,13 @@ export interface UnzipDataType {
|
|
|
20
27
|
files?: (ZipDataFilterType | string)[];
|
|
21
28
|
output: string;
|
|
22
29
|
verbose?: boolean;
|
|
23
|
-
|
|
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>;
|
|
24
37
|
}
|
|
25
38
|
export declare function buildArguments(filters: (ZipDataFilterType | string)[]): string[];
|
|
26
39
|
export declare function checkSSEOption(command?: string): Promise<boolean>;
|
|
@@ -46,7 +59,7 @@ declare type ListZipStream = {
|
|
|
46
59
|
export declare function listZip(data: {
|
|
47
60
|
command?: string;
|
|
48
61
|
path: string;
|
|
49
|
-
onStream: (item: ListZipStream) => void
|
|
62
|
+
onStream: (item: ListZipStream) => Promise<void>;
|
|
50
63
|
verbose?: boolean;
|
|
51
64
|
}): Promise<void>;
|
|
52
65
|
export declare type ZipStream = {
|
|
@@ -70,10 +83,15 @@ export declare function zip(data: ZipDataType): Promise<{
|
|
|
70
83
|
export declare type UnzipStream = {
|
|
71
84
|
type: "progress";
|
|
72
85
|
data: {
|
|
73
|
-
|
|
86
|
+
percent: number;
|
|
74
87
|
files: number;
|
|
75
88
|
path: string;
|
|
76
89
|
};
|
|
77
90
|
};
|
|
78
|
-
export declare function unzip(data: UnzipDataType): Promise<
|
|
91
|
+
export declare function unzip(data: UnzipDataType): Promise<{
|
|
92
|
+
files: number;
|
|
93
|
+
stdout: string;
|
|
94
|
+
stderr: string;
|
|
95
|
+
exitCode: number;
|
|
96
|
+
}>;
|
|
79
97
|
export {};
|
package/util/zip-util.js
CHANGED
|
@@ -32,7 +32,11 @@ function buildArguments(filters) {
|
|
|
32
32
|
exports.buildArguments = buildArguments;
|
|
33
33
|
let checkSSEOptionResult;
|
|
34
34
|
async function checkSSEOption(command = "7z") {
|
|
35
|
-
const result = await (0, process_util_1.exec)(command
|
|
35
|
+
const result = await (0, process_util_1.exec)(command, [], {}, {
|
|
36
|
+
stdout: {
|
|
37
|
+
save: true,
|
|
38
|
+
},
|
|
39
|
+
});
|
|
36
40
|
if (typeof checkSSEOptionResult === "boolean")
|
|
37
41
|
return checkSSEOptionResult;
|
|
38
42
|
return (checkSSEOptionResult = result.stdout.includes(" -sse"));
|
|
@@ -73,10 +77,10 @@ async function listZip(data) {
|
|
|
73
77
|
onExitCodeError: (data, error) => (data.exitCode > 2 ? error : false),
|
|
74
78
|
stdout: {
|
|
75
79
|
parseLines: true,
|
|
76
|
-
onData: (line) => {
|
|
80
|
+
onData: async (line) => {
|
|
77
81
|
const stream = parseListZipLine(line, buffer);
|
|
78
82
|
if (stream) {
|
|
79
|
-
data.onStream?.(stream);
|
|
83
|
+
await data.onStream?.(stream);
|
|
80
84
|
}
|
|
81
85
|
},
|
|
82
86
|
},
|
|
@@ -85,12 +89,13 @@ async function listZip(data) {
|
|
|
85
89
|
exports.listZip = listZip;
|
|
86
90
|
function parseZipLine(line) {
|
|
87
91
|
let matches = null;
|
|
88
|
-
|
|
92
|
+
line = line.trim();
|
|
93
|
+
if (!line.length)
|
|
89
94
|
return;
|
|
90
|
-
if ((matches =
|
|
95
|
+
if ((matches = /^(\d+)% (\d+ )?\+/.exec(line))) {
|
|
91
96
|
const path = line.slice(line.indexOf("+") + 1).trim();
|
|
92
97
|
const progress = Number(matches[1]);
|
|
93
|
-
const files = Number(matches[2]);
|
|
98
|
+
const files = matches[2] ? Number(matches[2]) : 1;
|
|
94
99
|
return {
|
|
95
100
|
type: "progress",
|
|
96
101
|
data: { progress, path, files },
|
|
@@ -109,10 +114,16 @@ function parseZipLine(line) {
|
|
|
109
114
|
}
|
|
110
115
|
}
|
|
111
116
|
async function zip(data) {
|
|
112
|
-
let
|
|
117
|
+
let summary = {
|
|
113
118
|
folders: 0,
|
|
114
119
|
files: 0,
|
|
115
120
|
};
|
|
121
|
+
await data.onProgress?.({
|
|
122
|
+
current: 0,
|
|
123
|
+
percent: 0,
|
|
124
|
+
total: 0,
|
|
125
|
+
type: "start",
|
|
126
|
+
});
|
|
116
127
|
await (0, process_util_1.exec)(data.command ?? "7z", [
|
|
117
128
|
"a",
|
|
118
129
|
// https://sourceforge.net/p/sevenzip/bugs/2099/,
|
|
@@ -130,33 +141,58 @@ async function zip(data) {
|
|
|
130
141
|
log: data.verbose ?? false,
|
|
131
142
|
onExitCodeError: (data, error) => (data.exitCode > 2 ? error : false),
|
|
132
143
|
stdout: {
|
|
133
|
-
onData: (
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
144
|
+
onData: async (lines) => {
|
|
145
|
+
for (const line of lines.replaceAll("\b", "").split(/\r?\n/)) {
|
|
146
|
+
const stream = parseZipLine(line);
|
|
147
|
+
if (stream) {
|
|
148
|
+
if (stream.type === "summary")
|
|
149
|
+
summary = stream.data;
|
|
150
|
+
if (stream.type === "progress") {
|
|
151
|
+
const current = Math.max(0, stream.data.files - 1);
|
|
152
|
+
await data.onProgress?.({
|
|
153
|
+
total: summary.files,
|
|
154
|
+
current,
|
|
155
|
+
path: stream.data.path,
|
|
156
|
+
percent: stream.data.progress,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
await data.onStream?.(stream);
|
|
160
|
+
}
|
|
139
161
|
}
|
|
140
162
|
},
|
|
141
163
|
},
|
|
142
164
|
});
|
|
143
|
-
|
|
165
|
+
await data.onProgress?.({
|
|
166
|
+
total: summary.files,
|
|
167
|
+
current: summary.files,
|
|
168
|
+
percent: 100,
|
|
169
|
+
type: "end",
|
|
170
|
+
});
|
|
171
|
+
return summary;
|
|
144
172
|
}
|
|
145
173
|
exports.zip = zip;
|
|
146
174
|
function parseUnzipLine(line) {
|
|
147
175
|
let matches = null;
|
|
148
|
-
if ((matches = /^\s*(
|
|
149
|
-
const progress = Number(matches[
|
|
150
|
-
const files = Number(matches[2]);
|
|
176
|
+
if ((matches = /^\s*(?<percent>\d+)%(?: (?<files>\d+))? \-/.exec(line))) {
|
|
177
|
+
const progress = Number(matches.groups["percent"]);
|
|
178
|
+
const files = matches.groups["files"] ? Number(matches[2]) : 1;
|
|
151
179
|
const path = line.slice(line.indexOf("-") + 1).trim();
|
|
152
180
|
return {
|
|
153
181
|
type: "progress",
|
|
154
|
-
data: { progress, path, files },
|
|
182
|
+
data: { percent: progress, path, files },
|
|
155
183
|
};
|
|
156
184
|
}
|
|
157
185
|
}
|
|
158
186
|
async function unzip(data) {
|
|
159
|
-
|
|
187
|
+
let summary = {
|
|
188
|
+
files: 0,
|
|
189
|
+
};
|
|
190
|
+
await data.onProgress?.({
|
|
191
|
+
current: summary.files,
|
|
192
|
+
percent: 0,
|
|
193
|
+
type: "start",
|
|
194
|
+
});
|
|
195
|
+
const result = await (0, process_util_1.exec)(data.command ?? "7z", [
|
|
160
196
|
"x",
|
|
161
197
|
"-bsp1",
|
|
162
198
|
(0, path_1.normalize)(data.input),
|
|
@@ -167,15 +203,36 @@ async function unzip(data) {
|
|
|
167
203
|
log: data.verbose ?? false,
|
|
168
204
|
stderr: { toExitCode: true },
|
|
169
205
|
stdout: {
|
|
170
|
-
...(data.onStream && {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
206
|
+
...((data.onStream || data.onProgress) && {
|
|
207
|
+
onData: async (chunk) => {
|
|
208
|
+
const lines = chunk.replaceAll("\b", "").split(/\r?\n/);
|
|
209
|
+
for (const line of lines) {
|
|
210
|
+
const stream = parseUnzipLine(line);
|
|
211
|
+
if (stream) {
|
|
212
|
+
if (stream.type === "progress") {
|
|
213
|
+
const current = Math.max(0, stream.data.files - 1);
|
|
214
|
+
summary.files = stream.data.files;
|
|
215
|
+
await data.onProgress?.({
|
|
216
|
+
current,
|
|
217
|
+
percent: stream.data.percent,
|
|
218
|
+
path: stream.data.path,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
await data.onStream?.(stream);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
176
224
|
},
|
|
177
225
|
}),
|
|
178
226
|
},
|
|
179
227
|
});
|
|
228
|
+
await data.onProgress?.({
|
|
229
|
+
current: summary.files,
|
|
230
|
+
percent: 100,
|
|
231
|
+
type: "end",
|
|
232
|
+
});
|
|
233
|
+
return {
|
|
234
|
+
...result,
|
|
235
|
+
...summary,
|
|
236
|
+
};
|
|
180
237
|
}
|
|
181
238
|
exports.unzip = unzip;
|