@datatruck/cli 0.34.3 → 0.34.5

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.
Files changed (48) hide show
  1. package/lib/actions/BackupAction.js +125 -39
  2. package/lib/actions/ConfigAction.js +1 -1
  3. package/lib/actions/CopyAction.js +110 -74
  4. package/lib/actions/InitAction.js +1 -1
  5. package/lib/actions/PruneAction.js +3 -2
  6. package/lib/actions/RestoreAction.d.ts +0 -2
  7. package/lib/actions/RestoreAction.js +131 -62
  8. package/lib/cli.js +1 -1
  9. package/lib/commands/StartServerCommand.js +2 -1
  10. package/lib/repositories/DatatruckRepository.d.ts +1 -1
  11. package/lib/repositories/DatatruckRepository.js +31 -18
  12. package/lib/repositories/GitRepository.js +11 -3
  13. package/lib/repositories/RepositoryAbstract.d.ts +2 -1
  14. package/lib/repositories/RepositoryAbstract.js +3 -1
  15. package/lib/repositories/ResticRepository.js +1 -1
  16. package/lib/tasks/GitTask.js +2 -1
  17. package/lib/tasks/MssqlTask.js +2 -2
  18. package/lib/tasks/MysqlDumpTask.js +1 -1
  19. package/lib/tasks/SqlDumpTaskAbstract.js +2 -2
  20. package/lib/utils/async-process.js +3 -2
  21. package/lib/utils/cli.js +10 -10
  22. package/lib/utils/data-format.js +3 -3
  23. package/lib/utils/datatruck/client.d.ts +7 -3
  24. package/lib/utils/datatruck/client.js +9 -2
  25. package/lib/utils/datatruck/command.js +1 -1
  26. package/lib/utils/datatruck/config.js +4 -4
  27. package/lib/utils/datatruck/report-list.js +2 -1
  28. package/lib/utils/datatruck/repository.d.ts +3 -3
  29. package/lib/utils/datatruck/repository.js +4 -4
  30. package/lib/utils/datatruck/task.js +1 -1
  31. package/lib/utils/{datatruck/error.d.ts → error.d.ts} +1 -1
  32. package/lib/utils/{datatruck/error.js → error.js} +2 -2
  33. package/lib/utils/fs.d.ts +2 -1
  34. package/lib/utils/fs.js +22 -3
  35. package/lib/utils/git.d.ts +5 -0
  36. package/lib/utils/git.js +10 -0
  37. package/lib/utils/list.d.ts +3 -1
  38. package/lib/utils/list.js +2 -3
  39. package/lib/utils/mysql.js +1 -1
  40. package/lib/utils/object.d.ts +1 -1
  41. package/lib/utils/object.js +1 -1
  42. package/lib/utils/progress.d.ts +8 -1
  43. package/lib/utils/progress.js +38 -5
  44. package/lib/utils/reportSteps.js +3 -2
  45. package/lib/utils/string.js +1 -1
  46. package/lib/utils/temp.d.ts +13 -10
  47. package/lib/utils/temp.js +47 -40
  48. package/package.json +1 -1
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.DataFormat = exports.dataFormats = void 0;
7
- const error_1 = require("./datatruck/error");
7
+ const error_1 = require("./error");
8
8
  const stream_1 = require("./stream");
9
9
  const tty_table_1 = __importDefault(require("tty-table"));
10
10
  const util_1 = require("util");
@@ -47,13 +47,13 @@ class DataFormat {
47
47
  }
48
48
  formatToTable() {
49
49
  if (!this.options.table)
50
- throw new Error(`Unsupported format: table`);
50
+ throw new error_1.AppError(`Unsupported format: table`);
51
51
  const table = (0, tty_table_1.default)(this.options.table.headers, this.options.table.rows(), {});
52
52
  return table.render();
53
53
  }
54
54
  formatToList() {
55
55
  if (!this.options.list)
56
- throw new Error(`Unsupported format: list`);
56
+ throw new error_1.AppError(`Unsupported format: list`);
57
57
  return this.options.list().join("\n");
58
58
  }
