@datatruck/cli 0.1.0 → 0.3.1
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 +1 -0
- package/Action/RestoreAction.js +1 -0
- package/CHANGELOG.md +32 -0
- package/Config/TaskConfig.d.ts +4 -0
- package/Config/TaskConfig.js +2 -0
- package/Factory/TaskFactory.js +4 -0
- package/JsonSchema/DefinitionEnum.d.ts +2 -1
- package/JsonSchema/DefinitionEnum.js +3 -2
- package/JsonSchema/JsonSchema.js +14 -0
- package/Repository/LocalRepository.js +2 -0
- package/Repository/ResticRepository.js +33 -13
- package/Task/MssqlTask.js +1 -0
- package/Task/ScriptTask.d.ts +42 -0
- package/Task/ScriptTask.js +180 -0
- package/Task/SqlDumpTaskAbstract.js +2 -0
- package/config.schema.json +154 -1
- package/package.json +1 -1
- package/util/ResticUtil.d.ts +6 -4
- package/util/ResticUtil.js +26 -3
- package/util/datatruck/config-util.d.ts +32 -0
- package/util/datatruck/config-util.js +12 -1
- package/util/fs-util.d.ts +3 -0
- package/util/fs-util.js +35 -1
- package/util/string-util.js +7 -1
package/Action/BackupAction.js
CHANGED
package/Action/RestoreAction.js
CHANGED
|
@@ -206,6 +206,7 @@ class RestoreAction {
|
|
|
206
206
|
let packages = (0, config_util_1.filterPackages)(this.config, this.options);
|
|
207
207
|
packages = (0, config_util_1.resolvePackages)(packages, {
|
|
208
208
|
snapshotId: this.options.snapshotId,
|
|
209
|
+
snapshotDate: snapshots[0].date,
|
|
209
210
|
action: "restore",
|
|
210
211
|
});
|
|
211
212
|
const snapshotAndConfigs = this.assocConfigs(packages, snapshots);
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @datatruck/cli
|
|
2
2
|
|
|
3
|
+
## 0.3.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`c3bb4c6`](https://github.com/swordev/datatruck/commit/c3bb4c609887c5525cf35487ea237750addb6e75) Thanks [@juanrgm](https://github.com/juanrgm)! - Fix restic stdout parser
|
|
8
|
+
|
|
9
|
+
## 0.3.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [`d63fd25`](https://github.com/swordev/datatruck/commit/d63fd25ffa8d2e539d2125dfd6a3f55020086804) Thanks [@juanrgm](https://github.com/juanrgm)! - Add `snapshotDate` param
|
|
14
|
+
|
|
15
|
+
* [`486ef4a`](https://github.com/swordev/datatruck/commit/486ef4add27ae1dbfd166b16c257522f43537ecd) Thanks [@juanrgm](https://github.com/juanrgm)! - Resolve params in `include` and `exclude`
|
|
16
|
+
|
|
17
|
+
- [`617dae2`](https://github.com/swordev/datatruck/commit/617dae2c8ed90e6e65e8109f03cfad0e64bd7c02) Thanks [@juanrgm](https://github.com/juanrgm)! - Add `script` task
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- [`d1b3ea9`](https://github.com/swordev/datatruck/commit/d1b3ea9c9540d30898c00490963523a4fbc68193) Thanks [@juanrgm](https://github.com/juanrgm)! - Avoid use gitignore if is not necessary in restic repository
|
|
22
|
+
|
|
23
|
+
## 0.2.0
|
|
24
|
+
|
|
25
|
+
### Minor Changes
|
|
26
|
+
|
|
27
|
+
- [`120460c`](https://github.com/swordev/datatruck/commit/120460c8824cef4184e43f571a4cc0798b899b66) Thanks [@juanrgm](https://github.com/juanrgm)! - Enable `include` option in restic repository
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- [`e30ede3`](https://github.com/swordev/datatruck/commit/e30ede371bc7ab3fc1cd47758fdac7a28e8e2705) Thanks [@juanrgm](https://github.com/juanrgm)! - Resolve `RESTIC_PASSWORD_FILE` path
|
|
32
|
+
|
|
33
|
+
* [`8539d28`](https://github.com/swordev/datatruck/commit/8539d285b2c51d700aa811cd772d573fa0d613eb) Thanks [@juanrgm](https://github.com/juanrgm)! - Allow empty backup in restic repository
|
|
34
|
+
|
|
3
35
|
## 0.1.0
|
|
4
36
|
|
|
5
37
|
### Minor Changes
|
package/Config/TaskConfig.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { MariadbTaskConfigType, mariadbTaskName } from "../Task/MariadbTask";
|
|
|
3
3
|
import { MssqlTaskConfigType, mssqlTaskName } from "../Task/MssqlTask";
|
|
4
4
|
import { MysqlDumpTaskConfigType, mysqlDumpTaskName } from "../Task/MysqlDumpTask";
|
|
5
5
|
import { PostgresqlDumpTaskConfigType, postgresqlDumpTaskName } from "../Task/PostgresqlDumpTask";
|
|
6
|
+
import { ScriptTaskConfigType, scriptTaskName } from "../Task/ScriptTask";
|
|
6
7
|
import { JSONSchema7 } from "json-schema";
|
|
7
8
|
export declare const taskConfigDefinition: JSONSchema7;
|
|
8
9
|
export declare type TaskConfigType = {
|
|
@@ -20,4 +21,7 @@ export declare type TaskConfigType = {
|
|
|
20
21
|
} | {
|
|
21
22
|
name: typeof postgresqlDumpTaskName;
|
|
22
23
|
config: PostgresqlDumpTaskConfigType;
|
|
24
|
+
} | {
|
|
25
|
+
name: typeof scriptTaskName;
|
|
26
|
+
config: ScriptTaskConfigType;
|
|
23
27
|
};
|
package/Config/TaskConfig.js
CHANGED
|
@@ -7,12 +7,14 @@ const MariadbTask_1 = require("../Task/MariadbTask");
|
|
|
7
7
|
const MssqlTask_1 = require("../Task/MssqlTask");
|
|
8
8
|
const MysqlDumpTask_1 = require("../Task/MysqlDumpTask");
|
|
9
9
|
const PostgresqlDumpTask_1 = require("../Task/PostgresqlDumpTask");
|
|
10
|
+
const ScriptTask_1 = require("../Task/ScriptTask");
|
|
10
11
|
const names = {
|
|
11
12
|
[GitTask_1.gitTaskName]: DefinitionEnum_1.DefinitionEnum.gitTask,
|
|
12
13
|
[MariadbTask_1.mariadbTaskName]: DefinitionEnum_1.DefinitionEnum.mariadbTask,
|
|
13
14
|
[MssqlTask_1.mssqlTaskName]: DefinitionEnum_1.DefinitionEnum.mssqlTask,
|
|
14
15
|
[MysqlDumpTask_1.mysqlDumpTaskName]: DefinitionEnum_1.DefinitionEnum.mysqlDumpTask,
|
|
15
16
|
[PostgresqlDumpTask_1.postgresqlDumpTaskName]: DefinitionEnum_1.DefinitionEnum.postgresqlDumpTask,
|
|
17
|
+
[ScriptTask_1.scriptTaskName]: DefinitionEnum_1.DefinitionEnum.scriptTask,
|
|
16
18
|
};
|
|
17
19
|
exports.taskConfigDefinition = {
|
|
18
20
|
type: "object",
|
package/Factory/TaskFactory.js
CHANGED
|
@@ -7,6 +7,7 @@ const MariadbTask_1 = require("../Task/MariadbTask");
|
|
|
7
7
|
const MssqlTask_1 = require("../Task/MssqlTask");
|
|
8
8
|
const MysqlDumpTask_1 = require("../Task/MysqlDumpTask");
|
|
9
9
|
const PostgresqlDumpTask_1 = require("../Task/PostgresqlDumpTask");
|
|
10
|
+
const ScriptTask_1 = require("../Task/ScriptTask");
|
|
10
11
|
function TaskFactory(task) {
|
|
11
12
|
if (task.name === GitTask_1.gitTaskName) {
|
|
12
13
|
return new GitTask_1.GitTask(task.config ?? {});
|
|
@@ -23,6 +24,9 @@ function TaskFactory(task) {
|
|
|
23
24
|
else if (task.name === MssqlTask_1.mssqlTaskName) {
|
|
24
25
|
return new MssqlTask_1.MssqlTask(task.config ?? {});
|
|
25
26
|
}
|
|
27
|
+
else if (task.name === ScriptTask_1.scriptTaskName) {
|
|
28
|
+
return new ScriptTask_1.ScriptTask(task.config ?? {});
|
|
29
|
+
}
|
|
26
30
|
else {
|
|
27
31
|
throw new AppError_1.AppError(`Invalid task name: ${task["name"]}`);
|
|
28
32
|
}
|
|
@@ -11,6 +11,7 @@ export declare enum DefinitionEnum {
|
|
|
11
11
|
gitRepository = "git-repository",
|
|
12
12
|
gitPackageRepository = "git-package-repository",
|
|
13
13
|
gitTask = "git-task",
|
|
14
|
+
scriptTask = "script-task",
|
|
14
15
|
mariadbTask = "mariadb-task",
|
|
15
16
|
mssqlTask = "mssql-task",
|
|
16
17
|
mysqlDumpTask = "mysql-dump-task",
|
|
@@ -20,6 +21,6 @@ export declare enum DefinitionEnum {
|
|
|
20
21
|
prunePolicy = "prune-policy",
|
|
21
22
|
pathsObject = "paths-object"
|
|
22
23
|
}
|
|
23
|
-
export declare function makeRef(type: DefinitionEnum): {
|
|
24
|
+
export declare function makeRef(type: DefinitionEnum, subType?: string): {
|
|
24
25
|
$ref: string;
|
|
25
26
|
};
|
|
@@ -15,6 +15,7 @@ var DefinitionEnum;
|
|
|
15
15
|
DefinitionEnum["gitRepository"] = "git-repository";
|
|
16
16
|
DefinitionEnum["gitPackageRepository"] = "git-package-repository";
|
|
17
17
|
DefinitionEnum["gitTask"] = "git-task";
|
|
18
|
+
DefinitionEnum["scriptTask"] = "script-task";
|
|
18
19
|
DefinitionEnum["mariadbTask"] = "mariadb-task";
|
|
19
20
|
DefinitionEnum["mssqlTask"] = "mssql-task";
|
|
20
21
|
DefinitionEnum["mysqlDumpTask"] = "mysql-dump-task";
|
|
@@ -24,9 +25,9 @@ var DefinitionEnum;
|
|
|
24
25
|
DefinitionEnum["prunePolicy"] = "prune-policy";
|
|
25
26
|
DefinitionEnum["pathsObject"] = "paths-object";
|
|
26
27
|
})(DefinitionEnum = exports.DefinitionEnum || (exports.DefinitionEnum = {}));
|
|
27
|
-
function makeRef(type) {
|
|
28
|
+
function makeRef(type, subType) {
|
|
28
29
|
return {
|
|
29
|
-
$ref: `#/definitions/${type}
|
|
30
|
+
$ref: `#/definitions/${type}` + (subType ? `_${subType}` : ""),
|
|
30
31
|
};
|
|
31
32
|
}
|
|
32
33
|
exports.makeRef = makeRef;
|
package/JsonSchema/JsonSchema.js
CHANGED
|
@@ -15,6 +15,7 @@ const MariadbTask_1 = require("../Task/MariadbTask");
|
|
|
15
15
|
const MssqlTask_1 = require("../Task/MssqlTask");
|
|
16
16
|
const MysqlDumpTask_1 = require("../Task/MysqlDumpTask");
|
|
17
17
|
const PostgresqlDumpTask_1 = require("../Task/PostgresqlDumpTask");
|
|
18
|
+
const ScriptTask_1 = require("../Task/ScriptTask");
|
|
18
19
|
const SqlDumpTaskAbstract_1 = require("../Task/SqlDumpTaskAbstract");
|
|
19
20
|
const DefinitionEnum_1 = require("./DefinitionEnum");
|
|
20
21
|
exports.definitions = {
|
|
@@ -35,6 +36,7 @@ exports.definitions = {
|
|
|
35
36
|
[DefinitionEnum_1.DefinitionEnum.resticRepository]: ResticRepository_1.resticRepositoryDefinition,
|
|
36
37
|
[DefinitionEnum_1.DefinitionEnum.resticPackageRepository]: ResticRepository_1.resticPackageRepositoryDefinition,
|
|
37
38
|
[DefinitionEnum_1.DefinitionEnum.gitTask]: GitTask_1.gitTaskDefinition,
|
|
39
|
+
[DefinitionEnum_1.DefinitionEnum.scriptTask]: ScriptTask_1.scriptTaskDefinition,
|
|
38
40
|
[DefinitionEnum_1.DefinitionEnum.sqlDumpTask]: SqlDumpTaskAbstract_1.sqlDumpTaskDefinition,
|
|
39
41
|
[DefinitionEnum_1.DefinitionEnum.mariadbTask]: MariadbTask_1.mariadbTaskDefinition,
|
|
40
42
|
[DefinitionEnum_1.DefinitionEnum.mssqlTask]: MssqlTask_1.mssqlTaskDefinition,
|
|
@@ -44,6 +46,18 @@ exports.definitions = {
|
|
|
44
46
|
[DefinitionEnum_1.DefinitionEnum.prunePolicy]: PrunePolicyConfig_1.prunePolicyConfigDefinition,
|
|
45
47
|
[DefinitionEnum_1.DefinitionEnum.pathsObject]: PackageConfig_1.pathsObjectDefinition,
|
|
46
48
|
};
|
|
49
|
+
for (const key in exports.definitions) {
|
|
50
|
+
const schemaKey = key;
|
|
51
|
+
const schema = exports.definitions[schemaKey];
|
|
52
|
+
for (const defName in schema.definitions || {}) {
|
|
53
|
+
exports.definitions[`${schemaKey}_${defName}`] =
|
|
54
|
+
schema.definitions[defName];
|
|
55
|
+
}
|
|
56
|
+
exports.definitions[schemaKey] = {
|
|
57
|
+
...schema,
|
|
58
|
+
};
|
|
59
|
+
delete exports.definitions[schemaKey].definitions;
|
|
60
|
+
}
|
|
47
61
|
exports.schema = {
|
|
48
62
|
definitions: exports.definitions,
|
|
49
63
|
...(0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.config),
|
|
@@ -205,6 +205,8 @@ class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
205
205
|
paths: stream,
|
|
206
206
|
packs: compress?.packs,
|
|
207
207
|
});
|
|
208
|
+
if (data.options.verbose)
|
|
209
|
+
(0, cli_util_1.logExec)(`Path lists: ${pathLists.path}`);
|
|
208
210
|
let currentFiles = 0;
|
|
209
211
|
if (compress?.packs) {
|
|
210
212
|
let packIndex = 0;
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.ResticRepository = exports.resticPackageRepositoryDefinition = exports.resticRepositoryDefinition = exports.resticRepositoryName = void 0;
|
|
4
7
|
const AppError_1 = require("../Error/AppError");
|
|
5
8
|
const ResticUtil_1 = require("../util/ResticUtil");
|
|
9
|
+
const cli_util_1 = require("../util/cli-util");
|
|
6
10
|
const paths_util_1 = require("../util/datatruck/paths-util");
|
|
7
11
|
const fs_util_1 = require("../util/fs-util");
|
|
8
12
|
const string_util_1 = require("../util/string-util");
|
|
9
13
|
const RepositoryAbstract_1 = require("./RepositoryAbstract");
|
|
10
14
|
const assert_1 = require("assert");
|
|
15
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
11
16
|
const micromatch_1 = require("micromatch");
|
|
12
17
|
const path_1 = require("path");
|
|
13
18
|
exports.resticRepositoryName = "restic";
|
|
@@ -54,7 +59,7 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
54
59
|
if (this.env)
|
|
55
60
|
return this.env;
|
|
56
61
|
return (this.env = {
|
|
57
|
-
RESTIC_PASSWORD_FILE: this.config.passwordFile,
|
|
62
|
+
RESTIC_PASSWORD_FILE: (0, path_1.resolve)(this.config.passwordFile),
|
|
58
63
|
RESTIC_REPOSITORY: await ResticUtil_1.ResticUtil.formatRepository(this.config.repository),
|
|
59
64
|
});
|
|
60
65
|
}
|
|
@@ -150,14 +155,31 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
150
155
|
const pkg = data.package;
|
|
151
156
|
const sourcePath = data.targetPath ?? data.package.path;
|
|
152
157
|
(0, assert_1.ok)(sourcePath);
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
158
|
+
let gitignorePath;
|
|
159
|
+
if (pkg.include || pkg.exclude) {
|
|
160
|
+
const include = await (0, paths_util_1.parsePaths)(pkg.include ?? ["**"], {
|
|
161
|
+
cwd: sourcePath,
|
|
162
|
+
verbose: data.options.verbose,
|
|
163
|
+
});
|
|
164
|
+
const exclude = pkg.exclude
|
|
165
|
+
? await (0, paths_util_1.parsePaths)(pkg.exclude, {
|
|
166
|
+
cwd: sourcePath,
|
|
167
|
+
verbose: data.options.verbose,
|
|
168
|
+
})
|
|
169
|
+
: undefined;
|
|
170
|
+
const stream = fast_glob_1.default.stream(include, {
|
|
171
|
+
cwd: sourcePath,
|
|
172
|
+
ignore: exclude,
|
|
173
|
+
dot: true,
|
|
174
|
+
onlyFiles: true,
|
|
175
|
+
markDirectories: true,
|
|
176
|
+
});
|
|
177
|
+
if (data.options.verbose)
|
|
178
|
+
(0, cli_util_1.logExec)(`Writing paths lists`);
|
|
179
|
+
gitignorePath = await (0, fs_util_1.writeGitIgnoreList)({
|
|
180
|
+
paths: stream,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
161
183
|
if (data.options.tags?.some((tag) => tag.startsWith(ResticRepository.refPrefix)))
|
|
162
184
|
throw new AppError_1.AppError(`Tag prefix is not allowed`);
|
|
163
185
|
const packageTag = ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.PACKAGE, data.package.name);
|
|
@@ -170,15 +192,13 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
170
192
|
await restic.backup({
|
|
171
193
|
cwd: sourcePath,
|
|
172
194
|
paths: ["."],
|
|
195
|
+
allowEmptySnapshot: true,
|
|
196
|
+
excludeFile: gitignorePath ? [gitignorePath] : undefined,
|
|
173
197
|
parent: lastSnapshot?.id,
|
|
174
198
|
// https://github.com/restic/restic/pull/3200
|
|
175
199
|
...((await restic.checkBackupSetPathSupport()) && {
|
|
176
200
|
setPaths: [`/datatruck/${data.package.name}`],
|
|
177
201
|
}),
|
|
178
|
-
exclude: (await (0, paths_util_1.parsePaths)(pkg.exclude ?? [], {
|
|
179
|
-
cwd: sourcePath,
|
|
180
|
-
verbose: data.options.verbose,
|
|
181
|
-
})).map(path_1.normalize),
|
|
182
202
|
tags: [
|
|
183
203
|
ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.ID, data.snapshot.id),
|
|
184
204
|
ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.SHORT_ID, data.snapshot.id.slice(0, 8)),
|
package/Task/MssqlTask.js
CHANGED
|
@@ -96,6 +96,7 @@ class MssqlTask extends TaskAbstract_1.TaskAbstract {
|
|
|
96
96
|
database: databaseName,
|
|
97
97
|
packageName: data.package.name,
|
|
98
98
|
snapshotId: data.options.snapshotId,
|
|
99
|
+
snapshotDate: data.snapshot.date,
|
|
99
100
|
});
|
|
100
101
|
const databasePath = (0, path_1.join)(restorePath, file);
|
|
101
102
|
const exists = await this.fetchDatabaseNames(databaseName);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { BackupDataType, RestoreDataType, TaskAbstract } from "./TaskAbstract";
|
|
2
|
+
import { JSONSchema7 } from "json-schema";
|
|
3
|
+
export declare type ProcessStepConfig = {
|
|
4
|
+
command: string;
|
|
5
|
+
env?: Record<string, string>;
|
|
6
|
+
args?: string[];
|
|
7
|
+
};
|
|
8
|
+
export declare type NodeStepConfig = {
|
|
9
|
+
env?: Record<string, string>;
|
|
10
|
+
code: string | string[];
|
|
11
|
+
};
|
|
12
|
+
export declare type Step = {
|
|
13
|
+
type: "process";
|
|
14
|
+
config: ProcessStepConfig;
|
|
15
|
+
} | {
|
|
16
|
+
type: "node";
|
|
17
|
+
config: NodeStepConfig;
|
|
18
|
+
};
|
|
19
|
+
export declare type ScriptTaskConfigType = {
|
|
20
|
+
env?: Record<string, string | undefined>;
|
|
21
|
+
backupSteps: Step[];
|
|
22
|
+
restoreSteps: Step[];
|
|
23
|
+
};
|
|
24
|
+
export declare const scriptTaskName = "script";
|
|
25
|
+
export declare const scriptTaskDefinition: JSONSchema7;
|
|
26
|
+
export declare class ScriptTask extends TaskAbstract<ScriptTaskConfigType> {
|
|
27
|
+
protected verbose?: boolean;
|
|
28
|
+
onBeforeBackup(): Promise<{
|
|
29
|
+
targetPath: string;
|
|
30
|
+
}>;
|
|
31
|
+
protected getVars(data: BackupDataType | RestoreDataType): Record<string, string | undefined>;
|
|
32
|
+
static processSteps(input: Step[] | Step, options: {
|
|
33
|
+
env?: Record<string, string | undefined>;
|
|
34
|
+
vars: Record<string, string | undefined>;
|
|
35
|
+
verbose?: boolean;
|
|
36
|
+
}): Promise<void>;
|
|
37
|
+
onBackup(data: BackupDataType): Promise<void>;
|
|
38
|
+
onBeforeRestore(): Promise<{
|
|
39
|
+
targetPath: string;
|
|
40
|
+
}>;
|
|
41
|
+
onRestore(data: RestoreDataType): Promise<void>;
|
|
42
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ScriptTask = exports.scriptTaskDefinition = exports.scriptTaskName = void 0;
|
|
4
|
+
const DefinitionEnum_1 = require("../JsonSchema/DefinitionEnum");
|
|
5
|
+
const fs_util_1 = require("../util/fs-util");
|
|
6
|
+
const process_util_1 = require("../util/process-util");
|
|
7
|
+
const string_util_1 = require("../util/string-util");
|
|
8
|
+
const TaskAbstract_1 = require("./TaskAbstract");
|
|
9
|
+
const assert_1 = require("assert");
|
|
10
|
+
const promises_1 = require("fs/promises");
|
|
11
|
+
const path_1 = require("path");
|
|
12
|
+
var ScriptTaskDefinitionEnum;
|
|
13
|
+
(function (ScriptTaskDefinitionEnum) {
|
|
14
|
+
ScriptTaskDefinitionEnum["step"] = "step";
|
|
15
|
+
ScriptTaskDefinitionEnum["processStepConfig"] = "processStepConfig";
|
|
16
|
+
ScriptTaskDefinitionEnum["nodeStepConfig"] = "nodeStepConfig";
|
|
17
|
+
})(ScriptTaskDefinitionEnum || (ScriptTaskDefinitionEnum = {}));
|
|
18
|
+
const stepTypes = {
|
|
19
|
+
process: ScriptTaskDefinitionEnum.processStepConfig,
|
|
20
|
+
node: ScriptTaskDefinitionEnum.nodeStepConfig,
|
|
21
|
+
};
|
|
22
|
+
exports.scriptTaskName = "script";
|
|
23
|
+
exports.scriptTaskDefinition = {
|
|
24
|
+
definitions: {
|
|
25
|
+
step: {
|
|
26
|
+
type: "object",
|
|
27
|
+
required: ["type"],
|
|
28
|
+
properties: {
|
|
29
|
+
type: { enum: Object.keys(stepTypes) },
|
|
30
|
+
config: {},
|
|
31
|
+
},
|
|
32
|
+
anyOf: Object.keys(stepTypes).map((name) => ({
|
|
33
|
+
if: {
|
|
34
|
+
type: "object",
|
|
35
|
+
properties: {
|
|
36
|
+
type: { const: name },
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
then: {
|
|
40
|
+
type: "object",
|
|
41
|
+
properties: {
|
|
42
|
+
config: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.scriptTask, stepTypes[name]),
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
else: false,
|
|
46
|
+
})),
|
|
47
|
+
},
|
|
48
|
+
processStepConfig: {
|
|
49
|
+
type: "object",
|
|
50
|
+
required: ["command"],
|
|
51
|
+
properties: {
|
|
52
|
+
command: { type: "string" },
|
|
53
|
+
env: {
|
|
54
|
+
type: "object",
|
|
55
|
+
patternProperties: { ".+": { type: "string" } },
|
|
56
|
+
},
|
|
57
|
+
args: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
nodeStepConfig: {
|
|
61
|
+
type: "object",
|
|
62
|
+
required: ["code"],
|
|
63
|
+
properties: {
|
|
64
|
+
code: {
|
|
65
|
+
anyOf: [{ type: "string" }, (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil)],
|
|
66
|
+
},
|
|
67
|
+
env: {
|
|
68
|
+
type: "object",
|
|
69
|
+
patternProperties: { ".+": { type: "string" } },
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
type: "object",
|
|
75
|
+
additionalProperties: false,
|
|
76
|
+
required: ["backupSteps", "restoreSteps"],
|
|
77
|
+
properties: {
|
|
78
|
+
env: {
|
|
79
|
+
type: "object",
|
|
80
|
+
patternProperties: {
|
|
81
|
+
".+": { type: "string" },
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
backupSteps: {
|
|
85
|
+
type: "array",
|
|
86
|
+
items: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.scriptTask, ScriptTaskDefinitionEnum.step),
|
|
87
|
+
},
|
|
88
|
+
restoreSteps: {
|
|
89
|
+
type: "array",
|
|
90
|
+
items: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.scriptTask, ScriptTaskDefinitionEnum.step),
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
class ScriptTask extends TaskAbstract_1.TaskAbstract {
|
|
95
|
+
async onBeforeBackup() {
|
|
96
|
+
return {
|
|
97
|
+
targetPath: await (0, fs_util_1.mkTmpDir)(ScriptTask.name),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
getVars(data) {
|
|
101
|
+
return {
|
|
102
|
+
DTT_SNAPSHOT_ID: data.snapshot.id,
|
|
103
|
+
DTT_SNAPSHOT_DATE: data.snapshot.date,
|
|
104
|
+
DTT_PACKAGE_NAME: data.package.name,
|
|
105
|
+
DTT_PACKAGE_PATH: data.package.path,
|
|
106
|
+
DTT_TARGET_PATH: data.targetPath,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
static async processSteps(input, options) {
|
|
110
|
+
const steps = Array.isArray(input) ? input : [input];
|
|
111
|
+
for (const step of steps) {
|
|
112
|
+
if (step.type === "process") {
|
|
113
|
+
await (0, process_util_1.exec)(step.config.command, (step.config.args || []).map((v) => (0, string_util_1.render)(v, options.vars)), {
|
|
114
|
+
env: {
|
|
115
|
+
...process.env,
|
|
116
|
+
...options.vars,
|
|
117
|
+
...options.env,
|
|
118
|
+
...step.config.env,
|
|
119
|
+
},
|
|
120
|
+
}, {
|
|
121
|
+
log: options.verbose,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
else if (step.type === "node") {
|
|
125
|
+
const tempDir = await (0, fs_util_1.mkTmpDir)("script-task-node-step");
|
|
126
|
+
const scriptPath = (0, path_1.join)(tempDir, "script.js");
|
|
127
|
+
await (0, promises_1.writeFile)(scriptPath, Array.isArray(step.config.code)
|
|
128
|
+
? step.config.code.join("\n")
|
|
129
|
+
: step.config.code);
|
|
130
|
+
await (0, process_util_1.exec)("node", [scriptPath], {
|
|
131
|
+
env: {
|
|
132
|
+
...process.env,
|
|
133
|
+
...options.vars,
|
|
134
|
+
...options.env,
|
|
135
|
+
...step.config.env,
|
|
136
|
+
},
|
|
137
|
+
}, {
|
|
138
|
+
log: options.verbose,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
throw new Error(`Invalid step type: ${step.type}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
async onBackup(data) {
|
|
147
|
+
this.verbose = data.options.verbose;
|
|
148
|
+
const config = this.config;
|
|
149
|
+
const path = data.package.path;
|
|
150
|
+
const targetPath = data.targetPath;
|
|
151
|
+
(0, assert_1.ok)(typeof path === "string");
|
|
152
|
+
(0, assert_1.ok)(typeof targetPath === "string");
|
|
153
|
+
await ScriptTask.processSteps(config.backupSteps, {
|
|
154
|
+
env: config.env,
|
|
155
|
+
vars: this.getVars(data),
|
|
156
|
+
verbose: this.verbose,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
async onBeforeRestore() {
|
|
160
|
+
return {
|
|
161
|
+
targetPath: await (0, fs_util_1.mkTmpDir)(ScriptTask.name),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
async onRestore(data) {
|
|
165
|
+
this.verbose = data.options.verbose;
|
|
166
|
+
const config = this.config;
|
|
167
|
+
const restorePath = data.package.restorePath;
|
|
168
|
+
const targetPath = data.targetPath;
|
|
169
|
+
(0, assert_1.ok)(typeof restorePath === "string");
|
|
170
|
+
(0, assert_1.ok)(typeof targetPath === "string");
|
|
171
|
+
await (0, fs_util_1.mkdirIfNotExists)(restorePath);
|
|
172
|
+
await (0, fs_util_1.ensureEmptyDir)(restorePath);
|
|
173
|
+
await ScriptTask.processSteps(config.restoreSteps, {
|
|
174
|
+
env: config.env,
|
|
175
|
+
vars: this.getVars(data),
|
|
176
|
+
verbose: this.verbose,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
exports.ScriptTask = ScriptTask;
|
|
@@ -111,6 +111,7 @@ class SqlDumpTaskAbstract extends TaskAbstract_1.TaskAbstract {
|
|
|
111
111
|
name: (0, config_util_1.resolveDatabaseName)(this.config.database, {
|
|
112
112
|
packageName: data.package.name,
|
|
113
113
|
snapshotId: data.options.snapshotId,
|
|
114
|
+
snapshotDate: data.snapshot.date,
|
|
114
115
|
action: "restore",
|
|
115
116
|
database: undefined,
|
|
116
117
|
}),
|
|
@@ -119,6 +120,7 @@ class SqlDumpTaskAbstract extends TaskAbstract_1.TaskAbstract {
|
|
|
119
120
|
database.name = (0, config_util_1.resolveDatabaseName)(this.config.targetDatabase.name, {
|
|
120
121
|
packageName: data.package.name,
|
|
121
122
|
snapshotId: data.options.snapshotId,
|
|
123
|
+
snapshotDate: data.snapshot.date,
|
|
122
124
|
action: "restore",
|
|
123
125
|
database: database.name,
|
|
124
126
|
});
|
package/config.schema.json
CHANGED
|
@@ -261,7 +261,8 @@
|
|
|
261
261
|
"mariadb",
|
|
262
262
|
"mssql",
|
|
263
263
|
"mysql-dump",
|
|
264
|
-
"postgresql-dump"
|
|
264
|
+
"postgresql-dump",
|
|
265
|
+
"script"
|
|
265
266
|
]
|
|
266
267
|
},
|
|
267
268
|
"config": {}
|
|
@@ -361,6 +362,25 @@
|
|
|
361
362
|
}
|
|
362
363
|
},
|
|
363
364
|
"else": false
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"if": {
|
|
368
|
+
"type": "object",
|
|
369
|
+
"properties": {
|
|
370
|
+
"name": {
|
|
371
|
+
"const": "script"
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
"then": {
|
|
376
|
+
"type": "object",
|
|
377
|
+
"properties": {
|
|
378
|
+
"config": {
|
|
379
|
+
"$ref": "#/definitions/script-task"
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
"else": false
|
|
364
384
|
}
|
|
365
385
|
]
|
|
366
386
|
},
|
|
@@ -551,6 +571,36 @@
|
|
|
551
571
|
}
|
|
552
572
|
}
|
|
553
573
|
},
|
|
574
|
+
"script-task": {
|
|
575
|
+
"type": "object",
|
|
576
|
+
"additionalProperties": false,
|
|
577
|
+
"required": [
|
|
578
|
+
"backupSteps",
|
|
579
|
+
"restoreSteps"
|
|
580
|
+
],
|
|
581
|
+
"properties": {
|
|
582
|
+
"env": {
|
|
583
|
+
"type": "object",
|
|
584
|
+
"patternProperties": {
|
|
585
|
+
".+": {
|
|
586
|
+
"type": "string"
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
"backupSteps": {
|
|
591
|
+
"type": "array",
|
|
592
|
+
"items": {
|
|
593
|
+
"$ref": "#/definitions/script-task_step"
|
|
594
|
+
}
|
|
595
|
+
},
|
|
596
|
+
"restoreSteps": {
|
|
597
|
+
"type": "array",
|
|
598
|
+
"items": {
|
|
599
|
+
"$ref": "#/definitions/script-task_step"
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
},
|
|
554
604
|
"sqldump-task": {
|
|
555
605
|
"type": "object",
|
|
556
606
|
"required": [
|
|
@@ -810,6 +860,109 @@
|
|
|
810
860
|
"else": false
|
|
811
861
|
}
|
|
812
862
|
]
|
|
863
|
+
},
|
|
864
|
+
"script-task_step": {
|
|
865
|
+
"type": "object",
|
|
866
|
+
"required": [
|
|
867
|
+
"type"
|
|
868
|
+
],
|
|
869
|
+
"properties": {
|
|
870
|
+
"type": {
|
|
871
|
+
"enum": [
|
|
872
|
+
"process",
|
|
873
|
+
"node"
|
|
874
|
+
]
|
|
875
|
+
},
|
|
876
|
+
"config": {}
|
|
877
|
+
},
|
|
878
|
+
"anyOf": [
|
|
879
|
+
{
|
|
880
|
+
"if": {
|
|
881
|
+
"type": "object",
|
|
882
|
+
"properties": {
|
|
883
|
+
"type": {
|
|
884
|
+
"const": "process"
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
},
|
|
888
|
+
"then": {
|
|
889
|
+
"type": "object",
|
|
890
|
+
"properties": {
|
|
891
|
+
"config": {
|
|
892
|
+
"$ref": "#/definitions/script-task_processStepConfig"
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
},
|
|
896
|
+
"else": false
|
|
897
|
+
},
|
|
898
|
+
{
|
|
899
|
+
"if": {
|
|
900
|
+
"type": "object",
|
|
901
|
+
"properties": {
|
|
902
|
+
"type": {
|
|
903
|
+
"const": "node"
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
},
|
|
907
|
+
"then": {
|
|
908
|
+
"type": "object",
|
|
909
|
+
"properties": {
|
|
910
|
+
"config": {
|
|
911
|
+
"$ref": "#/definitions/script-task_nodeStepConfig"
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
},
|
|
915
|
+
"else": false
|
|
916
|
+
}
|
|
917
|
+
]
|
|
918
|
+
},
|
|
919
|
+
"script-task_processStepConfig": {
|
|
920
|
+
"type": "object",
|
|
921
|
+
"required": [
|
|
922
|
+
"command"
|
|
923
|
+
],
|
|
924
|
+
"properties": {
|
|
925
|
+
"command": {
|
|
926
|
+
"type": "string"
|
|
927
|
+
},
|
|
928
|
+
"env": {
|
|
929
|
+
"type": "object",
|
|
930
|
+
"patternProperties": {
|
|
931
|
+
".+": {
|
|
932
|
+
"type": "string"
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
},
|
|
936
|
+
"args": {
|
|
937
|
+
"$ref": "#/definitions/stringlist-util"
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
},
|
|
941
|
+
"script-task_nodeStepConfig": {
|
|
942
|
+
"type": "object",
|
|
943
|
+
"required": [
|
|
944
|
+
"code"
|
|
945
|
+
],
|
|
946
|
+
"properties": {
|
|
947
|
+
"code": {
|
|
948
|
+
"anyOf": [
|
|
949
|
+
{
|
|
950
|
+
"type": "string"
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
"$ref": "#/definitions/stringlist-util"
|
|
954
|
+
}
|
|
955
|
+
]
|
|
956
|
+
},
|
|
957
|
+
"env": {
|
|
958
|
+
"type": "object",
|
|
959
|
+
"patternProperties": {
|
|
960
|
+
".+": {
|
|
961
|
+
"type": "string"
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
813
966
|
}
|
|
814
967
|
},
|
|
815
968
|
"$ref": "#/definitions/config"
|
package/package.json
CHANGED
package/util/ResticUtil.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ExecSettingsInterface } from "./process-util";
|
|
1
|
+
import { ExecResultType, ExecSettingsInterface } from "./process-util";
|
|
2
2
|
import { UriType } from "./string-util";
|
|
3
3
|
export declare type RepositoryType = {
|
|
4
4
|
name?: string;
|
|
@@ -43,7 +43,7 @@ export declare class ResticUtil {
|
|
|
43
43
|
static formatRepository(input: RepositoryType, hidePassword?: boolean): Promise<string>;
|
|
44
44
|
exec(args: string[], settings?: ExecSettingsInterface, options?: {
|
|
45
45
|
cwd?: string;
|
|
46
|
-
}): Promise<
|
|
46
|
+
}): Promise<ExecResultType>;
|
|
47
47
|
checkRepository(): Promise<boolean>;
|
|
48
48
|
forget(options: {
|
|
49
49
|
snapshotId?: string;
|
|
@@ -81,12 +81,14 @@ export declare class ResticUtil {
|
|
|
81
81
|
paths: string[];
|
|
82
82
|
setPaths?: string[];
|
|
83
83
|
exclude?: string[];
|
|
84
|
+
excludeFile?: string[];
|
|
84
85
|
parent?: string;
|
|
86
|
+
allowEmptySnapshot?: boolean;
|
|
85
87
|
onStream?: (data: BackupStreamType) => Promise<void>;
|
|
86
|
-
}): Promise<
|
|
88
|
+
}): Promise<ExecResultType>;
|
|
87
89
|
restore(options: {
|
|
88
90
|
id: string;
|
|
89
91
|
target: string;
|
|
90
92
|
onStream?: (data: BackupStreamType) => Promise<void>;
|
|
91
|
-
}): Promise<
|
|
93
|
+
}): Promise<ExecResultType>;
|
|
92
94
|
}
|
package/util/ResticUtil.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ResticUtil = void 0;
|
|
4
|
+
const fs_util_1 = require("./fs-util");
|
|
4
5
|
const process_util_1 = require("./process-util");
|
|
5
6
|
const string_util_1 = require("./string-util");
|
|
6
7
|
const fs_extra_1 = require("fs-extra");
|
|
8
|
+
const promises_1 = require("fs/promises");
|
|
7
9
|
const path_1 = require("path");
|
|
8
10
|
class ResticUtil {
|
|
9
11
|
constructor(options) {
|
|
@@ -13,7 +15,7 @@ class ResticUtil {
|
|
|
13
15
|
if (input.backend === "local") {
|
|
14
16
|
if (typeof input.path !== "string")
|
|
15
17
|
throw new Error(`Invalid path at "${input.name}" repository: ${input.path}`);
|
|
16
|
-
return (0, path_1.
|
|
18
|
+
return (0, path_1.resolve)(input.path);
|
|
17
19
|
}
|
|
18
20
|
if (input.passwordFile)
|
|
19
21
|
input = {
|
|
@@ -36,7 +38,7 @@ class ResticUtil {
|
|
|
36
38
|
stderr: true,
|
|
37
39
|
colorize: true,
|
|
38
40
|
allToStderr: true,
|
|
39
|
-
envNames: ["RESTIC_REPOSITORY"],
|
|
41
|
+
envNames: ["RESTIC_REPOSITORY", "RESTIC_PASSWORD_FILE"],
|
|
40
42
|
}
|
|
41
43
|
: {},
|
|
42
44
|
...(settings ?? {}),
|
|
@@ -99,10 +101,11 @@ class ResticUtil {
|
|
|
99
101
|
return result.stderr.includes("flag needs an argument");
|
|
100
102
|
}
|
|
101
103
|
async backup(options) {
|
|
102
|
-
|
|
104
|
+
const exec = async () => await this.exec([
|
|
103
105
|
"backup",
|
|
104
106
|
"--json",
|
|
105
107
|
...(options.exclude?.flatMap((v) => ["-e", v]) ?? []),
|
|
108
|
+
...(options.excludeFile?.flatMap((v) => ["--exclude-file", v]) ?? []),
|
|
106
109
|
...(options.tags?.flatMap((v) => ["--tag", v]) ?? []),
|
|
107
110
|
...(options.setPaths?.flatMap((v) => ["--set-path", v]) ?? []),
|
|
108
111
|
...(options.parent ? ["--parent", options.parent] : []),
|
|
@@ -114,6 +117,7 @@ class ResticUtil {
|
|
|
114
117
|
stdout: {
|
|
115
118
|
...(options.onStream && {
|
|
116
119
|
onData: async (data) => {
|
|
120
|
+
data = data.trim();
|
|
117
121
|
if (data.startsWith("{") && data.endsWith("}")) {
|
|
118
122
|
await options.onStream?.(JSON.parse(data));
|
|
119
123
|
}
|
|
@@ -123,6 +127,25 @@ class ResticUtil {
|
|
|
123
127
|
}, {
|
|
124
128
|
cwd: options.cwd,
|
|
125
129
|
});
|
|
130
|
+
try {
|
|
131
|
+
return await exec();
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
if (options.allowEmptySnapshot &&
|
|
135
|
+
error.message.includes("unable to save snapshot: snapshot is empty")) {
|
|
136
|
+
const emptyPath = await (0, fs_util_1.mkTmpDir)("empty");
|
|
137
|
+
await (0, promises_1.writeFile)(`${emptyPath}/.empty`, "");
|
|
138
|
+
return await this.backup({
|
|
139
|
+
...options,
|
|
140
|
+
cwd: emptyPath,
|
|
141
|
+
allowEmptySnapshot: false,
|
|
142
|
+
paths: ["."],
|
|
143
|
+
exclude: [],
|
|
144
|
+
excludeFile: [],
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
126
149
|
}
|
|
127
150
|
async restore(options) {
|
|
128
151
|
return await this.exec(["restore", "--json", options.id, "--target", options.target], {
|
|
@@ -18,6 +18,7 @@ declare type ResolveDatabaseNameParamsType = ResolvePackageParamsType & {
|
|
|
18
18
|
export declare function resolveDatabaseName(value: string, params: ResolveDatabaseNameParamsType): string;
|
|
19
19
|
declare type ResolvePackageParamsType = {
|
|
20
20
|
snapshotId: string;
|
|
21
|
+
snapshotDate: string;
|
|
21
22
|
action: "backup" | "restore";
|
|
22
23
|
};
|
|
23
24
|
export declare function resolvePackage(pkg: PackageConfigType, params: ResolvePackageParamsType): PackageConfigType;
|
|
@@ -25,6 +26,20 @@ export declare function resolvePackages(packages: PackageConfigType[], params: R
|
|
|
25
26
|
export declare const pkgPathParams: {
|
|
26
27
|
[name in "temp" | Exclude<keyof ResolvePackagePathParamsType, "path">]: string;
|
|
27
28
|
};
|
|
29
|
+
export declare const pkgIncludeParams: {
|
|
30
|
+
snapshotDate: string;
|
|
31
|
+
packageName: string;
|
|
32
|
+
temp: string;
|
|
33
|
+
snapshotId: string;
|
|
34
|
+
action: string;
|
|
35
|
+
};
|
|
36
|
+
export declare const pkgExcludeParams: {
|
|
37
|
+
snapshotDate: string;
|
|
38
|
+
packageName: string;
|
|
39
|
+
temp: string;
|
|
40
|
+
snapshotId: string;
|
|
41
|
+
action: string;
|
|
42
|
+
};
|
|
28
43
|
export declare const pkgRestorePathParams: {
|
|
29
44
|
[name in "temp" | keyof ResolvePackagePathParamsType]: string;
|
|
30
45
|
};
|
|
@@ -33,20 +48,37 @@ export declare const dbNameParams: {
|
|
|
33
48
|
};
|
|
34
49
|
export declare const params: {
|
|
35
50
|
pkgPath: {
|
|
51
|
+
snapshotDate: string;
|
|
36
52
|
packageName: string;
|
|
37
53
|
temp: string;
|
|
38
54
|
snapshotId: string;
|
|
39
55
|
action: string;
|
|
40
56
|
};
|
|
41
57
|
pkgRestorePath: {
|
|
58
|
+
snapshotDate: string;
|
|
42
59
|
packageName: string;
|
|
43
60
|
path: string;
|
|
44
61
|
temp: string;
|
|
45
62
|
snapshotId: string;
|
|
46
63
|
action: string;
|
|
47
64
|
};
|
|
65
|
+
pkgInclude: {
|
|
66
|
+
snapshotDate: string;
|
|
67
|
+
packageName: string;
|
|
68
|
+
temp: string;
|
|
69
|
+
snapshotId: string;
|
|
70
|
+
action: string;
|
|
71
|
+
};
|
|
72
|
+
pkgExclude: {
|
|
73
|
+
snapshotDate: string;
|
|
74
|
+
packageName: string;
|
|
75
|
+
temp: string;
|
|
76
|
+
snapshotId: string;
|
|
77
|
+
action: string;
|
|
78
|
+
};
|
|
48
79
|
dbName: {
|
|
49
80
|
snapshotId: string;
|
|
81
|
+
snapshotDate: string;
|
|
50
82
|
action: string;
|
|
51
83
|
packageName: string;
|
|
52
84
|
database: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.params = exports.dbNameParams = exports.pkgRestorePathParams = exports.pkgPathParams = exports.resolvePackages = exports.resolvePackage = exports.resolveDatabaseName = exports.resolvePackagePath = exports.filterPackages = exports.findRepositoryOrFail = void 0;
|
|
3
|
+
exports.params = exports.dbNameParams = exports.pkgRestorePathParams = exports.pkgExcludeParams = exports.pkgIncludeParams = exports.pkgPathParams = exports.resolvePackages = exports.resolvePackage = exports.resolveDatabaseName = exports.resolvePackagePath = exports.filterPackages = exports.findRepositoryOrFail = void 0;
|
|
4
4
|
const AppError_1 = require("../../Error/AppError");
|
|
5
5
|
const fs_util_1 = require("../fs-util");
|
|
6
6
|
const string_util_1 = require("../string-util");
|
|
@@ -53,6 +53,10 @@ function resolvePackage(pkg, params) {
|
|
|
53
53
|
packageName: pkg.name,
|
|
54
54
|
path: undefined,
|
|
55
55
|
};
|
|
56
|
+
if (pkg.include)
|
|
57
|
+
pkg.include = pkg.include.map((v) => typeof v === "string" ? (0, string_util_1.render)(v, pkgParams) : v);
|
|
58
|
+
if (pkg.exclude)
|
|
59
|
+
pkg.exclude = pkg.exclude.map((v) => typeof v === "string" ? (0, string_util_1.render)(v, pkgParams) : v);
|
|
56
60
|
if (pkg.path)
|
|
57
61
|
pkg.path = resolvePackagePath(pkg.path, pkgParams);
|
|
58
62
|
if (pkg.restorePath)
|
|
@@ -71,23 +75,30 @@ exports.pkgPathParams = {
|
|
|
71
75
|
action: "{action}",
|
|
72
76
|
packageName: "{packageName}",
|
|
73
77
|
snapshotId: "{snapshotId}",
|
|
78
|
+
snapshotDate: "{snapshotDate}",
|
|
74
79
|
temp: "{temp}",
|
|
75
80
|
};
|
|
81
|
+
exports.pkgIncludeParams = exports.pkgPathParams;
|
|
82
|
+
exports.pkgExcludeParams = exports.pkgPathParams;
|
|
76
83
|
exports.pkgRestorePathParams = {
|
|
77
84
|
action: "{action}",
|
|
78
85
|
packageName: "{packageName}",
|
|
79
86
|
path: "{path}",
|
|
80
87
|
snapshotId: "{snapshotId}",
|
|
88
|
+
snapshotDate: "{snapshotDate}",
|
|
81
89
|
temp: "{temp}",
|
|
82
90
|
};
|
|
83
91
|
exports.dbNameParams = {
|
|
84
92
|
action: "{action}",
|
|
85
93
|
packageName: "{packageName}",
|
|
86
94
|
snapshotId: "{snapshotId}",
|
|
95
|
+
snapshotDate: "{snapshotDate}",
|
|
87
96
|
database: "{database}",
|
|
88
97
|
};
|
|
89
98
|
exports.params = {
|
|
90
99
|
pkgPath: exports.pkgPathParams,
|
|
91
100
|
pkgRestorePath: exports.pkgRestorePathParams,
|
|
101
|
+
pkgInclude: exports.pkgIncludeParams,
|
|
102
|
+
pkgExclude: exports.pkgExcludeParams,
|
|
92
103
|
dbName: exports.dbNameParams,
|
|
93
104
|
};
|
package/util/fs-util.d.ts
CHANGED
|
@@ -23,6 +23,9 @@ export declare function readPartialFile(path: string, positions: [number, number
|
|
|
23
23
|
export declare function checkFile(path: string): Promise<boolean>;
|
|
24
24
|
export declare function checkDir(path: string): Promise<boolean>;
|
|
25
25
|
export declare function forEachFile(dirPath: string, cb: (path: string, dir: boolean) => void, includeDir?: boolean): Promise<void>;
|
|
26
|
+
export declare function writeGitIgnoreList(options: {
|
|
27
|
+
paths: NodeJS.ReadableStream | string[];
|
|
28
|
+
}): Promise<string>;
|
|
26
29
|
export declare function writePathLists(options: {
|
|
27
30
|
paths: NodeJS.ReadableStream | string[];
|
|
28
31
|
packs?: {
|
package/util/fs-util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.writePathLists = exports.forEachFile = exports.checkDir = exports.checkFile = exports.readPartialFile = exports.mkTmpDir = exports.tmpDir = exports.sessionTmpDir = exports.parentTmpDir = exports.existsFile = exports.findFile = exports.parsePackageFile = exports.parseFile = exports.parseFileExtensions = exports.readdirIfExists = exports.writeJSONFile = exports.existsDir = exports.ensureEmptyDir = exports.mkdirIfNotExists = exports.isDirEmpty = exports.isLocalDir = void 0;
|
|
3
|
+
exports.writePathLists = exports.writeGitIgnoreList = exports.forEachFile = exports.checkDir = exports.checkFile = exports.readPartialFile = exports.mkTmpDir = exports.tmpDir = exports.sessionTmpDir = exports.parentTmpDir = exports.existsFile = exports.findFile = exports.parsePackageFile = exports.parseFile = exports.parseFileExtensions = exports.readdirIfExists = exports.writeJSONFile = exports.existsDir = exports.ensureEmptyDir = exports.mkdirIfNotExists = exports.isDirEmpty = exports.isLocalDir = void 0;
|
|
4
4
|
const path_util_1 = require("./path-util");
|
|
5
5
|
const crypto_1 = require("crypto");
|
|
6
6
|
const fs_1 = require("fs");
|
|
@@ -190,6 +190,40 @@ async function forEachFile(dirPath, cb, includeDir) {
|
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
192
|
exports.forEachFile = forEachFile;
|
|
193
|
+
async function writeGitIgnoreList(options) {
|
|
194
|
+
const tempDir = await mkTmpDir("gitignore-list");
|
|
195
|
+
const path = (0, path_1.join)(tempDir, `.gitignore`);
|
|
196
|
+
const stream = (0, fs_2.createWriteStream)(path);
|
|
197
|
+
const dirs = new Set();
|
|
198
|
+
stream.write("*\n");
|
|
199
|
+
for await (const value of options.paths) {
|
|
200
|
+
const dir = (0, path_1.dirname)(value.toString());
|
|
201
|
+
if (dir !== ".") {
|
|
202
|
+
let parentPath;
|
|
203
|
+
for (const value of dir.split("/")) {
|
|
204
|
+
if (!parentPath) {
|
|
205
|
+
parentPath = `!${value}`;
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
parentPath += `/${value}`;
|
|
209
|
+
}
|
|
210
|
+
if (!dirs.has(parentPath)) {
|
|
211
|
+
stream.write(`${parentPath}\n`);
|
|
212
|
+
stream.write(`${parentPath.slice(1)}/*\n`);
|
|
213
|
+
dirs.add(parentPath);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
stream.write(`!${value}\n`);
|
|
218
|
+
}
|
|
219
|
+
await new Promise((resolve, reject) => {
|
|
220
|
+
stream.close();
|
|
221
|
+
stream.on("close", resolve);
|
|
222
|
+
stream.on("error", reject);
|
|
223
|
+
});
|
|
224
|
+
return path;
|
|
225
|
+
}
|
|
226
|
+
exports.writeGitIgnoreList = writeGitIgnoreList;
|
|
193
227
|
async function writePathLists(options) {
|
|
194
228
|
const tempDir = await mkTmpDir("path-lists");
|
|
195
229
|
const includedPaths = [];
|
package/util/string-util.js
CHANGED
|
@@ -21,7 +21,13 @@ function snakeCase(value, char = "_") {
|
|
|
21
21
|
}
|
|
22
22
|
exports.snakeCase = snakeCase;
|
|
23
23
|
function render(subject, vars) {
|
|
24
|
-
return subject.replace(/{(\w
|
|
24
|
+
return subject.replace(/{([\w/]*)}/g, function (match, name) {
|
|
25
|
+
if (!name.length) {
|
|
26
|
+
return "{";
|
|
27
|
+
}
|
|
28
|
+
else if (name === "/") {
|
|
29
|
+
return "}";
|
|
30
|
+
}
|
|
25
31
|
const value = vars[name];
|
|
26
32
|
if (typeof value === "undefined")
|
|
27
33
|
throw new AppError_1.AppError(`Variable is not defined: '${subject}' (${name})`);
|