@datatruck/cli 0.32.3 → 0.34.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 (133) hide show
  1. package/config.schema.json +377 -31
  2. package/lib/{Action → actions}/BackupAction.d.ts +13 -19
  3. package/lib/{Action → actions}/BackupAction.js +52 -91
  4. package/lib/{Action → actions}/ConfigAction.d.ts +4 -2
  5. package/lib/{Action → actions}/ConfigAction.js +16 -8
  6. package/lib/{Action → actions}/CopyAction.d.ts +20 -13
  7. package/lib/actions/CopyAction.js +296 -0
  8. package/lib/{Action → actions}/InitAction.d.ts +1 -1
  9. package/lib/{Action → actions}/InitAction.js +3 -3
  10. package/lib/{Action → actions}/PruneAction.d.ts +1 -2
  11. package/lib/{Action → actions}/PruneAction.js +2 -2
  12. package/lib/{Action → actions}/RestoreAction.d.ts +4 -13
  13. package/lib/{Action → actions}/RestoreAction.js +17 -17
  14. package/lib/{Action → actions}/SnapshotsAction.d.ts +2 -3
  15. package/lib/{Action → actions}/SnapshotsAction.js +3 -3
  16. package/lib/cli.d.ts +3 -3
  17. package/lib/cli.js +18 -17
  18. package/lib/commands/BackupCommand.d.ts +45 -0
  19. package/lib/{Command → commands}/BackupCommand.js +7 -6
  20. package/lib/{Command → commands}/CleanCacheCommand.d.ts +4 -2
  21. package/lib/{Command → commands}/CleanCacheCommand.js +6 -5
  22. package/lib/{Command → commands}/CommandAbstract.d.ts +10 -6
  23. package/lib/{Command → commands}/CommandAbstract.js +5 -3
  24. package/lib/commands/ConfigCommand.d.ts +22 -0
  25. package/lib/{Command → commands}/ConfigCommand.js +5 -5
  26. package/lib/commands/CopyCommand.d.ts +17 -0
  27. package/lib/{Command → commands}/CopyCommand.js +7 -6
  28. package/lib/commands/InitCommand.d.ts +19 -0
  29. package/lib/{Command → commands}/InitCommand.js +9 -9
  30. package/lib/{Command → commands}/PruneCommand.d.ts +7 -4
  31. package/lib/{Command → commands}/PruneCommand.js +11 -11
  32. package/lib/commands/RestoreCommand.d.ts +38 -0
  33. package/lib/{Command → commands}/RestoreCommand.js +7 -6
  34. package/lib/{Command → commands}/SnapshotsCommand.d.ts +8 -6
  35. package/lib/{Command → commands}/SnapshotsCommand.js +12 -12
  36. package/lib/{Command → commands}/StartServerCommand.d.ts +4 -2
  37. package/lib/{Command → commands}/StartServerCommand.js +5 -5
  38. package/lib/index.d.ts +20 -23
  39. package/lib/index.js +8 -8
  40. package/lib/{Repository → repositories}/DatatruckRepository.d.ts +6 -2
  41. package/lib/{Repository → repositories}/DatatruckRepository.js +13 -5
  42. package/lib/{Repository → repositories}/GitRepository.d.ts +6 -2
  43. package/lib/{Repository → repositories}/GitRepository.js +8 -3
  44. package/lib/{Repository → repositories}/RepositoryAbstract.d.ts +13 -9
  45. package/lib/{Repository → repositories}/ResticRepository.d.ts +6 -2
  46. package/lib/{Repository → repositories}/ResticRepository.js +17 -10
  47. package/lib/{Task → tasks}/MssqlTask.js +2 -2
  48. package/lib/{Task → tasks}/MysqlDumpTask.js +4 -4
  49. package/lib/{Task → tasks}/ScriptTask.d.ts +2 -2
  50. package/lib/{Task → tasks}/SqlDumpTaskAbstract.js +4 -4
  51. package/lib/{Task → tasks}/TaskAbstract.d.ts +4 -4
  52. package/lib/utils/DataFormat.js +3 -3
  53. package/lib/utils/Restic.d.ts +2 -2
  54. package/lib/utils/Restic.js +12 -10
  55. package/lib/utils/cli.d.ts +9 -3
  56. package/lib/utils/cli.js +17 -1
  57. package/lib/utils/cron.d.ts +11 -0
  58. package/lib/utils/cron.js +27 -0
  59. package/lib/utils/datatruck/client.d.ts +3 -1
  60. package/lib/utils/datatruck/client.js +1 -1
  61. package/lib/utils/datatruck/command.d.ts +29 -0
  62. package/lib/utils/datatruck/command.js +61 -0
  63. package/lib/{Config/RepositoryConfig.d.ts → utils/datatruck/config-repository-type.d.ts} +19 -8
  64. package/lib/{Config/TaskConfig.d.ts → utils/datatruck/config-task-type.d.ts} +6 -6
  65. package/lib/utils/datatruck/config-type.d.ts +51 -0
  66. package/lib/utils/datatruck/config.d.ts +19 -10
  67. package/lib/utils/datatruck/config.js +43 -7
  68. package/lib/utils/datatruck/cron-server.d.ts +27 -6
  69. package/lib/utils/datatruck/cron-server.js +38 -20
  70. package/lib/utils/datatruck/paths.d.ts +2 -2
  71. package/lib/utils/datatruck/report-list.d.ts +14 -0
  72. package/lib/utils/datatruck/report-list.js +57 -0
  73. package/lib/utils/datatruck/repository-server.js +3 -2
  74. package/lib/utils/datatruck/repository.d.ts +16 -0
  75. package/lib/utils/datatruck/repository.js +30 -0
  76. package/lib/utils/datatruck/snapshot.d.ts +2 -2
  77. package/lib/utils/datatruck/task.d.ts +3 -0
  78. package/lib/{Factory/TaskFactory.js → utils/datatruck/task.js} +8 -8
  79. package/lib/utils/date.js +6 -2
  80. package/lib/utils/fs.d.ts +3 -0
  81. package/lib/utils/fs.js +24 -4
  82. package/lib/utils/http.d.ts +3 -1
  83. package/lib/utils/http.js +6 -1
  84. package/lib/utils/list.d.ts +5 -5
  85. package/lib/utils/mysql.js +5 -5
  86. package/lib/utils/object.d.ts +13 -0
  87. package/lib/utils/object.js +32 -1
  88. package/lib/utils/process.js +4 -1
  89. package/lib/utils/string.d.ts +1 -0
  90. package/lib/utils/string.js +7 -3
  91. package/lib/utils/ts.d.ts +16 -0
  92. package/lib/utils/virtual-fs.d.ts +6 -2
  93. package/lib/utils/virtual-fs.js +4 -1
  94. package/lib/utils/watcher.d.ts +10 -0
  95. package/lib/utils/watcher.js +34 -0
  96. package/package.json +4 -4
  97. package/lib/Action/CopyAction.js +0 -164
  98. package/lib/Command/BackupCommand.d.ts +0 -19
  99. package/lib/Command/ConfigCommand.d.ts +0 -15
  100. package/lib/Command/CopyCommand.d.ts +0 -16
  101. package/lib/Command/InitCommand.d.ts +0 -13
  102. package/lib/Command/RestoreCommand.d.ts +0 -17
  103. package/lib/Config/Config.d.ts +0 -28
  104. package/lib/Config/PackageConfig.d.ts +0 -24
  105. package/lib/Config/PackageRepositoryConfig.d.ts +0 -15
  106. package/lib/Config/PrunePolicyConfig.d.ts +0 -2
  107. package/lib/Config/RepositoryConfig.js +0 -2
  108. package/lib/Config/TaskConfig.js +0 -2
  109. package/lib/Factory/CommandFactory.d.ts +0 -45
  110. package/lib/Factory/CommandFactory.js +0 -96
  111. package/lib/Factory/RepositoryFactory.d.ts +0 -3
  112. package/lib/Factory/RepositoryFactory.js +0 -23
  113. package/lib/Factory/TaskFactory.d.ts +0 -3
  114. /package/lib/{Action → actions}/CleanCacheAction.d.ts +0 -0
  115. /package/lib/{Action → actions}/CleanCacheAction.js +0 -0
  116. /package/lib/{Repository → repositories}/RepositoryAbstract.js +0 -0
  117. /package/lib/{Task → tasks}/GitTask.d.ts +0 -0
  118. /package/lib/{Task → tasks}/GitTask.js +0 -0
  119. /package/lib/{Task → tasks}/MariadbTask.d.ts +0 -0
  120. /package/lib/{Task → tasks}/MariadbTask.js +0 -0
  121. /package/lib/{Task → tasks}/MssqlTask.d.ts +0 -0
  122. /package/lib/{Task → tasks}/MysqlDumpTask.d.ts +0 -0
  123. /package/lib/{Task → tasks}/PostgresqlDumpTask.d.ts +0 -0
  124. /package/lib/{Task → tasks}/PostgresqlDumpTask.js +0 -0
  125. /package/lib/{Task → tasks}/ScriptTask.js +0 -0
  126. /package/lib/{Task → tasks}/SqlDumpTaskAbstract.d.ts +0 -0
  127. /package/lib/{Task → tasks}/TaskAbstract.js +0 -0
  128. /package/lib/{Config/Config.js → utils/datatruck/config-repository-type.js} +0 -0
  129. /package/lib/{Config/PackageConfig.js → utils/datatruck/config-task-type.js} +0 -0
  130. /package/lib/{Config/PackageRepositoryConfig.js → utils/datatruck/config-type.js} +0 -0
  131. /package/lib/{Error/AppError.d.ts → utils/datatruck/error.d.ts} +0 -0
  132. /package/lib/{Error/AppError.js → utils/datatruck/error.js} +0 -0
  133. /package/lib/{Config/PrunePolicyConfig.js → utils/ts.js} +0 -0
