@datatruck/cli 0.33.0 → 0.34.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.
Files changed (48) hide show
  1. package/config.schema.json +3 -0
  2. package/lib/actions/BackupAction.d.ts +8 -2
  3. package/lib/actions/BackupAction.js +22 -8
  4. package/lib/actions/CopyAction.d.ts +4 -1
  5. package/lib/actions/CopyAction.js +15 -4
  6. package/lib/commands/BackupCommand.d.ts +2 -0
  7. package/lib/repositories/DatatruckRepository.d.ts +6 -2
  8. package/lib/repositories/DatatruckRepository.js +11 -3
  9. package/lib/repositories/GitRepository.d.ts +6 -2
  10. package/lib/repositories/GitRepository.js +8 -3
  11. package/lib/repositories/RepositoryAbstract.d.ts +6 -2
  12. package/lib/repositories/ResticRepository.d.ts +6 -2
  13. package/lib/repositories/ResticRepository.js +11 -5
  14. package/lib/tasks/GitTask.js +32 -50
  15. package/lib/tasks/MariadbTask.js +43 -56
  16. package/lib/tasks/MssqlTask.js +5 -11
  17. package/lib/tasks/MysqlDumpTask.js +4 -4
  18. package/lib/tasks/PostgresqlDumpTask.d.ts +1 -1
  19. package/lib/tasks/PostgresqlDumpTask.js +9 -32
  20. package/lib/tasks/SqlDumpTaskAbstract.d.ts +1 -2
  21. package/lib/tasks/SqlDumpTaskAbstract.js +1 -1
  22. package/lib/utils/Git.d.ts +9 -7
  23. package/lib/utils/Git.js +30 -29
  24. package/lib/utils/Restic.d.ts +11 -11
  25. package/lib/utils/Restic.js +72 -90
  26. package/lib/utils/async-process.d.ts +66 -0
  27. package/lib/utils/async-process.js +237 -0
  28. package/lib/utils/async.d.ts +3 -5
  29. package/lib/utils/async.js +2 -2
  30. package/lib/utils/datatruck/client.d.ts +3 -1
  31. package/lib/utils/datatruck/client.js +1 -1
  32. package/lib/utils/datatruck/config-type.d.ts +1 -0
  33. package/lib/utils/datatruck/cron-server.js +2 -2
  34. package/lib/utils/datatruck/report-list.d.ts +2 -0
  35. package/lib/utils/datatruck/report-list.js +1 -1
  36. package/lib/utils/fs.d.ts +7 -2
  37. package/lib/utils/fs.js +0 -1
  38. package/lib/utils/http.d.ts +3 -1
  39. package/lib/utils/http.js +6 -1
  40. package/lib/utils/mysql.d.ts +8 -10
  41. package/lib/utils/mysql.js +60 -79
  42. package/lib/utils/process.d.ts +3 -92
  43. package/lib/utils/process.js +7 -311
  44. package/lib/utils/spawnSteps.js +9 -10
  45. package/lib/utils/tar.js +29 -49
  46. package/lib/utils/virtual-fs.d.ts +6 -2
  47. package/lib/utils/virtual-fs.js +4 -1
  48. package/package.json +2 -2
@@ -3,100 +3,22 @@ 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.exec = exports.createProcess = exports.logProcessExec = exports.waitForClose = exports.parseStreamData = exports.logExecStderr = exports.logExecStdout = void 0;
6
+ exports.logProcess = exports.logStderr = exports.logStdout = void 0;
7
7
  const cli_1 = require("./cli");
8
- const fs_1 = require("./fs");
9
- const math_1 = require("./math");
10
8
  const chalk_1 = __importDefault(require("chalk"));
11
- const child_process_1 = require("child_process");
12
- const fs_2 = require("fs");
13
- const promises_1 = require("fs/promises");
14
- const readline_1 = require("readline");
15
9
  const stream_1 = require("stream");
