@datatruck/cli 0.32.3 → 0.33.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.
Files changed (127) hide show
  1. package/config.schema.json +374 -31
  2. package/lib/{Action → actions}/BackupAction.d.ts +5 -17
  3. package/lib/{Action → actions}/BackupAction.js +32 -85
  4. package/lib/{Action → actions}/ConfigAction.d.ts +4 -2
  5. package/lib/{Action → actions}/ConfigAction.js +16 -8
  6. package/lib/{Action → actions}/CopyAction.d.ts +17 -13
  7. package/lib/actions/CopyAction.js +285 -0
  8. package/lib/{Action → actions}/InitAction.d.ts +1 -1
  9. package/lib/{Action → actions}/InitAction.js +3 -3
  10. package/lib/{Action → actions}/PruneAction.d.ts +1 -2
  11. package/lib/{Action → actions}/PruneAction.js +2 -2
  12. package/lib/{Action → actions}/RestoreAction.d.ts +4 -13
  13. package/lib/{Action → actions}/RestoreAction.js +17 -17
  14. package/lib/{Action → actions}/SnapshotsAction.d.ts +2 -3
  15. package/lib/{Action → actions}/SnapshotsAction.js +3 -3
  16. package/lib/cli.d.ts +3 -3
  17. package/lib/cli.js +18 -17
  18. package/lib/commands/BackupCommand.d.ts +43 -0
  19. package/lib/{Command → commands}/BackupCommand.js +7 -6
  20. package/lib/{Command → commands}/CleanCacheCommand.d.ts +4 -2
  21. package/lib/{Command → commands}/CleanCacheCommand.js +6 -5
  22. package/lib/{Command → commands}/CommandAbstract.d.ts +10 -6
  23. package/lib/{Command → commands}/CommandAbstract.js +5 -3
  24. package/lib/commands/ConfigCommand.d.ts +22 -0
  25. package/lib/{Command → commands}/ConfigCommand.js +5 -5
  26. package/lib/commands/CopyCommand.d.ts +17 -0
  27. package/lib/{Command → commands}/CopyCommand.js +7 -6
  28. package/lib/commands/InitCommand.d.ts +19 -0
  29. package/lib/{Command → commands}/InitCommand.js +9 -9
  30. package/lib/{Command → commands}/PruneCommand.d.ts +7 -4
  31. package/lib/{Command → commands}/PruneCommand.js +11 -11
  32. package/lib/commands/RestoreCommand.d.ts +38 -0
  33. package/lib/{Command → commands}/RestoreCommand.js +7 -6
  34. package/lib/{Command → commands}/SnapshotsCommand.d.ts +8 -6
  35. package/lib/{Command → commands}/SnapshotsCommand.js +12 -12
  36. package/lib/{Command → commands}/StartServerCommand.d.ts +4 -2
  37. package/lib/{Command → commands}/StartServerCommand.js +5 -5
  38. package/lib/index.d.ts +20 -23
  39. package/lib/index.js +8 -8
  40. package/lib/{Repository → repositories}/DatatruckRepository.js +2 -2
  41. package/lib/{Repository → repositories}/RepositoryAbstract.d.ts +7 -7
  42. package/lib/{Repository → repositories}/ResticRepository.js +7 -6
  43. package/lib/{Task → tasks}/MssqlTask.js +2 -2
  44. package/lib/{Task → tasks}/MysqlDumpTask.js +4 -4
  45. package/lib/{Task → tasks}/ScriptTask.d.ts +2 -2
  46. package/lib/{Task → tasks}/SqlDumpTaskAbstract.js +4 -4
  47. package/lib/{Task → tasks}/TaskAbstract.d.ts +4 -4
  48. package/lib/utils/DataFormat.js +3 -3
  49. package/lib/utils/Restic.d.ts +1 -0
  50. package/lib/utils/Restic.js +12 -2
  51. package/lib/utils/cli.d.ts +9 -3
  52. package/lib/utils/cli.js +17 -1
  53. package/lib/utils/cron.d.ts +11 -0
  54. package/lib/utils/cron.js +27 -0
  55. package/lib/utils/datatruck/command.d.ts +29 -0
  56. package/lib/utils/datatruck/command.js +61 -0
  57. package/lib/{Config/RepositoryConfig.d.ts → utils/datatruck/config-repository-type.d.ts} +19 -8
  58. package/lib/{Config/TaskConfig.d.ts → utils/datatruck/config-task-type.d.ts} +6 -6
  59. package/lib/utils/datatruck/config-type.d.ts +50 -0
  60. package/lib/utils/datatruck/config.d.ts +19 -10
  61. package/lib/utils/datatruck/config.js +43 -7
  62. package/lib/utils/datatruck/cron-server.d.ts +27 -6
  63. package/lib/utils/datatruck/cron-server.js +38 -20
  64. package/lib/utils/datatruck/paths.d.ts +2 -2
  65. package/lib/utils/datatruck/report-list.d.ts +12 -0
  66. package/lib/utils/datatruck/report-list.js +57 -0
  67. package/lib/utils/datatruck/repository-server.js +3 -2
  68. package/lib/utils/datatruck/repository.d.ts +16 -0
  69. package/lib/utils/datatruck/repository.js +30 -0
  70. package/lib/utils/datatruck/snapshot.d.ts +2 -2
  71. package/lib/utils/datatruck/task.d.ts +3 -0
  72. package/lib/{Factory/TaskFactory.js → utils/datatruck/task.js} +8 -8
  73. package/lib/utils/date.js +6 -2
  74. package/lib/utils/fs.d.ts +3 -0
  75. package/lib/utils/fs.js +24 -4
  76. package/lib/utils/list.d.ts +5 -5
  77. package/lib/utils/mysql.js +5 -5
  78. package/lib/utils/object.d.ts +13 -0
  79. package/lib/utils/object.js +32 -1
  80. package/lib/utils/process.js +4 -1
  81. package/lib/utils/string.d.ts +1 -0
  82. package/lib/utils/string.js +7 -3
  83. package/lib/utils/ts.d.ts +16 -0
  84. package/lib/utils/watcher.d.ts +10 -0
  85. package/lib/utils/watcher.js +34 -0
  86. package/package.json +3 -3
  87. package/lib/Action/CopyAction.js +0 -164
  88. package/lib/Command/BackupCommand.d.ts +0 -19
  89. package/lib/Command/ConfigCommand.d.ts +0 -15
  90. package/lib/Command/CopyCommand.d.ts +0 -16
  91. package/lib/Command/InitCommand.d.ts +0 -13
  92. package/lib/Command/RestoreCommand.d.ts +0 -17
  93. package/lib/Config/Config.d.ts +0 -28
  94. package/lib/Config/PackageConfig.d.ts +0 -24
  95. package/lib/Config/PackageRepositoryConfig.d.ts +0 -15
  96. package/lib/Config/PrunePolicyConfig.d.ts +0 -2
  97. package/lib/Config/RepositoryConfig.js +0 -2
  98. package/lib/Config/TaskConfig.js +0 -2
  99. package/lib/Factory/CommandFactory.d.ts +0 -45
  100. package/lib/Factory/CommandFactory.js +0 -96
  101. package/lib/Factory/RepositoryFactory.d.ts +0 -3
  102. package/lib/Factory/RepositoryFactory.js +0 -23
  103. package/lib/Factory/TaskFactory.d.ts +0 -3
  104. /package/lib/{Action → actions}/CleanCacheAction.d.ts +0 -0
  105. /package/lib/{Action → actions}/CleanCacheAction.js +0 -0
  106. /package/lib/{Repository → repositories}/DatatruckRepository.d.ts +0 -0
  107. /package/lib/{Repository → repositories}/GitRepository.d.ts +0 -0
  108. /package/lib/{Repository → repositories}/GitRepository.js +0 -0
  109. /package/lib/{Repository → repositories}/RepositoryAbstract.js +0 -0
  110. /package/lib/{Repository → repositories}/ResticRepository.d.ts +0 -0
  111. /package/lib/{Task → tasks}/GitTask.d.ts +0 -0
  112. /package/lib/{Task → tasks}/GitTask.js +0 -0
  113. /package/lib/{Task → tasks}/MariadbTask.d.ts +0 -0
  114. /package/lib/{Task → tasks}/MariadbTask.js +0 -0
  115. /package/lib/{Task → tasks}/MssqlTask.d.ts +0 -0
  116. /package/lib/{Task → tasks}/MysqlDumpTask.d.ts +0 -0
  117. /package/lib/{Task → tasks}/PostgresqlDumpTask.d.ts +0 -0
  118. /package/lib/{Task → tasks}/PostgresqlDumpTask.js +0 -0
  119. /package/lib/{Task → tasks}/ScriptTask.js +0 -0
  120. /package/lib/{Task → tasks}/SqlDumpTaskAbstract.d.ts +0 -0
  121. /package/lib/{Task → tasks}/TaskAbstract.js +0 -0
  122. /package/lib/{Config/Config.js → utils/datatruck/config-repository-type.js} +0 -0
  123. /package/lib/{Config/PackageConfig.js → utils/datatruck/config-task-type.js} +0 -0
  124. /package/lib/{Config/PackageRepositoryConfig.js → utils/datatruck/config-type.js} +0 -0
  125. /package/lib/{Error/AppError.d.ts → utils/datatruck/error.d.ts} +0 -0
  126. /package/lib/{Error/AppError.js → utils/datatruck/error.js} +0 -0
  127. /package/lib/{Config/PrunePolicyConfig.js → utils/ts.js} +0 -0