package/lib/index.js CHANGED
@@ -1,21 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseArgs = exports.SnapshotsAction = exports.RestoreAction = exports.PruneAction = exports.InitAction = exports.CopyAction = exports.ConfigAction = exports.CleanCacheAction = exports.BackupAction = void 0;
4
- var BackupAction_1 = require("./Action/BackupAction");
4
+ var BackupAction_1 = require("./actions/BackupAction");
5
5
  Object.defineProperty(exports, "BackupAction", { enumerable: true, get: function () { return BackupAction_1.BackupAction; } });
6
- var CleanCacheAction_1 = require("./Action/CleanCacheAction");
6
+ var CleanCacheAction_1 = require("./actions/CleanCacheAction");
7
7
  Object.defineProperty(exports, "CleanCacheAction", { enumerable: true, get: function () { return CleanCacheAction_1.CleanCacheAction; } });
8
- var ConfigAction_1 = require("./Action/ConfigAction");
8
+ var ConfigAction_1 = require("./actions/ConfigAction");
9
9
  Object.defineProperty(exports, "ConfigAction", { enumerable: true, get: function () { return ConfigAction_1.ConfigAction; } });
10
- var CopyAction_1 = require("./Action/CopyAction");
10
+ var CopyAction_1 = require("./actions/CopyAction");
11
11
  Object.defineProperty(exports, "CopyAction", { enumerable: true, get: function () { return CopyAction_1.CopyAction; } });
