@datatruck/cli 0.26.2 → 0.28.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 +69 -34
- package/Action/BackupAction.js +284 -244
- package/Action/CleanCacheAction.d.ts +8 -4
- package/Action/CleanCacheAction.js +8 -5
- package/Action/ConfigAction.d.ts +12 -5
- package/Action/ConfigAction.js +14 -18
- package/Action/CopyAction.d.ts +49 -0
- package/Action/CopyAction.js +144 -0
- package/Action/InitAction.d.ts +3 -3
- package/Action/InitAction.js +9 -9
- package/Action/PruneAction.d.ts +9 -9
- package/Action/PruneAction.js +39 -23
- package/Action/RestoreAction.d.ts +48 -23
- package/Action/RestoreAction.js +158 -195
- package/Action/SnapshotsAction.d.ts +8 -8
- package/Action/SnapshotsAction.js +8 -8
- package/CHANGELOG.md +495 -0
- package/Command/BackupCommand.d.ts +6 -4
- package/Command/BackupCommand.js +9 -26
- package/Command/CleanCacheCommand.d.ts +4 -4
- package/Command/CleanCacheCommand.js +26 -5
- package/Command/CommandAbstract.d.ts +10 -7
- package/Command/CommandAbstract.js +4 -1
- package/Command/ConfigCommand.d.ts +6 -9
- package/Command/ConfigCommand.js +13 -8
- package/Command/CopyCommand.d.ts +15 -0
- package/Command/CopyCommand.js +61 -0
- package/Command/InitCommand.d.ts +4 -4
- package/Command/InitCommand.js +11 -15
- package/Command/PruneCommand.d.ts +3 -3
- package/Command/PruneCommand.js +13 -12
- package/Command/RestoreCommand.js +9 -17
- package/Command/SnapshotsCommand.d.ts +4 -4
- package/Command/SnapshotsCommand.js +16 -15
- package/Command/StartServerCommand.d.ts +6 -0
- package/Command/StartServerCommand.js +24 -0
- package/Config/Config.d.ts +11 -0
- package/Config/Config.js +43 -0
- package/Config/PrunePolicyConfig.d.ts +2 -2
- package/Factory/CommandFactory.d.ts +29 -33
- package/Factory/CommandFactory.js +32 -53
- package/Factory/RepositoryFactory.d.ts +1 -1
- package/Factory/RepositoryFactory.js +3 -3
- package/Factory/TaskFactory.d.ts +1 -1
- package/Factory/TaskFactory.js +3 -3
- package/Repository/DatatruckRepository.d.ts +17 -16
- package/Repository/DatatruckRepository.js +131 -149
- package/Repository/GitRepository.d.ts +9 -8
- package/Repository/GitRepository.js +22 -25
- package/Repository/RepositoryAbstract.d.ts +39 -37
- package/Repository/RepositoryAbstract.js +4 -5
- package/Repository/ResticRepository.d.ts +9 -8
- package/Repository/ResticRepository.js +30 -28
- package/Task/GitTask.d.ts +6 -7
- package/Task/GitTask.js +24 -30
- package/Task/MariadbTask.d.ts +4 -5
- package/Task/MariadbTask.js +26 -32
- package/Task/MssqlTask.d.ts +5 -3
- package/Task/MssqlTask.js +11 -12
- package/Task/MysqlDumpTask.d.ts +10 -3
- package/Task/MysqlDumpTask.js +107 -31
- package/Task/ScriptTask.d.ts +23 -18
- package/Task/ScriptTask.js +34 -24
- package/Task/SqlDumpTaskAbstract.d.ts +8 -3
- package/Task/SqlDumpTaskAbstract.js +31 -19
- package/Task/TaskAbstract.d.ts +24 -25
- package/Task/TaskAbstract.js +6 -10
- package/cli.js +14 -5
- package/config.schema.json +124 -3
- package/package.json +4 -5
- package/utils/DataFormat.d.ts +23 -12
- package/utils/DataFormat.js +36 -14
- package/utils/cli.d.ts +2 -9
- package/utils/cli.js +9 -52
- package/utils/datatruck/client.d.ts +24 -0
- package/utils/datatruck/client.js +99 -0
- package/utils/datatruck/config.d.ts +8 -6
- package/utils/datatruck/config.js +18 -3
- package/utils/datatruck/paths.d.ts +5 -9
- package/utils/datatruck/paths.js +2 -2
- package/utils/datatruck/server.d.ts +21 -0
- package/utils/datatruck/server.js +96 -0
- package/utils/datatruck/snapshot.d.ts +2 -2
- package/utils/date.d.ts +7 -3
- package/utils/date.js +22 -14
- package/utils/fs.d.ts +27 -15
- package/utils/fs.js +110 -62
- package/utils/http.d.ts +21 -0
- package/utils/http.js +154 -0
- package/utils/list.d.ts +64 -0
- package/utils/list.js +145 -0
- package/utils/mysql.d.ts +2 -0
- package/utils/mysql.js +21 -2
- package/utils/process.d.ts +1 -0
- package/utils/process.js +24 -31
- package/utils/progress.d.ts +33 -0
- package/utils/progress.js +113 -0
- package/utils/steps.d.ts +11 -0
- package/utils/steps.js +22 -10
- package/utils/stream.d.ts +7 -0
- package/utils/stream.js +10 -0
- package/utils/string.d.ts +0 -1
- package/utils/string.js +1 -13
- package/utils/tar.d.ts +10 -3
- package/utils/tar.js +70 -44
- package/utils/temp.d.ts +26 -0
- package/utils/temp.js +133 -0
- package/utils/virtual-fs.d.ts +37 -0
- package/utils/virtual-fs.js +65 -0
- package/Action/BackupSessionsAction.d.ts +0 -13
- package/Action/BackupSessionsAction.js +0 -18
- package/Action/RestoreSessionsAction.d.ts +0 -13
- package/Action/RestoreSessionsAction.js +0 -18
- package/Command/BackupSessionsCommand.d.ts +0 -12
- package/Command/BackupSessionsCommand.js +0 -92
- package/Command/RestoreSessionsCommand.d.ts +0 -12
- package/Command/RestoreSessionsCommand.js +0 -91
- package/Decorator/EntityDecorator.d.ts +0 -11
- package/Decorator/EntityDecorator.js +0 -17
- package/Entity/BackupSessionEntity.d.ts +0 -6
- package/Entity/BackupSessionEntity.js +0 -25
- package/Entity/BackupSessionRepositoryEntity.d.ts +0 -6
- package/Entity/BackupSessionRepositoryEntity.js +0 -25
- package/Entity/BackupSessionTaskEntity.d.ts +0 -5
- package/Entity/BackupSessionTaskEntity.js +0 -24
- package/Entity/CrudEntityAbstract.d.ts +0 -5
- package/Entity/CrudEntityAbstract.js +0 -9
- package/Entity/RestoreSessionEntity.d.ts +0 -5
- package/Entity/RestoreSessionEntity.js +0 -24
- package/Entity/RestoreSessionRepositoryEntity.d.ts +0 -6
- package/Entity/RestoreSessionRepositoryEntity.js +0 -25
- package/Entity/RestoreSessionTaskEntity.d.ts +0 -5
- package/Entity/RestoreSessionTaskEntity.js +0 -24
- package/Entity/StateEntityAbstract.d.ts +0 -9
- package/Entity/StateEntityAbstract.js +0 -12
- package/Factory/EntityFactory.d.ts +0 -6
- package/Factory/EntityFactory.js +0 -40
- package/SessionDriver/ConsoleSessionDriver.d.ts +0 -42
- package/SessionDriver/ConsoleSessionDriver.js +0 -208
- package/SessionDriver/SessionDriverAbstract.d.ts +0 -77
- package/SessionDriver/SessionDriverAbstract.js +0 -28
- package/SessionDriver/SqliteSessionDriver.d.ts +0 -20
- package/SessionDriver/SqliteSessionDriver.js +0 -173
- package/SessionManager/BackupSessionManager.d.ts +0 -45
- package/SessionManager/BackupSessionManager.js +0 -218
- package/SessionManager/RestoreSessionManager.d.ts +0 -47
- package/SessionManager/RestoreSessionManager.js +0 -218
- package/SessionManager/SessionManagerAbstract.d.ts +0 -18
- package/SessionManager/SessionManagerAbstract.js +0 -36
- package/migrations/001-initial.sql +0 -98
- package/utils/entity.d.ts +0 -4
- package/utils/entity.js +0 -10
package/utils/tar.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.extractTar = exports.createTar = exports.checkPigzLib = exports.listTar = exports.getTarVendor = exports.compressDefinition = void 0;
|
|
3
|
+
exports.extractTar = exports.normalizeTarPath = exports.createTar = exports.checkPigzLib = exports.listTar = exports.getTarVendor = exports.compressDefinition = void 0;
|
|
4
4
|
const cli_1 = require("./cli");
|
|
5
5
|
const fs_1 = require("./fs");
|
|
6
6
|
const math_1 = require("./math");
|
|
@@ -52,13 +52,18 @@ async function getTarVendor(cache = true, log = false) {
|
|
|
52
52
|
}
|
|
53
53
|
exports.getTarVendor = getTarVendor;
|
|
54
54
|
async function listTar(options) {
|
|
55
|
+
const vendor = await getTarVendor(true, options.verbose);
|
|
55
56
|
let total = 0;
|
|
56
|
-
await (0, process_1.exec)("tar", [
|
|
57
|
+
await (0, process_1.exec)("tar", [
|
|
58
|
+
"-tf",
|
|
59
|
+
toLocalPath(options.input),
|
|
60
|
+
...(vendor === "bsdtar" ? [] : ["--force-local"]),
|
|
61
|
+
], {}, {
|
|
57
62
|
log: options.verbose,
|
|
58
63
|
stdout: {
|
|
59
64
|
parseLines: "skip-empty",
|
|
60
65
|
onData: (path) => {
|
|
61
|
-
options.onEntry?.({ path });
|
|
66
|
+
options.onEntry?.({ path: normalizeTarPath(path) });
|
|
62
67
|
total++;
|
|
63
68
|
},
|
|
64
69
|
},
|
|
@@ -91,7 +96,9 @@ async function ifX(input, cb) {
|
|
|
91
96
|
}
|
|
92
97
|
async function createTar(options) {
|
|
93
98
|
const vendor = await getTarVendor(true, options.verbose);
|
|
94
|
-
const total =
|
|
99
|
+
const total = "include" in options
|
|
100
|
+
? options.include.length
|
|
101
|
+
: await (0, fs_1.countFileLines)(options.includeList);
|
|
95
102
|
const compress = await ifX(options.compress, async (compress) => ({
|
|
96
103
|
...compress,
|
|
97
104
|
cores: await resolveCores(compress.cores),
|
|
@@ -103,16 +110,27 @@ async function createTar(options) {
|
|
|
103
110
|
GZIP_OPT: compress.level.toString(),
|
|
104
111
|
}),
|
|
105
112
|
};
|
|
113
|
+
const onData = (line) => {
|
|
114
|
+
current++;
|
|
115
|
+
let path = vendor === "bsdtar" ? line.slice(2) : line;
|
|
116
|
+
options.onEntry?.({
|
|
117
|
+
path: normalizeTarPath(path),
|
|
118
|
+
progress: {
|
|
119
|
+
total,
|
|
120
|
+
current,
|
|
121
|
+
percent: (0, math_1.progressPercent)(total, current),
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
};
|
|
106
125
|
await (0, process_1.exec)("tar", [
|
|
107
126
|
"--no-recursion",
|
|
108
127
|
"-C",
|
|
109
128
|
toLocalPath(options.path),
|
|
110
129
|
compress?.cores === 1 ? "-czvf" : "-cvf",
|
|
111
130
|
toLocalPath(options.output),
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
"--
|
|
115
|
-
"--force-local",
|
|
131
|
+
// https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=172293
|
|
132
|
+
...(vendor === "bsdtar" ? [] : ["--ignore-failed-read"]),
|
|
133
|
+
...(vendor === "bsdtar" ? [] : ["--force-local"]),
|
|
116
134
|
...(compress && compress.cores > 1
|
|
117
135
|
? [
|
|
118
136
|
"-I",
|
|
@@ -126,6 +144,9 @@ async function createTar(options) {
|
|
|
126
144
|
.join(" ")}"`,
|
|
127
145
|
]
|
|
128
146
|
: []),
|
|
147
|
+
...("includeList" in options
|
|
148
|
+
? ["-T", toLocalPath(options.includeList)]
|
|
149
|
+
: ["--", ...options.include]),
|
|
129
150
|
], {
|
|
130
151
|
...(compress &&
|
|
131
152
|
compress.cores > 1 && {
|
|
@@ -137,24 +158,16 @@ async function createTar(options) {
|
|
|
137
158
|
},
|
|
138
159
|
}, {
|
|
139
160
|
log: options.verbose ? { envNames: Object.keys(env) } : false,
|
|
140
|
-
|
|
141
|
-
stdout: options.onEntry
|
|
161
|
+
...(vendor === "bsdtar"
|
|
142
162
|
? {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const path = vendor === "bsdtar" ? line.slice(2) : line;
|
|
147
|
-
options.onEntry?.({
|
|
148
|
-
path,
|
|
149
|
-
progress: {
|
|
150
|
-
total,
|
|
151
|
-
current,
|
|
152
|
-
percent: (0, math_1.progressPercent)(total, current),
|
|
153
|
-
},
|
|
154
|
-
});
|
|
155
|
-
},
|
|
163
|
+
stderr: options.onEntry
|
|
164
|
+
? { toExitCode: true, parseLines: "skip-empty", onData }
|
|
165
|
+
: { toExitCode: true },
|
|
156
166
|
}
|
|
157
|
-
:
|
|
167
|
+
: {
|
|
168
|
+
stderr: { toExitCode: true },
|
|
169
|
+
stdout: { parseLines: "skip-empty", onData },
|
|
170
|
+
}),
|
|
158
171
|
});
|
|
159
172
|
}
|
|
160
173
|
exports.createTar = createTar;
|
|
@@ -164,9 +177,18 @@ exports.createTar = createTar;
|
|
|
164
177
|
function toLocalPath(path) {
|
|
165
178
|
return (0, os_1.platform)() === "win32" ? path.replace(/\\/g, "/") : path;
|
|
166
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* bsdtar (only windows?) fails if path ends with slash
|
|
182
|
+
*/
|
|
183
|
+
function normalizeTarPath(path) {
|
|
184
|
+
return path.endsWith("/") ? path.slice(0, -1) : path;
|
|
185
|
+
}
|
|
186
|
+
exports.normalizeTarPath = normalizeTarPath;
|
|
167
187
|
async function extractTar(options) {
|
|
168
|
-
let total = options.
|
|
169
|
-
|
|
188
|
+
let total = options.onEntry
|
|
189
|
+
? options.total ??
|
|
190
|
+
(await listTar({ input: options.input, verbose: options.verbose }))
|
|
191
|
+
: undefined;
|
|
170
192
|
if (!(await (0, fs_1.existsDir)(options.output))) {
|
|
171
193
|
if (options.verbose)
|
|
172
194
|
(0, cli_1.logExec)("mkdir", ["-p", options.output]);
|
|
@@ -177,12 +199,25 @@ async function extractTar(options) {
|
|
|
177
199
|
cores: await resolveCores(decompress.cores),
|
|
178
200
|
}));
|
|
179
201
|
let current = 0;
|
|
202
|
+
const vendor = await getTarVendor(true, options.verbose);
|
|
203
|
+
const onData = (line) => {
|
|
204
|
+
const path = vendor === "bsdtar" ? line.slice(2) : line;
|
|
205
|
+
current++;
|
|
206
|
+
options.onEntry?.({
|
|
207
|
+
path: normalizeTarPath(path),
|
|
208
|
+
progress: {
|
|
209
|
+
total: total,
|
|
210
|
+
current,
|
|
211
|
+
percent: (0, math_1.progressPercent)(total, current),
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
};
|
|
180
215
|
await (0, process_1.exec)("tar", [
|
|
181
216
|
decompress?.cores === 1 ? "-xzvpf" : "-xvpf",
|
|
182
217
|
toLocalPath(options.input),
|
|
183
218
|
"-C",
|
|
184
219
|
toLocalPath(options.output),
|
|
185
|
-
"--force-local",
|
|
220
|
+
...(vendor === "bsdtar" ? [] : ["--force-local"]),
|
|
186
221
|
...(decompress && decompress.cores > 1
|
|
187
222
|
? ["-I", `"pigz -p ${decompress.cores}"`]
|
|
188
223
|
: []),
|
|
@@ -193,25 +228,16 @@ async function extractTar(options) {
|
|
|
193
228
|
}),
|
|
194
229
|
}, {
|
|
195
230
|
log: options.verbose,
|
|
196
|
-
|
|
197
|
-
toExitCode: true,
|
|
198
|
-
},
|
|
199
|
-
stdout: options.onEntry
|
|
231
|
+
...(vendor === "bsdtar"
|
|
200
232
|
? {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
options.onEntry?.({
|
|
205
|
-
path,
|
|
206
|
-
progress: {
|
|
207
|
-
total,
|
|
208
|
-
current,
|
|
209
|
-
percent: (0, math_1.progressPercent)(total, current),
|
|
210
|
-
},
|
|
211
|
-
});
|
|
212
|
-
},
|
|
233
|
+
stderr: options.onEntry
|
|
234
|
+
? { toExitCode: true, parseLines: "skip-empty", onData }
|
|
235
|
+
: { toExitCode: true },
|
|
213
236
|
}
|
|
214
|
-
:
|
|
237
|
+
: {
|
|
238
|
+
stderr: { toExitCode: true },
|
|
239
|
+
stdout: { parseLines: "skip-empty", onData },
|
|
240
|
+
}),
|
|
215
241
|
});
|
|
216
242
|
}
|
|
217
243
|
exports.extractTar = extractTar;
|
package/utils/temp.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
export declare function parentTmpDir(): string;
|
|
3
|
+
export declare function sessionTmpDir(): string;
|
|
4
|
+
export declare function ensureFreeDiskTempSpace(size: number | string): Promise<void>;
|
|
5
|
+
export declare function isTmpDir(path: string): boolean;
|
|
6
|
+
export declare function rmTmpDir(input: string | string[]): Promise<void>;
|
|
7
|
+
export declare function tmpDir(...keys: [string, ...string[]]): string;
|
|
8
|
+
export declare function mkTmpDir(...keys: [string, ...string[]]): Promise<string>;
|
|
9
|
+
export declare function useTempDir(...keys: [string, ...string[]]): Promise<AsyncDisposable & {
|
|
10
|
+
path: string;
|
|
11
|
+
}>;
|
|
12
|
+
export declare function useTempFile(path: string): AsyncDisposable & {
|
|
13
|
+
path: string;
|
|
14
|
+
};
|
|
15
|
+
export declare class CleanupListener {
|
|
16
|
+
readonly paths: string[];
|
|
17
|
+
stop(): void;
|
|
18
|
+
dispose(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export declare class GargabeCollector {
|
|
21
|
+
protected listeners: Set<CleanupListener>;
|
|
22
|
+
get pending(): boolean;
|
|
23
|
+
cleanup(cb?: () => any): Promise<void>;
|
|
24
|
+
cleanupOnFinish(cb: () => any): Promise<void>;
|
|
25
|
+
cleanupIfFail(cb: () => any): Promise<CleanupListener>;
|
|
26
|
+
}
|
package/utils/temp.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.GargabeCollector = exports.CleanupListener = exports.useTempFile = exports.useTempDir = exports.mkTmpDir = exports.tmpDir = exports.rmTmpDir = exports.isTmpDir = exports.ensureFreeDiskTempSpace = exports.sessionTmpDir = exports.parentTmpDir = void 0;
|
|
7
|
+
const globalData_1 = __importDefault(require("../globalData"));
|
|
8
|
+
const fs_1 = require("./fs");
|
|
9
|
+
const crypto_1 = require("crypto");
|
|
10
|
+
const promises_1 = require("fs/promises");
|
|
11
|
+
const path_1 = require("path");
|
|
12
|
+
Symbol.dispose ??= Symbol("Symbol.dispose");
|
|
13
|
+
Symbol.asyncDispose ??= Symbol("Symbol.asyncDispose");
|
|
14
|
+
function parentTmpDir() {
|
|
15
|
+
return (0, path_1.join)(globalData_1.default.tempDir, "datatruck-temp");
|
|
16
|
+
}
|
|
17
|
+
exports.parentTmpDir = parentTmpDir;
|
|
18
|
+
function sessionTmpDir() {
|
|
19
|
+
return (0, path_1.join)(parentTmpDir(), process.pid.toString());
|
|
20
|
+
}
|
|
21
|
+
exports.sessionTmpDir = sessionTmpDir;
|
|
22
|
+
async function ensureFreeDiskTempSpace(size) {
|
|
23
|
+
const path = sessionTmpDir();
|
|
24
|
+
await (0, fs_1.mkdirIfNotExists)(sessionTmpDir());
|
|
25
|
+
await (0, fs_1.ensureFreeDiskSpace)([path], size);
|
|
26
|
+
}
|
|
27
|
+
exports.ensureFreeDiskTempSpace = ensureFreeDiskTempSpace;
|
|
28
|
+
function isTmpDir(path) {
|
|
29
|
+
return path.startsWith(sessionTmpDir()) && path.includes("datatruck-temp");
|
|
30
|
+
}
|
|
31
|
+
exports.isTmpDir = isTmpDir;
|
|
32
|
+
async function rmTmpDir(input) {
|
|
33
|
+
if (typeof input === "string") {
|
|
34
|
+
if (!isTmpDir(input))
|
|
35
|
+
throw new Error(`Path is not a temp dir: ${input}`);
|
|
36
|
+
await (0, promises_1.rm)(input, { recursive: true });
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
for (const path of input)
|
|
40
|
+
await rmTmpDir(path);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.rmTmpDir = rmTmpDir;
|
|
44
|
+
function tmpDir(...keys) {
|
|
45
|
+
const id = (0, crypto_1.randomUUID)().slice(0, 8);
|
|
46
|
+
const path = (0, path_1.join)(sessionTmpDir(), [...keys, id].map(encodeURIComponent).join("-"));
|
|
47
|
+
for (const listener of listeners)
|
|
48
|
+
listener.paths.push(path);
|
|
49
|
+
return path;
|
|
50
|
+
}
|
|
51
|
+
exports.tmpDir = tmpDir;
|
|
52
|
+
const listeners = new Set();
|
|
53
|
+
async function mkTmpDir(...keys) {
|
|
54
|
+
const path = tmpDir(...keys);
|
|
55
|
+
await (0, promises_1.mkdir)(path, { recursive: true });
|
|
56
|
+
return path;
|
|
57
|
+
}
|
|
58
|
+
exports.mkTmpDir = mkTmpDir;
|
|
59
|
+
async function useTempDir(...keys) {
|
|
60
|
+
const path = await mkTmpDir(...keys);
|
|
61
|
+
return {
|
|
62
|
+
path,
|
|
63
|
+
async [Symbol.asyncDispose]() {
|
|
64
|
+
try {
|
|
65
|
+
await rmTmpDir(path);
|
|
66
|
+
}
|
|
67
|
+
catch (_) { }
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
exports.useTempDir = useTempDir;
|
|
72
|
+
function useTempFile(path) {
|
|
73
|
+
return {
|
|
74
|
+
path,
|
|
75
|
+
async [Symbol.asyncDispose]() {
|
|
76
|
+
try {
|
|
77
|
+
await (0, promises_1.rm)(path, { recursive: true });
|
|
78
|
+
}
|
|
79
|
+
catch (_) { }
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
exports.useTempFile = useTempFile;
|
|
84
|
+
class CleanupListener {
|
|
85
|
+
paths = [];
|
|
86
|
+
stop() {
|
|
87
|
+
listeners.delete(this);
|
|
88
|
+
}
|
|
89
|
+
async dispose() {
|
|
90
|
+
this.stop();
|
|
91
|
+
await rmTmpDir(this.paths);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.CleanupListener = CleanupListener;
|
|
95
|
+
class GargabeCollector {
|
|
96
|
+
listeners = new Set();
|
|
97
|
+
get pending() {
|
|
98
|
+
return this.listeners.size > 0;
|
|
99
|
+
}
|
|
100
|
+
async cleanup(cb) {
|
|
101
|
+
try {
|
|
102
|
+
await cb?.();
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
for (const listener of this.listeners) {
|
|
106
|
+
this.listeners.delete(listener);
|
|
107
|
+
await listener.dispose();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async cleanupOnFinish(cb) {
|
|
112
|
+
const cleanup = new CleanupListener();
|
|
113
|
+
try {
|
|
114
|
+
await cb();
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
cleanup.dispose();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async cleanupIfFail(cb) {
|
|
121
|
+
const cleanup = new CleanupListener();
|
|
122
|
+
try {
|
|
123
|
+
await cb();
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
await cleanup.dispose();
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
this.listeners.add(cleanup);
|
|
130
|
+
return cleanup;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
exports.GargabeCollector = GargabeCollector;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { DiskStats } from "./fs";
|
|
2
|
+
export declare function resolvePath(path: string): string;
|
|
3
|
+
export type FsOptions = {
|
|
4
|
+
backend: string;
|
|
5
|
+
};
|
|
6
|
+
export declare abstract class AbstractFs {
|
|
7
|
+
readonly options: FsOptions;
|
|
8
|
+
constructor(options: FsOptions);
|
|
9
|
+
resolvePath(path: string): string;
|
|
10
|
+
abstract isLocal(): boolean;
|
|
11
|
+
isRemote(): boolean;
|
|
12
|
+
abstract existsDir(path: string): Promise<boolean>;
|
|
13
|
+
abstract mkdir(path: string): Promise<void>;
|
|
14
|
+
abstract readFile(path: string): Promise<string>;
|
|
15
|
+
abstract rmAll(path: string): Promise<void>;
|
|
16
|
+
abstract readFileIfExists(path: string): Promise<string | undefined>;
|
|
17
|
+
abstract readdir(path: string): Promise<string[]>;
|
|
18
|
+
abstract ensureEmptyDir(path: string): Promise<void>;
|
|
19
|
+
abstract writeFile(path: string, contents: string): Promise<void>;
|
|
20
|
+
abstract upload(source: string, target: string): Promise<void>;
|
|
21
|
+
abstract download(source: string, target: string): Promise<void>;
|
|
22
|
+
abstract fetchDiskStats(source: string): Promise<DiskStats>;
|
|
23
|
+
}
|
|
24
|
+
export declare class LocalFs extends AbstractFs {
|
|
25
|
+
isLocal(): boolean;
|
|
26
|
+
existsDir(path: string): Promise<boolean>;
|
|
27
|
+
mkdir(path: string): Promise<void>;
|
|
28
|
+
ensureEmptyDir(path: string): Promise<void>;
|
|
29
|
+
readFile(path: string): Promise<string>;
|
|
30
|
+
readFileIfExists(inPath: string): Promise<string | undefined>;
|
|
31
|
+
readdir(path: string): Promise<string[]>;
|
|
32
|
+
writeFile(path: string, contents: string): Promise<void>;
|
|
33
|
+
rmAll(path: string): Promise<void>;
|
|
34
|
+
fetchDiskStats(source: string): Promise<DiskStats>;
|
|
35
|
+
upload(source: string, target: string): Promise<void>;
|
|
36
|
+
download(source: string, target: string): Promise<void>;
|
|
37
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LocalFs = exports.AbstractFs = exports.resolvePath = void 0;
|
|
4
|
+
const fs_1 = require("./fs");
|
|
5
|
+
const promises_1 = require("fs/promises");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
function resolvePath(path) {
|
|
8
|
+
const { pathname } = new URL(`file:///${path}`);
|
|
9
|
+
return pathname;
|
|
10
|
+
}
|
|
11
|
+
exports.resolvePath = resolvePath;
|
|
12
|
+
class AbstractFs {
|
|
13
|
+
options;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.options = options;
|
|
16
|
+
}
|
|
17
|
+
resolvePath(path) {
|
|
18
|
+
return (0, path_1.resolve)((0, path_1.join)(this.options.backend ?? ".", resolvePath(path)));
|
|
19
|
+
}
|
|
20
|
+
isRemote() {
|
|
21
|
+
return !this.isLocal();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.AbstractFs = AbstractFs;
|
|
25
|
+
class LocalFs extends AbstractFs {
|
|
26
|
+
isLocal() {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
async existsDir(path) {
|
|
30
|
+
return (0, fs_1.existsDir)(this.resolvePath(path));
|
|
31
|
+
}
|
|
32
|
+
async mkdir(path) {
|
|
33
|
+
await (0, fs_1.mkdirIfNotExists)(this.resolvePath(path));
|
|
34
|
+
}
|
|
35
|
+
async ensureEmptyDir(path) {
|
|
36
|
+
await (0, fs_1.ensureEmptyDir)(this.resolvePath(path));
|
|
37
|
+
}
|
|
38
|
+
async readFile(path) {
|
|
39
|
+
return (await (0, promises_1.readFile)(this.resolvePath(path))).toString();
|
|
40
|
+
}
|
|
41
|
+
async readFileIfExists(inPath) {
|
|
42
|
+
return (await (0, fs_1.existsFile)(this.resolvePath(inPath)))
|
|
43
|
+
? await this.readFile(inPath)
|
|
44
|
+
: undefined;
|
|
45
|
+
}
|
|
46
|
+
async readdir(path) {
|
|
47
|
+
return await (0, promises_1.readdir)(this.resolvePath(path));
|
|
48
|
+
}
|
|
49
|
+
async writeFile(path, contents) {
|
|
50
|
+
await (0, promises_1.writeFile)(this.resolvePath(path), contents);
|
|
51
|
+
}
|
|
52
|
+
async rmAll(path) {
|
|
53
|
+
await (0, promises_1.rm)(this.resolvePath(path), { recursive: true });
|
|
54
|
+
}
|
|
55
|
+
async fetchDiskStats(source) {
|
|
56
|
+
return await (0, fs_1.fetchDiskStats)(this.resolvePath(source));
|
|
57
|
+
}
|
|
58
|
+
async upload(source, target) {
|
|
59
|
+
await (0, promises_1.cp)(source, this.resolvePath(target));
|
|
60
|
+
}
|
|
61
|
+
async download(source, target) {
|
|
62
|
+
await (0, promises_1.cp)(this.resolvePath(source), target);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.LocalFs = LocalFs;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { ConfigType } from "../Config/Config";
|
|
2
|
-
import { ReadDataType } from "../SessionDriver/SessionDriverAbstract";
|
|
3
|
-
import { BackupSessionManager } from "../SessionManager/BackupSessionManager";
|
|
4
|
-
import { IfRequireKeys } from "../utils/ts";
|
|
5
|
-
export type BackupSessionsActionOptionsType = ReadDataType & {
|
|
6
|
-
verbose?: boolean;
|
|
7
|
-
};
|
|
8
|
-
export declare class BackupSessionsAction<TRequired extends boolean = true> {
|
|
9
|
-
readonly config: ConfigType;
|
|
10
|
-
readonly options: IfRequireKeys<TRequired, BackupSessionsActionOptionsType>;
|
|
11
|
-
constructor(config: ConfigType, options: IfRequireKeys<TRequired, BackupSessionsActionOptionsType>);
|
|
12
|
-
exec(session: BackupSessionManager): Promise<import("../SessionDriver/SessionDriverAbstract").ReadResultType[]>;
|
|
13
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BackupSessionsAction = void 0;
|
|
4
|
-
class BackupSessionsAction {
|
|
5
|
-
config;
|
|
6
|
-
options;
|
|
7
|
-
constructor(config, options) {
|
|
8
|
-
this.config = config;
|
|
9
|
-
this.options = options;
|
|
10
|
-
}
|
|
11
|
-
async exec(session) {
|
|
12
|
-
await session.initDrivers();
|
|
13
|
-
const result = await session.readAll(this.options);
|
|
14
|
-
await session.endDrivers();
|
|
15
|
-
return result;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
exports.BackupSessionsAction = BackupSessionsAction;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { ConfigType } from "../Config/Config";
|
|
2
|
-
import { ReadDataType } from "../SessionDriver/SessionDriverAbstract";
|
|
3
|
-
import { RestoreSessionManager } from "../SessionManager/RestoreSessionManager";
|
|
4
|
-
import { IfRequireKeys } from "../utils/ts";
|
|
5
|
-
export type RestoreSessionsActionOptionsType = ReadDataType & {
|
|
6
|
-
verbose?: boolean;
|
|
7
|
-
};
|
|
8
|
-
export declare class RestoreSessionsAction<TRequired extends boolean = true> {
|
|
9
|
-
readonly config: ConfigType;
|
|
10
|
-
readonly options: IfRequireKeys<TRequired, RestoreSessionsActionOptionsType>;
|
|
11
|
-
constructor(config: ConfigType, options: IfRequireKeys<TRequired, RestoreSessionsActionOptionsType>);
|
|
12
|
-
exec(manager: RestoreSessionManager): Promise<import("../SessionDriver/SessionDriverAbstract").ReadResultType[]>;
|
|
13
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RestoreSessionsAction = void 0;
|
|
4
|
-
class RestoreSessionsAction {
|
|
5
|
-
config;
|
|
6
|
-
options;
|
|
7
|
-
constructor(config, options) {
|
|
8
|
-
this.config = config;
|
|
9
|
-
this.options = options;
|
|
10
|
-
}
|
|
11
|
-
async exec(manager) {
|
|
12
|
-
await manager.initDrivers();
|
|
13
|
-
const result = await manager.readAll(this.options);
|
|
14
|
-
await manager.endDrivers();
|
|
15
|
-
return result;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
exports.RestoreSessionsAction = RestoreSessionsAction;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { If } from "../utils/ts";
|
|
2
|
-
import { CommandAbstract } from "./CommandAbstract";
|
|
3
|
-
export type BackupSessionsCommandOptionsType<TResolved = false> = {
|
|
4
|
-
package?: If<TResolved, string[]>;
|
|
5
|
-
repository?: If<TResolved, string[]>;
|
|
6
|
-
tag?: If<TResolved, string[]>;
|
|
7
|
-
limit?: number;
|
|
8
|
-
};
|
|
9
|
-
export declare class BackupSessionsCommand extends CommandAbstract<BackupSessionsCommandOptionsType<false>, BackupSessionsCommandOptionsType<true>> {
|
|
10
|
-
onOptions(): import("../utils/cli").OptionsType<BackupSessionsCommandOptionsType<false>, BackupSessionsCommandOptionsType<true>>;
|
|
11
|
-
onExec(): Promise<number>;
|
|
12
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BackupSessionsCommand = void 0;
|
|
4
|
-
const BackupSessionsAction_1 = require("../Action/BackupSessionsAction");
|
|
5
|
-
const ConfigAction_1 = require("../Action/ConfigAction");
|
|
6
|
-
const SqliteSessionDriver_1 = require("../SessionDriver/SqliteSessionDriver");
|
|
7
|
-
const BackupSessionManager_1 = require("../SessionManager/BackupSessionManager");
|
|
8
|
-
const DataFormat_1 = require("../utils/DataFormat");
|
|
9
|
-
const cli_1 = require("../utils/cli");
|
|
10
|
-
const string_1 = require("../utils/string");
|
|
11
|
-
const CommandAbstract_1 = require("./CommandAbstract");
|
|
12
|
-
class BackupSessionsCommand extends CommandAbstract_1.CommandAbstract {
|
|
13
|
-
onOptions() {
|
|
14
|
-
return this.returnsOptions({
|
|
15
|
-
package: {
|
|
16
|
-
description: "Filter by package names",
|
|
17
|
-
option: "-p,--package <values>",
|
|
18
|
-
parser: string_1.parseStringList,
|
|
19
|
-
},
|
|
20
|
-
repository: {
|
|
21
|
-
description: "Filter by repository names",
|
|
22
|
-
option: "-r,--repository <values>",
|
|
23
|
-
parser: string_1.parseStringList,
|
|
24
|
-
},
|
|
25
|
-
tag: {
|
|
26
|
-
description: "Filter by tags",
|
|
27
|
-
option: "-t,--tag <values>",
|
|
28
|
-
parser: string_1.parseStringList,
|
|
29
|
-
},
|
|
30
|
-
limit: {
|
|
31
|
-
description: "Limit",
|
|
32
|
-
option: "-l,--limit <value>",
|
|
33
|
-
defaults: 10,
|
|
34
|
-
parser: Number,
|
|
35
|
-
},
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
async onExec() {
|
|
39
|
-
const verbose = this.globalOptions.verbose ?? 0;
|
|
40
|
-
const config = await ConfigAction_1.ConfigAction.fromGlobalOptions(this.globalOptions);
|
|
41
|
-
const action = new BackupSessionsAction_1.BackupSessionsAction(config, {
|
|
42
|
-
packageNames: this.options.package,
|
|
43
|
-
repositoryNames: this.options.repository,
|
|
44
|
-
tags: this.options.tag,
|
|
45
|
-
limit: this.options.limit,
|
|
46
|
-
verbose: verbose > 0,
|
|
47
|
-
});
|
|
48
|
-
const manager = new BackupSessionManager_1.BackupSessionManager({
|
|
49
|
-
driver: new SqliteSessionDriver_1.SqliteSessionDriver({
|
|
50
|
-
verbose: verbose > 1,
|
|
51
|
-
}),
|
|
52
|
-
verbose: verbose > 1,
|
|
53
|
-
progressInterval: this.globalOptions.progressInterval,
|
|
54
|
-
});
|
|
55
|
-
const items = await action.exec(manager);
|
|
56
|
-
const dataFormat = new DataFormat_1.DataFormat({
|
|
57
|
-
items,
|
|
58
|
-
table: {
|
|
59
|
-
labels: [
|
|
60
|
-
" ",
|
|
61
|
-
"Id.",
|
|
62
|
-
"Snapshot id.",
|
|
63
|
-
"Date",
|
|
64
|
-
"Repository",
|
|
65
|
-
"Repository type",
|
|
66
|
-
"Package",
|
|
67
|
-
"",
|
|
68
|
-
],
|
|
69
|
-
handler: (item) => [
|
|
70
|
-
(0, cli_1.resultColumn)(item.error, item.state),
|
|
71
|
-
item.id,
|
|
72
|
-
item.snapshotId.slice(0, 8),
|
|
73
|
-
(0, string_1.formatDateTime)(item.creationDate),
|
|
74
|
-
item.repositoryName,
|
|
75
|
-
item.repositoryType,
|
|
76
|
-
item.packageName,
|
|
77
|
-
(0, cli_1.errorColumn)(item.error, verbose),
|
|
78
|
-
],
|
|
79
|
-
},
|
|
80
|
-
});
|
|
81
|
-
if (this.globalOptions.outputFormat)
|
|
82
|
-
console.info(dataFormat.format(this.globalOptions.outputFormat, {
|
|
83
|
-
tpl: {
|
|
84
|
-
sids: () => items.map((i) => i.snapshotId).join(),
|
|
85
|
-
ssids: () => items.map((i) => i.snapshotId.slice(0, 8)).join(),
|
|
86
|
-
pkgNames: () => items.map((i) => i.packageName).join(),
|
|
87
|
-
},
|
|
88
|
-
}));
|
|
89
|
-
return 0;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
exports.BackupSessionsCommand = BackupSessionsCommand;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { If } from "../utils/ts";
|
|
2
|
-
import { CommandAbstract } from "./CommandAbstract";
|
|
3
|
-
export type RestoreSessionsCommandOptionsType<TResolved = false> = {
|
|
4
|
-
package?: If<TResolved, string[]>;
|
|
5
|
-
repository?: If<TResolved, string[]>;
|
|
6
|
-
tag?: If<TResolved, string[]>;
|
|
7
|
-
limit?: number | null;
|
|
8
|
-
};
|
|
9
|
-
export declare class RestoreSessionsCommand extends CommandAbstract<RestoreSessionsCommandOptionsType<false>, RestoreSessionsCommandOptionsType<true>> {
|
|
10
|
-
onOptions(): import("../utils/cli").OptionsType<RestoreSessionsCommandOptionsType<false>, RestoreSessionsCommandOptionsType<true>>;
|
|
11
|
-
onExec(): Promise<number>;
|
|
12
|
-
}
|