@datatruck/cli 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Action/BackupAction.js +4 -2
- package/Action/BackupSessionsAction.js +2 -0
- package/Action/CleanCacheAction.js +1 -0
- package/Action/ConfigAction.js +1 -0
- package/Action/InitAction.js +2 -0
- package/Action/PruneAction.js +2 -0
- package/Action/RestoreAction.js +4 -2
- package/Action/RestoreSessionsAction.js +2 -0
- package/Action/SnapshotsAction.js +2 -0
- package/Command/CommandAbstract.js +2 -0
- package/Entity/BackupSessionEntity.js +5 -2
- package/Entity/BackupSessionRepositoryEntity.js +5 -2
- package/Entity/BackupSessionTaskEntity.js +4 -2
- package/Entity/CrudEntityAbstract.js +3 -0
- package/Entity/RestoreSessionEntity.js +4 -2
- package/Entity/RestoreSessionRepositoryEntity.js +5 -2
- package/Entity/RestoreSessionTaskEntity.js +4 -2
- package/Entity/StateEntityAbstract.js +5 -0
- package/Factory/CommandFactory.js +1 -1
- package/JsonSchema/DefinitionEnum.js +1 -1
- package/Repository/DatatruckRepository.d.ts +8 -13
- package/Repository/DatatruckRepository.js +112 -229
- package/Repository/GitRepository.js +1 -1
- package/Repository/RepositoryAbstract.js +4 -2
- package/Repository/ResticRepository.js +2 -1
- package/SessionDriver/ConsoleSessionDriver.js +9 -5
- package/SessionDriver/SessionDriverAbstract.js +3 -2
- package/SessionDriver/SqliteSessionDriver.js +2 -4
- package/SessionManager/BackupSessionManager.js +3 -6
- package/SessionManager/RestoreSessionManager.js +3 -6
- package/SessionManager/SessionManagerAbstract.js +4 -0
- package/Task/GitTask.js +1 -0
- package/Task/MariadbTask.js +5 -4
- package/Task/MssqlTask.js +2 -1
- package/Task/ScriptTask.js +1 -0
- package/Task/SqlDumpTaskAbstract.js +1 -0
- package/Task/TaskAbstract.js +2 -1
- package/config.schema.json +23 -37
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +9 -8
- package/utils/DataFormat.js +1 -0
- package/utils/Git.js +1 -0
- package/utils/ObjectVault.js +3 -5
- package/utils/Restic.js +1 -0
- package/utils/fs.d.ts +3 -9
- package/utils/fs.js +24 -32
- package/utils/tar.d.ts +32 -0
- package/utils/tar.js +92 -0
- package/utils/zip.d.ts +0 -97
- package/utils/zip.js +0 -238
package/Task/TaskAbstract.js
CHANGED
|
@@ -3,9 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.TaskAbstract = void 0;
|
|
4
4
|
const fs_1 = require("../utils/fs");
|
|
5
5
|
class TaskAbstract {
|
|
6
|
+
config;
|
|
7
|
+
tmpDirs = [];
|
|
6
8
|
constructor(config) {
|
|
7
9
|
this.config = config;
|
|
8
|
-
this.tmpDirs = [];
|
|
9
10
|
}
|
|
10
11
|
async mkTmpDir(prefix, id) {
|
|
11
12
|
const dir = await (0, fs_1.mkTmpDir)(prefix, id);
|
package/config.schema.json
CHANGED
|
@@ -458,45 +458,31 @@
|
|
|
458
458
|
"additionalProperties": false,
|
|
459
459
|
"properties": {
|
|
460
460
|
"compress": {
|
|
461
|
-
"
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
},
|
|
484
|
-
"exclude": {
|
|
485
|
-
"$ref": "#/definitions/stringlist-util"
|
|
486
|
-
},
|
|
487
|
-
"onePackByResult": {
|
|
488
|
-
"type": "boolean"
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
}
|
|
461
|
+
"type": "boolean"
|
|
462
|
+
},
|
|
463
|
+
"packs": {
|
|
464
|
+
"type": "array",
|
|
465
|
+
"items": {
|
|
466
|
+
"type": "object",
|
|
467
|
+
"additionalProperties": false,
|
|
468
|
+
"required": [
|
|
469
|
+
"include"
|
|
470
|
+
],
|
|
471
|
+
"properties": {
|
|
472
|
+
"name": {
|
|
473
|
+
"type": "string"
|
|
474
|
+
},
|
|
475
|
+
"include": {
|
|
476
|
+
"$ref": "#/definitions/stringlist-util"
|
|
477
|
+
},
|
|
478
|
+
"exclude": {
|
|
479
|
+
"$ref": "#/definitions/stringlist-util"
|
|
480
|
+
},
|
|
481
|
+
"onePackByResult": {
|
|
482
|
+
"type": "boolean"
|
|
493
483
|
}
|
|
494
484
|
}
|
|
495
|
-
|
|
496
|
-
},
|
|
497
|
-
"fileCopyConcurrency": {
|
|
498
|
-
"type": "integer",
|
|
499
|
-
"minimum": 1
|
|
485
|
+
}
|
|
500
486
|
}
|
|
501
487
|
}
|
|
502
488
|
},
|
package/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datatruck/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"ajv": "^8.12.0",
|
|
6
6
|
"async": "^3.2.4",
|
|
7
7
|
"chalk": "^4.1.2",
|
|
8
8
|
"cli-table3": "^0.6.3",
|
|
9
|
-
"commander": "^
|
|
10
|
-
"dayjs": "^1.11.
|
|
11
|
-
"fast-folder-size": "^
|
|
12
|
-
"fast-glob": "^3.
|
|
9
|
+
"commander": "^11.0.0",
|
|
10
|
+
"dayjs": "^1.11.10",
|
|
11
|
+
"fast-folder-size": "^2.2.0",
|
|
12
|
+
"fast-glob": "^3.3.1",
|
|
13
13
|
"micromatch": "^4.0.5",
|
|
14
14
|
"pretty-bytes": "^5.6.0",
|
|
15
|
-
"sqlite": "^
|
|
16
|
-
"sqlite3": "^5.1.
|
|
15
|
+
"sqlite": "^5.0.1",
|
|
16
|
+
"sqlite3": "^5.1.6",
|
|
17
|
+
"tar": "^6.2.0"
|
|
17
18
|
},
|
|
18
19
|
"optionalDependencies": {
|
|
19
20
|
"ts-node": "^10.9.1",
|
|
20
|
-
"yaml": "^2.2
|
|
21
|
+
"yaml": "^2.3.2"
|
|
21
22
|
},
|
|
22
23
|
"engine": {
|
|
23
24
|
"node": ">=16.0.0"
|
package/utils/DataFormat.js
CHANGED
package/utils/Git.js
CHANGED
package/utils/ObjectVault.js
CHANGED
|
@@ -2,11 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ObjectVault = void 0;
|
|
4
4
|
class ObjectVault {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
this.objects = {};
|
|
9
|
-
}
|
|
5
|
+
counter = 0;
|
|
6
|
+
ids = {};
|
|
7
|
+
objects = {};
|
|
10
8
|
static serializeKeys(keys) {
|
|
11
9
|
return JSON.stringify(keys);
|
|
12
10
|
}
|
package/utils/Restic.js
CHANGED
package/utils/fs.d.ts
CHANGED
|
@@ -104,18 +104,12 @@ export declare function createFileScanner(options: {
|
|
|
104
104
|
include: string[];
|
|
105
105
|
};
|
|
106
106
|
onProgress: (data: Progress) => Promise<void>;
|
|
107
|
-
disableCounting?: boolean;
|
|
108
|
-
disableEndProgress?: boolean;
|
|
109
107
|
}): Promise<{
|
|
108
|
+
disposed: boolean;
|
|
110
109
|
total: number;
|
|
111
110
|
current: number;
|
|
112
|
-
progress: (description: string,
|
|
113
|
-
|
|
114
|
-
current: number;
|
|
115
|
-
type?: "start" | "end";
|
|
116
|
-
percent?: number;
|
|
117
|
-
}) => Promise<void>;
|
|
118
|
-
updateProgress: (end?: boolean) => Promise<void>;
|
|
111
|
+
progress: (description: string, path?: string) => Promise<void>;
|
|
112
|
+
end: () => Promise<void>;
|
|
119
113
|
start: (cb?: ((entry: Required<Entry>) => any) | undefined) => Promise<void>;
|
|
120
114
|
}>;
|
|
121
115
|
export {};
|
package/utils/fs.js
CHANGED
|
@@ -458,62 +458,54 @@ async function cpy(options) {
|
|
|
458
458
|
exports.cpy = cpy;
|
|
459
459
|
async function createFileScanner(options) {
|
|
460
460
|
const object = {
|
|
461
|
+
disposed: false,
|
|
461
462
|
total: 0,
|
|
462
463
|
current: 0,
|
|
463
|
-
progress: async (description,
|
|
464
|
+
progress: async (description, path) => {
|
|
465
|
+
if (object.disposed)
|
|
466
|
+
return;
|
|
467
|
+
if (path)
|
|
468
|
+
object.current++;
|
|
464
469
|
await options.onProgress({
|
|
465
470
|
relative: {
|
|
466
471
|
description,
|
|
467
|
-
payload:
|
|
468
|
-
percent: data.percent,
|
|
472
|
+
payload: path,
|
|
469
473
|
},
|
|
470
474
|
absolute: {
|
|
471
475
|
total: object.total,
|
|
472
|
-
current: object.current
|
|
473
|
-
percent: (0, math_1.progressPercent)(object.total, object.current
|
|
476
|
+
current: object.current,
|
|
477
|
+
percent: (0, math_1.progressPercent)(object.total, object.current),
|
|
474
478
|
},
|
|
475
479
|
});
|
|
476
|
-
if (data.type === "end") {
|
|
477
|
-
object.current += data.current;
|
|
478
|
-
}
|
|
479
480
|
},
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
await options.onProgress({
|
|
485
|
-
relative: {
|
|
486
|
-
description: end ? "Scanned files" : "Scanning files",
|
|
487
|
-
payload: object.total.toString(),
|
|
488
|
-
},
|
|
489
|
-
});
|
|
490
|
-
lastTime = currentTime;
|
|
491
|
-
}
|
|
481
|
+
end: async () => {
|
|
482
|
+
if (!object.disposed)
|
|
483
|
+
await object.progress("Finished");
|
|
484
|
+
object.disposed = true;
|
|
492
485
|
},
|
|
493
486
|
start: async (cb) => {
|
|
487
|
+
let lastTime = performance.now();
|
|
488
|
+
await object.progress("Scanning files");
|
|
494
489
|
for await (const entry of pathIterator(stream)) {
|
|
495
|
-
if (
|
|
490
|
+
if (cb) {
|
|
491
|
+
if (await cb(entry))
|
|
492
|
+
object.total++;
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
496
495
|
object.total++;
|
|
497
|
-
|
|
498
|
-
if (
|
|
499
|
-
await
|
|
496
|
+
}
|
|
497
|
+
if (lastTime - performance.now() > 500)
|
|
498
|
+
await object.progress("Scanning files");
|
|
500
499
|
}
|
|
501
|
-
|
|
502
|
-
await object.updateProgress(true);
|
|
500
|
+
await object.progress("Scanned files");
|
|
503
501
|
},
|
|
504
502
|
};
|
|
505
|
-
await options.onProgress({
|
|
506
|
-
relative: {
|
|
507
|
-
description: "Scanning files",
|
|
508
|
-
},
|
|
509
|
-
});
|
|
510
503
|
const stream = fast_glob_1.default.stream(options.glob.include, {
|
|
511
504
|
dot: true,
|
|
512
505
|
markDirectories: true,
|
|
513
506
|
stats: true,
|
|
514
507
|
...options.glob,
|
|
515
508
|
});
|
|
516
|
-
let lastTime = performance.now();
|
|
517
509
|
return object;
|
|
518
510
|
}
|
|
519
511
|
exports.createFileScanner = createFileScanner;
|
package/utils/tar.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type Progress = {
|
|
2
|
+
percent: number;
|
|
3
|
+
current: number;
|
|
4
|
+
total: number;
|
|
5
|
+
};
|
|
6
|
+
export type TarEntry = {
|
|
7
|
+
path: string;
|
|
8
|
+
progress: Progress;
|
|
9
|
+
};
|
|
10
|
+
export interface CreateTarOptions {
|
|
11
|
+
path: string;
|
|
12
|
+
verbose?: boolean;
|
|
13
|
+
output: string;
|
|
14
|
+
include: string[];
|
|
15
|
+
compress?: boolean;
|
|
16
|
+
onEntry?: (entry: TarEntry) => void;
|
|
17
|
+
}
|
|
18
|
+
export interface ExtractOptions {
|
|
19
|
+
input: string;
|
|
20
|
+
output: string;
|
|
21
|
+
verbose?: boolean;
|
|
22
|
+
total?: number;
|
|
23
|
+
onEntry?: (entry: TarEntry) => void;
|
|
24
|
+
}
|
|
25
|
+
export type ListTarOptions = {
|
|
26
|
+
input: string;
|
|
27
|
+
onEntry?: (entry: Pick<TarEntry, "path">) => void;
|
|
28
|
+
verbose?: boolean;
|
|
29
|
+
};
|
|
30
|
+
export declare function listTar(options: ListTarOptions): Promise<number>;
|
|
31
|
+
export declare function createTar(options: CreateTarOptions): Promise<void>;
|
|
32
|
+
export declare function extractTar(options: ExtractOptions): Promise<void>;
|
package/utils/tar.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
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.extractTar = exports.createTar = exports.listTar = void 0;
|
|
7
|
+
const cli_1 = require("./cli");
|
|
8
|
+
const fs_1 = require("./fs");
|
|
9
|
+
const math_1 = require("./math");
|
|
10
|
+
const fs_2 = require("fs");
|
|
11
|
+
const promises_1 = require("fs/promises");
|
|
12
|
+
const tar_1 = __importDefault(require("tar"));
|
|
13
|
+
async function listTar(options) {
|
|
14
|
+
if (options.verbose)
|
|
15
|
+
(0, cli_1.logExec)("tar", ["-ztvf", options.input]);
|
|
16
|
+
let total = 0;
|
|
17
|
+
await tar_1.default.list({
|
|
18
|
+
file: options.input,
|
|
19
|
+
onentry(entry) {
|
|
20
|
+
options.onEntry?.({ path: entry.path });
|
|
21
|
+
total++;
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
return total;
|
|
25
|
+
}
|
|
26
|
+
exports.listTar = listTar;
|
|
27
|
+
async function createTar(options) {
|
|
28
|
+
if (options.verbose)
|
|
29
|
+
(0, cli_1.logExec)("tar", [
|
|
30
|
+
options.compress ? "-czvf" : "-cvf",
|
|
31
|
+
options.output,
|
|
32
|
+
options.path,
|
|
33
|
+
]);
|
|
34
|
+
let total = options.include.length;
|
|
35
|
+
if (!total)
|
|
36
|
+
throw new Error("'include' option is empty");
|
|
37
|
+
let current = 0;
|
|
38
|
+
let progressPromise;
|
|
39
|
+
const inStream = tar_1.default.create({
|
|
40
|
+
gzip: options.compress,
|
|
41
|
+
cwd: options.path,
|
|
42
|
+
filter(path) {
|
|
43
|
+
current++;
|
|
44
|
+
options.onEntry?.({
|
|
45
|
+
path: path,
|
|
46
|
+
progress: {
|
|
47
|
+
total,
|
|
48
|
+
current,
|
|
49
|
+
percent: (0, math_1.progressPercent)(total, current),
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
return true;
|
|
53
|
+
},
|
|
54
|
+
}, options.include);
|
|
55
|
+
const outStream = (0, fs_2.createWriteStream)(options.output);
|
|
56
|
+
await new Promise((resolve, reject) => {
|
|
57
|
+
inStream.on("error", reject);
|
|
58
|
+
outStream.on("error", reject);
|
|
59
|
+
inStream.pipe(outStream);
|
|
60
|
+
outStream.on("close", resolve);
|
|
61
|
+
});
|
|
62
|
+
await progressPromise;
|
|
63
|
+
}
|
|
64
|
+
exports.createTar = createTar;
|
|
65
|
+
async function extractTar(options) {
|
|
66
|
+
let total = options.total ??
|
|
67
|
+
(await listTar({ input: options.input, verbose: options.verbose }));
|
|
68
|
+
if (options.verbose) {
|
|
69
|
+
(0, cli_1.logExec)("tar", ["-xzvfp", options.input, "-C", options.output]);
|
|
70
|
+
(0, cli_1.logExec)("mkdir", ["-p", options.output]);
|
|
71
|
+
}
|
|
72
|
+
let current = 0;
|
|
73
|
+
await (0, promises_1.mkdir)(options.output, { recursive: true });
|
|
74
|
+
await (0, fs_1.ensureEmptyDir)(options.output);
|
|
75
|
+
await tar_1.default.extract({
|
|
76
|
+
file: options.input,
|
|
77
|
+
cwd: options.output,
|
|
78
|
+
preserveOwner: true,
|
|
79
|
+
onentry(entry) {
|
|
80
|
+
current++;
|
|
81
|
+
options.onEntry?.({
|
|
82
|
+
path: entry.path,
|
|
83
|
+
progress: {
|
|
84
|
+
total,
|
|
85
|
+
current,
|
|
86
|
+
percent: (0, math_1.progressPercent)(total, current),
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
exports.extractTar = extractTar;
|
package/utils/zip.d.ts
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
export interface ZipDataFilterType {
|
|
2
|
-
recursive?: boolean;
|
|
3
|
-
exclude?: boolean;
|
|
4
|
-
patterns: string[];
|
|
5
|
-
}
|
|
6
|
-
export interface ZipDataType {
|
|
7
|
-
command?: string;
|
|
8
|
-
path: string;
|
|
9
|
-
filter?: (ZipDataFilterType | string)[];
|
|
10
|
-
output: string;
|
|
11
|
-
deleteOnZip?: boolean;
|
|
12
|
-
includeList?: string;
|
|
13
|
-
excludeList?: string;
|
|
14
|
-
verbose?: boolean;
|
|
15
|
-
onProgress?: (data: {
|
|
16
|
-
percent: number;
|
|
17
|
-
total: number;
|
|
18
|
-
current: number;
|
|
19
|
-
path?: string;
|
|
20
|
-
type?: "start" | "end";
|
|
21
|
-
}) => void | Promise<void>;
|
|
22
|
-
onStream?: (data: ZipStream) => void | Promise<void>;
|
|
23
|
-
}
|
|
24
|
-
export interface UnzipDataType {
|
|
25
|
-
command?: string;
|
|
26
|
-
input: string;
|
|
27
|
-
files?: (ZipDataFilterType | string)[];
|
|
28
|
-
output: string;
|
|
29
|
-
verbose?: boolean;
|
|
30
|
-
onProgress?: (data: {
|
|
31
|
-
percent: number;
|
|
32
|
-
current: number;
|
|
33
|
-
path?: string;
|
|
34
|
-
type?: "start" | "end";
|
|
35
|
-
}) => void | Promise<void>;
|
|
36
|
-
onStream?: (data: UnzipStream) => void | Promise<void>;
|
|
37
|
-
}
|
|
38
|
-
export declare function buildArguments(filters: (ZipDataFilterType | string)[]): string[];
|
|
39
|
-
export declare function checkSSEOption(command?: string): Promise<boolean>;
|
|
40
|
-
type ListZipStream = {
|
|
41
|
-
Path?: string;
|
|
42
|
-
Folder?: string;
|
|
43
|
-
Size?: string;
|
|
44
|
-
"Packed Size"?: string;
|
|
45
|
-
Modified?: string;
|
|
46
|
-
Created?: string;
|
|
47
|
-
Accessed?: string;
|
|
48
|
-
Attributes?: string;
|
|
49
|
-
Encrypted?: string;
|
|
50
|
-
Comment?: string;
|
|
51
|
-
CRC?: string;
|
|
52
|
-
Method?: string;
|
|
53
|
-
Characteristics?: string;
|
|
54
|
-
"Host OS"?: string;
|
|
55
|
-
Version?: string;
|
|
56
|
-
Volume?: string;
|
|
57
|
-
Offset?: string;
|
|
58
|
-
};
|
|
59
|
-
export declare function listZip(data: {
|
|
60
|
-
command?: string;
|
|
61
|
-
path: string;
|
|
62
|
-
onStream: (item: ListZipStream) => Promise<void>;
|
|
63
|
-
verbose?: boolean;
|
|
64
|
-
}): Promise<void>;
|
|
65
|
-
export type ZipStream = {
|
|
66
|
-
type: "progress";
|
|
67
|
-
data: {
|
|
68
|
-
progress: number;
|
|
69
|
-
files: number;
|
|
70
|
-
path: string;
|
|
71
|
-
};
|
|
72
|
-
} | {
|
|
73
|
-
type: "summary";
|
|
74
|
-
data: {
|
|
75
|
-
folders: number;
|
|
76
|
-
files: number;
|
|
77
|
-
};
|
|
78
|
-
};
|
|
79
|
-
export declare function zip(data: ZipDataType): Promise<{
|
|
80
|
-
folders: number;
|
|
81
|
-
files: number;
|
|
82
|
-
}>;
|
|
83
|
-
export type UnzipStream = {
|
|
84
|
-
type: "progress";
|
|
85
|
-
data: {
|
|
86
|
-
percent: number;
|
|
87
|
-
files: number;
|
|
88
|
-
path: string;
|
|
89
|
-
};
|
|
90
|
-
};
|
|
91
|
-
export declare function unzip(data: UnzipDataType): Promise<{
|
|
92
|
-
files: number;
|
|
93
|
-
stdout: string;
|
|
94
|
-
stderr: string;
|
|
95
|
-
exitCode: number;
|
|
96
|
-
}>;
|
|
97
|
-
export {};
|