12
- var InitAction_1 = require("./Action/InitAction");
12
+ var InitAction_1 = require("./actions/InitAction");
13
13
  Object.defineProperty(exports, "InitAction", { enumerable: true, get: function () { return InitAction_1.InitAction; } });
14
- var PruneAction_1 = require("./Action/PruneAction");
14
+ var PruneAction_1 = require("./actions/PruneAction");
15
15
  Object.defineProperty(exports, "PruneAction", { enumerable: true, get: function () { return PruneAction_1.PruneAction; } });
16
- var RestoreAction_1 = require("./Action/RestoreAction");
16
+ var RestoreAction_1 = require("./actions/RestoreAction");
17
17
  Object.defineProperty(exports, "RestoreAction", { enumerable: true, get: function () { return RestoreAction_1.RestoreAction; } });
18
- var SnapshotsAction_1 = require("./Action/SnapshotsAction");
18
+ var SnapshotsAction_1 = require("./actions/SnapshotsAction");
19
19
  Object.defineProperty(exports, "SnapshotsAction", { enumerable: true, get: function () { return SnapshotsAction_1.SnapshotsAction; } });
20
20
  var cli_1 = require("./cli");
21
21
  Object.defineProperty(exports, "parseArgs", { enumerable: true, get: function () { return cli_1.parseArgs; } });
@@ -50,8 +50,12 @@ export declare class DatatruckRepository extends RepositoryAbstract<DatatruckRep
50
50
  init(data: RepoInitData): Promise<void>;
51
51
  prune(data: RepoPruneData): Promise<void>;
52
52
  fetchSnapshots(data: RepoFetchSnapshotsData): Promise<Snapshot[]>;
53
- backup(data: RepoBackupData<DatatruckPackageRepositoryConfig>): Promise<void>;
54
- copy(data: RepoCopyData<DatatruckRepositoryConfig>): Promise<void>;
53
+ backup(data: RepoBackupData<DatatruckPackageRepositoryConfig>): Promise<{
54
+ bytes: number;
55
+ }>;
56
+ copy(data: RepoCopyData<DatatruckRepositoryConfig>): Promise<{
57
+ bytes: number;
58
+ }>;
55
59
  restore(data: RepoRestoreData<DatatruckPackageRepositoryConfig>): Promise<void>;
56
60
  }
57
61
  export {};
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DatatruckRepository = exports.datatruckRepositoryName = void 0;
4
- const AppError_1 = require("../Error/AppError");
5
4
  const cli_1 = require("../utils/cli");
6
5
  const crypto_1 = require("../utils/crypto");
7
6
  const client_1 = require("../utils/datatruck/client");
7
+ const error_1 = require("../utils/datatruck/error");
8
8
  const paths_1 = require("../utils/datatruck/paths");
9
9
  const fs_1 = require("../utils/fs");
10
10
  const math_1 = require("../utils/math");
@@ -203,6 +203,7 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
203
203
  }
204
204
  scanner.end();
205
205
  // Meta
206
+ const size = Object.values(tarStats).reduce((total, { size }) => total + size, 0);
206
207
  const metaPath = `${snapshotName}/meta.json`;
207
208
  const nodePkg = (0, fs_1.parsePackageFile)();
208
209
  const meta = {
@@ -212,12 +213,15 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
212
213
  package: data.package.name,
213
214
  task: data.package.task?.name,
214
215
  version: nodePkg.version,
215
- size: Object.values(tarStats).reduce((total, { size }) => total + size, 0),
216
+ size,
216
217
  tarStats,
217
218
  };
218
219
  if (data.options.verbose)
219
220
  (0, cli_1.logExec)(`Writing metadata into ${fs.resolvePath(metaPath)}`);
220
221
  await fs.writeFile(`${snapshotName}/meta.json`, JSON.stringify(meta));
222
+ return {
223
+ bytes: size,
224
+ };
221
225
  }
