@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.
- package/Action/BackupAction.js +4 -2
- package/Action/BackupSessionsAction.js +2 -0
- package/Action/CleanCacheAction.js +1 -0
- package/Action/ConfigAction.js +1 -0
- package/Action/InitAction.js +2 -0
- package/Action/PruneAction.js +2 -0
- package/Action/RestoreAction.js +4 -2
- package/Action/RestoreSessionsAction.js +2 -0
- package/Action/SnapshotsAction.js +2 -0
- package/Command/CommandAbstract.js +2 -0
- package/Entity/BackupSessionEntity.js +5 -2
- package/Entity/BackupSessionRepositoryEntity.js +5 -2
- package/Entity/BackupSessionTaskEntity.js +4 -2
- package/Entity/CrudEntityAbstract.js +3 -0
- package/Entity/RestoreSessionEntity.js +4 -2
- package/Entity/RestoreSessionRepositoryEntity.js +5 -2
- package/Entity/RestoreSessionTaskEntity.js +4 -2
- package/Entity/StateEntityAbstract.js +5 -0
- package/Factory/CommandFactory.js +1 -1
- package/JsonSchema/DefinitionEnum.js +1 -1
- package/Repository/DatatruckRepository.d.ts +8 -14
- package/Repository/DatatruckRepository.js +115 -298
- package/Repository/GitRepository.js +1 -1
- package/Repository/RepositoryAbstract.js +4 -2
- package/Repository/ResticRepository.js +2 -1
- package/SessionDriver/ConsoleSessionDriver.js +9 -5
- package/SessionDriver/SessionDriverAbstract.js +3 -2
- package/SessionDriver/SqliteSessionDriver.js +2 -4
- package/SessionManager/BackupSessionManager.js +3 -6
- package/SessionManager/RestoreSessionManager.js +3 -6
- package/SessionManager/SessionManagerAbstract.js +4 -0
- package/Task/GitTask.js +1 -0
- package/Task/MariadbTask.d.ts +11 -0
- package/Task/MariadbTask.js +234 -51
- package/Task/MssqlTask.js +2 -1
- package/Task/ScriptTask.js +1 -0
- package/Task/SqlDumpTaskAbstract.js +1 -0
- package/Task/TaskAbstract.js +2 -1
- package/config.schema.json +67 -37
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +10 -9
- package/utils/DataFormat.js +1 -0
- package/utils/Git.js +1 -0
- package/utils/ObjectVault.js +3 -5
- package/utils/Restic.js +1 -0
- package/utils/datatruck/config.d.ts +1 -1
- package/utils/fs.d.ts +17 -2
- package/utils/fs.js +58 -7
- package/utils/process.d.ts +55 -3
- package/utils/process.js +159 -19
- package/utils/tar.d.ts +32 -0
- package/utils/tar.js +92 -0
- package/utils/zip.d.ts +0 -97
- package/utils/zip.js +0 -238
package/Task/MariadbTask.d.ts
CHANGED
|
@@ -11,6 +11,17 @@ export type MariadbTaskConfigType = {
|
|
|
11
11
|
excludeTables?: string[];
|
|
12
12
|
includeDatabases?: string[];
|
|
13
13
|
excludeDatabases?: string[];
|
|
14
|
+
/**
|
|
15
|
+
* @default "auto"
|
|
16
|
+
*/
|
|
17
|
+
parallel?: number | "auto";
|
|
18
|
+
compress?: {
|
|
19
|
+
command: string;
|
|
20
|
+
args?: string[];
|
|
21
|
+
} | {
|
|
22
|
+
type: "gzip" | "pigz";
|
|
23
|
+
args?: string[];
|
|
24
|
+
};
|
|
14
25
|
};
|
|
15
26
|
export declare const mariadbTaskName = "mariadb";
|
|
16
27
|
export declare const mariadbTaskDefinition: JSONSchema7;
|
package/Task/MariadbTask.js
CHANGED
|
@@ -6,11 +6,13 @@ const cli_1 = require("../utils/cli");
|
|
|
6
6
|
const fs_1 = require("../utils/fs");
|
|
7
7
|
const math_1 = require("../utils/math");
|
|
8
8
|
const process_1 = require("../utils/process");
|
|
9
|
+
const tar_1 = require("../utils/tar");
|
|
9
10
|
const TaskAbstract_1 = require("./TaskAbstract");
|
|
10
11
|
const assert_1 = require("assert");
|
|
12
|
+
const fs_2 = require("fs");
|
|
11
13
|
const promises_1 = require("fs/promises");
|
|
14
|
+
const os_1 = require("os");
|
|
12
15
|
const path_1 = require("path");
|
|
13
|
-
const posix_1 = require("path/posix");
|
|
14
16
|
exports.mariadbTaskName = "mariadb";
|
|
15
17
|
exports.mariadbTaskDefinition = {
|
|
16
18
|
type: "object",
|
|
@@ -39,9 +41,67 @@ exports.mariadbTaskDefinition = {
|
|
|
39
41
|
excludeTables: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
|
|
40
42
|
includeDatabases: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
|
|
41
43
|
excludeDatabases: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
|
|
44
|
+
parallel: {
|
|
45
|
+
anyOf: [{ type: "integer", minimum: 1 }, { enum: ["auto"] }],
|
|
46
|
+
},
|
|
47
|
+
compress: {
|
|
48
|
+
anyOf: [
|
|
49
|
+
{
|
|
50
|
+
type: "object",
|
|
51
|
+
additionalProperties: false,
|
|
52
|
+
properties: {
|
|
53
|
+
command: { type: "string" },
|
|
54
|
+
args: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
type: "object",
|
|
59
|
+
additionalProperties: false,
|
|
60
|
+
properties: {
|
|
61
|
+
type: { enum: ["gzip", "pigz"] },
|
|
62
|
+
args: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
42
67
|
},
|
|
43
68
|
};
|
|
69
|
+
function normalizeConfig(input) {
|
|
70
|
+
let parallel = input.parallel ?? "auto";
|
|
71
|
+
let cores = (0, os_1.cpus)().length;
|
|
72
|
+
if (parallel === "auto") {
|
|
73
|
+
parallel = input.compress ? Math.round(cores / 2) : cores;
|
|
74
|
+
cores = Math.max(1, cores - parallel);
|
|
75
|
+
}
|
|
76
|
+
let compress;
|
|
77
|
+
if (input.compress && "type" in input.compress) {
|
|
78
|
+
if (input.compress.type === "pigz") {
|
|
79
|
+
compress = { command: "pigz", args: [] };
|
|
80
|
+
if (!input.compress.args?.includes("-p")) {
|
|
81
|
+
compress.args.push("-p", cores.toString());
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else if (input.compress.type === "gzip") {
|
|
85
|
+
compress = { command: "gzip" };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
compress = input.compress;
|
|
90
|
+
}
|
|
91
|
+
return { parallel, compress };
|
|
92
|
+
}
|
|
93
|
+
const parseLineRegex = /^(?:\[(?<step>\d+)\] )?(?<dateTime>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})?\s+(?<text>.+)\s*$/;
|
|
94
|
+
function parseLine(line) {
|
|
95
|
+
const result = parseLineRegex.exec(line);
|
|
96
|
+
if (result) {
|
|
97
|
+
return result.groups;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
return { text: line };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
44
103
|
class MariadbTask extends TaskAbstract_1.TaskAbstract {
|
|
104
|
+
verbose;
|
|
45
105
|
get command() {
|
|
46
106
|
return this.config.command ?? "mariabackup";
|
|
47
107
|
}
|
|
@@ -58,18 +118,25 @@ class MariadbTask extends TaskAbstract_1.TaskAbstract {
|
|
|
58
118
|
const targetPath = data.targetPath;
|
|
59
119
|
(0, assert_1.ok)(typeof sourcePath === "string");
|
|
60
120
|
(0, assert_1.ok)(typeof targetPath === "string");
|
|
121
|
+
const { parallel, compress } = normalizeConfig(config);
|
|
61
122
|
const args = [
|
|
62
123
|
`--backup`,
|
|
63
124
|
`--datadir=${sourcePath}`,
|
|
64
|
-
`--target-dir=${targetPath}`,
|
|
65
125
|
`--host=${config.hostname}`,
|
|
66
126
|
`--user=${config.username}`,
|
|
127
|
+
`--parallel=${parallel}`,
|
|
67
128
|
`--password=${typeof config.password === "string"
|
|
68
129
|
? config.password
|
|
69
130
|
: config.password
|
|
70
131
|
? (await (0, promises_1.readFile)(config.password.path)).toString()
|
|
71
132
|
: ""}`,
|
|
72
133
|
];
|
|
134
|
+
if (compress) {
|
|
135
|
+
args.push(`--stream=xbstream`);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
args.push(`--target-dir=${targetPath}`);
|
|
139
|
+
}
|
|
73
140
|
if (config.includeDatabases)
|
|
74
141
|
args.push(`--databases=${config.includeDatabases.join(" ")}`);
|
|
75
142
|
if (config.excludeDatabases)
|
|
@@ -83,34 +150,23 @@ class MariadbTask extends TaskAbstract_1.TaskAbstract {
|
|
|
83
150
|
await (0, fs_1.forEachFile)(sourcePath, () => {
|
|
84
151
|
total++;
|
|
85
152
|
});
|
|
86
|
-
let
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
fatalError = true;
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
const matches = pathRegex.exec(line);
|
|
99
|
-
if (matches) {
|
|
100
|
-
current++;
|
|
101
|
-
paths.push(matches[1]);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
if (fatalError) {
|
|
106
|
-
childProcess.kill();
|
|
153
|
+
let p1;
|
|
154
|
+
let lastLineText;
|
|
155
|
+
const pathRegex = /((Copying|Streaming) .+) to/;
|
|
156
|
+
const onData = async (line) => {
|
|
157
|
+
const { text } = parseLine(line);
|
|
158
|
+
lastLineText = text;
|
|
159
|
+
if (line.includes("[ERROR] InnoDB: Unsupported redo log format.") ||
|
|
160
|
+
line.includes("Error: cannot read redo log header")) {
|
|
161
|
+
p1.kill();
|
|
107
162
|
}
|
|
108
|
-
else
|
|
109
|
-
const
|
|
163
|
+
else {
|
|
164
|
+
const matches = pathRegex.exec(text);
|
|
165
|
+
if (matches)
|
|
166
|
+
current++;
|
|
110
167
|
await data.onProgress({
|
|
111
168
|
relative: {
|
|
112
|
-
|
|
113
|
-
payload: path,
|
|
169
|
+
payload: matches ? matches[1] : text,
|
|
114
170
|
},
|
|
115
171
|
absolute: {
|
|
116
172
|
current,
|
|
@@ -120,36 +176,163 @@ class MariadbTask extends TaskAbstract_1.TaskAbstract {
|
|
|
120
176
|
});
|
|
121
177
|
}
|
|
122
178
|
};
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
179
|
+
const stats = { xbFiles: total };
|
|
180
|
+
await (0, promises_1.writeFile)((0, path_1.join)(targetPath, "stats.dtt.json"), JSON.stringify(stats));
|
|
181
|
+
if (compress) {
|
|
182
|
+
const p0 = (0, fs_2.createWriteStream)((0, path_1.join)(targetPath, "db.xb.gz"));
|
|
183
|
+
p1 = (0, process_1.createProcess)(command, args, {
|
|
184
|
+
$log: {
|
|
185
|
+
exec: this.verbose,
|
|
186
|
+
stderr: this.verbose,
|
|
187
|
+
},
|
|
188
|
+
$stderr: {
|
|
189
|
+
parseLines: true,
|
|
190
|
+
onData,
|
|
191
|
+
},
|
|
192
|
+
$onExitCode: (code) => `Exit code: ${code} - ${lastLineText}`,
|
|
193
|
+
});
|
|
194
|
+
const p2 = (0, process_1.createProcess)(compress.command, compress.args);
|
|
195
|
+
p1.stdout.pipe(p2.stdin, { end: true });
|
|
196
|
+
p2.stdout.pipe(p0, { end: true });
|
|
197
|
+
await Promise.all([p1, p2, (0, fs_1.waitForClose)(p0)]);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
p1 = (0, process_1.createProcess)(command, args, {
|
|
201
|
+
$log: this.verbose,
|
|
202
|
+
$stdout: {
|
|
203
|
+
parseLines: true,
|
|
204
|
+
onData,
|
|
205
|
+
},
|
|
206
|
+
$stderr: {
|
|
207
|
+
parseLines: true,
|
|
208
|
+
onData,
|
|
209
|
+
},
|
|
210
|
+
$onExitCode: (code) => `Exit code: ${code} - ${lastLineText}`,
|
|
211
|
+
});
|
|
212
|
+
await p1;
|
|
213
|
+
await (0, process_1.exec)(command, [`--prepare`, `--target-dir=${targetPath}`], undefined, {
|
|
214
|
+
log: this.verbose,
|
|
215
|
+
stderr: { onData: () => { } },
|
|
216
|
+
});
|
|
217
|
+
}
|
|
139
218
|
}
|
|
140
219
|
async onRestore(data) {
|
|
141
220
|
this.verbose = data.options.verbose;
|
|
142
221
|
const restorePath = data.package.restorePath;
|
|
143
222
|
(0, assert_1.ok)(typeof restorePath === "string");
|
|
144
223
|
await (0, fs_1.mkdirIfNotExists)(restorePath);
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
224
|
+
const removeFiles = [];
|
|
225
|
+
let files = [];
|
|
226
|
+
const reloadFiles = async (data = {}) => {
|
|
227
|
+
if (data.removeFile)
|
|
228
|
+
removeFiles.push(data.removeFile);
|
|
229
|
+
return (files = (await (0, fs_1.readDir)(restorePath)).filter((v) => !removeFiles.includes(v)));
|
|
230
|
+
};
|
|
231
|
+
await reloadFiles();
|
|
232
|
+
const absolute = {
|
|
233
|
+
format: "amount",
|
|
234
|
+
total: 3,
|
|
235
|
+
current: 0,
|
|
236
|
+
description: undefined,
|
|
237
|
+
payload: undefined,
|
|
238
|
+
percent: undefined,
|
|
239
|
+
};
|
|
240
|
+
// Stats
|
|
241
|
+
const statsFile = files.find((file) => file === "stats.dtt.json");
|
|
242
|
+
let stats;
|
|
243
|
+
if (statsFile) {
|
|
244
|
+
const statsFilePath = (0, path_1.join)(restorePath, statsFile);
|
|
245
|
+
const statsBuffer = await (0, promises_1.readFile)(statsFilePath);
|
|
246
|
+
stats = JSON.parse(statsBuffer.toString());
|
|
247
|
+
await reloadFiles({ removeFile: statsFile });
|
|
248
|
+
}
|
|
249
|
+
const zipFile = files.find((file) => file.endsWith(".gz"));
|
|
250
|
+
absolute.current++;
|
|
251
|
+
absolute.percent = (0, math_1.progressPercent)(absolute.total, absolute.current);
|
|
252
|
+
// Extract
|
|
253
|
+
if (files.length === 1 && zipFile) {
|
|
254
|
+
absolute.description = "Extracting";
|
|
255
|
+
absolute.payload = zipFile;
|
|
256
|
+
await data.onProgress({
|
|
257
|
+
absolute,
|
|
258
|
+
});
|
|
259
|
+
await (0, tar_1.extractTar)({
|
|
260
|
+
input: (0, path_1.join)(restorePath, zipFile),
|
|
261
|
+
output: restorePath,
|
|
262
|
+
verbose: this.verbose,
|
|
263
|
+
async onEntry(item) {
|
|
264
|
+
await data.onProgress({
|
|
265
|
+
absolute,
|
|
266
|
+
relative: {
|
|
267
|
+
payload: item.path,
|
|
268
|
+
format: "amount",
|
|
269
|
+
percent: item.progress.percent,
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
},
|
|
273
|
+
});
|
|
274
|
+
await reloadFiles({ removeFile: zipFile });
|
|
275
|
+
}
|
|
276
|
+
// Extract stream
|
|
277
|
+
const xbFile = files.find((file) => file.endsWith(".xb"));
|
|
278
|
+
absolute.current++;
|
|
279
|
+
absolute.percent = (0, math_1.progressPercent)(absolute.total, absolute.current);
|
|
280
|
+
if (files.length === 1 && xbFile) {
|
|
281
|
+
const xbFilePath = (0, path_1.join)(restorePath, xbFile);
|
|
282
|
+
const xbStream = (0, fs_2.createReadStream)(xbFilePath);
|
|
283
|
+
removeFiles.push(xbFile);
|
|
284
|
+
absolute.description = "Extracting stream";
|
|
285
|
+
absolute.payload = xbFile;
|
|
286
|
+
await data.onProgress({
|
|
287
|
+
absolute,
|
|
288
|
+
});
|
|
289
|
+
let currentXbFiles = 0;
|
|
290
|
+
const { parallel } = normalizeConfig({ parallel: this.config.parallel });
|
|
291
|
+
const p1 = (0, process_1.createProcess)("mbstream", ["-x", "-C", restorePath, "-v", "-p", parallel], {
|
|
292
|
+
$log: this.verbose,
|
|
293
|
+
$stderr: {
|
|
294
|
+
parseLines: true,
|
|
295
|
+
async onData(line) {
|
|
296
|
+
const { text: path } = parseLine(line);
|
|
297
|
+
await data.onProgress({
|
|
298
|
+
absolute,
|
|
299
|
+
relative: {
|
|
300
|
+
payload: path,
|
|
301
|
+
format: "amount",
|
|
302
|
+
current: ++currentXbFiles,
|
|
303
|
+
total: stats?.xbFiles,
|
|
304
|
+
percent: stats?.xbFiles
|
|
305
|
+
? (0, math_1.progressPercent)(stats.xbFiles, currentXbFiles)
|
|
306
|
+
: undefined,
|
|
307
|
+
},
|
|
308
|
+
});
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
});
|
|
312
|
+
xbStream.pipe(p1.stdin, { end: true });
|
|
313
|
+
await Promise.all([(0, fs_1.waitForClose)(xbStream), p1]);
|
|
314
|
+
}
|
|
315
|
+
// Prepare
|
|
316
|
+
absolute.current++;
|
|
317
|
+
absolute.percent = (0, math_1.progressPercent)(absolute.total, absolute.current);
|
|
318
|
+
if (files.length === 1 && xbFile) {
|
|
319
|
+
absolute.description = "Preparing";
|
|
320
|
+
await data.onProgress({
|
|
321
|
+
absolute,
|
|
322
|
+
});
|
|
323
|
+
await (0, process_1.exec)(this.command, [`--prepare`, `--target-dir=${restorePath}`], undefined, {
|
|
324
|
+
log: this.verbose,
|
|
325
|
+
stderr: { onData: () => { } },
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
await reloadFiles();
|
|
329
|
+
removeFiles.push(...files.filter((file) => file.startsWith("ib_logfile")));
|
|
330
|
+
// Remove files
|
|
331
|
+
for (const file of removeFiles) {
|
|
332
|
+
const filePath = (0, path_1.join)(restorePath, file);
|
|
333
|
+
if (this.verbose)
|
|
334
|
+
(0, cli_1.logExec)("rm", [filePath]);
|
|
335
|
+
await (0, promises_1.rm)(filePath);
|
|
153
336
|
}
|
|
154
337
|
}
|
|
155
338
|
}
|
package/Task/MssqlTask.js
CHANGED
|
@@ -25,6 +25,8 @@ exports.mssqlTaskDefinition = {
|
|
|
25
25
|
},
|
|
26
26
|
};
|
|
27
27
|
class MssqlTask extends TaskAbstract_1.TaskAbstract {
|
|
28
|
+
static SUFFIX = ".BAK";
|
|
29
|
+
verbose;
|
|
28
30
|
get command() {
|
|
29
31
|
return this.config.command ?? "sqlcmd";
|
|
30
32
|
}
|
|
@@ -106,4 +108,3 @@ class MssqlTask extends TaskAbstract_1.TaskAbstract {
|
|
|
106
108
|
}
|
|
107
109
|
}
|
|
108
110
|
exports.MssqlTask = MssqlTask;
|
|
109
|
-
MssqlTask.SUFFIX = ".BAK";
|
package/Task/ScriptTask.js
CHANGED
package/Task/TaskAbstract.js
CHANGED
|
@@ -3,9 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.TaskAbstract = void 0;
|
|
4
4
|
const fs_1 = require("../utils/fs");
|
|
5
5
|
class TaskAbstract {
|
|
6
|
+
config;
|
|
7
|
+
tmpDirs = [];
|
|
6
8
|
constructor(config) {
|
|
7
9
|
this.config = config;
|
|
8
|
-
this.tmpDirs = [];
|
|
9
10
|
}
|
|
10
11
|
async mkTmpDir(prefix, id) {
|
|
11
12
|
const dir = await (0, fs_1.mkTmpDir)(prefix, id);
|
package/config.schema.json
CHANGED
|
@@ -458,45 +458,31 @@
|
|
|
458
458
|
"additionalProperties": false,
|
|
459
459
|
"properties": {
|
|
460
460
|
"compress": {
|
|
461
|
-
"
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
},
|
|
484
|
-
"exclude": {
|
|
485
|
-
"$ref": "#/definitions/stringlist-util"
|
|
486
|
-
},
|
|
487
|
-
"onePackByResult": {
|
|
488
|
-
"type": "boolean"
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
}
|
|
461
|
+
"type": "boolean"
|
|
462
|
+
},
|
|
463
|
+
"packs": {
|
|
464
|
+
"type": "array",
|
|
465
|
+
"items": {
|
|
466
|
+
"type": "object",
|
|
467
|
+
"additionalProperties": false,
|
|
468
|
+
"required": [
|
|
469
|
+
"include"
|
|
470
|
+
],
|
|
471
|
+
"properties": {
|
|
472
|
+
"name": {
|
|
473
|
+
"type": "string"
|
|
474
|
+
},
|
|
475
|
+
"include": {
|
|
476
|
+
"$ref": "#/definitions/stringlist-util"
|
|
477
|
+
},
|
|
478
|
+
"exclude": {
|
|
479
|
+
"$ref": "#/definitions/stringlist-util"
|
|
480
|
+
},
|
|
481
|
+
"onePackByResult": {
|
|
482
|
+
"type": "boolean"
|
|
493
483
|
}
|
|
494
484
|
}
|
|
495
|
-
|
|
496
|
-
},
|
|
497
|
-
"fileCopyConcurrency": {
|
|
498
|
-
"type": "integer",
|
|
499
|
-
"minimum": 1
|
|
485
|
+
}
|
|
500
486
|
}
|
|
501
487
|
}
|
|
502
488
|
},
|
|
@@ -798,6 +784,50 @@
|
|
|
798
784
|
},
|
|
799
785
|
"excludeDatabases": {
|
|
800
786
|
"$ref": "#/definitions/stringlist-util"
|
|
787
|
+
},
|
|
788
|
+
"parallel": {
|
|
789
|
+
"anyOf": [
|
|
790
|
+
{
|
|
791
|
+
"type": "integer",
|
|
792
|
+
"minimum": 1
|
|
793
|
+
},
|
|
794
|
+
{
|
|
795
|
+
"enum": [
|
|
796
|
+
"auto"
|
|
797
|
+
]
|
|
798
|
+
}
|
|
799
|
+
]
|
|
800
|
+
},
|
|
801
|
+
"compress": {
|
|
802
|
+
"anyOf": [
|
|
803
|
+
{
|
|
804
|
+
"type": "object",
|
|
805
|
+
"additionalProperties": false,
|
|
806
|
+
"properties": {
|
|
807
|
+
"command": {
|
|
808
|
+
"type": "string"
|
|
809
|
+
},
|
|
810
|
+
"args": {
|
|
811
|
+
"$ref": "#/definitions/stringlist-util"
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
},
|
|
815
|
+
{
|
|
816
|
+
"type": "object",
|
|
817
|
+
"additionalProperties": false,
|
|
818
|
+
"properties": {
|
|
819
|
+
"type": {
|
|
820
|
+
"enum": [
|
|
821
|
+
"gzip",
|
|
822
|
+
"pigz"
|
|
823
|
+
]
|
|
824
|
+
},
|
|
825
|
+
"args": {
|
|
826
|
+
"$ref": "#/definitions/stringlist-util"
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
]
|
|
801
831
|
}
|
|
802
832
|
}
|
|
803
833
|
},
|
package/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datatruck/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"dependencies": {
|
|
5
|
-
"ajv": "^8.
|
|
5
|
+
"ajv": "^8.12.0",
|
|
6
6
|
"async": "^3.2.4",
|
|
7
7
|
"chalk": "^4.1.2",
|
|
8
8
|
"cli-table3": "^0.6.3",
|
|
9
|
-
"commander": "^
|
|
10
|
-
"dayjs": "^1.11.
|
|
11
|
-
"fast-folder-size": "^
|
|
12
|
-
"fast-glob": "^3.
|
|
9
|
+
"commander": "^11.0.0",
|
|
10
|
+
"dayjs": "^1.11.10",
|
|
11
|
+
"fast-folder-size": "^2.2.0",
|
|
12
|
+
"fast-glob": "^3.3.1",
|
|
13
13
|
"micromatch": "^4.0.5",
|
|
14
14
|
"pretty-bytes": "^5.6.0",
|
|
15
|
-
"sqlite": "^
|
|
16
|
-
"sqlite3": "^5.1.
|
|
15
|
+
"sqlite": "^5.0.1",
|
|
16
|
+
"sqlite3": "^5.1.6",
|
|
17
|
+
"tar": "^6.2.0"
|
|
17
18
|
},
|
|
18
19
|
"optionalDependencies": {
|
|
19
20
|
"ts-node": "^10.9.1",
|
|
20
|
-
"yaml": "^2.2
|
|
21
|
+
"yaml": "^2.3.2"
|
|
21
22
|
},
|
|
22
23
|
"engine": {
|
|
23
24
|
"node": ">=16.0.0"
|
package/utils/DataFormat.js
CHANGED
package/utils/Git.js
CHANGED
package/utils/ObjectVault.js
CHANGED
|
@@ -2,11 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ObjectVault = void 0;
|
|
4
4
|
class ObjectVault {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
this.objects = {};
|
|
9
|
-
}
|
|
5
|
+
counter = 0;
|
|
6
|
+
ids = {};
|
|
7
|
+
objects = {};
|
|
10
8
|
static serializeKeys(keys) {
|
|
11
9
|
return JSON.stringify(keys);
|
|
12
10
|
}
|
package/utils/Restic.js
CHANGED
package/utils/fs.d.ts
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
/// <reference types="node" />
|
|
3
3
|
/// <reference types="node" />
|
|
4
4
|
/// <reference types="node" />
|
|
5
|
-
import {
|
|
5
|
+
import { Progress } from "./progress";
|
|
6
|
+
import { Entry, Options } from "fast-glob";
|
|
7
|
+
import { Dirent, ReadStream, Stats } from "fs";
|
|
6
8
|
import { WriteStream } from "fs";
|
|
7
9
|
import { Interface } from "readline";
|
|
8
10
|
export declare const isWSLSystem: boolean;
|
|
@@ -51,7 +53,7 @@ export declare function writeGitIgnoreList(options: {
|
|
|
51
53
|
paths: NodeJS.ReadableStream | string[];
|
|
52
54
|
outDir: string;
|
|
53
55
|
}): Promise<string>;
|
|
54
|
-
export declare function waitForClose(stream: WriteStream): Promise<
|
|
56
|
+
export declare function waitForClose(stream: WriteStream | ReadStream): Promise<void>;
|
|
55
57
|
export declare function copyFileWithStreams(source: string, target: string): Promise<unknown>;
|
|
56
58
|
export declare function updateFileStats(path: string, fileInfo: Stats): Promise<void>;
|
|
57
59
|
export declare function isNotFoundError(error: unknown): boolean;
|
|
@@ -97,4 +99,17 @@ export declare function cpy(options: {
|
|
|
97
99
|
files: number;
|
|
98
100
|
dirs: number;
|
|
99
101
|
}>;
|
|
102
|
+
export declare function createFileScanner(options: {
|
|
103
|
+
glob: Options & {
|
|
104
|
+
include: string[];
|
|
105
|
+
};
|
|
106
|
+
onProgress: (data: Progress) => Promise<void>;
|
|
107
|
+
}): Promise<{
|
|
108
|
+
disposed: boolean;
|
|
109
|
+
total: number;
|
|
110
|
+
current: number;
|
|
111
|
+
progress: (description: string, path?: string) => Promise<void>;
|
|
112
|
+
end: () => Promise<void>;
|
|
113
|
+
start: (cb?: ((entry: Required<Entry>) => any) | undefined) => Promise<void>;
|
|
114
|
+
}>;
|
|
100
115
|
export {};
|