@datatruck/cli 0.36.8 → 0.38.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/config.schema.json +168 -108
- package/lib/actions/BackupAction.d.ts +61 -20
- package/lib/actions/BackupAction.js +43 -17
- package/lib/actions/CleanCacheAction.d.ts +6 -7
- package/lib/actions/CleanCacheAction.js +2 -1
- package/lib/actions/ConfigAction.d.ts +3 -5
- package/lib/actions/ConfigAction.js +0 -1
- package/lib/actions/CopyAction.d.ts +43 -12
- package/lib/actions/CopyAction.js +31 -4
- package/lib/actions/ExportAction.d.ts +94 -0
- package/lib/actions/ExportAction.js +236 -0
- package/lib/actions/InitAction.d.ts +17 -7
- package/lib/actions/InitAction.js +9 -1
- package/lib/actions/PruneAction.d.ts +76 -17
- package/lib/actions/PruneAction.js +62 -2
- package/lib/actions/RestoreAction.d.ts +61 -22
- package/lib/actions/RestoreAction.js +46 -58
- package/lib/actions/SnapshotsAction.d.ts +80 -21
- package/lib/actions/SnapshotsAction.js +82 -1
- package/lib/cli.d.ts +0 -3
- package/lib/cli.js +31 -56
- package/lib/commands/BackupCommand.d.ts +121 -13
- package/lib/commands/BackupCommand.js +29 -54
- package/lib/commands/CleanCacheCommand.d.ts +10 -3
- package/lib/commands/CleanCacheCommand.js +14 -6
- package/lib/commands/CommandAbstract.d.ts +11 -10
- package/lib/commands/CommandAbstract.js +6 -9
- package/lib/commands/ConfigCommand.d.ts +72 -9
- package/lib/commands/ConfigCommand.js +36 -28
- package/lib/commands/CopyCommand.d.ts +103 -10
- package/lib/commands/CopyCommand.js +25 -44
- package/lib/commands/ExportCommand.d.ts +143 -0
- package/lib/commands/ExportCommand.js +50 -0
- package/lib/commands/InitCommand.d.ts +43 -7
- package/lib/commands/InitCommand.js +22 -19
- package/lib/commands/PruneCommand.d.ts +237 -17
- package/lib/commands/PruneCommand.js +27 -99
- package/lib/commands/RestoreCommand.d.ts +127 -13
- package/lib/commands/RestoreCommand.js +27 -53
- package/lib/commands/RunCommand.d.ts +29 -0
- package/lib/commands/RunCommand.js +44 -0
- package/lib/commands/SnapshotsCommand.d.ts +240 -23
- package/lib/commands/SnapshotsCommand.js +23 -101
- package/lib/commands/StartServerCommand.d.ts +10 -3
- package/lib/commands/StartServerCommand.js +23 -15
- package/lib/repositories/DatatruckRepository.js +1 -1
- package/lib/tasks/MssqlTask.js +1 -1
- package/lib/tasks/MysqlDumpTask.js +1 -1
- package/lib/tasks/SqlDumpTaskAbstract.js +2 -2
- package/lib/utils/cli.d.ts +1 -18
- package/lib/utils/cli.js +9 -49
- package/lib/utils/datatruck/command.d.ts +8 -5
- package/lib/utils/datatruck/command.js +8 -4
- package/lib/utils/datatruck/config-type.d.ts +4 -0
- package/lib/utils/datatruck/cron-server.d.ts +8 -39
- package/lib/utils/datatruck/cron-server.js +35 -57
- package/lib/utils/datatruck/job.d.ts +41 -0
- package/lib/utils/datatruck/job.js +82 -0
- package/lib/utils/datatruck/report-list.js +1 -1
- package/lib/utils/datatruck/repository.d.ts +1 -0
- package/lib/utils/datatruck/repository.js +8 -1
- package/lib/utils/list.d.ts +5 -0
- package/lib/utils/list.js +9 -0
- package/lib/utils/math.js +1 -1
- package/lib/utils/object.d.ts +5 -0
- package/lib/utils/object.js +10 -1
- package/lib/utils/options.d.ts +24 -0
- package/lib/utils/options.js +94 -0
- package/lib/utils/progress.js +1 -1
- package/lib/utils/restic.js +1 -1
- package/lib/utils/string.d.ts +2 -1
- package/lib/utils/string.js +5 -1
- package/lib/utils/watcher.js +1 -1
- package/package.json +4 -4
package/lib/utils/cli.js
CHANGED
|
@@ -3,8 +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.logJson = exports.colorizeObject = exports.colorizeValue = exports.waitForStdDrain = exports.confirm = exports.
|
|
7
|
-
const error_1 = require("./error");
|
|
6
|
+
exports.logJson = exports.colorizeObject = exports.colorizeValue = exports.waitForStdDrain = exports.confirm = exports.renderObject = exports.renderListTaskItem = exports.renderError = exports.renderResult = exports.logExec = exports.renderProgressBar = exports.showCursorCommand = void 0;
|
|
8
7
|
const chalk_1 = __importDefault(require("chalk"));
|
|
9
8
|
const chalk_2 = require("chalk");
|
|
10
9
|
const readline_1 = require("readline");
|
|
@@ -59,20 +58,15 @@ function renderResult(error, color = true) {
|
|
|
59
58
|
: "✓";
|
|
60
59
|
}
|
|
61
60
|
exports.renderResult = renderResult;
|
|
62
|
-
function renderError(error,
|
|
63
|
-
if (!error)
|
|
61
|
+
function renderError(error, index) {
|
|
62
|
+
if (!error)
|
|
64
63
|
return "";
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
const message = error.split(/\r?\n/).shift() ?? "";
|
|
74
|
-
return chalk_1.default.red(message.trim());
|
|
75
|
-
}
|
|
64
|
+
const message = error instanceof Error
|
|
65
|
+
? error.message
|
|
66
|
+
: (error.split(/\r?\n/).shift() ?? "").trim();
|
|
67
|
+
return chalk_1.default.red(typeof index === "number" && index !== -1
|
|
68
|
+
? `${index + 1}. ${message}`
|
|
69
|
+
: message);
|
|
76
70
|
}
|
|
77
71
|
exports.renderError = renderError;
|
|
78
72
|
function renderListTaskItem(item, color, config) {
|
|
@@ -98,40 +92,6 @@ function renderObject(object, color) {
|
|
|
98
92
|
return values.join(` `);
|
|
99
93
|
}
|
|
100
94
|
exports.renderObject = renderObject;
|
|
101
|
-
function parseOptions(object, options) {
|
|
102
|
-
const result = {};
|
|
103
|
-
for (const key in options) {
|
|
104
|
-
const isNegative = options[key].option.startsWith("--no");
|
|
105
|
-
const defaultsValue = isNegative ? true : options[key].defaults;
|
|
106
|
-
const value = object?.[key] ?? defaultsValue;
|
|
107
|
-
const parser = options[key].parser;
|
|
108
|
-
if (typeof value !== "undefined") {
|
|
109
|
-
result[key] = parser ? parser(value) : value;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return result;
|
|
113
|
-
}
|
|
114
|
-
exports.parseOptions = parseOptions;
|
|
115
|
-
function stringifyOptions(options, object) {
|
|
116
|
-
const result = [];
|
|
117
|
-
for (const key in options) {
|
|
118
|
-
const fullOpt = options[key].option;
|
|
119
|
-
const [opt] = fullOpt.split(",");
|
|
120
|
-
const isNegative = fullOpt.startsWith("--no");
|
|
121
|
-
const isBool = !fullOpt.includes("<") && !fullOpt.includes("[");
|
|
122
|
-
const defaultsValue = isNegative ? true : options[key].defaults;
|
|
123
|
-
const value = object?.[key] ?? defaultsValue;
|
|
124
|
-
if (isBool) {
|
|
125
|
-
if (object[key])
|
|
126
|
-
result.push(opt);
|
|
127
|
-
}
|
|
128
|
-
else if (value !== undefined) {
|
|
129
|
-
result.push(opt, `${value}`);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
return result;
|
|
133
|
-
}
|
|
134
|
-
exports.stringifyOptions = stringifyOptions;
|
|
135
95
|
function confirm(message) {
|
|
136
96
|
const rl = (0, readline_1.createInterface)({
|
|
137
97
|
input: process.stdin,
|
|
@@ -3,27 +3,30 @@ import { CleanCacheCommand } from "../../commands/CleanCacheCommand";
|
|
|
3
3
|
import { GlobalOptions } from "../../commands/CommandAbstract";
|
|
4
4
|
import { ConfigCommand } from "../../commands/ConfigCommand";
|
|
5
5
|
import { CopyCommand } from "../../commands/CopyCommand";
|
|
6
|
+
import { ExportCommand } from "../../commands/ExportCommand";
|
|
6
7
|
import { InitCommand } from "../../commands/InitCommand";
|
|
7
8
|
import { PruneCommand } from "../../commands/PruneCommand";
|
|
8
9
|
import { RestoreCommand } from "../../commands/RestoreCommand";
|
|
10
|
+
import { RunCommand } from "../../commands/RunCommand";
|
|
9
11
|
import { SnapshotsCommand } from "../../commands/SnapshotsCommand";
|
|
10
12
|
import { StartServerCommand } from "../../commands/StartServerCommand";
|
|
11
13
|
import { StdStreams } from "../stream";
|
|
12
|
-
export declare const
|
|
14
|
+
export declare const datatruckCommands: {
|
|
13
15
|
config: typeof ConfigCommand;
|
|
14
16
|
init: typeof InitCommand;
|
|
15
17
|
snapshots: typeof SnapshotsCommand;
|
|
16
18
|
prune: typeof PruneCommand;
|
|
17
19
|
backup: typeof BackupCommand;
|
|
18
20
|
restore: typeof RestoreCommand;
|
|
21
|
+
run: typeof RunCommand;
|
|
19
22
|
copy: typeof CopyCommand;
|
|
20
23
|
cleanCache: typeof CleanCacheCommand;
|
|
21
24
|
startServer: typeof StartServerCommand;
|
|
25
|
+
export: typeof ExportCommand;
|
|
22
26
|
};
|
|
23
|
-
export type DatatruckCommandMap = typeof
|
|
24
|
-
export type InferDatatruckCommandOptions<T extends keyof DatatruckCommandMap> = InstanceType<DatatruckCommandMap[T]>["inputOptions"];
|
|
27
|
+
export type DatatruckCommandMap = typeof datatruckCommands;
|
|
25
28
|
export type InferDatatruckCommandResult<T extends keyof DatatruckCommandMap, R = Awaited<ReturnType<InstanceType<DatatruckCommandMap[T]>["exec"]>>> = "result" extends keyof R ? R["result"] : undefined;
|
|
26
|
-
export declare function createCommand<T extends keyof DatatruckCommandMap>(name: T, globalOptions: GlobalOptions<true>, options:
|
|
29
|
+
export declare function createCommand<T extends keyof DatatruckCommandMap>(name: T, globalOptions: GlobalOptions<true>, options: InstanceType<DatatruckCommandMap[T]>["options"], streams?: Partial<StdStreams>, configPath?: string): BackupCommand | CopyCommand | PruneCommand | CleanCacheCommand | ConfigCommand | ExportCommand | InitCommand | RestoreCommand | RunCommand | SnapshotsCommand | StartServerCommand;
|
|
27
30
|
export declare function createCommands(globalOptions: GlobalOptions<true>): {
|
|
28
|
-
[K in keyof DatatruckCommandMap as `${K}`]: (options:
|
|
31
|
+
[K in keyof DatatruckCommandMap as `${K}`]: (options: InstanceType<DatatruckCommandMap[K]>["options"]) => Promise<InferDatatruckCommandResult<K>>;
|
|
29
32
|
};
|
|
@@ -1,30 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createCommands = exports.createCommand = exports.
|
|
3
|
+
exports.createCommands = exports.createCommand = exports.datatruckCommands = void 0;
|
|
4
4
|
const BackupCommand_1 = require("../../commands/BackupCommand");
|
|
5
5
|
const CleanCacheCommand_1 = require("../../commands/CleanCacheCommand");
|
|
6
6
|
const ConfigCommand_1 = require("../../commands/ConfigCommand");
|
|
7
7
|
const CopyCommand_1 = require("../../commands/CopyCommand");
|
|
8
|
+
const ExportCommand_1 = require("../../commands/ExportCommand");
|
|
8
9
|
const InitCommand_1 = require("../../commands/InitCommand");
|
|
9
10
|
const PruneCommand_1 = require("../../commands/PruneCommand");
|
|
10
11
|
const RestoreCommand_1 = require("../../commands/RestoreCommand");
|
|
12
|
+
const RunCommand_1 = require("../../commands/RunCommand");
|
|
11
13
|
const SnapshotsCommand_1 = require("../../commands/SnapshotsCommand");
|
|
12
14
|
const StartServerCommand_1 = require("../../commands/StartServerCommand");
|
|
13
15
|
const error_1 = require("../error");
|
|
14
16
|
const stream_1 = require("stream");
|
|
15
|
-
exports.
|
|
17
|
+
exports.datatruckCommands = {
|
|
16
18
|
config: ConfigCommand_1.ConfigCommand,
|
|
17
19
|
init: InitCommand_1.InitCommand,
|
|
18
20
|
snapshots: SnapshotsCommand_1.SnapshotsCommand,
|
|
19
21
|
prune: PruneCommand_1.PruneCommand,
|
|
20
22
|
backup: BackupCommand_1.BackupCommand,
|
|
21
23
|
restore: RestoreCommand_1.RestoreCommand,
|
|
24
|
+
run: RunCommand_1.RunCommand,
|
|
22
25
|
copy: CopyCommand_1.CopyCommand,
|
|
23
26
|
cleanCache: CleanCacheCommand_1.CleanCacheCommand,
|
|
24
27
|
startServer: StartServerCommand_1.StartServerCommand,
|
|
28
|
+
export: ExportCommand_1.ExportCommand,
|
|
25
29
|
};
|
|
26
30
|
function createCommand(name, globalOptions, options, streams, configPath) {
|
|
27
|
-
const constructor = exports.
|
|
31
|
+
const constructor = exports.datatruckCommands[name];
|
|
28
32
|
if (!constructor)
|
|
29
33
|
throw new error_1.AppError(`Invalid command name: ${name}`);
|
|
30
34
|
return new constructor(globalOptions, options, streams, configPath);
|
|
@@ -32,7 +36,7 @@ function createCommand(name, globalOptions, options, streams, configPath) {
|
|
|
32
36
|
exports.createCommand = createCommand;
|
|
33
37
|
function createCommands(globalOptions) {
|
|
34
38
|
const object = {};
|
|
35
|
-
for (const name in exports.
|
|
39
|
+
for (const name in exports.datatruckCommands) {
|
|
36
40
|
object[name] = async (options) => {
|
|
37
41
|
let stdoutData = "";
|
|
38
42
|
const stdout = new stream_1.Writable({
|
|
@@ -5,6 +5,7 @@ import type { SpawnStep } from "../spawnSteps";
|
|
|
5
5
|
import type { PackageRepositoryConfig, RepositoryConfigEnabledAction, RepositoryConfig } from "./config-repository-type";
|
|
6
6
|
import type { TaskConfig } from "./config-task-type";
|
|
7
7
|
import type { DatatruckCronServerOptions } from "./cron-server";
|
|
8
|
+
import type { Job } from "./job";
|
|
8
9
|
import type { DatatruckRepositoryServerOptions } from "./repository-server";
|
|
9
10
|
export { RepositoryConfig, RepositoryConfigEnabledAction, TaskConfig };
|
|
10
11
|
export type Config = {
|
|
@@ -15,6 +16,9 @@ export type Config = {
|
|
|
15
16
|
repositories: RepositoryConfig[];
|
|
16
17
|
packages: PackageConfig[];
|
|
17
18
|
server?: DatatruckServerOptions;
|
|
19
|
+
jobs?: {
|
|
20
|
+
[name: string]: Job;
|
|
21
|
+
};
|
|
18
22
|
reports?: DatatruckReportConfig[];
|
|
19
23
|
prunePolicy?: DatatruckPolicyConfig;
|
|
20
24
|
};
|
|
@@ -1,44 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { PruneCommandOptions } from "../../commands/PruneCommand";
|
|
4
|
-
export type CronScheduleObject = {
|
|
5
|
-
minute?: number | {
|
|
6
|
-
each: number;
|
|
7
|
-
};
|
|
8
|
-
hour?: number | {
|
|
9
|
-
each: number;
|
|
10
|
-
};
|
|
11
|
-
day?: number | {
|
|
12
|
-
each: number;
|
|
13
|
-
};
|
|
14
|
-
month?: number | {
|
|
15
|
-
each: number;
|
|
16
|
-
};
|
|
17
|
-
weekDay?: number | {
|
|
18
|
-
each: number;
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
export type CronAction = {
|
|
22
|
-
schedule: string | CronScheduleObject;
|
|
23
|
-
} & ({
|
|
24
|
-
name: "backup";
|
|
25
|
-
options: BackupCommandOptions;
|
|
26
|
-
} | {
|
|
27
|
-
name: "copy";
|
|
28
|
-
options: CopyCommandOptions;
|
|
29
|
-
} | {
|
|
30
|
-
name: "prune";
|
|
31
|
-
options: Omit<PruneCommandOptions, "confirm">;
|
|
32
|
-
});
|
|
1
|
+
import { JobConfig } from "./job";
|
|
2
|
+
export declare const defaultsLogPath: string;
|
|
33
3
|
export type DatatruckCronServerOptions = {
|
|
34
4
|
enabled?: boolean;
|
|
35
|
-
|
|
5
|
+
/**
|
|
6
|
+
* @default '/var/logs/datatruck'
|
|
7
|
+
*/
|
|
8
|
+
logPath?: string | boolean;
|
|
36
9
|
};
|
|
37
|
-
export declare function createCronServer(options:
|
|
38
|
-
log: boolean;
|
|
39
|
-
verbose: boolean;
|
|
40
|
-
configPath: string;
|
|
41
|
-
}): {
|
|
10
|
+
export declare function createCronServer(options: JobConfig): Promise<{
|
|
42
11
|
start: () => void;
|
|
43
12
|
stop: () => void;
|
|
44
|
-
}
|
|
13
|
+
}>;
|
|
@@ -1,89 +1,67 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createCronServer = void 0;
|
|
3
|
+
exports.createCronServer = exports.defaultsLogPath = void 0;
|
|
4
4
|
const ConfigAction_1 = require("../../actions/ConfigAction");
|
|
5
|
-
const async_process_1 = require("../async-process");
|
|
6
5
|
const cli_1 = require("../cli");
|
|
7
6
|
const cron_1 = require("../cron");
|
|
8
7
|
const string_1 = require("../string");
|
|
9
8
|
const watcher_1 = require("../watcher");
|
|
10
|
-
const
|
|
9
|
+
const job_1 = require("./job");
|
|
11
10
|
const croner_1 = require("croner");
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
11
|
+
const os_1 = require("os");
|
|
12
|
+
const path_1 = require("path");
|
|
13
|
+
exports.defaultsLogPath = (0, os_1.platform)() === "win32"
|
|
14
|
+
? (0, path_1.join)(process.env.APPDATA ?? `${process.env.HOMEDRIVE ?? "C:"}\\ProgramData`, "datatruck\\logs")
|
|
15
|
+
: "/var/logs/datatruck";
|
|
16
|
+
function createCrons(jobs, options) {
|
|
17
|
+
const crons = [];
|
|
18
|
+
for (const name in jobs) {
|
|
19
|
+
const job = jobs[name];
|
|
20
|
+
if (job.schedule)
|
|
21
|
+
crons.push((0, croner_1.Cron)(typeof job.schedule === "string"
|
|
22
|
+
? job.schedule
|
|
23
|
+
: (0, cron_1.formatCronScheduleObject)(job.schedule), {
|
|
24
|
+
paused: true,
|
|
25
|
+
context: name,
|
|
26
|
+
catch: true,
|
|
27
|
+
protect: true,
|
|
28
|
+
}, () => (0, job_1.runJob)(job, name, options)));
|
|
24
29
|
}
|
|
25
|
-
return
|
|
30
|
+
return crons;
|
|
26
31
|
}
|
|
27
|
-
function createCronServer(options
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const command = new Command({ config: { packages: [], repositories: [] } }, {});
|
|
33
|
-
const cliOptions = (0, cli_1.stringifyOptions)(command.optionsConfig(), action.name === "prune"
|
|
34
|
-
? ({ ...action.options, confirm: true })
|
|
35
|
-
: action.options);
|
|
36
|
-
const [node, bin] = process.argv;
|
|
37
|
-
const p = new async_process_1.AsyncProcess(node, [
|
|
38
|
-
process.env.pm_exec_path ?? bin,
|
|
39
|
-
"-c",
|
|
40
|
-
config.configPath,
|
|
41
|
-
action.name,
|
|
42
|
-
...cliOptions,
|
|
43
|
-
], { $log: config.verbose, $exitCode: false });
|
|
44
|
-
pid = p.child.pid || 0;
|
|
45
|
-
if (config.log)
|
|
46
|
-
(0, cli_1.logJson)("cron-server", `${action.name} started`, { pid });
|
|
47
|
-
const exitCode = await p.waitForClose();
|
|
48
|
-
if (config.log)
|
|
49
|
-
(0, cli_1.logJson)("cron-server", `${action.name} finished`, { pid, exitCode });
|
|
50
|
-
}
|
|
51
|
-
catch (error) {
|
|
52
|
-
if (config.log)
|
|
53
|
-
(0, cli_1.logJson)("cron-server", `${action.name} failed`, { pid });
|
|
54
|
-
console.error(error);
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
let jobs = createJobs(options.actions || [], worker);
|
|
32
|
+
async function createCronServer(options) {
|
|
33
|
+
const config = await ConfigAction_1.ConfigAction.fromGlobalOptions({
|
|
34
|
+
config: options.configPath,
|
|
35
|
+
});
|
|
36
|
+
let crons = createCrons(config.jobs || {}, options);
|
|
58
37
|
const watcher = (0, watcher_1.createWatcher)({
|
|
59
|
-
onRead: () => ConfigAction_1.ConfigAction.findAndParseFile(
|
|
38
|
+
onRead: () => ConfigAction_1.ConfigAction.findAndParseFile(options.configPath),
|
|
60
39
|
onCheck: (prev, current) => (0, string_1.compareJsons)(prev, current),
|
|
61
40
|
onError: (error) => {
|
|
62
|
-
if (
|
|
41
|
+
if (options.log) {
|
|
63
42
|
(0, cli_1.logJson)("cron-server", "job update error");
|
|
64
43
|
console.error(error);
|
|
65
44
|
}
|
|
66
45
|
},
|
|
67
46
|
onChange: (data) => {
|
|
68
|
-
if (
|
|
47
|
+
if (options.log)
|
|
69
48
|
(0, cli_1.logJson)("cron-server", "jobs updated");
|
|
70
49
|
handler.stop();
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
jobs = enabled ? createJobs(cron?.actions || [], worker) : [];
|
|
50
|
+
const enabled = data?.server?.cron?.enabled ?? true;
|
|
51
|
+
crons = enabled ? createCrons(data?.jobs || {}, options) : [];
|
|
74
52
|
handler.start();
|
|
75
53
|
},
|
|
76
54
|
});
|
|
77
55
|
const handler = {
|
|
78
56
|
start: () => {
|
|
79
|
-
for (const
|
|
80
|
-
|
|
57
|
+
for (const cron of crons)
|
|
58
|
+
cron.resume();
|
|
81
59
|
watcher.start();
|
|
82
60
|
},
|
|
83
61
|
stop: () => {
|
|
84
62
|
watcher.stop();
|
|
85
|
-
for (const
|
|
86
|
-
|
|
63
|
+
for (const cron of crons)
|
|
64
|
+
cron.stop();
|
|
87
65
|
},
|
|
88
66
|
};
|
|
89
67
|
return handler;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { BackupCommandOptions } from "../../commands/BackupCommand";
|
|
2
|
+
import { CopyCommandOptions } from "../../commands/CopyCommand";
|
|
3
|
+
import { PruneCommandOptions } from "../../commands/PruneCommand";
|
|
4
|
+
export type JobScheduleObject = {
|
|
5
|
+
minute?: number | {
|
|
6
|
+
each: number;
|
|
7
|
+
};
|
|
8
|
+
hour?: number | {
|
|
9
|
+
each: number;
|
|
10
|
+
};
|
|
11
|
+
day?: number | {
|
|
12
|
+
each: number;
|
|
13
|
+
};
|
|
14
|
+
month?: number | {
|
|
15
|
+
each: number;
|
|
16
|
+
};
|
|
17
|
+
weekDay?: number | {
|
|
18
|
+
each: number;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export type JobAction = {
|
|
22
|
+
action: "backup";
|
|
23
|
+
options: BackupCommandOptions;
|
|
24
|
+
} | {
|
|
25
|
+
action: "copy";
|
|
26
|
+
options: CopyCommandOptions;
|
|
27
|
+
} | {
|
|
28
|
+
action: "prune";
|
|
29
|
+
options: Omit<PruneCommandOptions, "confirm">;
|
|
30
|
+
};
|
|
31
|
+
export type JobSchedule = string | JobScheduleObject;
|
|
32
|
+
export type Job = JobAction & {
|
|
33
|
+
schedule?: JobSchedule;
|
|
34
|
+
};
|
|
35
|
+
export type JobConfig = {
|
|
36
|
+
log: boolean;
|
|
37
|
+
logPath: string | boolean | undefined;
|
|
38
|
+
verbose: boolean;
|
|
39
|
+
configPath: string;
|
|
40
|
+
};
|
|
41
|
+
export declare function runJob(job: Job, name: string, config: JobConfig): Promise<void>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runJob = void 0;
|
|
4
|
+
const async_process_1 = require("../async-process");
|
|
5
|
+
const cli_1 = require("../cli");
|
|
6
|
+
const fs_1 = require("../fs");
|
|
7
|
+
const options_1 = require("../options");
|
|
8
|
+
const command_1 = require("./command");
|
|
9
|
+
const cron_server_1 = require("./cron-server");
|
|
10
|
+
const fs_2 = require("fs");
|
|
11
|
+
const promises_1 = require("fs/promises");
|
|
12
|
+
const path_1 = require("path");
|
|
13
|
+
async function runJob(job, name, config) {
|
|
14
|
+
let pid = 0;
|
|
15
|
+
try {
|
|
16
|
+
const Command = command_1.datatruckCommands[job.action];
|
|
17
|
+
const command = new Command({ config: { packages: [], repositories: [] } }, {});
|
|
18
|
+
const cliOptions = (0, options_1.stringifyOptions)(command.optionsConfig, job.action === "prune"
|
|
19
|
+
? ({ ...job.options, confirm: true })
|
|
20
|
+
: job.options);
|
|
21
|
+
const [node, bin] = process.argv;
|
|
22
|
+
const baseLogPath = typeof config.logPath === "string"
|
|
23
|
+
? config.logPath
|
|
24
|
+
: config.logPath === true || config.logPath === undefined
|
|
25
|
+
? cron_server_1.defaultsLogPath
|
|
26
|
+
: config.logPath;
|
|
27
|
+
let stream;
|
|
28
|
+
let logPath;
|
|
29
|
+
const dt = new Date().toISOString().replaceAll(":", "-");
|
|
30
|
+
const argv = [
|
|
31
|
+
process.env.pm_exec_path ?? bin,
|
|
32
|
+
"--tty",
|
|
33
|
+
"false",
|
|
34
|
+
"--progress",
|
|
35
|
+
"interval:3000",
|
|
36
|
+
"-c",
|
|
37
|
+
config.configPath,
|
|
38
|
+
job.action,
|
|
39
|
+
...cliOptions,
|
|
40
|
+
];
|
|
41
|
+
if (baseLogPath) {
|
|
42
|
+
const tmpLogPath = (0, path_1.join)(baseLogPath, dt) + ".log";
|
|
43
|
+
await (0, promises_1.mkdir)(baseLogPath, { recursive: true });
|
|
44
|
+
stream = (0, fs_2.createWriteStream)(tmpLogPath);
|
|
45
|
+
stream.write(`+ dtt ${argv.join(" ")}\n`);
|
|
46
|
+
}
|
|
47
|
+
const p = new async_process_1.AsyncProcess(node, argv, {
|
|
48
|
+
$log: config.verbose,
|
|
49
|
+
$exitCode: false,
|
|
50
|
+
env: {
|
|
51
|
+
...process.env,
|
|
52
|
+
COLUMNS: "160",
|
|
53
|
+
NO_COLOR: "1",
|
|
54
|
+
JOB_NAME: name,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
pid = p.child.pid || 0;
|
|
58
|
+
if (config.log)
|
|
59
|
+
(0, cli_1.logJson)("job", `'${name}' started`, { pid });
|
|
60
|
+
const [exitCode] = await Promise.all([
|
|
61
|
+
p.waitForClose(),
|
|
62
|
+
stream && p.stderr.pipe(stream),
|
|
63
|
+
stream && p.stdout.pipe(stream),
|
|
64
|
+
]);
|
|
65
|
+
if (stream) {
|
|
66
|
+
const base = (0, path_1.dirname)(stream.path.toString());
|
|
67
|
+
await (0, fs_1.safeRename)(stream.path.toString(), (logPath = (0, path_1.join)(base, `${dt}-${pid}.log`)));
|
|
68
|
+
}
|
|
69
|
+
if (config.log)
|
|
70
|
+
(0, cli_1.logJson)("job", `'${name}' finished`, {
|
|
71
|
+
pid,
|
|
72
|
+
exitCode,
|
|
73
|
+
...(logPath && { log: logPath }),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
if (config.log)
|
|
78
|
+
(0, cli_1.logJson)("job", `'${name}' failed`, { pid });
|
|
79
|
+
console.error(error);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.runJob = runJob;
|
|
@@ -42,7 +42,7 @@ function createReportListTasks(list, options) {
|
|
|
42
42
|
else if ((0, reportSteps_1.isReportStep)(report.run)) {
|
|
43
43
|
await (0, reportSteps_1.runReportSteps)(report.run, {
|
|
44
44
|
data: {
|
|
45
|
-
title: `[${options.hostname}] DTT ${options.action}`,
|
|
45
|
+
title: `[${options.hostname}] DTT ${process.env.JOB_NAME ?? options.action}`,
|
|
46
46
|
message,
|
|
47
47
|
success,
|
|
48
48
|
},
|
|
@@ -13,4 +13,5 @@ export declare function getRepoConstructor(type: keyof typeof repoMap): {
|
|
|
13
13
|
};
|
|
14
14
|
export declare function createRepo(repository: RepositoryConfig, verbose: boolean | undefined): RepositoryAbstract<any>;
|
|
15
15
|
export declare function createAndInitRepo(repository: RepositoryConfig, verbose: boolean | undefined): Promise<RepositoryAbstract<any>>;
|
|
16
|
+
export declare function initSnapshotPath(path: string, minFreeDiskSpace?: string | number): Promise<void>;
|
|
16
17
|
export {};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createAndInitRepo = exports.createRepo = exports.getRepoConstructor = void 0;
|
|
3
|
+
exports.initSnapshotPath = exports.createAndInitRepo = exports.createRepo = exports.getRepoConstructor = void 0;
|
|
4
4
|
const DatatruckRepository_1 = require("../../repositories/DatatruckRepository");
|
|
5
5
|
const GitRepository_1 = require("../../repositories/GitRepository");
|
|
6
6
|
const ResticRepository_1 = require("../../repositories/ResticRepository");
|
|
7
7
|
const error_1 = require("../error");
|
|
8
|
+
const fs_1 = require("../fs");
|
|
8
9
|
const repoMap = {
|
|
9
10
|
[GitRepository_1.gitRepositoryName]: GitRepository_1.GitRepository,
|
|
10
11
|
[ResticRepository_1.resticRepositoryName]: ResticRepository_1.ResticRepository,
|
|
@@ -28,3 +29,9 @@ async function createAndInitRepo(repository, verbose) {
|
|
|
28
29
|
return repo;
|
|
29
30
|
}
|
|
30
31
|
exports.createAndInitRepo = createAndInitRepo;
|
|
32
|
+
async function initSnapshotPath(path, minFreeDiskSpace) {
|
|
33
|
+
await (0, fs_1.initEmptyDir)(path);
|
|
34
|
+
if (minFreeDiskSpace)
|
|
35
|
+
await (0, fs_1.ensureFreeDiskSpace)([path], minFreeDiskSpace);
|
|
36
|
+
}
|
|
37
|
+
exports.initSnapshotPath = initSnapshotPath;
|
package/lib/utils/list.d.ts
CHANGED
|
@@ -63,6 +63,11 @@ export declare class Listr3<T extends Listr3Context> extends Listr<void, "defaul
|
|
|
63
63
|
getSummaryResult(): List3SummaryResult;
|
|
64
64
|
getResult(): (List3SummaryResult | Listr3TaskResult<T>)[];
|
|
65
65
|
protected release(): void;
|
|
66
|
+
execAndParse(verbose: boolean | undefined): Promise<{
|
|
67
|
+
result: (List3SummaryResult | Listr3TaskResult<T>)[];
|
|
68
|
+
exitCode: number;
|
|
69
|
+
errors: Error[];
|
|
70
|
+
}>;
|
|
66
71
|
exec(): Promise<(Listr3TaskResult<T> | List3SummaryResult)[]>;
|
|
67
72
|
}
|
|
68
73
|
export {};
|
package/lib/utils/list.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Listr3 = exports.List3Logger = void 0;
|
|
4
4
|
const date_1 = require("./date");
|
|
5
|
+
const error_1 = require("./error");
|
|
5
6
|
const exit_1 = require("./exit");
|
|
6
7
|
const stream_1 = require("./stream");
|
|
7
8
|
const listr2_1 = require("listr2");
|
|
@@ -135,6 +136,14 @@ class Listr3 extends listr2_1.Listr {
|
|
|
135
136
|
task.state$ = listr2_1.ListrTaskState.FAILED;
|
|
136
137
|
this["renderer"].end(new Error("Interrupted."));
|
|
137
138
|
}
|
|
139
|
+
async execAndParse(verbose) {
|
|
140
|
+
const result = await this.exec();
|
|
141
|
+
const exitCode = result.some((item) => item.error) ? 1 : 0;
|
|
142
|
+
const errors = result
|
|
143
|
+
.filter((item) => item.error && (verbose || !(item.error instanceof error_1.AppError)))
|
|
144
|
+
.map(({ error }) => error);
|
|
145
|
+
return { result, exitCode, errors };
|
|
146
|
+
}
|
|
138
147
|
async exec() {
|
|
139
148
|
const dispose = (0, exit_1.onExit)(() => {
|
|
140
149
|
this.$options.progressManager?.dispose();
|
package/lib/utils/math.js
CHANGED
package/lib/utils/object.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export declare function merge<T extends Record<string, unknown>>(target: T, ...sources: Record<string, unknown>[]): T;
|
|
2
2
|
export declare function omitProp<T extends Record<string, any>, N extends keyof T>(object: T, name: N): Omit<T, N>;
|
|
3
|
+
export declare function pickProps<T extends Record<string, any>, I extends {
|
|
4
|
+
[K in keyof T]?: boolean;
|
|
5
|
+
}>(object: T, input: I): {
|
|
6
|
+
[K in keyof T as K extends keyof I ? [I[K]] extends [true] ? K : never : never]: T[K];
|
|
7
|
+
};
|
|
3
8
|
export declare function getErrorProperties(error: Error): Record<string, string>;
|
|
4
9
|
type GroupByKeyParamType<TItem> = ((item: TItem) => string[] | string) | (keyof TItem)[] | keyof TItem;
|
|
5
10
|
export declare function groupBy<TItem>(items: TItem[], keyOrCb: GroupByKeyParamType<TItem>): Record<string, TItem[]>;
|
package/lib/utils/object.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.StrictMap = exports.groupBy = exports.getErrorProperties = exports.omitProp = exports.merge = void 0;
|
|
3
|
+
exports.StrictMap = exports.groupBy = exports.getErrorProperties = exports.pickProps = exports.omitProp = exports.merge = void 0;
|
|
4
4
|
function merge(target, ...sources) {
|
|
5
5
|
const isObject = (o) => typeof o === "object" && o !== null;
|
|
6
6
|
for (const source of sources)
|
|
@@ -19,6 +19,15 @@ function omitProp(object, name) {
|
|
|
19
19
|
return result;
|
|
20
20
|
}
|
|
21
21
|
exports.omitProp = omitProp;
|
|
22
|
+
function pickProps(object, input) {
|
|
23
|
+
const result = {};
|
|
24
|
+
for (const name in input) {
|
|
25
|
+
if (input[name])
|
|
26
|
+
result[name] = object[name];
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
exports.pickProps = pickProps;
|
|
22
31
|
function getErrorProperties(error) {
|
|
23
32
|
const alt = {};
|
|
24
33
|
for (const key of Object.getOwnPropertyNames(error)) {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type OptionsConfigObject = {
|
|
2
|
+
flag?: string | false;
|
|
3
|
+
shortFlag?: string;
|
|
4
|
+
description: string;
|
|
5
|
+
required?: boolean;
|
|
6
|
+
defaults?: any;
|
|
7
|
+
value?: "boolean" | "number" | "string" | "array" | ((value: string) => any);
|
|
8
|
+
};
|
|
9
|
+
export type OptionsConfig = Record<string, OptionsConfigObject>;
|
|
10
|
+
export type InferOptionsValue<O extends OptionsConfigObject> = [
|
|
11
|
+
O["value"]
|
|
12
|
+
] extends ["number"] ? number : [O["value"]] extends ["boolean"] ? boolean : [O["value"]] extends ["array"] ? string[] : O["value"] extends (value: any) => any ? ReturnType<O["value"]> : string;
|
|
13
|
+
export type InferOptions<T extends OptionsConfig> = {
|
|
14
|
+
[K in keyof T as [T[K]["required"]] extends [true] ? K : never]: InferOptionsValue<T[K]>;
|
|
15
|
+
} & {
|
|
16
|
+
[K in keyof T as [T[K]["required"]] extends [true] ? never : K]?: InferOptionsValue<T[K]>;
|
|
17
|
+
};
|
|
18
|
+
export type CommandConfig<T extends OptionsConfig = OptionsConfig> = {
|
|
19
|
+
name: string;
|
|
20
|
+
alias?: string;
|
|
21
|
+
options: T;
|
|
22
|
+
};
|
|
23
|
+
export declare function createCommand<T extends OptionsConfig>(config: CommandConfig<T>, action: (options: InferOptions<T>) => any): import("commander").Command;
|
|
24
|
+
export declare function stringifyOptions(options: OptionsConfig, object: any): string[];
|