222
226
  async copy(data) {
223
227
  const sourceFs = (0, client_1.createFs)(this.config.backend);
@@ -236,6 +240,7 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
236
240
  await targetFs.ensureEmptyDir(tmpSnapshotName);
237
241
  const entries = await sourceFs.readdir(snapshotName);
238
242
  const total = entries.length;
243
+ let bytes = 0;
239
244
  let current = 0;
240
245
  for (const entry of entries) {
241
246
  const absolute = {
@@ -250,7 +255,7 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
250
255
  const sourceEntry = `${snapshotName}/${entry}`;
251
256
  const targetEntry = `${tmpSnapshotName}/${entry}`;
252
257
  if (targetFs.isLocal()) {
253
- await sourceFs.download(sourceEntry, targetFs.resolvePath(targetEntry), {
258
+ const downloaded = await sourceFs.download(sourceEntry, targetFs.resolvePath(targetEntry), {
254
259
  onProgress: (progress) => data.onProgress({
255
260
  absolute,
256
261
  relative: {
@@ -260,12 +265,13 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
260
265
  },
261
266
  }),
262
267
  });
268
+ bytes += downloaded.bytes;
263
269
  }
264
270
  else {
265
271
  const tempDir = await (0, temp_1.mkTmpDir)(exports.datatruckRepositoryName, "repo", "remote-copy", entry);
266
272
  const tempFile = (0, path_1.join)(tempDir, entry);
267
273
  try {
268
- await sourceFs.download(sourceEntry, tempFile, {
274
+ const downloaded = await sourceFs.download(sourceEntry, tempFile, {
269
275
  onProgress: (progress) => data.onProgress({
270
276
  absolute,
271
277
  relative: {
@@ -275,6 +281,7 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
275
281
  },
276
282
  }),
277
283
  });
284
+ bytes += downloaded.bytes;
278
285
  await targetFs.upload(tempFile, targetEntry);
279
286
  }
280
287
  finally {
@@ -283,6 +290,7 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
283
290
  }
284
291
  }
285
292
  await targetFs.rename(tmpSnapshotName, snapshotName);
293
+ return { bytes };
286
294
  }
287
295
  async restore(data) {
288
296
  const fs = (0, client_1.createFs)(this.config.backend);
@@ -295,7 +303,7 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
295
303
  },
296
304
  });
297
305
  if (!snapshot)
298
- throw new AppError_1.AppError("Snapshot not found");
306
+ throw new error_1.AppError("Snapshot not found");
299
307
  const snapshotName = DatatruckRepository.buildSnapshotName(snapshot, data.package);
300
308
  const meta = await DatatruckRepository.parseMetaData(await fs.readFile(`${snapshotName}/meta.json`));
301
309
  const progress = (0, fs_1.createProgress)({ onProgress: data.onProgress });
@@ -22,7 +22,11 @@ export declare class GitRepository extends RepositoryAbstract<GitRepositoryConfi
22
22
  init(data: RepoInitData): Promise<void>;
23
23
  prune(data: RepoPruneData): Promise<void>;
24
24
  fetchSnapshots(data: RepoFetchSnapshotsData): Promise<Snapshot[]>;
25
- backup(data: RepoBackupData<GitPackageRepositoryConfig>): Promise<void>;
26
- copy(data: RepoCopyData<GitRepositoryConfig>): Promise<void>;
25
+ backup(data: RepoBackupData<GitPackageRepositoryConfig>): Promise<{
26
+ bytes: number;
27
+ }>;
28
+ copy(data: RepoCopyData<GitRepositoryConfig>): Promise<{
29
+ bytes: number;
30
+ }>;
27
31
  restore(data: RepoRestoreData<GitPackageRepositoryConfig>): Promise<void>;
28
32
  }
@@ -187,6 +187,8 @@ class GitRepository extends RepositoryAbstract_1.RepositoryAbstract {
187
187
  if (await git.haveChanges())
188
188
  await git.exec(["commit", "-m", data.snapshot.id]);
189
189
  const nodePkg = (0, fs_1.parsePackageFile)();
190
+ const size = (await (0, fs_1.fastFolderSizeAsync)(tmpPath)) -
191
+ (await (0, fs_1.fastFolderSizeAsync)((0, path_1.join)(tmpPath, ".git")));
190
192
  const meta = GitRepository.buildSnapshotTag({
191
193
  id: data.snapshot.id,
192
194
  shortId: data.snapshot.id.slice(0, 8),
@@ -195,16 +197,19 @@ class GitRepository extends RepositoryAbstract_1.RepositoryAbstract {
195
197
  package: data.package.name,
196
198
  task: data.package.task?.name,
197
199
  version: nodePkg.version,
198
- size: ((await (0, fs_1.fastFolderSizeAsync)(tmpPath)) -
199
- (await (0, fs_1.fastFolderSizeAsync)((0, path_1.join)(tmpPath, ".git")))).toString(),
200
+ size: size.toString(),
200
201
  });
201
202
  await git.addTag(meta.name, meta.message);
202
203
  await git.push({ branchName });
203
204
  await git.pushTags();
204
205
  await (0, promises_1.rm)(tmpPath, { recursive: true });
206
+ return {
207
+ bytes: size,
208
+ };
205
209
  }
206
- copy(data) {
210
+ async copy(data) {
207
211
  throw new Error("Method not implemented.");
212
+ return { bytes: 0 };
208
213
  }
209
214
  async restore(data) {
210
215
  const restorePath = data.snapshotPath;
@@ -1,9 +1,7 @@
1
- import type { BackupActionOptions } from "../Action/BackupAction";
2
- import type { InitActionOptions } from "../Action/InitAction";
3
- import type { RestoreActionOptions } from "../Action/RestoreAction";
4
- import type { ExtendedSnapshot, SnapshotsActionOptions } from "../Action/SnapshotsAction";
5
- import type { PackageConfig } from "../Config/PackageConfig";
6
- import type { RepositoryConfig } from "../Config/RepositoryConfig";
1
+ import type { BackupActionOptions } from "../actions/BackupAction";
2
+ import type { RestoreActionOptions } from "../actions/RestoreAction";
3
+ import type { ExtendedSnapshot, SnapshotsActionOptions } from "../actions/SnapshotsAction";
4
+ import type { PackageConfig, RepositoryConfig } from "../utils/datatruck/config-type";
7
5
  import { type DiskStats } from "../utils/fs";
8
6
  import type { Progress } from "../utils/progress";
9
7
  export type PreSnapshot = {
@@ -18,7 +16,9 @@ export type Snapshot = PreSnapshot & {
18
16
  size: number;
19
17
  };
20
18
  export type RepoInitData = {
21
- options: InitActionOptions;
19
+ options: {
20
+ verbose?: boolean;
21
+ };
22
22
  };
23
23
  export type RepoFetchSnapshotsData = {
24
24
  options: Pick<SnapshotsActionOptions, "ids" | "packageNames" | "packageTaskNames" | "verbose" | "tags">;
@@ -83,7 +83,11 @@ export declare abstract class RepositoryAbstract<TConfig> {
83
83
  abstract init(data: RepoInitData): Promise<void>;
84
84
  abstract prune(data: RepoPruneData): Promise<void>;
85
85
  abstract fetchSnapshots(data: RepoFetchSnapshotsData): Promise<Snapshot[]>;
86
- abstract copy(data: RepoCopyData<TConfig>): Promise<void>;
87
- abstract backup(data: RepoBackupData<unknown>): Promise<void>;
86
+ abstract copy(data: RepoCopyData<TConfig>): Promise<{
87
+ bytes: number;
88
+ }>;
89
+ abstract backup(data: RepoBackupData<unknown>): Promise<{
90
+ bytes: number;
91
+ }>;
88
92
  abstract restore(data: RepoRestoreData<unknown>): Promise<void>;
89
93
  }
@@ -33,7 +33,11 @@ export declare class ResticRepository extends RepositoryAbstract<ResticRepositor
33
33
  init(data: RepoInitData): Promise<void>;
34
34
  fetchSnapshots(data: RepoFetchSnapshotsData): Promise<Snapshot[]>;
35
35
  prune(data: RepoPruneData): Promise<void>;
36
- backup(data: RepoBackupData<ResticPackageRepositoryConfig>): Promise<void>;
37
- copy(data: RepoCopyData<ResticRepositoryConfig>): Promise<void>;
36
+ backup(data: RepoBackupData<ResticPackageRepositoryConfig>): Promise<{
37
+ bytes: number;
38
+ }>;
39
+ copy(data: RepoCopyData<ResticRepositoryConfig>): Promise<{
40
+ bytes: number;
41
+ }>;
38
42
  restore(data: RepoRestoreData<ResticPackageRepositoryConfig>): Promise<void>;
39
43
  }
@@ -4,9 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ResticRepository = exports.resticRepositoryName = void 0;
7
- const AppError_1 = require("../Error/AppError");
8
7
  const Restic_1 = require("../utils/Restic");
9
8
  const cli_1 = require("../utils/cli");
9
+ const error_1 = require("../utils/datatruck/error");
10
10
  const paths_1 = require("../utils/datatruck/paths");
11
11
  const fs_1 = require("../utils/fs");
12
12
  const math_1 = require("../utils/math");
@@ -175,7 +175,7 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
175
175
  });
176
176
  }
177
177
  if (data.options.tags?.some((tag) => tag.startsWith(ResticRepository.refPrefix)))
178
- throw new AppError_1.AppError(`Tag prefix is not allowed`);
178
+ throw new error_1.AppError(`Tag prefix is not allowed`);
179
179
  const packageTag = ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.PACKAGE, data.package.name);
180
180
  data.onProgress({
181
181
  relative: {
@@ -204,10 +204,6 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
204
204
  allowEmptySnapshot: true,
205
205
  excludeFile: gitignorePath ? [gitignorePath] : undefined,
206
206
  parent: lastSnapshot?.id,
207
- // https://github.com/restic/restic/pull/3200
208
- ...((await restic.checkBackupSetPathSupport()) && {
209
- setPaths: [`/datatruck/${data.package.name}`],
210
- }),
211
207
  tags: [
212
208
  ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.ID, data.snapshot.id),
213
209
  ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.SHORT_ID, data.snapshot.id.slice(0, 8)),
@@ -255,9 +251,9 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
255
251
  },
256
252
  });
257
253
  if (typeof resticSnapshotId !== "string")
258
- throw new AppError_1.AppError(`Restic snapshot id is is not defined`);
254
+ throw new error_1.AppError(`Restic snapshot id is is not defined`);
259
255
  if (typeof resticTotalBytes !== "number")
260
- throw new AppError_1.AppError(`Restic snapshot total bytes is not defined`);
256
+ throw new error_1.AppError(`Restic snapshot total bytes is not defined`);
261
257
  const sizeTag = ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.SIZE, resticTotalBytes.toString());
262
258
  await restic.exec(["tag", "--add", sizeTag, resticSnapshotId]);
263
259
  data.onProgress({
@@ -267,6 +263,9 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
267
263
  percent: 100,
268
264
  },
269
265
  });
