@datatruck/cli 0.28.0 → 0.29.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.d.ts +7 -1
- package/Action/BackupAction.js +192 -176
- package/Action/CopyAction.d.ts +3 -1
- package/Action/CopyAction.js +67 -46
- package/Action/PruneAction.d.ts +2 -8
- package/Action/PruneAction.js +22 -35
- package/Action/RestoreAction.d.ts +1 -1
- package/Action/RestoreAction.js +12 -6
- package/Action/SnapshotsAction.js +1 -1
- package/CHANGELOG.md +18 -0
- package/Command/BackupCommand.d.ts +1 -0
- package/Command/BackupCommand.js +5 -0
- package/Command/CopyCommand.d.ts +2 -1
- package/Command/CopyCommand.js +6 -1
- package/Command/InitCommand.js +2 -2
- package/Command/PruneCommand.d.ts +2 -8
- package/Command/RestoreCommand.d.ts +1 -1
- package/Command/RestoreCommand.js +4 -4
- package/Config/Config.d.ts +2 -0
- package/Config/Config.js +1 -0
- package/Repository/DatatruckRepository.d.ts +1 -0
- package/Repository/DatatruckRepository.js +5 -0
- package/Task/MysqlDumpTask.js +1 -7
- package/Task/SqlDumpTaskAbstract.js +1 -1
- package/config.schema.json +3 -0
- package/package.json +1 -1
- package/utils/cli.d.ts +3 -2
- package/utils/cli.js +12 -5
- package/utils/crypto.d.ts +1 -0
- package/utils/crypto.js +15 -0
- package/utils/datatruck/snapshot.d.ts +4 -1
- package/utils/datatruck/snapshot.js +12 -22
- package/utils/date.d.ts +14 -1
- package/utils/date.js +25 -11
- package/utils/list.js +1 -1
- package/utils/tar.js +3 -1
package/Action/PruneAction.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.PruneAction = void 0;
|
|
4
4
|
const RepositoryFactory_1 = require("../Factory/RepositoryFactory");
|
|
5
5
|
const snapshot_1 = require("../utils/datatruck/snapshot");
|
|
6
|
+
const date_1 = require("../utils/date");
|
|
6
7
|
const object_1 = require("../utils/object");
|
|
7
8
|
const SnapshotsAction_1 = require("./SnapshotsAction");
|
|
8
9
|
class PruneAction {
|
|
@@ -36,43 +37,28 @@ class PruneAction {
|
|
|
36
37
|
});
|
|
37
38
|
const snapshots = await snapshotsAction.exec("prune");
|
|
38
39
|
const snapshotsDeleted = [];
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
};
|
|
43
|
-
const keepFilter = {
|
|
44
|
-
last: this.options.keepLast,
|
|
45
|
-
lastMinutely: this.options.keepMinutely,
|
|
46
|
-
lastHourly: this.options.keepHourly,
|
|
47
|
-
lastDaily: this.options.keepDaily,
|
|
48
|
-
lastMonthly: this.options.keepMonthly,
|
|
49
|
-
lastWeekly: this.options.keepWeekly,
|
|
50
|
-
lastYearly: this.options.keepYearly,
|
|
51
|
-
};
|
|
52
|
-
const hasIdFilter = Object.values(idFilter).some((v) => typeof v !== "undefined");
|
|
53
|
-
const hasKeepFilter = Object.values(keepFilter).some((v) => typeof v !== "undefined");
|
|
40
|
+
const hasIdFilter = typeof this.options.ids !== "undefined";
|
|
41
|
+
const keepFilter = (0, date_1.createFilterByLastOptions)(this.options);
|
|
42
|
+
const hasKeepFilter = Object.values(keepFilter).some((v) => typeof v === "number");
|
|
54
43
|
if (hasIdFilter && hasKeepFilter)
|
|
55
44
|
throw new Error(`Snapshot id filter can not be used with 'keep' filters`);
|
|
56
|
-
const
|
|
45
|
+
const prunePolicy = !hasIdFilter && !hasKeepFilter;
|
|
46
|
+
if (prunePolicy && !this.options.groupBy?.includes("packageName"))
|
|
47
|
+
throw new Error(`Policy config requires groupBy packageName`);
|
|
57
48
|
const keepSnapshots = hasKeepFilter
|
|
58
|
-
? (0, snapshot_1.groupAndFilter)(snapshots, this.options.groupBy,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const
|
|
49
|
+
? (0, snapshot_1.groupAndFilter)(snapshots, this.options.groupBy, keepFilter)
|
|
50
|
+
: prunePolicy
|
|
51
|
+
? (0, snapshot_1.groupAndFilter)(snapshots, this.options.groupBy, (groups) => {
|
|
52
|
+
const [snapshot] = groups;
|
|
53
|
+
const packageName = snapshot.packageName;
|
|
62
54
|
const config = this.config.packages.find((pkg) => pkg.name === packageName);
|
|
63
|
-
const prunePolicy = config?.prunePolicy ?? {};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
lastWeekly: prunePolicy.keepWeekly,
|
|
71
|
-
lastYearly: prunePolicy.keepYearly,
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
: keepFilter, reasons)
|
|
75
|
-
: [];
|
|
55
|
+
const prunePolicy = config?.prunePolicy ?? this.config.prunePolicy ?? {};
|
|
56
|
+
const hasPrunePolicy = Object.values(prunePolicy).some((v) => typeof v === "number");
|
|
57
|
+
return hasPrunePolicy
|
|
58
|
+
? (0, date_1.createFilterByLastOptions)(prunePolicy)
|
|
59
|
+
: "no-policy";
|
|
60
|
+
})
|
|
61
|
+
: [];
|
|
76
62
|
const result = {
|
|
77
63
|
total: snapshots.length,
|
|
78
64
|
prune: 0,
|
|
@@ -80,13 +66,14 @@ class PruneAction {
|
|
|
80
66
|
};
|
|
81
67
|
let snapshotIndex = 0;
|
|
82
68
|
for (const snapshot of snapshots) {
|
|
83
|
-
const
|
|
69
|
+
const keepSnapshot = keepSnapshots.find(({ item }) => item === snapshot);
|
|
70
|
+
const prune = !keepSnapshot;
|
|
84
71
|
if (prune)
|
|
85
72
|
result.prune++;
|
|
86
73
|
if (prune || this.options.returnsAll)
|
|
87
74
|
snapshotsDeleted.push({
|
|
88
75
|
...snapshot,
|
|
89
|
-
exclusionReasons: reasons[
|
|
76
|
+
exclusionReasons: keepSnapshot?.reasons || [],
|
|
90
77
|
});
|
|
91
78
|
snapshotIndex++;
|
|
92
79
|
}
|
|
@@ -17,7 +17,7 @@ export type RestoreActionOptions = {
|
|
|
17
17
|
repositoryNames?: string[];
|
|
18
18
|
repositoryTypes?: string[];
|
|
19
19
|
verbose?: boolean;
|
|
20
|
-
|
|
20
|
+
initial?: boolean;
|
|
21
21
|
tty?: "auto" | boolean;
|
|
22
22
|
progress?: "auto" | "interval" | boolean;
|
|
23
23
|
progressInterval?: number;
|
package/Action/RestoreAction.js
CHANGED
|
@@ -69,7 +69,7 @@ class RestoreAction {
|
|
|
69
69
|
let { snapshot, pkg, task } = data;
|
|
70
70
|
const repoConfig = (0, config_1.findRepositoryOrFail)(this.config, snapshot.repositoryName);
|
|
71
71
|
const repo = (0, RepositoryFactory_1.createRepo)(repoConfig);
|
|
72
|
-
if (
|
|
72
|
+
if (this.options.initial)
|
|
73
73
|
pkg = { ...pkg, restorePath: pkg.path };
|
|
74
74
|
let snapshotPath = pkg.restorePath ?? pkg.path;
|
|
75
75
|
await data.gc.cleanupIfFail(async () => {
|
|
@@ -101,7 +101,7 @@ class RestoreAction {
|
|
|
101
101
|
let title = item.key.slice(0, 1).toUpperCase() + item.key.slice(1);
|
|
102
102
|
return item.key === "restore" && color ? chalk_1.default.cyan(title) : title;
|
|
103
103
|
};
|
|
104
|
-
const renderData = (item, color) => {
|
|
104
|
+
const renderData = (item, color, result = []) => {
|
|
105
105
|
const g = (v) => (color ? `${chalk_1.default.gray(`(${v})`)}` : `(${v})`);
|
|
106
106
|
return item.key === "snapshots"
|
|
107
107
|
? `${item.data.id.slice(0, 8)} ${g(`${item.data.packages} packages`)}`
|
|
@@ -109,7 +109,13 @@ class RestoreAction {
|
|
|
109
109
|
? `${item.data.packageName} ${g(item.data.taskName)}`
|
|
110
110
|
: item.key === "restore"
|
|
111
111
|
? `${item.data.packageName} ${g(item.data.repositoryName)}`
|
|
112
|
-
: ""
|
|
112
|
+
: item.key === "summary"
|
|
113
|
+
? (0, cli_1.renderObject)({
|
|
114
|
+
errors: item.data.errors,
|
|
115
|
+
restores: result.filter((r) => !r.error && r.key === "restore")
|
|
116
|
+
.length,
|
|
117
|
+
})
|
|
118
|
+
: "";
|
|
113
119
|
};
|
|
114
120
|
return new DataFormat_1.DataFormat({
|
|
115
121
|
streams: options.streams,
|
|
@@ -123,11 +129,11 @@ class RestoreAction {
|
|
|
123
129
|
{ value: "Error", width: 50 },
|
|
124
130
|
],
|
|
125
131
|
rows: () => result.map((item) => [
|
|
126
|
-
(0, cli_1.
|
|
132
|
+
(0, cli_1.renderResult)(item.error),
|
|
127
133
|
renderTitle(item, true),
|
|
128
|
-
renderData(item, true),
|
|
134
|
+
renderData(item, true, result),
|
|
129
135
|
(0, date_1.duration)(item.elapsed),
|
|
130
|
-
(0, cli_1.
|
|
136
|
+
(0, cli_1.renderError)(item.error, options.verbose),
|
|
131
137
|
]),
|
|
132
138
|
},
|
|
133
139
|
});
|
|
@@ -44,7 +44,7 @@ class SnapshotsAction {
|
|
|
44
44
|
result.push(...extentedItems);
|
|
45
45
|
}
|
|
46
46
|
result = result.sort((a, b) => b.date.localeCompare(a.date));
|
|
47
|
-
return (0, snapshot_1.groupAndFilter)(result, this.options.groupBy, this.options);
|
|
47
|
+
return (0, snapshot_1.groupAndFilter)(result, this.options.groupBy, this.options).map(({ item }) => item);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
exports.SnapshotsAction = SnapshotsAction;
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @datatruck/cli
|
|
2
2
|
|
|
3
|
+
## 0.29.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`363fc0d`](https://github.com/swordev/datatruck/commit/363fc0d8158aba6ae6a171769ef01dcd0fd2de08) Thanks [@juanrgm](https://github.com/juanrgm)! - Add `--prune` option to the backup command
|
|
8
|
+
|
|
9
|
+
- [`e47ed46`](https://github.com/swordev/datatruck/commit/e47ed46c47fc93d7d5f3b76935d425c6b42ae9a5) Thanks [@juanrgm](https://github.com/juanrgm)! - Add `--last` option to the copy command
|
|
10
|
+
|
|
11
|
+
- [`0a760a2`](https://github.com/swordev/datatruck/commit/0a760a2038ff77966936b3a9a0a8e865f4dae4c4) Thanks [@juanrgm](https://github.com/juanrgm)! - Add global prune policy to the config
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [`1c5084d`](https://github.com/swordev/datatruck/commit/1c5084dab2058ab9699f1a908f2581cd03da0468) Thanks [@juanrgm](https://github.com/juanrgm)! - Rename `--no-restore-path` to `--initial`
|
|
16
|
+
|
|
17
|
+
- [`5fe3e91`](https://github.com/swordev/datatruck/commit/5fe3e91e994238cf901e570c9b9ef8254d79afa1) Thanks [@juanrgm](https://github.com/juanrgm)! - Fix prune policy
|
|
18
|
+
|
|
19
|
+
- [`bd4d42e`](https://github.com/swordev/datatruck/commit/bd4d42e0261f79bdb69dd55abc30ef8bb0bfdcd7) Thanks [@juanrgm](https://github.com/juanrgm)! - Fix reports
|
|
20
|
+
|
|
3
21
|
## 0.28.0
|
|
4
22
|
|
|
5
23
|
### Minor Changes
|
|
@@ -10,6 +10,7 @@ export type BackupCommandOptions<TResolved = false> = {
|
|
|
10
10
|
tag?: If<TResolved, string[]>;
|
|
11
11
|
dryRun?: boolean;
|
|
12
12
|
date?: string;
|
|
13
|
+
prune?: boolean;
|
|
13
14
|
};
|
|
14
15
|
export type BackupCommandResult = Unwrap<BackupAction["exec"]>;
|
|
15
16
|
export declare class BackupCommand extends CommandAbstract<BackupCommandOptions<false>, BackupCommandOptions<true>> {
|
package/Command/BackupCommand.js
CHANGED
|
@@ -41,6 +41,10 @@ class BackupCommand extends CommandAbstract_1.CommandAbstract {
|
|
|
41
41
|
description: "Date time (ISO)",
|
|
42
42
|
option: "--date <value>",
|
|
43
43
|
},
|
|
44
|
+
prune: {
|
|
45
|
+
description: "Prune backups",
|
|
46
|
+
option: "--prune",
|
|
47
|
+
},
|
|
44
48
|
});
|
|
45
49
|
}
|
|
46
50
|
async onExec() {
|
|
@@ -59,6 +63,7 @@ class BackupCommand extends CommandAbstract_1.CommandAbstract {
|
|
|
59
63
|
progress: this.globalOptions.progress,
|
|
60
64
|
progressInterval: this.globalOptions.progressInterval,
|
|
61
65
|
streams: this.streams,
|
|
66
|
+
prune: this.options.prune,
|
|
62
67
|
});
|
|
63
68
|
const result = await backup.exec();
|
|
64
69
|
if (this.globalOptions.outputFormat)
|
package/Command/CopyCommand.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { CopyAction } from "../Action/CopyAction";
|
|
|
2
2
|
import { If, Unwrap } from "../utils/ts";
|
|
3
3
|
import { CommandAbstract } from "./CommandAbstract";
|
|
4
4
|
export type CopyCommandOptionsType<TResolved = false> = {
|
|
5
|
-
id
|
|
5
|
+
id?: If<TResolved, string[]>;
|
|
6
|
+
last?: number;
|
|
6
7
|
package?: If<TResolved, string[]>;
|
|
7
8
|
packageTask?: If<TResolved, string[]>;
|
|
8
9
|
repository: string;
|
package/Command/CopyCommand.js
CHANGED
|
@@ -11,9 +11,13 @@ class CopyCommand extends CommandAbstract_1.CommandAbstract {
|
|
|
11
11
|
id: {
|
|
12
12
|
option: "-i,--id <ids>",
|
|
13
13
|
description: "Filter by identifiers",
|
|
14
|
-
required: true,
|
|
15
14
|
parser: string_1.parseStringList,
|
|
16
15
|
},
|
|
16
|
+
last: {
|
|
17
|
+
option: "-l,--last <amount>",
|
|
18
|
+
description: "Last snapshots",
|
|
19
|
+
parser: Number,
|
|
20
|
+
},
|
|
17
21
|
package: {
|
|
18
22
|
option: "-p,--package <names>",
|
|
19
23
|
description: "Filter by package names",
|
|
@@ -41,6 +45,7 @@ class CopyCommand extends CommandAbstract_1.CommandAbstract {
|
|
|
41
45
|
const config = await ConfigAction_1.ConfigAction.fromGlobalOptions(this.globalOptions);
|
|
42
46
|
const copy = new CopyAction_1.CopyAction(config, {
|
|
43
47
|
ids: this.options.id,
|
|
48
|
+
last: this.options.last,
|
|
44
49
|
packageNames: this.options.package,
|
|
45
50
|
packageTaskNames: this.options.packageTask,
|
|
46
51
|
repositoryName: this.options.repository,
|
package/Command/InitCommand.js
CHANGED
|
@@ -43,11 +43,11 @@ class InitCommand extends CommandAbstract_1.CommandAbstract {
|
|
|
43
43
|
{ value: "Error", width: 50 },
|
|
44
44
|
],
|
|
45
45
|
rows: () => response.map((item) => [
|
|
46
|
-
(0, cli_1.
|
|
46
|
+
(0, cli_1.renderResult)(item.error),
|
|
47
47
|
item.repositoryName,
|
|
48
48
|
item.repositoryType,
|
|
49
49
|
item.repositorySource,
|
|
50
|
-
(0, cli_1.
|
|
50
|
+
(0, cli_1.renderError)(item.error, verbose),
|
|
51
51
|
]),
|
|
52
52
|
},
|
|
53
53
|
});
|
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
import { SnapshotGroupByType } from "../Action/SnapshotsAction";
|
|
2
2
|
import { RepositoryConfigType } from "../Config/RepositoryConfig";
|
|
3
|
+
import { KeepObject } from "../utils/date";
|
|
3
4
|
import { If } from "../utils/ts";
|
|
4
5
|
import { CommandAbstract } from "./CommandAbstract";
|
|
5
|
-
export type PruneCommandOptions<TResolved = false> = {
|
|
6
|
+
export type PruneCommandOptions<TResolved = false> = KeepObject & {
|
|
6
7
|
id?: If<TResolved, string[]>;
|
|
7
8
|
longId?: boolean;
|
|
8
9
|
package?: If<TResolved, string[]>;
|
|
9
10
|
repository?: If<TResolved, string[]>;
|
|
10
11
|
repositoryType?: If<TResolved, RepositoryConfigType["type"][]>;
|
|
11
12
|
tag?: If<TResolved, string[]>;
|
|
12
|
-
keepLast?: number;
|
|
13
|
-
keepMinutely?: number;
|
|
14
|
-
keepHourly?: number;
|
|
15
|
-
keepDaily?: number;
|
|
16
|
-
keepWeekly?: number;
|
|
17
|
-
keepMonthly?: number;
|
|
18
|
-
keepYearly?: number;
|
|
19
13
|
groupBy?: If<TResolved, SnapshotGroupByType[]>;
|
|
20
14
|
dryRun?: boolean;
|
|
21
15
|
showAll?: boolean;
|
|
@@ -9,7 +9,7 @@ export type RestoreCommandOptionsType<TResolved = false> = {
|
|
|
9
9
|
repository?: If<TResolved, string[]>;
|
|
10
10
|
repositoryType?: If<TResolved, RepositoryConfigType["type"][]>;
|
|
11
11
|
tag?: If<TResolved, string[]>;
|
|
12
|
-
|
|
12
|
+
initial?: boolean;
|
|
13
13
|
};
|
|
14
14
|
export declare class RestoreCommand extends CommandAbstract<RestoreCommandOptionsType<false>, RestoreCommandOptionsType<true>> {
|
|
15
15
|
onOptions(): import("../utils/cli").OptionsType<RestoreCommandOptionsType<false>, RestoreCommandOptionsType<true>>;
|
|
@@ -18,9 +18,9 @@ class RestoreCommand extends CommandAbstract_1.CommandAbstract {
|
|
|
18
18
|
option: "-p,--package <values>",
|
|
19
19
|
parser: string_1.parseStringList,
|
|
20
20
|
},
|
|
21
|
-
|
|
22
|
-
description: "
|
|
23
|
-
option: "--
|
|
21
|
+
initial: {
|
|
22
|
+
description: "Initial restoring (disables restore path)",
|
|
23
|
+
option: "--initial",
|
|
24
24
|
},
|
|
25
25
|
packageTask: {
|
|
26
26
|
description: "Filter by package task names",
|
|
@@ -60,7 +60,7 @@ class RestoreCommand extends CommandAbstract_1.CommandAbstract {
|
|
|
60
60
|
repositoryTypes: this.options.repositoryType,
|
|
61
61
|
tags: this.options.tag,
|
|
62
62
|
verbose: verbose > 0,
|
|
63
|
-
|
|
63
|
+
initial: this.options.initial,
|
|
64
64
|
tty: this.globalOptions.tty,
|
|
65
65
|
progress: this.globalOptions.progress,
|
|
66
66
|
progressInterval: this.globalOptions.progressInterval,
|
package/Config/Config.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { FormatType } from "../utils/DataFormat";
|
|
|
2
2
|
import { DatatruckServerOptions } from "../utils/datatruck/server";
|
|
3
3
|
import { Step } from "../utils/steps";
|
|
4
4
|
import { PackageConfigType } from "./PackageConfig";
|
|
5
|
+
import { PrunePolicyConfigType } from "./PrunePolicyConfig";
|
|
5
6
|
import { RepositoryConfigType } from "./RepositoryConfig";
|
|
6
7
|
import type { JSONSchema7 } from "json-schema";
|
|
7
8
|
export type ConfigType = {
|
|
@@ -11,6 +12,7 @@ export type ConfigType = {
|
|
|
11
12
|
packages: PackageConfigType[];
|
|
12
13
|
server?: DatatruckServerOptions;
|
|
13
14
|
reports?: ReportConfig[];
|
|
15
|
+
prunePolicy?: PrunePolicyConfigType;
|
|
14
16
|
};
|
|
15
17
|
export type ReportConfig = {
|
|
16
18
|
when?: "success" | "error";
|
package/Config/Config.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.DatatruckRepository = exports.datatruckPackageRepositoryDefinition = exp
|
|
|
4
4
|
const AppError_1 = require("../Error/AppError");
|
|
5
5
|
const DefinitionEnum_1 = require("../JsonSchema/DefinitionEnum");
|
|
6
6
|
const cli_1 = require("../utils/cli");
|
|
7
|
+
const crypto_1 = require("../utils/crypto");
|
|
7
8
|
const client_1 = require("../utils/datatruck/client");
|
|
8
9
|
const paths_1 = require("../utils/datatruck/paths");
|
|
9
10
|
const fs_1 = require("../utils/fs");
|
|
@@ -213,6 +214,7 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
213
214
|
tarStats[packBasename] = {
|
|
214
215
|
files: stream.lines(packIndex),
|
|
215
216
|
size: 0,
|
|
217
|
+
checksum: "",
|
|
216
218
|
};
|
|
217
219
|
const tarPath = (0, path_1.join)(outPath, packBasename);
|
|
218
220
|
await (0, tar_1.createTar)({
|
|
@@ -223,8 +225,11 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
223
225
|
output: tarPath,
|
|
224
226
|
onEntry: async (data) => scanner.progress(pack.compress ? "Compressing" : "Packing", data.path),
|
|
225
227
|
});
|
|
228
|
+
scanner.progress("Fetching tar stats", (0, path_1.basename)(tarPath));
|
|
229
|
+
tarStats[packBasename].checksum = await (0, crypto_1.calcFileHash)(tarPath, "sha1");
|
|
226
230
|
tarStats[packBasename].size = (await (0, promises_1.stat)(tarPath)).size;
|
|
227
231
|
if (!fs.isLocal()) {
|
|
232
|
+
scanner.progress("Uploading tar", (0, path_1.basename)(tarPath));
|
|
228
233
|
await fs.upload(tarPath, `${snapshotName}/${packBasename}`);
|
|
229
234
|
await (0, promises_1.rm)(tarPath);
|
|
230
235
|
}
|
package/Task/MysqlDumpTask.js
CHANGED
|
@@ -36,12 +36,6 @@ class MysqlDumpTask extends TaskAbstract_1.TaskAbstract {
|
|
|
36
36
|
async backup(data) {
|
|
37
37
|
const compressAndClean = this.config.compress
|
|
38
38
|
? async (path) => {
|
|
39
|
-
data.onProgress({
|
|
40
|
-
relative: {
|
|
41
|
-
description: "Compressing",
|
|
42
|
-
payload: (0, path_1.basename)(path),
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
39
|
await (0, tar_1.createTar)({
|
|
46
40
|
include: [(0, path_1.relative)(snapshotPath, path)],
|
|
47
41
|
output: `${path}.tar.gz`,
|
|
@@ -207,7 +201,7 @@ class MysqlDumpTask extends TaskAbstract_1.TaskAbstract {
|
|
|
207
201
|
const database = {
|
|
208
202
|
name: (0, config_1.resolveDatabaseName)(this.config.database, params),
|
|
209
203
|
};
|
|
210
|
-
if (this.config.targetDatabase && data.options.
|
|
204
|
+
if (this.config.targetDatabase && !data.options.initial)
|
|
211
205
|
database.name = (0, config_1.resolveDatabaseName)(this.config.targetDatabase.name, {
|
|
212
206
|
...params,
|
|
213
207
|
database: database.name,
|
|
@@ -204,7 +204,7 @@ class SqlDumpTaskAbstract extends TaskAbstract_1.TaskAbstract {
|
|
|
204
204
|
database: undefined,
|
|
205
205
|
}),
|
|
206
206
|
};
|
|
207
|
-
if (this.config.targetDatabase && data.options.
|
|
207
|
+
if (this.config.targetDatabase && !data.options.initial) {
|
|
208
208
|
database.name = (0, config_1.resolveDatabaseName)(this.config.targetDatabase.name, {
|
|
209
209
|
packageName: data.package.name,
|
|
210
210
|
snapshotId: data.options.snapshotId,
|
package/config.schema.json
CHANGED
package/package.json
CHANGED
package/utils/cli.d.ts
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
export declare const showCursorCommand = "\u001B[?25h";
|
|
3
3
|
export declare function renderProgressBar(progress: number, size?: number, subprogress?: number): string;
|
|
4
4
|
export declare function logExec(command: string, argv?: string[], env?: NodeJS.ProcessEnv, logToStderr?: boolean): void;
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
5
|
+
export declare function renderResult(error: Error | null | string | boolean | undefined, color?: boolean): string;
|
|
6
|
+
export declare function renderError(error: Error | null | string | undefined, verbose?: number): string;
|
|
7
|
+
export declare function renderObject(object: Record<string, any>): string;
|
|
7
8
|
export type OptionsType<T1, T2 extends {
|
|
8
9
|
[K in keyof T1]: unknown;
|
|
9
10
|
}> = {
|
package/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.parseOptions = exports.
|
|
6
|
+
exports.confirm = exports.parseOptions = exports.renderObject = 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");
|
|
@@ -48,7 +48,7 @@ function logExec(command, argv = [], env, logToStderr) {
|
|
|
48
48
|
: console.info(text);
|
|
49
49
|
}
|
|
50
50
|
exports.logExec = logExec;
|
|
51
|
-
function
|
|
51
|
+
function renderResult(error, color = true) {
|
|
52
52
|
return error
|
|
53
53
|
? color
|
|
54
54
|
? chalk_1.default.red("Χ")
|
|
@@ -57,8 +57,8 @@ function resultColumn(error, color = true) {
|
|
|
57
57
|
? chalk_1.default.green("✓")
|
|
58
58
|
: "✓";
|
|
59
59
|
}
|
|
60
|
-
exports.
|
|
61
|
-
function
|
|
60
|
+
exports.renderResult = renderResult;
|
|
61
|
+
function renderError(error, verbose) {
|
|
62
62
|
let message = null;
|
|
63
63
|
if (typeof error === "string") {
|
|
64
64
|
message = error;
|
|
@@ -74,7 +74,14 @@ function errorColumn(error, verbose) {
|
|
|
74
74
|
}
|
|
75
75
|
return chalk_1.default.red(message.trim());
|
|
76
76
|
}
|
|
77
|
-
exports.
|
|
77
|
+
exports.renderError = renderError;
|
|
78
|
+
function renderObject(object) {
|
|
79
|
+
const values = [];
|
|
80
|
+
for (const key in object)
|
|
81
|
+
values.push(`${key}: ${(0, chalk_2.grey)(object[key])}`);
|
|
82
|
+
return values.join(` `);
|
|
83
|
+
}
|
|
84
|
+
exports.renderObject = renderObject;
|
|
78
85
|
function parseOptions(object, options) {
|
|
79
86
|
const result = {};
|
|
80
87
|
for (const key in options) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function calcFileHash(path: string, algorithm: string): Promise<string>;
|
package/utils/crypto.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calcFileHash = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
function calcFileHash(path, algorithm) {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
const hash = (0, crypto_1.createHash)(algorithm);
|
|
9
|
+
(0, fs_1.createReadStream)(path)
|
|
10
|
+
.on("error", reject)
|
|
11
|
+
.on("data", (chunk) => hash.update(chunk))
|
|
12
|
+
.on("end", () => resolve(hash.digest("hex")));
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
exports.calcFileHash = calcFileHash;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { SnapshotGroupByType } from "../../Action/SnapshotsAction";
|
|
2
2
|
import { Snapshot } from "../../Repository/RepositoryAbstract";
|
|
3
3
|
import { FilterByLastOptionsType } from "../date";
|
|
4
|
-
export declare function groupAndFilter<TSnapshot extends Snapshot>(snapshots: TSnapshot[],
|
|
4
|
+
export declare function groupAndFilter<TSnapshot extends Snapshot>(snapshots: TSnapshot[], groupKeys?: SnapshotGroupByType[], inFilter?: FilterByLastOptionsType | ((group: TSnapshot[]) => FilterByLastOptionsType | string)): {
|
|
5
|
+
item: TSnapshot;
|
|
6
|
+
reasons: string[];
|
|
7
|
+
}[];
|
|
@@ -3,29 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.groupAndFilter = void 0;
|
|
4
4
|
const date_1 = require("../date");
|
|
5
5
|
const object_1 = require("../object");
|
|
6
|
-
function groupAndFilter(snapshots,
|
|
7
|
-
const
|
|
8
|
-
? (0, object_1.groupBy)(snapshots,
|
|
6
|
+
function groupAndFilter(snapshots, groupKeys, inFilter) {
|
|
7
|
+
const groups = groupKeys?.length
|
|
8
|
+
? (0, object_1.groupBy)(snapshots, groupKeys)
|
|
9
9
|
: { "": snapshots };
|
|
10
|
-
const
|
|
11
|
-
for (const key in
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
result.push(...(0, date_1.filterByLast)(grouped[key], typeof filter === "function" ? filter(grouped[key]) : filter, groupReasons));
|
|
17
|
-
if (groupReasons && reasons) {
|
|
18
|
-
for (const groupItemIndex in groupReasons) {
|
|
19
|
-
const snapshot = grouped[key][groupItemIndex];
|
|
20
|
-
const snapshotIndex = snapshots.indexOf(snapshot);
|
|
21
|
-
reasons[snapshotIndex] = groupReasons[groupItemIndex];
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
result.push(...grouped[key]);
|
|
27
|
-
}
|
|
10
|
+
const keep = [];
|
|
11
|
+
for (const key in groups) {
|
|
12
|
+
const filter = typeof inFilter === "function" ? inFilter(groups[key]) : inFilter || {};
|
|
13
|
+
keep.push(...(typeof filter === "string"
|
|
14
|
+
? groups[key].map((item) => ({ item, reasons: [filter] }))
|
|
15
|
+
: (0, date_1.filterByLast)(groups[key], filter)));
|
|
28
16
|
}
|
|
29
|
-
return snapshots
|
|
17
|
+
return snapshots
|
|
18
|
+
.map((snapshot) => keep.find((v) => v.item === snapshot))
|
|
19
|
+
.filter((v) => !!v);
|
|
30
20
|
}
|
|
31
21
|
exports.groupAndFilter = groupAndFilter;
|
package/utils/date.d.ts
CHANGED
|
@@ -7,9 +7,22 @@ export type FilterByLastOptionsType = {
|
|
|
7
7
|
lastMonthly?: number;
|
|
8
8
|
lastYearly?: number;
|
|
9
9
|
};
|
|
10
|
+
export type KeepObject = {
|
|
11
|
+
keepLast?: number;
|
|
12
|
+
keepMinutely?: number;
|
|
13
|
+
keepHourly?: number;
|
|
14
|
+
keepDaily?: number;
|
|
15
|
+
keepWeekly?: number;
|
|
16
|
+
keepMonthly?: number;
|
|
17
|
+
keepYearly?: number;
|
|
18
|
+
};
|
|
19
|
+
export declare function createFilterByLastOptions(keep: KeepObject): FilterByLastOptionsType;
|
|
10
20
|
export declare function filterByLast<TItem extends {
|
|
11
21
|
date: string;
|
|
12
|
-
}>(items: TItem[], options: FilterByLastOptionsType
|
|
22
|
+
}>(items: TItem[], options: FilterByLastOptionsType): {
|
|
23
|
+
item: TItem;
|
|
24
|
+
reasons: string[];
|
|
25
|
+
}[];
|
|
13
26
|
export type Timer = {
|
|
14
27
|
reset: (min?: number) => boolean;
|
|
15
28
|
check: (min: number) => boolean;
|