@datatruck/cli 0.11.5 → 0.12.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.
@@ -11,6 +11,7 @@ export declare type RestoreActionOptionsType = {
11
11
  tags?: string[];
12
12
  packageNames?: string[];
13
13
  packageTaskNames?: string[];
14
+ packageConfig?: boolean;
14
15
  repositoryNames?: string[];
15
16
  repositoryTypes?: string[];
16
17
  verbose?: boolean;
@@ -9,6 +9,7 @@ const config_util_1 = require("../util/datatruck/config-util");
9
9
  const fs_util_1 = require("../util/fs-util");
10
10
  const object_util_1 = require("../util/object-util");
11
11
  const process_util_1 = require("../util/process-util");
12
+ const SnapshotsAction_1 = require("./SnapshotsAction");
12
13
  const assert_1 = require("assert");
13
14
  const os_1 = require("os");
14
15
  class RestoreAction {
@@ -26,8 +27,9 @@ class RestoreAction {
26
27
  }
27
28
  async init(session, snapshotId, snapshots) {
28
29
  await session.initDrivers();
29
- for (const [, pkg] of snapshots) {
30
- (0, assert_1.ok)(pkg);
30
+ for (const [snapshot, pkg] of snapshots) {
31
+ if (!pkg)
32
+ throw new AppError_1.AppError(`Package config not found: ${snapshot.packageName}`);
31
33
  const sessionId = await session.init({
32
34
  snapshotId: snapshotId,
33
35
  packageName: pkg.name,
@@ -56,17 +58,22 @@ class RestoreAction {
56
58
  if (this.options.repositoryTypes &&
57
59
  !this.options.repositoryTypes.includes(repository.type))
58
60
  continue;
59
- const repoInstance = (0, RepositoryFactory_1.RepositoryFactory)(repository);
60
- const snapshots = await repoInstance.onSnapshots({
61
- options: {
62
- packageNames: this.options.packageNames,
63
- packageTaskNames: this.options.packageTaskNames,
64
- ids: [this.options.snapshotId],
65
- tags: this.options.tags,
66
- },
61
+ const snapshotsAction = new SnapshotsAction_1.SnapshotsAction(this.config, {
62
+ repositoryNames: [repository.name],
63
+ ids: [this.options.snapshotId],
64
+ packageNames: this.options.packageNames,
65
+ packageTaskNames: this.options.packageTaskNames,
66
+ packageConfig: this.options.packageConfig,
67
+ tags: this.options.tags,
67
68
  });
68
- result.push(...snapshots.map((snapshot) => ({
69
- ...snapshot,
69
+ const snapshots = await snapshotsAction.exec("restore");
70
+ result.push(...snapshots.map((ss) => ({
71
+ date: ss.date,
72
+ id: ss.id,
73
+ originalId: ss.originalId,
74
+ packageName: ss.packageName,
75
+ packageTaskName: ss.packageTaskName,
76
+ tags: ss.tags,
70
77
  repositoryName: repository.name,
71
78
  })));
72
79
  }
@@ -8,6 +8,7 @@ export declare type SnapshotsActionOptionsType = {
8
8
  repositoryNames?: string[];
9
9
  packageNames?: string[];
10
10
  packageTaskNames?: string[];
11
+ packageConfig?: boolean;
11
12
  repositoryTypes?: string[];
12
13
  verbose?: boolean;
13
14
  tags?: string[];
@@ -23,12 +23,17 @@ class SnapshotsAction {
23
23
  !this.options.repositoryTypes.includes(repo.type))
24
24
  continue;
25
25
  const repoInstance = (0, RepositoryFactory_1.RepositoryFactory)(repo);
26
+ const configPackageNames = this.config.packages.map((pkg) => pkg.name);
27
+ const packageNames = this.options.packageNames?.filter((name) => configPackageNames.includes(name)) || configPackageNames;
26
28
  const snapshots = await repoInstance.onSnapshots({
27
- options: this.options,
29
+ options: {
30
+ ...this.options,
31
+ packageNames,
32
+ },
28
33
  });
29
- const extentedItems = snapshots.map((item) => ({
30
- ...item,
31
- shortId: item.id.slice(0, 8),
34
+ const extentedItems = snapshots.map((ss) => ({
35
+ ...ss,
36
+ shortId: ss.id.slice(0, 8),
32
37
  repositoryName: repo.name,
33
38
  repositoryType: repo.type,
34
39
  }));
@@ -17,27 +17,27 @@ class BackupCommand extends CommandAbstract_1.CommandAbstract {
17
17
  option: "--dryRun",
18
18
  },
19
19
  package: {
20
- description: "Package names",
20
+ description: "Filter by package names",
21
21
  option: "-p,--package <values>",
22
22
  parser: string_util_1.parseStringList,
23
23
  },
24
24
  packageTask: {
25
- description: "Package task names",
25
+ description: "Filter by package task names",
26
26
  option: "-pt,--package-task <values>",
27
27
  parser: string_util_1.parseStringList,
28
28
  },
29
29
  repository: {
30
- description: "Repository names",
30
+ description: "Filter by repository names",
31
31
  option: "-r,--repository <values>",
32
32
  parser: string_util_1.parseStringList,
33
33
  },
34
34
  repositoryType: {
35
- description: "Repository types",
35
+ description: "Filter by repository types",
36
36
  option: "-rt,--repository-type <values>",
37
37
  parser: (v) => (0, string_util_1.parseStringList)(v),
38
38
  },
39
39
  tag: {
40
- description: "Tags",
40
+ description: "Filter by tags",
41
41
  option: "-t,--tag <values>",
42
42
  parser: string_util_1.parseStringList,
43
43
  },
@@ -13,17 +13,17 @@ class BackupSessionsCommand extends CommandAbstract_1.CommandAbstract {
13
13
  onOptions() {
14
14
  return this.returnsOptions({
15
15
  package: {
16
- description: "Package names",
16
+ description: "Filter by package names",
17
17
  option: "-p,--package <values>",
18
18
  parser: string_util_1.parseStringList,
19
19
  },
20
20
  repository: {
21
- description: "Repository names",
21
+ description: "Filter by repository names",
22
22
  option: "-r,--repository <values>",
23
23
  parser: string_util_1.parseStringList,
24
24
  },
25
25
  tag: {
26
- description: "Tags",
26
+ description: "Filter by tags",
27
27
  option: "-t,--tag <values>",
28
28
  parser: string_util_1.parseStringList,
29
29
  },
@@ -10,22 +10,22 @@ class ConfigCommand extends CommandAbstract_1.CommandAbstract {
10
10
  onOptions() {
11
11
  return this.returnsOptions({
12
12
  package: {
13
- description: "Package names",
13
+ description: "Filter by package names",
14
14
  option: "-p,--package <values>",
15
15
  parser: string_util_1.parseStringList,
16
16
  },
17
17
  packageTask: {
18
- description: "Package task names",
18
+ description: "Filter by package task names",
19
19
  option: "-pt,--package-task <values>",
20
20
  parser: string_util_1.parseStringList,
21
21
  },
22
22
  repository: {
23
- description: "Repository names",
23
+ description: "Filter by repository names",
24
24
  option: "-r,--repository <values>",
25
25
  parser: string_util_1.parseStringList,
26
26
  },
27
27
  repositoryType: {
28
- description: "Repository types",
28
+ description: "Filter by repository types",
29
29
  option: "-rt,--repository-type <values>",
30
30
  parser: (v) => (0, string_util_1.parseStringList)(v),
31
31
  },
@@ -12,12 +12,12 @@ class InitCommand extends CommandAbstract_1.CommandAbstract {
12
12
  onOptions() {
13
13
  return this.returnsOptions({
14
14
  repository: {
15
- description: "Repository names",
15
+ description: "Filter by repository names",
16
16
  option: "-r,--repository <values>",
17
17
  parser: string_util_1.parseStringList,
18
18
  },
19
19
  repositoryType: {
20
- description: "Repository types",
20
+ description: "Filter by repository types",
21
21
  option: "-rt,--repository-type <values>",
22
22
  parser: (v) => (0, string_util_1.parseStringList)(v),
23
23
  },
@@ -26,7 +26,7 @@ class PruneCommand extends CommandAbstract_1.CommandAbstract {
26
26
  ]),
27
27
  },
28
28
  id: {
29
- description: "Snapshot id.",
29
+ description: "Filter by snapshot id",
30
30
  option: "-i,--id",
31
31
  parser: string_util_1.parseStringList,
32
32
  },
@@ -70,22 +70,22 @@ class PruneCommand extends CommandAbstract_1.CommandAbstract {
70
70
  option: "--longId",
71
71
  },
72
72
  package: {
73
- description: "Package names",
73
+ description: "Filter by package names",
74
74
  option: "-p,--package <values>",
75
75
  parser: string_util_1.parseStringList,
76
76
  },
77
77
  repository: {
78
- description: "Repository names",
78
+ description: "Filter by repository names",
79
79
  option: "-r,--repository <values>",
80
80
  parser: string_util_1.parseStringList,
81
81
  },
82
82
  repositoryType: {
83
- description: "Repository types",
83
+ description: "Filter by repository types",
84
84
  option: "-rt,--repository-type <values>",
85
85
  parser: (v) => (0, string_util_1.parseStringList)(v),
86
86
  },
87
87
  tag: {
88
- description: "Tags",
88
+ description: "Filter by tags",
89
89
  option: "-t,--tag <values>",
90
90
  parser: string_util_1.parseStringList,
91
91
  },
@@ -5,6 +5,7 @@ export declare type RestoreCommandOptionsType<TResolved = false> = {
5
5
  id: string;
6
6
  package?: If<TResolved, string[]>;
7
7
  packageTask?: If<TResolved, string[]>;
8
+ packageConfig?: boolean;
8
9
  repository?: If<TResolved, string[]>;
9
10
  repositoryType?: If<TResolved, RepositoryConfigType["type"][]>;
10
11
  tag?: If<TResolved, string[]>;
@@ -12,32 +12,36 @@ class RestoreCommand extends CommandAbstract_1.CommandAbstract {
12
12
  onOptions() {
13
13
  return this.returnsOptions({
14
14
  id: {
15
- description: "Snapshot id",
15
+ description: "Filter by snapshot id",
16
16
  option: "-i,--id <id>",
17
17
  required: true,
18
18
  },
19
19
  package: {
20
- description: "Package names",
20
+ description: "Filter by package names",
21
21
  option: "-p,--package <values>",
22
22
  parser: string_util_1.parseStringList,
23
23
  },
24
24
  packageTask: {
25
- description: "Package task names",
25
+ description: "Filter by package task names",
26
26
  option: "-pt,--package-task <values>",
27
27
  parser: string_util_1.parseStringList,
28
28
  },
29
+ packageConfig: {
30
+ description: "Filter by package config",
31
+ option: "-pc,--package-config",
32
+ },
29
33
  repository: {
30
- description: "Repository names",
34
+ description: "Filter by repository names",
31
35
  option: "-r,--repository <values>",
32
36
  parser: string_util_1.parseStringList,
33
37
  },
34
38
  repositoryType: {
35
- description: "Repository types",
39
+ description: "Filter by repository types",
36
40
  option: "-rt,--repository-type <values>",
37
41
  parser: (v) => (0, string_util_1.parseStringList)(v),
38
42
  },
39
43
  tag: {
40
- description: "Tags",
44
+ description: "Filter by tags",
41
45
  option: "-t,--tag <values>",
42
46
  parser: string_util_1.parseStringList,
43
47
  },
@@ -50,6 +54,7 @@ class RestoreCommand extends CommandAbstract_1.CommandAbstract {
50
54
  snapshotId: this.options.id,
51
55
  packageNames: this.options.package,
52
56
  packageTaskNames: this.options.packageTask,
57
+ packageConfig: this.options.packageConfig,
53
58
  repositoryNames: this.options.repository,
54
59
  repositoryTypes: this.options.repositoryType,
55
60
  tags: this.options.tag,
@@ -13,17 +13,17 @@ class RestoreSessionsCommand extends CommandAbstract_1.CommandAbstract {
13
13
  onOptions() {
14
14
  return this.returnsOptions({
15
15
  package: {
16
- description: "Package names",
16
+ description: "Filter by package names",
17
17
  option: "-p,--package <values>",
18
18
  parser: string_util_1.parseStringList,
19
19
  },
20
20
  repository: {
21
- description: "Repository names",
21
+ description: "Filter by repository names",
22
22
  option: "-r,--repository <values>",
23
23
  parser: string_util_1.parseStringList,
24
24
  },
25
25
  tag: {
26
- description: "Tags",
26
+ description: "Filter by tags",
27
27
  option: "-t,--tag <values>",
28
28
  parser: string_util_1.parseStringList,
29
29
  },
@@ -6,6 +6,7 @@ export declare type SnapshotsCommandOptionsType<TResolved = false> = {
6
6
  id?: If<TResolved, string[]>;
7
7
  package?: If<TResolved, string[]>;
8
8
  packageTask?: If<TResolved, string[]>;
9
+ packageConfig?: boolean;
9
10
  repository?: If<TResolved, string[]>;
10
11
  repositoryType?: If<TResolved, RepositoryConfigType["type"][]>;
11
12
  longId?: boolean;
@@ -15,72 +15,76 @@ class SnapshotsCommand extends CommandAbstract_1.CommandAbstract {
15
15
  description: `Group by values (${groupByValues.join(", ")})`,
16
16
  parser: (v) => (0, string_util_1.parseStringList)(v, groupByValues),
17
17
  },
18
+ longId: {
19
+ option: "--longId",
20
+ description: "Show long id",
21
+ },
18
22
  id: {
19
23
  option: "-i,--id <ids>",
20
- description: "Snapshot identifiers",
24
+ description: "Filter by identifiers",
21
25
  parser: string_util_1.parseStringList,
22
26
  },
23
27
  last: {
24
28
  option: "-l,--last <number>",
25
- description: "Last snapshots",
29
+ description: "Filter by last snapshots",
26
30
  parser: Number,
27
31
  },
28
32
  lastMinutely: {
29
33
  option: "--lastMinutely <number>",
30
- description: "Last minutely snapshots",
34
+ description: "Filter by last minutely",
31
35
  parser: Number,
32
36
  },
33
37
  lastDaily: {
34
38
  option: "--lastDaily <number>",
35
- description: "Last daily snapshots",
39
+ description: "Filter by last daily",
36
40
  parser: Number,
37
41
  },
38
42
  lastHourly: {
39
43
  option: "--lastHourly <number>",
40
- description: "Last hourly snapshots",
44
+ description: "Filter by last hourly",
41
45
  parser: Number,
42
46
  },
43
47
  lastMonthly: {
44
48
  option: "--lastMonthly <number>",
45
- description: "Last monthly snapshots",
49
+ description: "Filter by last monthly",
46
50
  parser: Number,
47
51
  },
48
52
  lastWeekly: {
49
53
  option: "--lastWeekly <number>",
50
- description: "Last weekly snapshots",
54
+ description: "Filter by last weekly",
51
55
  parser: Number,
52
56
  },
53
57
  lastYearly: {
54
58
  option: "--lastYearly <number>",
55
- description: "Last yearly snapshots",
59
+ description: "Filter by last yearly",
56
60
  parser: Number,
57
61
  },
58
- longId: {
59
- option: "--longId",
60
- description: "Show long id",
61
- },
62
62
  package: {
63
63
  option: "-p,--package <names>",
64
- description: "Package names",
64
+ description: "Filter by package names",
65
65
  parser: string_util_1.parseStringList,
66
66
  },
67
67
  packageTask: {
68
- description: "Package task names",
69
68
  option: "-pt,--package-task <values>",
69
+ description: "Filter by task names",
70
70
  parser: string_util_1.parseStringList,
71
71
  },
72
+ packageConfig: {
73
+ description: "Filter by package config",
74
+ option: "-pc,--package-config",
75
+ },
72
76
  repository: {
73
77
  option: "-r,--repository <names>",
74
- description: "Repository names",
78
+ description: "Filter by repository names",
75
79
  parser: string_util_1.parseStringList,
76
80
  },
77
81
  repositoryType: {
78
- option: "-t,--repositoryType <names>",
79
- description: "Repository types",
82
+ option: "-rt,--repository-type <names>",
83
+ description: "Filter by repository types",
80
84
  parser: (v) => (0, string_util_1.parseStringList)(v),
81
85
  },
82
86
  tag: {
83
- description: "Tags",
87
+ description: "Filter by tags",
84
88
  option: "-t,--tag <values>",
85
89
  parser: string_util_1.parseStringList,
86
90
  },
@@ -93,6 +97,7 @@ class SnapshotsCommand extends CommandAbstract_1.CommandAbstract {
93
97
  ids: this.options.id,
94
98
  packageNames: this.options.package,
95
99
  packageTaskNames: this.options.packageTask,
100
+ packageConfig: this.options.packageConfig,
96
101
  repositoryNames: this.options.repository,
97
102
  repositoryTypes: this.options.repositoryType,
98
103
  last: this.options.last,
@@ -55,7 +55,19 @@ exports.resticRepositoryDefinition = {
55
55
  },
56
56
  host: { type: "string" },
57
57
  username: { type: "string" },
58
- passwordFile: { type: "string" },
58
+ password: {
59
+ anyOf: [
60
+ { type: "string" },
61
+ {
62
+ type: "object",
63
+ additionalProperties: false,
64
+ required: ["path"],
65
+ properties: {
66
+ path: { type: "string" },
67
+ },
68
+ },
69
+ ],
70
+ },
59
71
  port: { type: "integer" },
60
72
  path: { type: "string" },
61
73
  },
@@ -184,7 +196,7 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
184
196
  step: "Writing excluded paths list...",
185
197
  });
186
198
  const tmpDir = await (0, fs_util_1.mkTmpDir)("restic-exclude");
187
- const ignoredContents = (0, fs_util_1.fastglobToGitIgnore)(exclude).join("\n");
199
+ const ignoredContents = (0, fs_util_1.fastglobToGitIgnore)(exclude, sourcePath).join("\n");
188
200
  gitignorePath = (0, path_1.join)(tmpDir, "ignored.txt");
189
201
  await (0, promises_1.writeFile)(gitignorePath, ignoredContents);
190
202
  }
@@ -565,8 +565,24 @@
565
565
  "username": {
566
566
  "type": "string"
567
567
  },
568
- "passwordFile": {
569
- "type": "string"
568
+ "password": {
569
+ "anyOf": [
570
+ {
571
+ "type": "string"
572
+ },
573
+ {
574
+ "type": "object",
575
+ "additionalProperties": false,
576
+ "required": [
577
+ "path"
578
+ ],
579
+ "properties": {
580
+ "path": {
581
+ "type": "string"
582
+ }
583
+ }
584
+ }
585
+ ]
570
586
  },
571
587
  "port": {
572
588
  "type": "integer"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datatruck/cli",
3
- "version": "0.11.5",
3
+ "version": "0.12.0",
4
4
  "dependencies": {
5
5
  "ajv": "^8.11.0",
6
6
  "async": "^3.2.4",
@@ -3,9 +3,11 @@ import { UriType } from "./string-util";
3
3
  export declare type RepositoryType = {
4
4
  name?: string;
5
5
  env?: Record<string, string>;
6
- passwordFile?: string;
6
+ password?: string | {
7
+ path: string;
8
+ };
7
9
  backend: "local" | "rest" | "sftp" | "s3" | "azure" | "gs" | "rclone";
8
- } & UriType;
10
+ } & Omit<UriType, "password">;
9
11
  export declare type BackupStreamType = {
10
12
  message_type: "status";
11
13
  seconds_elapsed: number;
@@ -16,12 +16,15 @@ class ResticUtil {
16
16
  throw new Error(`Invalid path at "${input.name}" repository: ${input.path}`);
17
17
  return (0, path_1.resolve)(input.path);
18
18
  }
19
- if (input.passwordFile)
19
+ if (input.password) {
20
20
  input = {
21
21
  ...input,
22
- password: (await (0, promises_1.readFile)(input.passwordFile)).toString(),
22
+ password: typeof input.password === "string"
23
+ ? input.password
24
+ : (await (0, promises_1.readFile)(input.password.path)).toString(),
23
25
  };
24
- return `${input.backend}:${(0, string_util_1.formatUri)(input, hidePassword)}`;
26
+ }
27
+ return `${input.backend}:${(0, string_util_1.formatUri)({ ...input, password: input.password }, hidePassword)}`;
25
28
  }
26
29
  async exec(args, settings, options) {
27
30
  return await (0, process_util_1.exec)("restic", args, {
package/util/fs-util.d.ts CHANGED
@@ -32,7 +32,7 @@ export declare function forEachFile(dirPath: string, cb: (path: string, dir: boo
32
32
  /**
33
33
  * @experimental
34
34
  */
35
- export declare function fastglobToGitIgnore(patterns: string[]): string[];
35
+ export declare function fastglobToGitIgnore(patterns: string[], baseDir: string): string[];
36
36
  export declare function writeGitIgnoreList(options: {
37
37
  paths: NodeJS.ReadableStream | string[];
38
38
  }): Promise<string>;
package/util/fs-util.js CHANGED
@@ -216,10 +216,10 @@ exports.forEachFile = forEachFile;
216
216
  /**
217
217
  * @experimental
218
218
  */
219
- function fastglobToGitIgnore(patterns) {
219
+ function fastglobToGitIgnore(patterns, baseDir) {
220
220
  // https://github.com/mrmlnc/fast-glob#readme
221
221
  // https://git-scm.com/docs/gitignore
222
- return patterns.map((p) => (p.startsWith("/") ? p : `/${p}`));
222
+ return patterns.map((p) => `${baseDir}/${p}`);
223
223
  }
224
224
  exports.fastglobToGitIgnore = fastglobToGitIgnore;
225
225
  async function writeGitIgnoreList(options) {