266
+ return {
267
+ bytes: resticTotalBytes,
268
+ };
270
269
  }
271
270
  async copy(data) {
272
271
  const config = data.mirrorRepositoryConfig;
@@ -274,10 +273,11 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
274
273
  options: {
275
274
  ids: [data.snapshot.id],
276
275
  packageNames: [data.package.name],
276
+ verbose: data.options.verbose,
277
277
  },
278
278
  });
279
279
  if (!snapshot)
280
- throw new AppError_1.AppError(`Snapshot not found`);
280
+ throw new error_1.AppError(`Snapshot not found`);
281
281
  const restic = new Restic_1.Restic({
282
282
  env: {
283
283
  ...(await this.buildEnv()),
@@ -288,9 +288,16 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
288
288
  },
289
289
  log: data.options.verbose,
290
290
  });
291
+ let bytes = 0;
291
292
  await restic.copy({
292
293
  id: snapshot.originalId,
294
+ onStream(data) {
295
+ if (data.message_type === "status") {
296
+ bytes = data.total_bytes;
297
+ }
298
+ },
293
299
  });
300
+ return { bytes };
294
301
  }
295
302
  async restore(data) {
296
303
  const restorePath = data.snapshotPath;
@@ -305,7 +312,7 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
305
312
  },
306
313
  });