59
59
  log(format, options) {
@@ -2,10 +2,14 @@ import { DiskStats } from "../fs";
2
2
  import { BasicProgress } from "../progress";
3
3
  import { AbstractFs, FsOptions } from "../virtual-fs";
4
4
  export declare class RemoteFs extends AbstractFs {
5
- readonly options: FsOptions;
5
+ readonly options: FsOptions & {
6
+ verbose?: boolean;
7
+ };
6
8
  protected url: string;
7
9
  protected headers: Record<string, string>;
8
- constructor(options: FsOptions);
10
+ constructor(options: FsOptions & {
11
+ verbose?: boolean;
12
+ });
9
13
  isLocal(): boolean;
10
14
  protected fetchJson(name: string, params: any[]): Promise<any>;
11
15
  protected post(name: string, params: any[], data: string): Promise<void>;
@@ -28,4 +32,4 @@ export declare class RemoteFs extends AbstractFs {
28
32
  }>;
29
33
  }
30
34
  export declare function isRemoteBackend(backend: string): boolean;
31
- export declare function createFs(backend: string): AbstractFs;
35
+ export declare function createFs(backend: string, verbose: boolean | undefined): AbstractFs;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createFs = exports.isRemoteBackend = exports.RemoteFs = void 0;
4
+ const cli_1 = require("../cli");
4
5
  const http_1 = require("../http");
5
6
  const virtual_fs_1 = require("../virtual-fs");
6
7
  const repository_server_1 = require("./repository-server");
@@ -69,9 +70,13 @@ class RemoteFs extends virtual_fs_1.AbstractFs {
69
70
  await this.fetchJson("rmAll", [path]);
70
71
  }
71
72
  async fetchDiskStats(path) {
73
+ if (this.options.verbose)
74
+ (0, cli_1.logExec)("fs.fetchDiskStats", [path]);
72
75
  return await this.fetchJson("fetchDiskStats", [path]);
73
76
  }
74
77
  async upload(source, target) {
78
+ if (this.options.verbose)
79
+ (0, cli_1.logExec)("fs.upload", [source, target]);
75
80
  await (0, http_1.uploadFile)(`${this.url}/upload`, source, {
76
81
  headers: this.headers,
77
82
  query: {
@@ -80,6 +85,8 @@ class RemoteFs extends virtual_fs_1.AbstractFs {
80
85
  });
81
86
  }
82
87
  async download(source, target, options = {}) {
88
+ if (this.options.verbose)
89
+ (0, cli_1.logExec)("fs.download", [source, target]);
83
90
  return await (0, http_1.downloadFile)(`${this.url}/download`, target, {
84
91
  ...options,
85
92
  headers: this.headers,
@@ -92,9 +99,9 @@ function isRemoteBackend(backend) {
92
99
  return backend.startsWith("http:") || backend.startsWith("https:");
93
100
  }
94
101
  exports.isRemoteBackend = isRemoteBackend;
95
- function createFs(backend) {
102
+ function createFs(backend, verbose) {
96
103
  return isRemoteBackend(backend)
97
- ? new RemoteFs({ backend })
104
+ ? new RemoteFs({ backend, verbose })
98
105
  : new virtual_fs_1.LocalFs({ backend });
99
106
  }
100
107
  exports.createFs = createFs;
@@ -10,7 +10,7 @@ const PruneCommand_1 = require("../../commands/PruneCommand");
10
10
  const RestoreCommand_1 = require("../../commands/RestoreCommand");
11
11
  const SnapshotsCommand_1 = require("../../commands/SnapshotsCommand");
12
12
  const StartServerCommand_1 = require("../../commands/StartServerCommand");
13
- const error_1 = require("./error");
13
+ const error_1 = require("../error");
14
14
  const stream_1 = require("stream");
15
15
  exports.datatruckCommandMap = {
16
16
  config: ConfigCommand_1.ConfigCommand,
@@ -1,21 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.params = exports.dbNameParams = exports.pkgRestorePathParams = exports.pkgExcludeParams = exports.pkgIncludeParams = exports.pkgPathParams = exports.resolvePackages = exports.resolvePackage = exports.resolveDatabaseName = exports.resolvePackagePath = exports.filterPackages = exports.filterRepositoryByEnabled = exports.ensureSameRepositoryType = exports.sortReposByType = exports.filterRepository = exports.findPackageRepositoryConfig = exports.findPackageOrFail = exports.findRepositoryOrFail = void 0;
4
+ const error_1 = require("../error");
4
5
  const string_1 = require("../string");
5
6
  const temp_1 = require("../temp");
6
- const error_1 = require("./error");
7
7
  const micromatch_1 = require("micromatch");
8
8
  function findRepositoryOrFail(config, repositoryName) {
9
9
  const repo = config.repositories.find((v) => v.name === repositoryName);
10
10
  if (!repo)
11
- throw new error_1.AppError(`Repository '${repositoryName}' not found`);
11
+ throw new error_1.AppError(`Repository '${repositoryName}' not found in the config`);
12
12
  return repo;
13
13
  }
14
14
  exports.findRepositoryOrFail = findRepositoryOrFail;
15
15
  function findPackageOrFail(config, packageName) {
16
16
  const pkg = config.packages.find((v) => v.name === packageName);
17
17
  if (!pkg)
18
- throw new error_1.AppError(`Package '${packageName}' not found`);
18
+ throw new error_1.AppError(`Package '${packageName}' not found in the config`);
19
19
  return pkg;
20
20
  }
21
21
  exports.findPackageOrFail = findPackageOrFail;
@@ -59,7 +59,7 @@ function ensureSameRepositoryType(a, b) {
59
59
  if (a.type !== b.type) {
60
60
  const names = [a.name, b.name].join(" and ");
61
61
  const types = [a.type, b.type].join(" != ");
62
- throw new Error(`Incompatible repository types between ${names} (${types})`);
62
+ throw new error_1.AppError(`Incompatible repository types between ${names} (${types})`);
63
63
  }
64
64
  }
65
65
  exports.ensureSameRepositoryType = ensureSameRepositoryType;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createReportListTasks = void 0;
4
+ const error_1 = require("../error");
4
5
  const reportSteps_1 = require("../reportSteps");
5
6
  const spawnSteps_1 = require("../spawnSteps");
6
7
  function createReportListTasks(list, options) {
@@ -48,7 +49,7 @@ function createReportListTasks(list, options) {
48
49
  });
49
50
  }
50
51
  else {
51
- throw new Error(`Invalid step type: ${report.run.type}`);
52
+ throw new error_1.AppError(`Invalid step type: ${report.run.type}`);
52
53
  }
53
54
  },
54
55
  });
@@ -9,8 +9,8 @@ declare const repoMap: {
9
9
  datatruck: typeof DatatruckRepository;
10
10
  };
11
11
  export declare function getRepoConstructor(type: keyof typeof repoMap): {
12
- new (config: RepositoryConfig): RepositoryAbstract<any>;
12
+ new (config: RepositoryConfig, verbose?: boolean): RepositoryAbstract<any>;
13
13
  };
14
- export declare function createRepo(repository: RepositoryConfig): RepositoryAbstract<any>;
15
- export declare function createAndInitRepo(repository: RepositoryConfig, verbose?: boolean): Promise<RepositoryAbstract<any>>;
14
+ export declare function createRepo(repository: RepositoryConfig, verbose: boolean | undefined): RepositoryAbstract<any>;
15
+ export declare function createAndInitRepo(repository: RepositoryConfig, verbose: boolean | undefined): Promise<RepositoryAbstract<any>>;
16
16
  export {};
@@ -4,7 +4,7 @@ exports.createAndInitRepo = exports.createRepo = exports.getRepoConstructor = vo
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
- const error_1 = require("./error");
7
+ const error_1 = require("../error");
8
8
  const repoMap = {
9
9
  [GitRepository_1.gitRepositoryName]: GitRepository_1.GitRepository,
10
10
  [ResticRepository_1.resticRepositoryName]: ResticRepository_1.ResticRepository,
@@ -17,13 +17,13 @@ function getRepoConstructor(type) {
17
17
  return Constructor;
18
18
  }
19
19
  exports.getRepoConstructor = getRepoConstructor;
20
- function createRepo(repository) {
20
+ function createRepo(repository, verbose) {
21
21
  const Constructor = getRepoConstructor(repository.type);
22
- return new Constructor(repository);
22
+ return new Constructor(repository, verbose);
23
23
  }
24
24
  exports.createRepo = createRepo;
25
25
  async function createAndInitRepo(repository, verbose) {
26
- const repo = createRepo(repository);
26
+ const repo = createRepo(repository, verbose);
27
27
  await repo.init({ options: { verbose } });
28
28
  return repo;
29
29
  }
@@ -7,7 +7,7 @@ const MssqlTask_1 = require("../../tasks/MssqlTask");
7
7
  const MysqlDumpTask_1 = require("../../tasks/MysqlDumpTask");
8
8
  const PostgresqlDumpTask_1 = require("../../tasks/PostgresqlDumpTask");
9
9
  const ScriptTask_1 = require("../../tasks/ScriptTask");
10
- const error_1 = require("./error");
10
+ const error_1 = require("../error");
11
11
  function createTask(task) {
12
12
  if (task.name === GitTask_1.gitTaskName) {
13
13
  return new GitTask_1.GitTask(task.config ?? {});
@@ -1,4 +1,4 @@
1
1
  export declare class AppError extends Error {
2
- constructor(message: string);
2
+ constructor(message: string, options?: ErrorOptions);
3
3
  static create(message: string, errors: Error[]): Error;
4
4
  }
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AppError = void 0;
4
4
  class AppError extends Error {
5
- constructor(message) {
6
- super(message);
5
+ constructor(message, options) {
6
+ super(message, options);
7
7
  this.name = AppError.name;
8
8
  }
9
9
  static create(message, errors) {
package/lib/utils/fs.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
3
  /// <reference types="node" />
4
- import { Progress } from "./progress";
4
+ import { Progress, ProgressStats } from "./progress";
5
5
  import { Entry, Options } from "fast-glob";
6
6
  import { Stats } from "fs";
7
7
  import { WriteStream } from "fs";
@@ -90,6 +90,7 @@ type ProgressObject = {
90
90
  total: number;
91
91
  current: number;
92
92
  update: (description: string, path?: string, increment?: boolean) => void;
93
+ updateRelative: (description: string, path: string, stats: ProgressStats) => void;
93
94
  };
94
95
  export declare function createProgress(options: {
95
96
  onProgress: (data: Progress) => void;
package/lib/utils/fs.js CHANGED
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.asFile = exports.groupFiles = exports.ensureFreeDiskSpace = exports.checkFreeDiskSpace = exports.fetchDiskStats = exports.initEmptyDir = exports.tryRm = exports.safeRename = exports.fetchData = exports.countFileLines = exports.createWriteStreamPool = exports.createFileScanner = exports.createProgress = exports.cpy = exports.readTextFile = exports.isNotFoundError = exports.updateFileStats = exports.copyFileWithStreams = exports.writeGitIgnoreList = exports.fastglobToGitIgnore = exports.forEachFile = exports.readDir = exports.readPartialFile = exports.fastFolderSizeAsync = exports.findFile = exports.parsePackageFile = exports.parseFile = exports.include = exports.parseFileExtensions = exports.writeJSONFile = exports.existsFile = exports.existsDir = exports.safeStat = exports.ensureExistsDir = exports.ensureSingleFile = exports.ensureEmptyDir = exports.mkdirIfNotExists = exports.isLocalDir = exports.isEmptyDir = exports.isWSLSystem = void 0;
7
7
  const pkg_1 = require("../pkg");
8
8
  const bytes_1 = require("./bytes");
9
+ const error_1 = require("./error");
9
10
  const math_1 = require("./math");
10
11
  const stream_1 = require("./stream");
11
12
  const string_1 = require("./string");
@@ -53,20 +54,20 @@ async function mkdirIfNotExists(path) {
53
54
  exports.mkdirIfNotExists = mkdirIfNotExists;
54
55
  async function ensureEmptyDir(path) {
55
56
  if (!(await isEmptyDir(path)))
56
- throw new Error(`Dir is not empty: ${path}`);
57
+ throw new error_1.AppError(`Dir is not empty: ${path}`);
57
58
  }
58
59
  exports.ensureEmptyDir = ensureEmptyDir;
59
60
  async function ensureSingleFile(path) {
60
61
  const files = await readDir(path);
61
62
  if (files.length !== 1)
62
- throw new Error(`Dir has not one file: ${files.length}`);
63
+ throw new error_1.AppError(`Dir has not one file: ${files.length}`);
63
64
  const [file] = files;
64
65
  return (0, path_1.join)(path, file);
65
66
  }
66
67
  exports.ensureSingleFile = ensureSingleFile;
67
68
  async function ensureExistsDir(path) {
68
69
  if (!(await existsDir(path)))
69
- throw new Error(`Dir is not created: ${path}`);
70
+ throw new error_1.AppError(`Dir is not created: ${path}`);
70
71
  }
71
72
  exports.ensureExistsDir = ensureExistsDir;
72
73
  async function safeStat(path) {
@@ -399,11 +400,29 @@ function createProgress(options) {
399
400
  disposed: false,
400
401
  total: 0,
401
402
  current: 0,
403
+ updateRelative(description, path, stats) {
404
+ if (progress.disposed)
405
+ return;
406
+ options.onProgress({
407
+ relative: {
408
+ ...stats,
409
+ description,
410
+ payload: path,
411
+ },
412
+ absolute: {
413
+ total: progress.total,
414
+ current: progress.current,
415
+ percent: (0, math_1.progressPercent)(progress.total, progress.current),
416
+ },
417
+ });
418
+ },
402
419
  update: (description, path, increment = true) => {
403
420
  if (progress.disposed)
404
421
  return;
405
422
  if (path && increment)
406
423
  progress.current++;
424
+ if (path === "." || path === "./")
425
+ return;
407
426
  options.onProgress({
408
427
  relative: {
409
428
  description,
@@ -28,6 +28,11 @@ export declare class Git {
28
28
  removeAll(): Promise<void>;
29
29
  haveChanges(): Promise<boolean>;
30
30
  fetchCommitId(tag: string): Promise<string>;
31
+ commit(description: string, options?: {
32
+ allowEmpty?: boolean;
33
+ userName?: string;
34
+ userEmail?: string;
35
+ }): Promise<void>;
31
36
  getTags(names?: string[]): Promise<{
32
37
  name: string;
33
38
  message?: string | undefined;
package/lib/utils/git.js CHANGED
@@ -70,6 +70,16 @@ class Git {
70
70
  async fetchCommitId(tag) {
71
71
  return (await this.stdout(["rev-list", "-n", "1", tag])).trim();
72
72
  }
73
+ async commit(description, options = {}) {
74
+ await this.exec([
75
+ ...(options.userName ? ["-c", `user.name='${options.userName}'`] : []),
76
+ ...(options.userEmail ? ["-c", `user.email='${options.userEmail}'`] : []),
77
+ "commit",
78
+ "-m",
79
+ description,
80
+ ...(options.allowEmpty ? ["--allow-empty"] : []),
81
+ ]);
82
+ }
73
83
  async getTags(names) {
74
84
  const stdout = await this.stdout(["tag", "-n", ...(names ?? [])]);
75
85
  return stdout.split(/\r?\n/).reduce((result, value) => {
@@ -1,6 +1,7 @@
1
1
  import { Timer } from "./date";
2
2
  import { ProgressManager } from "./progress";
3
3
  import { StdStreams } from "./stream";
4
+ import { GargabeCollector } from "./temp";
4
5
  import { Listr, ListrGetRendererClassFromValue, ListrLogger, ListrTask, ListrTaskWrapper } from "listr2";
5
6
  export declare class List3Logger<Levels extends string = string> extends ListrLogger<Levels> {
6
7
  constructor(options?: {
@@ -19,7 +20,6 @@ type Listr3Task<T extends Listr3Context, K extends keyof T> = {
19
20
  failed?: string;
20
21
  completed?: string;
21
22
  };
22
- runWrapper?: (cb: () => any) => any;
23
23
  run: (task: ListrTaskWrapper<any, any, any>, data: T[K]) => Promise<void | ListrTask[] | Listr | undefined> | void | undefined | ListrTask[] | Listr;
24
24
  exitOnError?: boolean;
25
25
  enabled?: boolean;
@@ -43,6 +43,7 @@ export declare class Listr3<T extends Listr3Context> extends Listr<void, "defaul
43
43
  readonly $options: {
44
44
  streams?: StdStreams;
45
45
  progressManager?: ProgressManager;
46
+ gargabeCollector?: GargabeCollector;
46
47
  };
47
48
  readonly resultMap: Record<string, Listr3TaskResult<T>>;
48
49
  readonly resultList: Listr3TaskResult<T>[];
@@ -51,6 +52,7 @@ export declare class Listr3<T extends Listr3Context> extends Listr<void, "defaul
51
52
  constructor($options: {
52
53
  streams?: StdStreams;
53
54
  progressManager?: ProgressManager;
55
+ gargabeCollector?: GargabeCollector;
54
56
  });
55
57
  private serializeKeyIndex;
56
58
  private createResultIndex;
package/lib/utils/list.js CHANGED
@@ -89,9 +89,7 @@ class Listr3 extends listr2_1.Listr {
89
89
  const timer = (0, date_1.createTimer)();
90
90
  if (title)
91
91
  try {
92
- const runResult = item.runWrapper
93
- ? await item.runWrapper(async () => await item.run(task, result.data))
94
- : await item.run(task, result.data);
92
+ const runResult = await item.run(task, result.data);
95
93
  if (title.completed)
96
94
  task.title = title.completed;
97
95
  return Array.isArray(runResult)
@@ -153,6 +151,7 @@ class Listr3 extends listr2_1.Listr {
153
151
  throw error;
154
152
  }
155
153
  finally {
154
+ await this.$options.gargabeCollector?.dispose();
156
155
  dispose();
157
156
  }
158
157
  }
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createMysqlCli = exports.assertDumpFile = void 0;
4
4
  const async_process_1 = require("./async-process");
5
5
  const cli_1 = require("./cli");
6
- const error_1 = require("./datatruck/error");
6
+ const error_1 = require("./error");
7
7
  const fs_1 = require("./fs");
8
8
  const process_1 = require("./process");
9
9
  const string_1 = require("./string");
@@ -11,7 +11,7 @@ export declare class StrictMap<K, V> {
11
11
  has(key: K): boolean;
12
12
  get(key: K): NonNullable<V>;
13
13
  set(key: K, value: V): void;
14
- with(key: K): {
14
+ withKey(key: K): {
15
15
  has: () => boolean;
16
16
  get: () => NonNullable<V>;
17
17
  set: (value: V) => void;
@@ -78,7 +78,7 @@ class StrictMap {
78
78
  throw new Error(`Map key already exists: ${stringKey}`);
79
79
  this.map.set(stringKey, value);
80
80
  }
81
- with(key) {
81
+ withKey(key) {
82
82
  return {
83
83
  has: () => this.has(key),
84
84
  get: () => this.get(key),
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
2
3
  import { Timer } from "./date";
3
4
  export type BasicProgress = {
4
5
  percent: number;
@@ -35,6 +36,7 @@ export declare class ProgressManager {
35
36
  protected interval: Timer | undefined;
36
37
  protected intervalMs: number;
37
38
  protected keydownListener: ((data: Buffer | undefined) => void) | undefined;
39
+ protected pendingProgress: Progress | undefined;
38
40
  readonly tty: Exclude<ProgressTty, "auto">;
39
41
  readonly mode: Exclude<ProgressMode, "auto" | `interval:${number}`>;
40
42
  constructor(options: {
@@ -51,7 +53,12 @@ export declare class ProgressManager {
51
53
  elapsed(): number;
52
54
  start(): void;
53
55
  dispose(): void;
54
- update(progress: Progress, cb: (text: string) => void): void;
56
+ create(input: ((text: string) => void) | {
57
+ output: string;
58
+ }, delay?: number): Disposable & {
59
+ update: (progress: Progress) => void;
60
+ };
61
+ renderProgress(progress: Progress, force?: boolean): string | undefined;
55
62
  }
56
63
  export declare function renderProgress(progress: Progress, bar?: boolean): string[];
57
64
  export declare function renderProgressStats(stats: ProgressStats, progressBar?: boolean): string;
@@ -13,6 +13,7 @@ class ProgressManager {
13
13
  interval = (0, date_1.createTimer)();
14
14
  intervalMs;
15
15
  keydownListener;
16
+ pendingProgress;
16
17
  tty;
17
18
  mode;
18
19
  constructor(options) {
@@ -66,19 +67,51 @@ class ProgressManager {
66
67
  this.keydownListener = undefined;
67
68
  }
68
69
  }
69
- update(progress, cb) {
70
- if (!this.mode)
70
+ create(input, delay = 1000) {
71
+ const update = (progress, force) => {
72
+ const text = this.renderProgress(progress, force);
73
+ if (typeof text === "string") {
74
+ if (typeof input === "function") {
75
+ input(text);
76
+ }
77
+ else {
78
+ input.output = text;
79
+ }
80
+ }
81
+ };
82
+ const updatePending = () => {
83
+ const pendingProgress = this.pendingProgress;
84
+ if (pendingProgress) {
85
+ this.pendingProgress = undefined;
86
+ update(pendingProgress, true);
87
+ }
88
+ };
89
+ const interval = setInterval(updatePending, delay);
90
+ return {
91
+ update,
92
+ [Symbol.dispose]: () => {
93
+ clearInterval(interval);
94
+ updatePending();
95
+ },
96
+ };
97
+ }
98
+ renderProgress(progress, force = false) {
99
+ if (!this.mode) {
71
100
  return;
72
- if (this.mode === "interval") {
101
+ }
102
+ else if (this.mode === "interval") {
73
103
  if (this.interval) {
74
- if (!this.interval.reset(this.intervalMs))
104
+ if (!this.interval.reset(this.intervalMs) && !force) {
105
+ this.pendingProgress = progress;
75
106
  return;
107
+ }
76
108
  }
77
109
  else {
78
110
  this.interval = (0, date_1.createTimer)();
79
111
  }
80
112
  }
81
- cb(renderProgress(progress, this.tty).join("\n"));
113
+ this.pendingProgress = undefined;
114
+ return renderProgress(progress, this.tty).join("\n");
82
115
  }
83
116
  }
84
117
  exports.ProgressManager = ProgressManager;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runReportSteps = exports.isReportStep = void 0;
4
+ const error_1 = require("./error");
4
5
  const http_1 = require("./http");
5
6
  function isReportStep(step) {
6
7
  return step.type === "telegram" || step.type === "ntfy";
@@ -25,7 +26,7 @@ async function runReportSteps(input, options) {
25
26
  .filter(Boolean)
26
27
  .join("-");
27
28
  if (topic.length < 32)
28
- throw new Error(`Topic is less than 32 characters: ${topic}`);
29
+ throw new error_1.AppError(`'step.config.topic' is less than 32 characters: ${topic}`);
29
30
  await (0, http_1.post)(`https://ntfy.sh/${topic}`, options.data.message, {
30
31
  headers: {
31
32
  Title: options.data.title,
@@ -34,7 +35,7 @@ async function runReportSteps(input, options) {
34
35
  });
35
36
  }
36
37
  else {
37
- throw new Error(`Invalid step type: ${step.type}`);
38
+ throw new error_1.AppError(`Invalid step type: ${step.type}`);
38
39
  }
39
40
  }
40
41
  }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.compareJsons = exports.undefIfEmpty = exports.checkMatch = exports.createMatchFilter = exports.endsWith = exports.match = exports.makePathPatterns = exports.formatUri = exports.parseStringList = exports.render = exports.snakeCase = void 0;
4
- const error_1 = require("./datatruck/error");
4
+ const error_1 = require("./error");
5
5
  const micromatch_1 = require("micromatch");
6
6
  function snakeCase(value, char = "_") {
7
7
  return value.replace(/[A-Z]/g, (letter) => `${char}${letter.toLowerCase()}`);
@@ -5,6 +5,7 @@ export declare function ensureFreeDiskTempSpace(size: number | string): Promise<
5
5
  export declare function isTmpDir(path: string): boolean;
6
6
  export declare function rmTmpDir(input: string | string[]): Promise<void>;
7
7
  export declare function tmpDir(...keys: [string, ...string[]]): string;
8
+ export declare const collectors: Set<GargabeCollector>;
8
9
  export declare function mkTmpDir(...keys: [string, ...string[]]): Promise<string>;
9
10
  export declare function useTempDir(...keys: [string, ...string[]]): Promise<AsyncDisposable & {
10
11
  path: string;
@@ -12,15 +13,17 @@ export declare function useTempDir(...keys: [string, ...string[]]): Promise<Asyn
12
13
  export declare function useTempFile(path: string): AsyncDisposable & {
13
14
  path: string;
14
15
  };
15
- export declare class CleanupListener {
16
- readonly paths: string[];
17
- stop(): void;
18
- dispose(): Promise<void>;
19
- }
20
16
  export declare class GargabeCollector {
21
- protected listeners: Set<CleanupListener>;
22
- get pending(): boolean;
23
- cleanup(cb?: () => any): Promise<void>;
24
- cleanupOnFinish(cb: () => any): Promise<void>;
25
- cleanupIfFail(cb: () => any): Promise<CleanupListener>;
17
+ protected parent?: GargabeCollector | undefined;
18
+ readonly paths: Set<string>;
19
+ readonly children: Set<GargabeCollector>;
20
+ constructor(parent?: GargabeCollector | undefined);
21
+ pending(): boolean;
22
+ cleanup(): Promise<void>;
23
+ dispose(): Promise<void>;
24
+ disposeIfFail<T>(cb: () => Promise<T>): Promise<T>;
25
+ disposeOnFinish(): {
26
+ [Symbol.asyncDispose]: () => Promise<void>;
27
+ };
28
+ create(): GargabeCollector;
26
29
  }