@@ -1,28 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createCronServer = void 0;
4
- const CommandFactory_1 = require("../../Factory/CommandFactory");
4
+ const ConfigAction_1 = require("../../actions/ConfigAction");
5
5
  const cli_1 = require("../cli");
6
+ const cron_1 = require("../cron");
6
7
  const process_1 = require("../process");
8
+ const string_1 = require("../string");
9
+ const watcher_1 = require("../watcher");
10
+ const command_1 = require("./command");
7
11
  const croner_1 = require("croner");
8
- function createJobs(actions, currentJobs = [], worker) {
12
+ function createJobs(actions, worker) {
9
13
  const jobs = [];
10
14
  for (const action of actions) {
11
15
  const index = actions.indexOf(action);
12
- const context = JSON.stringify({
13
- index: actions.indexOf(action),
14
- data: action,
15
- });
16
- const job = currentJobs.at(index);
17
- if (!job || job.options.context !== context) {
18
- job?.stop();
19
- jobs.push((0, croner_1.Cron)(action.schedule, {
20
- paused: true,
21
- context: JSON.stringify(action),
22
- catch: true,
23
- protect: true,
24
- }, () => worker(action, index)));
25
- }
16
+ jobs.push((0, croner_1.Cron)(typeof action.schedule === "string"
17
+ ? action.schedule
18
+ : (0, cron_1.formatCronScheduleObject)(action.schedule), {
19
+ paused: true,
20
+ context: index,
21
+ catch: true,
22
+ protect: true,
23
+ }, () => worker(action, index)));
26
24
  }
27
25
  return jobs;
28
26
  }
@@ -31,9 +29,9 @@ function createCronServer(options, config) {
31
29
  if (config.log)
32
30
  console.info(`> [job] ${index} - ${action.name}`);
33
31
  try {
34
- const Command = (0, CommandFactory_1.CommandConstructorFactory)(action.name);
32
+ const Command = command_1.datatruckCommandMap[action.name];
35
33
  const command = new Command({ config: { packages: [], repositories: [] } }, {});
36
- const cliOptions = (0, cli_1.stringifyOptions)(command.onOptions(), action.options);
34
+ const cliOptions = (0, cli_1.stringifyOptions)(command.optionsConfig(), action.options);
37
35
  const [node, bin] = process.argv;
38
36
  await (0, process_1.exec)(node, [bin, "-c", config.configPath, action.name, ...cliOptions], {}, { log: config.verbose });
39
37
  if (config.log)
@@ -44,16 +42,36 @@ function createCronServer(options, config) {
44
42
  console.error(`< [job] ${index} - ${action.name}`, error);
45
43
  }
46
44
  };
47
- const jobs = createJobs(options.actions || [], [], worker);
48
- return {
45
+ let jobs = createJobs(options.actions || [], worker);
46
+ const watcher = (0, watcher_1.createWatcher)({
47
+ onRead: () => ConfigAction_1.ConfigAction.findAndParseFile(config.configPath),
48
+ onCheck: (prev, current) => (0, string_1.compareJsons)(prev, current),
49
+ onError: (error) => {
50
+ if (config.log)
51
+ console.error(`< [jobs] update error`, error);
52
+ },
53
+ onChange: (data) => {
54
+ if (config.log)
55
+ console.info(`[jobs] updated`);
56
+ handler.stop();
57
+ const cron = data?.server?.cron;
58
+ const enabled = cron?.enabled ?? true;
59
+ jobs = enabled ? createJobs(cron?.actions || [], worker) : [];
60
+ handler.start();
61
+ },
62
+ });
63
+ const handler = {
49
64
  start: () => {
50
65
  for (const job of jobs)
51
66
  job.resume();
67
+ watcher.start();
52
68
  },
53
69
  stop: () => {
70
+ watcher.stop();
54
71
  for (const job of jobs)
55
72
  job.stop();
56
73
  },
57
74
  };
75
+ return handler;
58
76
  }
59
77
  exports.createCronServer = createCronServer;
@@ -1,6 +1,6 @@
1
- import { PackageConfig } from "../../Config/PackageConfig";
2
- import { PreSnapshot } from "../../Repository/RepositoryAbstract";
1
+ import { PreSnapshot } from "../../repositories/RepositoryAbstract";
3
2
  import { SpawnStep } from "../spawnSteps";
3
+ import type { PackageConfig } from "./config-type";
4
4
  export type ParsePathsOptions = {
5
5
  cwd?: string;
6
6
  verbose?: boolean;
@@ -0,0 +1,12 @@
1
+ import { Listr3, Listr3TaskResult, List3SummaryResult } from "../list";
2
+ import { DatatruckReportConfig } from "./config-type";
3
+ export type ReportListTaskContext = {
4
+ report: {
5
+ type: string;
6
+ };
7
+ };
8
+ export declare function createReportListTasks<T extends ReportListTaskContext>(list: Listr3<T>, options: {
9
+ reports: DatatruckReportConfig[];
10
+ onMessage: (result: (List3SummaryResult | Listr3TaskResult<T>)[], report: DatatruckReportConfig) => string;
11
+ verbose?: boolean;
12
+ }): import("listr2").ListrTask<any, any, any>[];
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createReportListTasks = void 0;
4
+ const reportSteps_1 = require("../reportSteps");
5
+ const spawnSteps_1 = require("../spawnSteps");
6
+ function createReportListTasks(list, options) {
7
+ return options.reports.map((report, index) => {
8
+ const reportIndex = index + 1;
9
+ return list.$task({
10
+ title: {
11
+ initial: `Send report ${reportIndex}`,
12
+ started: `Sending report ${reportIndex}`,
13
+ completed: `Report sent: ${reportIndex}`,
14
+ failed: `Report send failed: ${reportIndex}`,
15
+ },
16
+ key: "report",
17
+ keyIndex: index,
18
+ data: { type: report.run.type },
19
+ exitOnError: false,
20
+ run: async (task) => {
21
+ const result = list.getResult().filter((r) => r.key !== "report");
22
+ const success = result.every((r) => !r.error);
23
+ const enabled = !report.when ||
24
+ (report.when === "success" && success) ||
25
+ (report.when === "error" && !success);
26
+ if (!enabled)
27
+ return task.skip(`Report send skipped: ${reportIndex}`);
28
+ const message = options.onMessage(result, report);
29
+ if ((0, spawnSteps_1.isSpawnStep)(report.run)) {
30
+ await (0, spawnSteps_1.runSpawnSteps)(report.run, {
31
+ data: {
32
+ dtt: {
33
+ message,
34
+ result,
35
+ success,
36
+ },
37
+ },
38
+ verbose: options.verbose,
39
+ });
40
+ }
41
+ else if ((0, reportSteps_1.isReportStep)(report.run)) {
42
+ await (0, reportSteps_1.runReportSteps)(report.run, {
43
+ data: {
44
+ title: "DTT Backup",
45
+ message,
46
+ success,
47
+ },
48
+ });
49
+ }
50
+ else {
51
+ throw new Error(`Invalid step type: ${report.run.type}`);
52
+ }
53
+ },
54
+ });
55
+ });
56
+ }
57
+ exports.createReportListTasks = createReportListTasks;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createDatatruckRepositoryServer = exports.headerKey = void 0;
4
- const ConfigAction_1 = require("../../Action/ConfigAction");
4
+ const ConfigAction_1 = require("../../actions/ConfigAction");
5
5
  const http_1 = require("../http");
6
6
  const virtual_fs_1 = require("../virtual-fs");
7
7
  const fs_1 = require("fs");
@@ -67,7 +67,8 @@ function createDatatruckRepositoryServer(inOptions, config = {}) {
67
67
  return res.end();
68
68
  }
69
69
  const fileOptions = config.configPath
70
- ? (await ConfigAction_1.ConfigAction.parseFile(config.configPath)).server?.repository
70
+ ? (await ConfigAction_1.ConfigAction.findAndParseFile(config.configPath)).server
71
+ ?.repository
71
72
  : undefined;
72
73
  const options = fileOptions ?? inOptions;
73
74
  const backend = findRepositoryBackend(req, repository, options);
@@ -0,0 +1,16 @@
1
+ import { DatatruckRepository } from "../../repositories/DatatruckRepository";
2
+ import { GitRepository } from "../../repositories/GitRepository";
3
+ import type { RepositoryAbstract } from "../../repositories/RepositoryAbstract";
4
+ import { ResticRepository } from "../../repositories/ResticRepository";
5
+ import type { RepositoryConfig } from "./config-type";
6
+ declare const repoMap: {
7
+ git: typeof GitRepository;
8
+ restic: typeof ResticRepository;
9
+ datatruck: typeof DatatruckRepository;
10
+ };
11
+ export declare function getRepoConstructor(type: keyof typeof repoMap): {
12
+ new (config: RepositoryConfig): RepositoryAbstract<any>;
13
+ };
14
+ export declare function createRepo(repository: RepositoryConfig): RepositoryAbstract<any>;
15
+ export declare function createAndInitRepo(repository: RepositoryConfig, verbose?: boolean): Promise<RepositoryAbstract<any>>;
16
+ export {};
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAndInitRepo = exports.createRepo = exports.getRepoConstructor = void 0;
4
+ const DatatruckRepository_1 = require("../../repositories/DatatruckRepository");
5
+ const GitRepository_1 = require("../../repositories/GitRepository");
6
+ const ResticRepository_1 = require("../../repositories/ResticRepository");
7
+ const error_1 = require("./error");
8
+ const repoMap = {
9
+ [GitRepository_1.gitRepositoryName]: GitRepository_1.GitRepository,
10
+ [ResticRepository_1.resticRepositoryName]: ResticRepository_1.ResticRepository,
11
+ [DatatruckRepository_1.datatruckRepositoryName]: DatatruckRepository_1.DatatruckRepository,
12
+ };
13
+ function getRepoConstructor(type) {
14
+ const Constructor = repoMap[type];
15
+ if (!Constructor)
16
+ throw new error_1.AppError(`Invalid repository type: ${type}`);
17
+ return Constructor;
18
+ }
19
+ exports.getRepoConstructor = getRepoConstructor;
20
+ function createRepo(repository) {
21
+ const Constructor = getRepoConstructor(repository.type);
22
+ return new Constructor(repository);
23
+ }
24
+ exports.createRepo = createRepo;
25
+ async function createAndInitRepo(repository, verbose) {
26
+ const repo = createRepo(repository);
27
+ await repo.init({ options: { verbose } });
28
+ return repo;
29
+ }
30
+ exports.createAndInitRepo = createAndInitRepo;
@@ -1,5 +1,5 @@
1
- import { SnapshotGroupByType } from "../../Action/SnapshotsAction";
2
- import { Snapshot } from "../../Repository/RepositoryAbstract";
1
+ import { SnapshotGroupByType } from "../../actions/SnapshotsAction";
2
+ import { Snapshot } from "../../repositories/RepositoryAbstract";
3
3
  import { FilterByLastOptions } from "../date";
4
4
  export declare function groupAndFilter<TSnapshot extends Snapshot>(snapshots: TSnapshot[], groupKeys?: SnapshotGroupByType[], inFilter?: FilterByLastOptions | ((group: TSnapshot[]) => FilterByLastOptions | string)): {
5
5
  item: TSnapshot;
@@ -0,0 +1,3 @@
1
+ import type { TaskAbstract } from "../../tasks/TaskAbstract";
2
+ import type { TaskConfig } from "./config-type";
3
+ export declare function createTask(task: TaskConfig): TaskAbstract;
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createTask = void 0;
4
- const AppError_1 = require("../Error/AppError");
5
- const GitTask_1 = require("../Task/GitTask");
6
- const MariadbTask_1 = require("../Task/MariadbTask");
7
- const MssqlTask_1 = require("../Task/MssqlTask");
8
- const MysqlDumpTask_1 = require("../Task/MysqlDumpTask");
9
- const PostgresqlDumpTask_1 = require("../Task/PostgresqlDumpTask");
10
- const ScriptTask_1 = require("../Task/ScriptTask");
4
+ const GitTask_1 = require("../../tasks/GitTask");
5
+ const MariadbTask_1 = require("../../tasks/MariadbTask");
6
+ const MssqlTask_1 = require("../../tasks/MssqlTask");
7
+ const MysqlDumpTask_1 = require("../../tasks/MysqlDumpTask");
8
+ const PostgresqlDumpTask_1 = require("../../tasks/PostgresqlDumpTask");
9
+ const ScriptTask_1 = require("../../tasks/ScriptTask");
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 ?? {});
@@ -28,7 +28,7 @@ function createTask(task) {
28
28
  return new ScriptTask_1.ScriptTask(task.config ?? {});
29
29
  }
30
30
  else {
31
- throw new AppError_1.AppError(`Invalid task name: ${task["name"]}`);
31
+ throw new error_1.AppError(`Invalid task name: ${task["name"]}`);
32
32
  }
33
33
  }
34
34
  exports.createTask = createTask;
package/lib/utils/date.js CHANGED
@@ -27,7 +27,10 @@ function createFilterByLastOptions(keep) {
27
27
  exports.createFilterByLastOptions = createFilterByLastOptions;
28
28
  function filterByLast(items, options) {
29
29
  const filters = {
30
- last: { handler: (_, i) => i.toString(), value: options.last },
30
+ last: {
31
+ handler: (_, i) => i.toString(),
32
+ value: options.last,
33
+ },
31
34
  lastMinutely: {
32
35
  handler: (d) => d.format("YYYYMMDDHHmm"),
33
36
  value: options.lastMinutely,
@@ -53,7 +56,8 @@ function filterByLast(items, options) {
53
56
  let someFilter = false;
54
57
  for (const key in filters) {
55
58
  const object = filters[key];
56
- if (object?.value) {
59
+ if (object?.value ||
60
+ (key === "last" && typeof object?.value === "number")) {
57
61
  someFilter = true;
58
62
  }
59
63
  }
package/lib/utils/fs.d.ts CHANGED
@@ -18,6 +18,7 @@ export declare function existsDir(path: string): Promise<boolean>;
18
18
  export declare function existsFile(path: string): Promise<boolean>;
19
19
  export declare function writeJSONFile<T = any>(path: string, json: T): Promise<void>;
20
20
  export declare const parseFileExtensions: string[];
21
+ export declare function include(path: string): any;
21
22
  export declare function parseFile(path: string, jsKey?: string): Promise<any>;
22
23
  export declare function parsePackageFile(): {
23
24
  name: string;
@@ -41,6 +42,8 @@ export declare function waitForClose(stream: WriteStream | ReadStream): Promise<
41
42
  export declare function copyFileWithStreams(source: string, target: string): Promise<unknown>;
42
43
  export declare function updateFileStats(path: string, fileInfo: Stats): Promise<void>;
43
44
  export declare function isNotFoundError(error: unknown): boolean;
45
+ export declare function readTextFile(path: string): Promise<string>;
46
+ export declare function readTextFile(path: string, onlyIfExists: true): Promise<string | undefined>;
44
47
  export declare function cpy(options: {
45
48
  input: {
46
49
  type: "glob";
package/lib/utils/fs.js CHANGED
@@ -3,7 +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.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.isNotFoundError = exports.updateFileStats = exports.copyFileWithStreams = exports.waitForClose = exports.writeGitIgnoreList = exports.fastglobToGitIgnore = exports.forEachFile = exports.readDir = exports.readPartialFile = exports.fastFolderSizeAsync = exports.findFile = exports.parsePackageFile = exports.parseFile = 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;
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.waitForClose = 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
9
  const math_1 = require("./math");
@@ -20,6 +20,7 @@ const path_1 = require("path");
20
20
  const path_2 = require("path");
21
21
  const readline_1 = require("readline");
22
22
  const util_1 = require("util");
23
+ const yaml_1 = require("yaml");
23
24
  exports.isWSLSystem = (0, os_1.release)().includes("microsoft-standard-WSL");
24
25
  async function isEmptyDir(path) {
25
26
  const iterator = await (0, promises_1.opendir)(path);
@@ -87,6 +88,12 @@ async function writeJSONFile(path, json) {
87
88
  }
88
89
  exports.writeJSONFile = writeJSONFile;
89
90
  exports.parseFileExtensions = ["json", "js", "ts", "yaml", "yml"];
91
+ function include(path) {
92
+ path = (0, path_1.resolve)(path);
93
+ delete require.cache[path];
94
+ return require(path);
95
+ }
96
+ exports.include = include;
90
97
  async function parseFile(path, jsKey) {
91
98
  if (!(0, path_2.isAbsolute)(path))
92
99
  path = (0, path_1.join)(process.cwd(), path);
@@ -95,13 +102,13 @@ async function parseFile(path, jsKey) {
95
102
  $require("ts-node").register();
96
103
  if (path.endsWith(".yaml") || path.endsWith("yml")) {
97
104
  const contents = await (0, promises_1.readFile)(path);
98
- return require("yaml").parse(contents.toString());
105
+ return (0, yaml_1.parse)(contents.toString());
99
106
  }
100
107
  else if (path.endsWith(".json")) {
101
- return require(path);
108
+ return include(path);
102
109
  }
103
110
  else {
104
- const object = require(path);
111
+ const object = include(path);
105
112
  const value = jsKey ? object[jsKey] : object;
106
113
  return typeof value === "function" ? await value() : value;
107
114
  }
@@ -275,6 +282,19 @@ function isNotFoundError(error) {
275
282
  return error.code === "ENOENT";
276
283
  }
277
284
  exports.isNotFoundError = isNotFoundError;
285
+ async function readTextFile(path, onlyIfExists) {
286
+ let buffer;
287
+ try {
288
+ buffer = await (0, promises_1.readFile)(path);
289
+ }
290
+ catch (error) {
291
+ if (onlyIfExists && isNotFoundError(error))
292
+ return;
293
+ throw error;
294
+ }
295
+ return buffer.toString();
296
+ }
297
+ exports.readTextFile = readTextFile;
278
298
  async function cpy(options) {
279
299
  const stats = { paths: 0, files: 0, dirs: 0 };
280
300
  const dirs = new Set();
@@ -32,13 +32,13 @@ type List3TaskResultObject<K, D extends Record<string, any>> = {
32
32
  elapsed: number;
33
33
  error?: Error;
34
34
  };
35
- type SummaryResult = List3TaskResultObject<"summary", {
35
+ export type List3SummaryResult = List3TaskResultObject<"summary", {
36
36
  errors: number;
37
37
  }>;
38
38
  export type Listr3TaskResult<T extends Listr3Context> = {
39
39
  [K in keyof T]: List3TaskResultObject<K, T[K]>;
40
40
  }[keyof T];
41
- export type Listr3TaskResultEnd<T extends Listr3Context> = Listr3TaskResult<T> | SummaryResult;
41
+ export type Listr3TaskResultEnd<T extends Listr3Context> = Listr3TaskResult<T> | List3SummaryResult;
42
42
  export declare class Listr3<T extends Listr3Context> extends Listr<void, "default", "simple"> {
43
43
  readonly $options: {
44
44
  streams?: Streams;
@@ -58,9 +58,9 @@ export declare class Listr3<T extends Listr3Context> extends Listr<void, "defaul
58
58
  $task<K extends keyof T>(item: Listr3Task<T, K>): ListrTask;
59
59
  $tasks<K extends keyof T>(...items: (Listr3Task<T, K> | ListrTask | false)[]): ListrTask[];
60
60
  add(tasks: ListrTask<void, ListrGetRendererClassFromValue<"default">> | ListrTask<void, ListrGetRendererClassFromValue<"default">>[]): this;
61
- getSummaryResult(): SummaryResult;
62
- getResult(): (SummaryResult | Listr3TaskResult<T>)[];
61
+ getSummaryResult(): List3SummaryResult;
62
+ getResult(): (List3SummaryResult | Listr3TaskResult<T>)[];
63
63
  protected release(): void;
64
- exec(): Promise<(Listr3TaskResult<T> | SummaryResult)[]>;
64
+ exec(): Promise<(Listr3TaskResult<T> | List3SummaryResult)[]>;
65
65
  }
66
66
  export {};
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createMysqlCli = exports.assertDumpFile = void 0;
4
- const AppError_1 = require("../Error/AppError");
5
4
  const cli_1 = require("./cli");
5
+ const error_1 = require("./datatruck/error");
6
6
  const fs_1 = require("./fs");
7
7
  const process_1 = require("./process");
8
8
  const string_1 = require("./string");
@@ -32,12 +32,12 @@ async function assertDumpFile(path) {
32
32
  firstLine.startsWith("-- mariadb dump"));
33
33
  });
34
34
  if (!successHeader)
35
- throw new AppError_1.AppError("No start line found");
35
+ throw new error_1.AppError("No start line found");
36
36
  const successFooter = footerContents
37
37
  .split(/\r?\n/)
38
38
  .some((line) => line.trim().toLowerCase().startsWith("-- dump completed"));
39
39
  if (!successFooter)
40
- throw new AppError_1.AppError("No end line found (incomplete backup)");
40
+ throw new error_1.AppError("No end line found (incomplete backup)");
41
41
  }
42
42
  exports.assertDumpFile = assertDumpFile;
43
43
  async function createMysqlCli(options) {
@@ -223,7 +223,7 @@ async function createMysqlCli(options) {
223
223
  async function initSharedDir(sharedDir) {
224
224
  const secure_file_priv = await fetchVariable("secure_file_priv");
225
225
  if (secure_file_priv?.toUpperCase() === "NULL")
226
- throw new AppError_1.AppError("'secure_file_priv' is null in MySQL Server");
226
+ throw new error_1.AppError("'secure_file_priv' is null in MySQL Server");
227
227
  const dir = sharedDir ??
228
228
  secure_file_priv ??
229
229
  (await fetchVariable("tmpdir")) ??
@@ -241,7 +241,7 @@ async function createMysqlCli(options) {
241
241
  await sql.execute(`SELECT 1 INTO OUTFILE ${outFileVar}`);
242
242
  const exists = await (0, fs_1.existsFile)(outFile);
243
243
  if (!exists)
244
- throw new AppError_1.AppError(`MySQL shared dir is not reached: ${dir}`);
244
+ throw new error_1.AppError(`MySQL shared dir is not reached: ${dir}`);
245
245
  }
246
246
  finally {
247
247
  try {
@@ -4,4 +4,17 @@ export declare function getErrorProperties(error: Error): Record<string, string>
4
4
  type GroupByKeyParamType<TItem> = ((item: TItem) => string[] | string) | (keyof TItem)[] | keyof TItem;
5
5
  export declare function groupBy<TItem>(items: TItem[], keyOrCb: GroupByKeyParamType<TItem>): Record<string, TItem[]>;
6
6
  export declare function groupBy<TItem>(items: TItem[], keyOrCb: GroupByKeyParamType<TItem>, single: true): Record<string, TItem>;
7
+ export declare class StrictMap<K, V> {
8
+ readonly serializeKey: (params: K) => string;
9
+ constructor(serializeKey: (params: K) => string);
10
+ readonly map: Map<string, V | undefined>;
11
+ has(key: K): boolean;
12
+ get(key: K): NonNullable<V>;
13
+ set(key: K, value: V): void;
14
+ with(key: K): {
15
+ has: () => boolean;
16
+ get: () => NonNullable<V>;
17
+ set: (value: V) => void;
18
+ };
19
+ }
7
20
  export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.groupBy = exports.getErrorProperties = exports.omitProp = exports.merge = void 0;
3
+ exports.StrictMap = exports.groupBy = exports.getErrorProperties = 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)
@@ -56,3 +56,34 @@ function groupBy(items, keyOrCb, single) {
56
56
  }
57
57
  }
58
58
  exports.groupBy = groupBy;
59
+ class StrictMap {
60
+ serializeKey;
61
+ constructor(serializeKey) {
62
+ this.serializeKey = serializeKey;
63
+ }
64
+ map = new Map();
65
+ has(key) {
66
+ return this.map.has(this.serializeKey(key));
67
+ }
68
+ get(key) {
69
+ const stringKey = this.serializeKey(key);
70
+ const value = this.map.get(stringKey);
71
+ if (!value)
72
+ throw new Error(`Map key does not exist: ${stringKey}`);
73
+ return value;
74
+ }
75
+ set(key, value) {
76
+ const stringKey = this.serializeKey(key);
77
+ if (this.map.has(stringKey))
78
+ throw new Error(`Map key already exists: ${stringKey}`);
79
+ this.map.set(stringKey, value);
80
+ }
81
+ with(key) {
82
+ return {
83
+ has: () => this.has(key),
84
+ get: () => this.get(key),
85
+ set: (value) => this.set(key, value),
86
+ };
87
+ }
88
+ }
89
+ exports.StrictMap = StrictMap;
@@ -322,7 +322,10 @@ async function exec(command, argv = [], options = null, settings = {}) {
322
322
  rl.on("line", onData);
323
323
  rl.on("close", tryFinish);
324
324
  }
325
- else if (log[type] || settings[type]?.save || settings[type]?.onData) {
325
+ else if (log[type] ||
326
+ settings[type]?.save ||
327
+ settings[type]?.onData ||
328
+ (type === "stderr" && settings[type]?.toExitCode)) {
326
329
  p[type].on("data", onData);
327
330
  }
328
331
  }
@@ -17,4 +17,5 @@ export declare function endsWith(input: string, patterns: string[]): boolean;
17
17
  export declare function createMatchFilter(include?: string[], exclude?: string[]): (input: string) => boolean;
18
18
  export declare function checkMatch(subject: string | undefined, patterns: string[]): boolean;
19
19
  export declare function undefIfEmpty(input: string): string | undefined;
20
+ export declare function compareJsons(a: any, b: any): boolean;
20
21
  export {};
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.undefIfEmpty = exports.checkMatch = exports.createMatchFilter = exports.endsWith = exports.match = exports.makePathPatterns = exports.formatUri = exports.parseStringList = exports.render = exports.snakeCase = void 0;
4
- const AppError_1 = require("../Error/AppError");
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");
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()}`);
@@ -47,7 +47,7 @@ function parseStringList(value, validValues, defaultsValues) {
47
47
  if (validValues)
48
48
  for (const v of result)
49
49
  if (!validValues.includes(v))
50
- throw new AppError_1.AppError(`Invalid value: ${v}`);
50
+ throw new error_1.AppError(`Invalid value: ${v}`);
51
51
  return result;
52
52
  }
53
53
  exports.parseStringList = parseStringList;
@@ -105,3 +105,7 @@ function undefIfEmpty(input) {
105
105
  return input.length ? input : undefined;
106
106
  }
107
107
  exports.undefIfEmpty = undefIfEmpty;
108
+ function compareJsons(a, b) {
109
+ return JSON.stringify(a) === JSON.stringify(b);
110
+ }
111
+ exports.compareJsons = compareJsons;
@@ -0,0 +1,16 @@
1
+ export type DeepReadonly<T> = T extends (infer R)[] ? DeepReadonlyArray<R> : T extends Function ? T : T extends object ? DeepReadonlyObject<T> : T;
2
+ export interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {
3
+ }
4
+ export type DeepReadonlyObject<T> = {
5
+ readonly [P in keyof T]: DeepReadonly<T[P]>;
6
+ };
7
+ export type If<TResolved, T1, T2 = string> = TResolved extends true ? T1 : T2;
8
+ export type IfRequireKeys<TResolved, T1> = TResolved extends true ? RequiredKeys<T1> : T1;
9
+ export type Unwrap<T> = T extends Promise<infer U> ? U : T extends (...args: any) => Promise<infer U> ? U : T extends (...args: any) => infer U ? U : T;
10
+ export type RequiredKeys<T> = {
11
+ [K in keyof Required<T>]: T[K];
12
+ };
13
+ export type SimilarObject<T1> = {
14
+ [K in keyof T1]: unknown;
15
+ };
16
+ export {};
@@ -0,0 +1,10 @@
1
+ export declare function createWatcher<T = string>(options: {
2
+ onRead: () => Promise<T>;
3
+ onCheck?: (prev: T | undefined, current: T | undefined) => boolean;
4
+ onChange?: (data: T | undefined) => void;
5
+ onError?: (error: Error) => void;
6
+ interval?: number;
7
+ }): {
8
+ start: () => void;
9
+ stop: () => void;
10
+ };
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createWatcher = void 0;
4
+ function createWatcher(options) {
5
+ let prev;
6
+ let interval;
7
+ const onCheck = options.onCheck || ((prev, current) => prev === current);
8
+ const rutine = async (initial = false) => {
9
+ try {
10
+ let current = await options.onRead();
11
+ if (!onCheck(prev, current)) {
12
+ prev = current;
13
+ if (!initial)
14
+ options.onChange?.(current);
15
+ }
16
+ }
17
+ catch (error) {
18
+ options.onError?.(error);
19
+ }
20
+ };
21
+ return {
22
+ start: () => {
23
+ clearInterval(interval);
24
+ rutine(true).finally(() => {
25
+ interval = setInterval(rutine, options.interval ?? 5000);
26
+ });
27
+ },
28
+ stop: () => {
29
+ clearInterval(interval);
30
+ interval = undefined;
31
+ },
32
+ };
33
+ }
34
+ exports.createWatcher = createWatcher;