16
- function logExecStdout(input) {
10
+ function logStdout(input) {
17
11
  let text = input.colorize ? chalk_1.default.grey(input.data) : input.data;
18
12
  if (input.lineSalt)
19
13
  text += "\n";
20
14
  input.stderr ? process.stderr.write(text) : process.stdout.write(text);
21
15
  }
22
- exports.logExecStdout = logExecStdout;
23
- function logExecStderr(data, colorize) {
16
+ exports.logStdout = logStdout;
17
+ function logStderr(data, colorize) {
24
18
  process.stdout.write(colorize ? chalk_1.default.red(data) : data);
25
19
  }
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) {
20
+ exports.logStderr = logStderr;
21
+ async function logProcess(command, argv, options) {
100
22
  const logEnv = options.envNames?.reduce((env, key) => {
101
23
  const value = options?.env?.[key];
102
24
  if (typeof value !== "undefined")
@@ -111,230 +33,4 @@ async function logProcessExec(command, argv, options) {
111
33
  ]
112
34
  : argv, logEnv, options.toStderr);
113
35
  }
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;
173
- async function exec(command, argv = [], options = null, settings = {}) {
174
- const pipe = settings.pipe;
175
- let log = {};
176
- if (settings.log === true) {
177
- log.exec = log.stdout = log.stderr = log.allToStderr = log.colorize = true;
178
- }
179
- else if (settings.log) {
180
- log = settings.log;
181
- }
182
- if (log.exec)
183
- logProcessExec(command, argv, {
184
- env: options?.env,
185
- envNames: log.envNames,
186
- pipe: pipe?.stream,
187
- toStderr: log.allToStderr,
188
- });
189
- if (typeof options?.cwd === "string" && !(await (0, fs_1.existsDir)(options.cwd)))
190
- throw new Error(`Current working directory does not exist: ${options.cwd}`);
191
- if (pipe?.stream instanceof fs_2.ReadStream && "onReadProgress" in pipe) {
192
- const fileInfo = await (0, promises_1.stat)(pipe.stream.path);
193
- const totalBytes = fileInfo.size;
194
- let currentBytes = 0;
195
- pipe.stream.on("data", (data) => {
196
- currentBytes += data.length;
197
- pipe.onReadProgress?.({
198
- totalBytes: totalBytes,
199
- currentBytes: currentBytes,
200
- progress: (0, math_1.progressPercent)(totalBytes, currentBytes),
201
- });
202
- });
203
- }
204
- const p = (0, child_process_1.spawn)(command, argv, options ?? {});
205
- settings.onSpawn?.(p);
206
- let spawnError;
207
- const spawnData = {
208
- stdout: "",
209
- stderr: "",
210
- exitCode: 0,
211
- };
212
- let finishListeners = 1;
213
- if (pipe?.stream instanceof fs_2.WriteStream)
214
- finishListeners++;
215
- if (settings.stdout?.parseLines)
216
- finishListeners++;
217
- if (settings.stderr?.parseLines)
218
- finishListeners++;
219
- let streamError;
220
- return new Promise((resolve, reject) => {
221
- const tryFinish = () => {
222
- if (!--finishListeners)
223
- finish();
224
- };
225
- const finish = () => {
226
- if (spawnData.exitCode) {
227
- let exitCodeError;
228
- if (settings.stderr?.toExitCode) {
229
- exitCodeError = new Error(`Exit code ${spawnData.exitCode}: ${command} ${argv.join(" ")} | ${spawnData.stderr
230
- .split(/\r?\n/g)
231
- .filter((v) => !!v.length)
232
- .join(" | ")}`);
233
- }
234
- else {
235
- exitCodeError = new Error(`Exit code ${spawnData.exitCode}: ${command} ${argv.join(" ")}`);
236
- }
237
- const exitCodeErrorResult = settings.onExitCodeError?.(spawnData, exitCodeError);
238
- if (exitCodeErrorResult instanceof Error) {
239
- return reject(exitCodeErrorResult);
240
- }
241
- else if (exitCodeErrorResult !== false) {
242
- return reject(exitCodeError);
243
- }
244
- }
245
- if (streamError) {
246
- reject(streamError);
247
- }
248
- else if (spawnError) {
249
- reject(spawnError);
250
- }
251
- else {
252
- resolve(spawnData);
253
- }
254
- };
255
- if (pipe) {
256
- pipe.stream.on("error", (error) => {
257
- streamError = error;
258
- tryFinish();
259
- });
260
- if (pipe.stream instanceof fs_2.WriteStream) {
261
- if (!p.stdout)
262
- throw new Error(`stdout is not defined`);
263
- if (!p.stderr)
264
- throw new Error(`stderr is not defined`);
265
- if ("onWriteProgress" in pipe && pipe.onWriteProgress) {
266
- let totalBytes = 0;
267
- p.stdout.on("data", (chunk) => {
268
- totalBytes += chunk.length;
269
- pipe.onWriteProgress({ totalBytes });
270
- });
271
- p.stderr.on("data", (chunk) => {
272
- totalBytes += chunk.length;
273
- pipe.onWriteProgress({ totalBytes });
274
- });
275
- }
276
- p.stdout.pipe(pipe.stream, { end: false });
277
- p.stderr.pipe(pipe.stream, { end: false });
278
- p.on("close", tryFinish);
279
- }
280
- else if (pipe.stream instanceof stream_1.Readable) {
281
- if (!p.stdin)
282
- throw new Error(`stdin is not defined`);
283
- pipe.stream.pipe(p.stdin);
284
- }
285
- }
286
- const stdConfig = {
287
- stdout: { log: log.stdout, settings: settings.stdout },
288
- stderr: { log: log.stderr, settings: settings.stderr },
289
- };
290
- for (const inType in stdConfig) {
291
- const type = inType;
292
- const enabled = log[type] || settings[type];
293
- if (!enabled)
294
- continue;
295
- if (!p[type])
296
- throw new Error(`${type} is not defined`);
297
- const parseLines = settings[type]?.parseLines;
298
- const skipEmptyLines = parseLines === "skip-empty";
299
- const onData = (inData) => {
300
- let data = inData.toString();
301
- if (parseLines) {
302
- if (skipEmptyLines && !data.trim().length)
303
- return;
304
- data = `${inData}\n`;
305
- }
306
- if (log[type])
307
- logExecStdout({
308
- data,
309
- stderr: log.allToStderr,
310
- colorize: log.colorize,
311
- });
312
- if (settings[type]?.save ||
313
- (type === "stderr" && settings[type]?.toExitCode))
314
- spawnData[type] += data;
315
- if (settings[type]?.onData)
316
- settings[type].onData(inData.toString());
317
- };
318
- if (parseLines) {
319
- const rl = (0, readline_1.createInterface)({
320
- input: p[type],
321
- });
322
- rl.on("line", onData);
323
- rl.on("close", tryFinish);
324
- }
325
- else if (log[type] ||
326
- settings[type]?.save ||
327
- settings[type]?.onData ||
328
- (type === "stderr" && settings[type]?.toExitCode)) {
329
- p[type].on("data", onData);
330
- }
331
- }
332
- p.on("error", (error) => (spawnError = error)).on("close", (exitCode) => {
333
- spawnData.exitCode = exitCode ?? 0;
334
- if (pipe?.stream instanceof fs_2.WriteStream)
335
- pipe.stream.end();
336
- tryFinish();
337
- });
338
- });
339
- }
340
- exports.exec = exec;
36
+ exports.logProcess = logProcess;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runSpawnSteps = exports.isSpawnStep = void 0;
4
- const process_1 = require("./process");
4
+ const async_process_1 = require("./async-process");
5
5
  const string_1 = require("./string");
6
6
  const temp_1 = require("./temp");
7
7
  const promises_1 = require("fs/promises");
@@ -49,22 +49,21 @@ async function runSpawnSteps(input, options) {
49
49
  : []),
50
50
  ...(step.config.args || []).map((arg) => (0, string_1.render)(arg.toString(), data)),
51
51
  ];
52
- await (0, process_1.exec)(command, args, {
52
+ const p = new async_process_1.AsyncProcess(command, args, {
53
53
  cwd: options.cwd,
54
54
  env: {
55
55
  ...process.env,
56
56
  ...options.env,
57
57
  ...step.config.env,
58
58
  },
59
- }, {
60
- log: options.verbose,
61
- ...(options.onLine && {
62
- stdout: {
63
- parseLines: "skip-empty",
64
- onData: (line) => options.onLine(line),
65
- },
66
- }),
59
+ $log: options.verbose,
67
60
  });
61
+ if (options.onLine) {
62
+ await p.stdout.parseLines(options.onLine);
63
+ }
64
+ else {
65
+ await p.waitForClose();
66
+ }
68
67
  }
69
68
  else {
70
69
  throw new Error(`Invalid step type: ${step.type}`);
package/lib/utils/tar.js CHANGED
@@ -1,30 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.extractTar = exports.normalizeTarPath = exports.createTar = exports.checkPigzLib = exports.listTar = exports.getTarVendor = void 0;
4
+ const async_process_1 = require("./async-process");
4
5
  const cli_1 = require("./cli");
5
6
  const fs_1 = require("./fs");
6
7
  const math_1 = require("./math");
7
- const process_1 = require("./process");
8
8
  const promises_1 = require("fs/promises");
9
9
  const os_1 = require("os");
10
10
  let tarVendor;
11
11
  async function getTarVendor(cache = true, log = false) {
12
12
  if (cache && typeof tarVendor !== "undefined")
13
13
  return tarVendor;
14
- const p = await (0, process_1.exec)("tar", ["--help"], {}, {
15
- log,
16
- stdout: {
17
- save: true,
18
- },
19
- });
14
+ const stdout = await async_process_1.AsyncProcess.stdout("tar", ["--help"], { $log: log });
20
15
  const find = () => {
21
- if (p.stdout.includes("BusyBox")) {
16
+ if (stdout.includes("BusyBox")) {
22
17
  return "busybox";
23
18
  }
24
- else if (p.stdout.includes("bsdtar")) {
19
+ else if (stdout.includes("bsdtar")) {
25
20
  return "bsdtar";
26
21
  }
27
- else if (p.stdout.includes("GNU")) {
22
+ else if (stdout.includes("GNU")) {
28
23
  return "gnu";
29
24
  }
30
25
  else {
@@ -36,22 +31,14 @@ async function getTarVendor(cache = true, log = false) {
36
31
  exports.getTarVendor = getTarVendor;
37
32
  async function listTar(options) {
38
33
  const vendor = await getTarVendor(true, options.verbose);
39
- let total = 0;
40
- await (0, process_1.exec)("tar", [
34
+ const p = new async_process_1.AsyncProcess("tar", [
41
35
  "-tf",
42
36
  toLocalPath(options.input),
43
37
  ...(vendor === "bsdtar" ? [] : ["--force-local"]),
44
- ], {}, {
45
- log: options.verbose,
46
- stdout: {
47
- parseLines: "skip-empty",
48
- onData: (path) => {
49
- options.onEntry?.({ path: normalizeTarPath(path) });
50
- total++;
51
- },
52
- },
38
+ ], { $log: options.verbose });
39
+ return await p.stdout.parseLines((path) => {
40
+ options.onEntry?.({ path: normalizeTarPath(path) });
53
41
  });
54
- return total;
55
42
  }
56
43
  exports.listTar = listTar;
57
44
  let pigzLib;
@@ -59,7 +46,10 @@ async function checkPigzLib(cache = true) {
59
46
  if (cache && pigzLib !== undefined)
60
47
  return pigzLib;
61
48
  try {
62
- return !(await (0, process_1.exec)("pigz", ["-V"])).exitCode;
49
+ const exitCode = await async_process_1.AsyncProcess.exec("pigz", ["-V"], {
50
+ $exitCode: false,
51
+ });
52
+ return !exitCode;
63
53
  }
64
54
  catch {
65
55
  return false;
@@ -105,7 +95,7 @@ async function createTar(options) {
105
95
  },
106
96
  });
107
97
  };
108
- await (0, process_1.exec)("tar", [
98
+ const p = new async_process_1.AsyncProcess("tar", [
109
99
  "--no-recursion",
110
100
  "-C",
111
101
  toLocalPath(options.path),
@@ -139,21 +129,16 @@ async function createTar(options) {
139
129
  ...process.env,
140
130
  ...env,
141
131
  },
142
- }, {
143
- log: options.verbose
132
+ $log: options.verbose
144
133
  ? { envNames: Object.keys(env), exec: true, stderr: true, stdout: true }
145
134
  : false,
146
- ...(vendor === "bsdtar"
147
- ? {
148
- stderr: options.onEntry
149
- ? { toExitCode: true, parseLines: "skip-empty", onData }
150
- : { toExitCode: true },
151
- }
152
- : {
153
- stderr: { toExitCode: true },
154
- stdout: { parseLines: "skip-empty", onData },
155
- }),
156
135
  });
136
+ if (options.onEntry) {
137
+ await p[vendor === "bsdtar" ? "stderr" : "stdout"].parseLines(onData);
138
+ }
139
+ else {
140
+ await p.waitForClose();
141
+ }
157
142
  }
158
143
  exports.createTar = createTar;
159
144
  /**
@@ -197,7 +182,7 @@ async function extractTar(options) {
197
182
  },
198
183
  });
199
184
  };
200
- await (0, process_1.exec)("tar", [
185
+ const p = new async_process_1.AsyncProcess("tar", [
201
186
  decompress?.cores === 1 ? "-xzvpf" : "-xvpf",
202
187
  toLocalPath(options.input),
203
188
  "-C",
@@ -211,18 +196,13 @@ async function extractTar(options) {
211
196
  decompress.cores > 1 && {
212
197
  shell: true,
213
198
  }),
214
- }, {
215
- log: options.verbose,
216
- ...(vendor === "bsdtar"
217
- ? {
218
- stderr: options.onEntry
219
- ? { toExitCode: true, parseLines: "skip-empty", onData }
220
- : { toExitCode: true },
221
- }
222
- : {
223
- stderr: { toExitCode: true },
224
- stdout: { parseLines: "skip-empty", onData },
225
- }),
199
+ $log: options.verbose,
226
200
  });
201
+ if (options.onEntry) {
202
+ await p[vendor === "bsdtar" ? "stderr" : "stdout"].parseLines(onData);
203
+ }
204
+ else {
205
+ await p.waitForClose();
206
+ }
227
207
  }
228
208
  exports.extractTar = extractTar;
@@ -23,7 +23,9 @@ export declare abstract class AbstractFs {
23
23
  abstract download(source: string, target: string, options?: {
24
24
  timeout?: number;
25
25
  onProgress?: (progress: BasicProgress) => void;
26
- }): Promise<void>;
26
+ }): Promise<{
27
+ bytes: number;
28
+ }>;
27
29
  abstract fetchDiskStats(source: string): Promise<DiskStats>;
28
30
  }
29
31
  export declare class LocalFs extends AbstractFs {
@@ -39,5 +41,7 @@ export declare class LocalFs extends AbstractFs {
39
41
  rmAll(path: string): Promise<void>;
40
42
  fetchDiskStats(source: string): Promise<DiskStats>;
41
43
  upload(source: string, target: string): Promise<void>;
42
- download(source: string, target: string): Promise<void>;
44
+ download(source: string, target: string): Promise<{
45
+ bytes: number;
46
+ }>;
43
47
  }
@@ -62,7 +62,10 @@ class LocalFs extends AbstractFs {
62
62
  await (0, promises_1.cp)(source, this.resolvePath(target));
63
63
  }
64
64
  async download(source, target) {
65
- await (0, promises_1.cp)(this.resolvePath(source), target);
65
+ const path = this.resolvePath(source);
66
+ const { size: bytes } = await (0, promises_1.stat)(path);
67
+ await (0, promises_1.cp)(path, target);
68
+ return { bytes };
66
69
  }
67
70
  }
68
71
  exports.LocalFs = LocalFs;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datatruck/cli",
3
- "version": "0.33.0",
3
+ "version": "0.34.1",
4
4
  "description": "Tool for creating and managing backups",
5
5
  "homepage": "https://github.com/swordev/datatruck#readme",
6
6
  "bugs": {
@@ -35,7 +35,7 @@
35
35
  "dayjs": "^1.11.10",
36
36
  "fast-folder-size": "^2.2.0",
37
37
  "fast-glob": "^3.3.2",
38
- "listr2": "^8.0.0",
38
+ "listr2": "^8.0.1",
39
39
  "micromatch": "^4.0.5",
40
40
  "mysql2": "^3.6.5",
41
41
  "tty-table": "^4.2.3",