307
314
  if (!snapshot)
308
- throw new AppError_1.AppError(`Snapshot not found`);
315
+ throw new error_1.AppError(`Snapshot not found`);
309
316
  await restic.restore({
310
317
  id: snapshot.originalId,
311
318
  target: restorePath,
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MssqlTask = exports.mssqlTaskName = void 0;
4
- const AppError_1 = require("../Error/AppError");
5
4
  const config_1 = require("../utils/datatruck/config");
5
+ const error_1 = require("../utils/datatruck/error");
6
6
  const fs_1 = require("../utils/fs");
7
7
  const process_1 = require("../utils/process");
8
8
  const temp_1 = require("../utils/temp");
@@ -88,7 +88,7 @@ class MssqlTask extends TaskAbstract_1.TaskAbstract {
88
88
  const databasePath = (0, path_1.join)(snapshotPath, file);
89
89
  const exists = await this.fetchDatabaseNames(databaseName);
90
90
  if (exists.length)
91
- throw new AppError_1.AppError(`Target database already exists: ${databaseName}`);
91
+ throw new error_1.AppError(`Target database already exists: ${databaseName}`);
92
92
  await this.exec(`RESTORE DATABASE [${databaseName}] FROM disk='${databasePath}'`);
93
93
  }
94
94
  }
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MysqlDumpTask = exports.mysqlDumpTaskName = void 0;
4
- const AppError_1 = require("../Error/AppError");
5
4
  const async_1 = require("../utils/async");
6
5
  const cli_1 = require("../utils/cli");
7
6
  const config_1 = require("../utils/datatruck/config");
7
+ const error_1 = require("../utils/datatruck/error");
8
8
  const fs_1 = require("../utils/fs");
9
9
  const math_1 = require("../utils/math");
10
10
  const mysql_1 = require("../utils/mysql");
@@ -88,7 +88,7 @@ class MysqlDumpTask extends TaskAbstract_1.TaskAbstract {
88
88
  const successCsvDump = files.length === 2 &&
89
89
  files.every((file) => file === schemaFile || file === dataFile);
90
90
  if (!successCsvDump)
91
- throw new AppError_1.AppError(`Invalid csv dump files: ${files.join(", ")}`);
91
+ throw new error_1.AppError(`Invalid csv dump files: ${files.join(", ")}`);
92
92
  const schemaPath = (0, path_1.join)(snapshotPath, `${tableName}${suffix.tableSchema}`);
93
93
  await (0, fs_1.safeRename)((0, path_1.join)(tableSharedPath, schemaFile), schemaPath);
94
94
  await compressAndClean?.(schemaPath);
@@ -200,7 +200,7 @@ class MysqlDumpTask extends TaskAbstract_1.TaskAbstract {
200
200
  // Database check
201
201
  if (files.some((f) => f.endsWith(suffix.database)) &&
202
202
  !(await sql.isDatabaseEmpty(database.name)))
203
- throw new AppError_1.AppError(`Target database is not empty: ${database.name}`);
203
+ throw new error_1.AppError(`Target database is not empty: ${database.name}`);
204
204
  // Table check
205
205
  const restoreTables = [
206
206
  ...new Set(...files
@@ -210,7 +210,7 @@ class MysqlDumpTask extends TaskAbstract_1.TaskAbstract {
210
210
  const serverTables = await sql.fetchTableNames(database.name);
211
211
  const errorTables = restoreTables.filter((v) => serverTables.includes(v));
212
212
  if (errorTables.length)
213
- throw new AppError_1.AppError(`Target table already exists: ${errorTables.join(", ")}`);
213
+ throw new error_1.AppError(`Target table already exists: ${errorTables.join(", ")}`);
214
214
  // Data check
215
215
  const dataFiles = files.filter((f) => f.endsWith(suffix.tableData));
216
216
  const sharedDir = dataFiles.length
@@ -1,5 +1,5 @@
1
- import { PackageConfig } from "../Config/PackageConfig";
2
- import { PreSnapshot } from "../Repository/RepositoryAbstract";
1
+ import { PreSnapshot } from "../repositories/RepositoryAbstract";
2
+ import type { PackageConfig } from "../utils/datatruck/config-type";
3
3
  import { ProcessEnv } from "../utils/process";
4
4
  import { SpawnStep } from "../utils/spawnSteps";
5
5
  import { TaskBackupData, TaskPrepareRestoreData, TaskRestoreData, TaskAbstract } from "./TaskAbstract";
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SqlDumpTaskAbstract = void 0;
4
- const AppError_1 = require("../Error/AppError");
5
4
  const cli_1 = require("../utils/cli");
6
5
  const config_1 = require("../utils/datatruck/config");
6
+ const error_1 = require("../utils/datatruck/error");
7
7
  const fs_1 = require("../utils/fs");
8
8
  const math_1 = require("../utils/math");
9
9
  const temp_1 = require("../utils/temp");
@@ -23,7 +23,7 @@ function serializeSqlFile(input) {
23
23
  return `${input.table}.table.sql`;
24
24
  }
25
25
  else {
26
- throw new AppError_1.AppError(`Invalid sql file input: ${JSON.stringify(input)}`);
26
+ throw new error_1.AppError(`Invalid sql file input: ${JSON.stringify(input)}`);
27
27
  }
28
28
  }
29
29
  function parseSqlFile(fileName) {
@@ -177,7 +177,7 @@ class SqlDumpTaskAbstract extends TaskAbstract_1.TaskAbstract {
177
177
  // Database check
178
178
  const databaseItems = items.filter((v) => v.database);
179
179
  if (databaseItems.length && !(await this.onDatabaseIsEmpty(database.name)))
180
- throw new AppError_1.AppError(`Target database is not empty: ${database.name}`);
180
+ throw new error_1.AppError(`Target database is not empty: ${database.name}`);
181
181
  // Table check
182
182
  const restoreTables = items
183
183
  .filter((v) => v.table)
@@ -185,7 +185,7 @@ class SqlDumpTaskAbstract extends TaskAbstract_1.TaskAbstract {
185
185
  const serverTables = await this.onFetchTableNames(database.name);
186
186
  const errorTables = restoreTables.filter((v) => serverTables.includes(v));
187
187
  if (errorTables.length) {
188
- throw new AppError_1.AppError(`Target table already exists: ${errorTables.join(", ")}`);
188
+ throw new error_1.AppError(`Target table already exists: ${errorTables.join(", ")}`);
189
189
  }
190
190
  await this.onCreateDatabase(database);
191
191
  if (this.verbose)
@@ -1,7 +1,7 @@
1
- import { BackupActionOptions } from "../Action/BackupAction";
2
- import { RestoreActionOptions } from "../Action/RestoreAction";
3
- import { PackageConfig } from "../Config/PackageConfig";
4
- import { PreSnapshot } from "../Repository/RepositoryAbstract";
1
+ import { BackupActionOptions } from "../actions/BackupAction";
2
+ import { RestoreActionOptions } from "../actions/RestoreAction";
3
+ import { PreSnapshot } from "../repositories/RepositoryAbstract";
4
+ import type { PackageConfig } from "../utils/datatruck/config-type";
5
5
  import { Progress } from "../utils/progress";
6
6
  type TaskCommonData = {
7
7
  package: PackageConfig;
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.DataFormat = exports.dataFormats = void 0;
7
- const AppError_1 = require("../Error/AppError");
7
+ const error_1 = require("./datatruck/error");
8
8
  const stream_1 = require("./stream");
9
9
  const tty_table_1 = __importDefault(require("tty-table"));
10
10
  const util_1 = require("util");
@@ -84,12 +84,12 @@ class DataFormat {
84
84
  const tpl = options?.tpl || {};
85
85
  if (!(name in tpl)) {
86
86
  const tplNames = Object.keys(tpl).join(", ");
87
- throw new AppError_1.AppError(`Template name not found: ${name} (valid names: ${tplNames})`);
87
+ throw new error_1.AppError(`Template name not found: ${name} (valid names: ${tplNames})`);
88
88
  }
89
89
  return tpl[name]();
90
90
  }
91
91
  else {
92
- throw new AppError_1.AppError(`Invalid output format: ${format}`);
92
+ throw new error_1.AppError(`Invalid output format: ${format}`);
93
93
  }
94
94
  }
95
95
  }
@@ -68,6 +68,7 @@ export declare class Restic {
68
68
  paths?: string[];
69
69
  latest?: number;
70
70
  json?: boolean;
71
+ snapshotIds?: string[];
71
72
  }): Promise<{
72
73
  time: string;
73
74
  tree: string;
@@ -79,7 +80,6 @@ export declare class Restic {
79
80
  id: string;
80
81
  short_id: string;
81
82
  }[]>;
82
- checkBackupSetPathSupport(): Promise<boolean>;
83
83
  backup(options: {
84
84
  cwd?: string;
85
85
  tags?: string[];
@@ -94,7 +94,7 @@ export declare class Restic {
94
94
  }): Promise<ExecResult>;
95
95
  copy(options: {
96
96
  id: string;
97
- onStream?: (data: ResticBackupStream) => Promise<void>;
97
+ onStream?: (data: ResticBackupStream) => void;
98
98
  }): Promise<ExecResult>;
99
99
  restore(options: {
100
100
  id: string;
@@ -6,6 +6,7 @@ const process_1 = require("./process");
6
6
  const string_1 = require("./string");
7
7
  const promises_1 = require("fs/promises");
8
8
  const path_1 = require("path");
9
+ const emptySnapshotTag = "empty-snapshot";
9
10
  class Restic {
10
11
  options;
11
12
  constructor(options) {
@@ -95,19 +96,12 @@ class Restic {
95
96
  ...(options.json ? ["--json"] : []),
96
97
  ...(options.paths?.flatMap((path) => ["--path", path]) ?? []),
97
98
  ...(options.latest ? ["--latest", options.latest.toString()] : []),
99
+ ...(options.snapshotIds || []),
98
100
  ], {
99
101
  stdout: { save: true },
100
102
  });
101
103
  return JSON.parse(result.stdout);
102
104
  }
103
- async checkBackupSetPathSupport() {
104
- /*const result = await this.exec(["backup", "--set-path"], {
105
- onExitCodeError: () => false,
106
- stderr: { save: true },
107
- });
108
- return result.stderr.includes("flag needs an argument");*/
109
- return false;
110
- }
111
105
  async backup(options) {
112
106
  const exec = async () => await this.exec([
113
107
  "backup",
@@ -151,9 +145,10 @@ class Restic {
151
145
  error.message.includes("unable to save snapshot: snapshot is empty")) {
152
146
  if (options.createEmptyDir) {
153
147
  const emptyPath = await options.createEmptyDir();
154
- await (0, promises_1.writeFile)(`${emptyPath}/.empty`, "");
148
+ await (0, promises_1.writeFile)(`${emptyPath}/.${emptySnapshotTag}`, "");
155
149
  return await this.backup({
156
150
  ...options,
151
+ tags: [...(options.tags || []), emptySnapshotTag],
157
152
  cwd: emptyPath,
158
153
  allowEmptySnapshot: false,
159
154
  paths: ["."],
@@ -197,10 +192,14 @@ class Restic {
197
192
  progressTimeout = setTimeout(progressRutine, progressInterval);
198
193
  }
199
194
  }
195
+ const snapshots = await this.snapshots({
196
+ snapshotIds: [options.id],
197
+ json: true,
198
+ });
200
199
  if (typeof progressInterval === "number")
201
200
  progressRutine();
202
201
  try {
203
- return await this.exec(["restore", "--json", options.id, "--target", options.target], {
202
+ const result = await this.exec(["restore", "--json", options.id, "--target", options.target], {
204
203
  stderr: {
205
204
  toExitCode: true,
206
205
  },
@@ -214,6 +213,9 @@ class Restic {
214
213
  }),
215
214
  },
216
215
  });
216
+ if (snapshots.at(0)?.tags?.includes(emptySnapshotTag))
217
+ await (0, promises_1.rm)((0, path_1.join)(options.target, `.${emptySnapshotTag}`));
218
+ return result;
217
219
  }
218
220
  finally {
219
221
  clearTimeout(progressTimeout);
@@ -1,11 +1,17 @@
1
1
  /// <reference types="node" />
2
+ import { Listr3TaskResultEnd } from "./list";
2
3
  export declare const showCursorCommand = "\u001B[?25h";
3
4
  export declare function renderProgressBar(progress: number, size?: number, subprogress?: number): string;
4
5
  export declare function logExec(command: string, argv?: string[], env?: NodeJS.ProcessEnv, logToStderr?: boolean): void;
5
6
  export declare function renderResult(error: Error | null | string | boolean | undefined, color?: boolean): string;
6
7
  export declare function renderError(error: Error | null | string | undefined, verbose?: number): string;
8
+ export declare function renderListTaskItem<T extends Record<string, any>>(item: Listr3TaskResultEnd<T>, color: boolean | undefined, config: {
9
+ [K in Listr3TaskResultEnd<T>["key"]]: (data: Extract<Listr3TaskResultEnd<T>, {
10
+ key: K;
11
+ }>["data"]) => string | number | string[] | Record<string, string | number>;
12
+ }): string;
7
13
  export declare function renderObject(object: Record<string, any>, color?: boolean): string;
8
- export type OptionsType<T1, T2 extends {
14
+ export type OptionsConfig<T1, T2 extends {
9
15
  [K in keyof T1]: unknown;
10
16
  }> = {
11
17
  [K in keyof Required<T1>]: {
@@ -18,8 +24,8 @@ export type OptionsType<T1, T2 extends {
18
24
  };
19
25
  export declare function parseOptions<T1, T2 extends {
20
26
  [K in keyof T1]: unknown;
21
- }>(object: T1, options: OptionsType<T1, T2>): T2;
27
+ }>(object: T1, options: OptionsConfig<T1, T2>): T2;
22
28
  export declare function stringifyOptions<T1, T2 extends {
23
29
  [K in keyof T1]: unknown;
24
- }>(options: OptionsType<T1, T2>, object: any): string[];
30
+ }>(options: OptionsConfig<T1, T2>, object: any): string[];
25
31
  export declare function confirm(message: string): Promise<unknown>;
package/lib/utils/cli.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.confirm = exports.stringifyOptions = exports.parseOptions = exports.renderObject = exports.renderError = exports.renderResult = exports.logExec = exports.renderProgressBar = exports.showCursorCommand = void 0;
6
+ exports.confirm = exports.stringifyOptions = exports.parseOptions = exports.renderObject = exports.renderListTaskItem = exports.renderError = exports.renderResult = exports.logExec = exports.renderProgressBar = exports.showCursorCommand = void 0;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
8
  const chalk_2 = require("chalk");
9
9
  const readline_1 = require("readline");
@@ -75,6 +75,22 @@ function renderError(error, verbose) {
75
75
  return chalk_1.default.red(message.trim());
76
76
  }
77
77
  exports.renderError = renderError;
78
+ function renderListTaskItem(item, color, config) {
79
+ const result = config[item.key]?.(item.data);
80
+ if (typeof result === "string" || typeof result === "number") {
81
+ return result.toString();
82
+ }
83
+ else if (Array.isArray(result)) {
84
+ return result.join(" ");
85
+ }
86
+ else if (typeof result === "object" && !!result) {
87
+ return renderObject(result, color);
88
+ }
89
+ else {
90
+ return "";
91
+ }
92
+ }
93
+ exports.renderListTaskItem = renderListTaskItem;
78
94
  function renderObject(object, color) {
79
95
  const values = [];
80
96
  for (const key in object)
@@ -0,0 +1,11 @@
1
+ export type CronScheduleUnit = number | {
2
+ each: number;
3
+ };
4
+ export type CronScheduleObject = {
5
+ minute?: CronScheduleUnit;
6
+ hour?: CronScheduleUnit;
7
+ day?: CronScheduleUnit;
8
+ month?: CronScheduleUnit;
9
+ weekDay?: CronScheduleUnit;
10
+ };
11
+ export declare function formatCronScheduleObject(object: CronScheduleObject): string;