@datatruck/cli 0.33.0 → 0.34.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.
Files changed (48) hide show
  1. package/config.schema.json +3 -0
  2. package/lib/actions/BackupAction.d.ts +8 -2
  3. package/lib/actions/BackupAction.js +22 -8
  4. package/lib/actions/CopyAction.d.ts +4 -1
  5. package/lib/actions/CopyAction.js +15 -4
  6. package/lib/commands/BackupCommand.d.ts +2 -0
  7. package/lib/repositories/DatatruckRepository.d.ts +6 -2
  8. package/lib/repositories/DatatruckRepository.js +11 -3
  9. package/lib/repositories/GitRepository.d.ts +6 -2
  10. package/lib/repositories/GitRepository.js +8 -3
  11. package/lib/repositories/RepositoryAbstract.d.ts +6 -2
  12. package/lib/repositories/ResticRepository.d.ts +6 -2
  13. package/lib/repositories/ResticRepository.js +11 -5
  14. package/lib/tasks/GitTask.js +32 -50
  15. package/lib/tasks/MariadbTask.js +43 -56
  16. package/lib/tasks/MssqlTask.js +5 -11
  17. package/lib/tasks/MysqlDumpTask.js +4 -4
  18. package/lib/tasks/PostgresqlDumpTask.d.ts +1 -1
  19. package/lib/tasks/PostgresqlDumpTask.js +9 -32
  20. package/lib/tasks/SqlDumpTaskAbstract.d.ts +1 -2
  21. package/lib/tasks/SqlDumpTaskAbstract.js +1 -1
  22. package/lib/utils/Git.d.ts +9 -7
  23. package/lib/utils/Git.js +30 -29
  24. package/lib/utils/Restic.d.ts +11 -11
  25. package/lib/utils/Restic.js +72 -90
  26. package/lib/utils/async-process.d.ts +66 -0
  27. package/lib/utils/async-process.js +237 -0
  28. package/lib/utils/async.d.ts +3 -5
  29. package/lib/utils/async.js +2 -2
  30. package/lib/utils/datatruck/client.d.ts +3 -1
  31. package/lib/utils/datatruck/client.js +1 -1
  32. package/lib/utils/datatruck/config-type.d.ts +1 -0
  33. package/lib/utils/datatruck/cron-server.js +2 -2
  34. package/lib/utils/datatruck/report-list.d.ts +2 -0
  35. package/lib/utils/datatruck/report-list.js +1 -1
  36. package/lib/utils/fs.d.ts +7 -2
  37. package/lib/utils/fs.js +0 -1
  38. package/lib/utils/http.d.ts +3 -1
  39. package/lib/utils/http.js +6 -1
  40. package/lib/utils/mysql.d.ts +8 -10
  41. package/lib/utils/mysql.js +60 -79
  42. package/lib/utils/process.d.ts +3 -92
  43. package/lib/utils/process.js +7 -311
  44. package/lib/utils/spawnSteps.js +9 -10
  45. package/lib/utils/tar.js +29 -49
  46. package/lib/utils/virtual-fs.d.ts +6 -2
  47. package/lib/utils/virtual-fs.js +4 -1
  48. package/package.json +2 -2
package/lib/utils/http.js CHANGED
@@ -90,6 +90,7 @@ exports.post = post;
90
90
  async function downloadFile(url, output, options = {}) {
91
91
  const timeout = options.timeout ?? 3600 * 1000; // 60m
92
92
  const file = (0, fs_1.createWriteStream)(output);
93
+ let total = 0;
93
94
  await new Promise((resolve, reject) => {
94
95
  const req = request(href(url, options.query), {
95
96
  headers: options.headers,
@@ -97,7 +98,7 @@ async function downloadFile(url, output, options = {}) {
97
98
  const contentLength = res.headers["content-length"] ?? "";
98
99
  if (!/^\d+$/.test(contentLength))
99
100
  return reject(new Error(`Invalid 'content-length': ${contentLength}`));
100
- const total = Number(contentLength);
101
+ total = Number(contentLength);
101
102
  let current = 0;
102
103
  if (res.statusCode === 200) {
103
104
  if (options.onProgress) {
@@ -145,6 +146,10 @@ async function downloadFile(url, output, options = {}) {
145
146
  });
146
147
  req.end();
147
148
  });
149
+ const { size: bytes } = await (0, promises_1.stat)(output);
150
+ if (total !== bytes)
151
+ throw new Error(`Invalid download size: ${total} != ${bytes}`);
152
+ return { bytes };
148
153
  }
149
154
  exports.downloadFile = downloadFile;
150
155
  async function uploadFile(url, path, options = {}) {
@@ -1,5 +1,4 @@
1
1
  /// <reference types="node" />
2
- import { ChildProcess } from "child_process";
3
2
  export type MysqlCliOptions = {
4
3
  password: string | {
5
4
  path: string;
@@ -15,7 +14,6 @@ export declare function createMysqlCli(options: MysqlCliOptions): Promise<{
15
14
  options: MysqlCliOptions;
16
15
  initSharedDir: (sharedDir?: string) => Promise<string>;
17
16
  args: () => Promise<string[]>;
18
- run: (query: string, database?: string, extra?: string[], onSpawn?: ((p: ChildProcess) => void) | undefined) => Promise<import("./process").ExecResult>;
19
17
  execute: (query: string, params?: any[]) => Promise<void>;
20
18
  insert: (tableName: string, item: Record<string, any>) => Promise<void>;
21
19
  changeDatabase: (name: string) => Promise<void>;
@@ -25,18 +23,18 @@ export declare function createMysqlCli(options: MysqlCliOptions): Promise<{
25
23
  database: string;
26
24
  items?: string[] | undefined;
27
25
  onlyStoredPrograms?: boolean | undefined;
28
- onSpawn?: ((p: ChildProcess) => void) | undefined;
26
+ controller?: AbortController | undefined;
29
27
  onProgress?: ((data: {
30
28
  totalBytes: number;
31
29
  }) => void) | undefined;
32
- }) => Promise<[void, import("./process").ExecResult]>;
30
+ }) => Promise<void>;
33
31
  assertDumpFile: typeof assertDumpFile;
34
32
  fetchTableNames: (database: string, include?: string[], exclude?: string[]) => Promise<string[]>;
35
33
  importFile: (input: {
36
34
  path: string;
37
35
  database: string;
38
- onSpawn?: ((p: ChildProcess) => void) | undefined;
39
- }) => Promise<import("./process").ExecResult>;
36
+ controller?: AbortController;
37
+ }) => Promise<void>;
40
38
  isDatabaseEmpty: (database: string) => Promise<boolean>;
41
39
  createDatabase: (database: {
42
40
  name: string;
@@ -45,14 +43,14 @@ export declare function createMysqlCli(options: MysqlCliOptions): Promise<{
45
43
  csvDump: (input: {
46
44
  database: string;
47
45
  sharedPath: string;
48
- items?: string[] | undefined;
49
- onSpawn?: ((p: ChildProcess) => void) | undefined;
46
+ items?: string[];
47
+ controller?: AbortController;
50
48
  }) => Promise<void>;
51
49
  importCsvFile: (input: {
52
50
  path: string;
53
51
  database: string;
54
52
  table: string;
55
- onSpawn?: ((p: ChildProcess) => void) | undefined;
56
- }) => Promise<import("./process").ExecResult>;
53
+ controller?: AbortController;
54
+ }) => Promise<void>;
57
55
  fetchVariable: (name: string) => Promise<string | undefined>;
58
56
  }>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createMysqlCli = exports.assertDumpFile = void 0;
4
+ const async_process_1 = require("./async-process");
4
5
  const cli_1 = require("./cli");
5
6
  const error_1 = require("./datatruck/error");
6
7
  const fs_1 = require("./fs");
@@ -8,7 +9,6 @@ const process_1 = require("./process");
8
9
  const string_1 = require("./string");
9
10
  const temp_1 = require("./temp");
10
11
  const crypto_1 = require("crypto");
11
- const fs_2 = require("fs");
12
12
  const promises_1 = require("fs/promises");
13
13
  const promise_1 = require("mysql2/promise");
14
14
  const os_1 = require("os");
@@ -68,22 +68,6 @@ async function createMysqlCli(options) {
68
68
  async function args() {
69
69
  return [`--defaults-file=${await createSqlConfig()}`];
70
70
  }
71
- async function run(query, database, extra = [], onSpawn) {
72
- return await (0, process_1.exec)("mysql", [
73
- ...(await args()),
74
- ...(database ? [database] : []),
75
- ...(extra || []),
76
- "-e",
77
- flatQuery(query),
78
- "-N",
79
- "--silent",
80
- ], undefined, {
81
- onSpawn,
82
- log: options.verbose,
83
- stderr: { toExitCode: true },
84
- stdout: { save: true },
85
- });
86
- }
87
71
  async function fetchAll(query, params) {
88
72
  const [rows] = await sql.query(query, params);
89
73
  return rows;
@@ -103,46 +87,35 @@ async function createMysqlCli(options) {
103
87
  .filter((0, string_1.createMatchFilter)(include, exclude));
104
88
  }
105
89
  async function dump(input) {
106
- const stream = (0, fs_2.createWriteStream)(input.output);
107
- return await Promise.all([
108
- new Promise((resolve, reject) => {
109
- stream.on("close", resolve);
110
- stream.on("error", reject);
111
- }),
112
- await (0, process_1.exec)("mysqldump", [
113
- ...(await args()),
114
- input.database,
115
- "--lock-tables=false",
116
- "--skip-add-drop-table=false",
117
- ...(input.onlyStoredPrograms
118
- ? [
119
- "--routines",
120
- "--events",
121
- "--skip-triggers",
122
- "--no-create-info",
123
- "--no-data",
124
- "--no-create-db",
125
- "--skip-opt",
126
- ]
127
- : []),
128
- ...(input.items || []),
129
- ], null, {
130
- stderr: { toExitCode: true },
131
- onSpawn: input.onSpawn,
132
- pipe: {
133
- stream,
134
- onWriteProgress: input.onProgress,
135
- },
136
- log: {
137
- exec: options.verbose,
138
- stderr: options.verbose,
139
- allToStderr: true,
140
- },
141
- }),
142
- ]);
90
+ const process = new async_process_1.AsyncProcess("mysqldump", [
91
+ ...(await args()),
92
+ input.database,
93
+ "--lock-tables=false",
94
+ "--skip-add-drop-table=false",
95
+ ...(input.onlyStoredPrograms
96
+ ? [
97
+ "--routines",
98
+ "--events",
99
+ "--skip-triggers",
100
+ "--no-create-info",
101
+ "--no-data",
102
+ "--no-create-db",
103
+ "--skip-opt",
104
+ ]
105
+ : []),
106
+ ...(input.items || []),
107
+ ], {
108
+ $controller: input.controller,
109
+ $log: {
110
+ exec: options.verbose,
111
+ stderr: options.verbose,
112
+ allToStderr: true,
113
+ },
114
+ });
115
+ await process.stdout.pipe(input.output, input.onProgress);
143
116
  }
144
117
  async function csvDump(input) {
145
- await (0, process_1.exec)("mysqldump", [
118
+ const process = new async_process_1.AsyncProcess("mysqldump", [
146
119
  ...(await args()),
147
120
  input.database,
148
121
  "--lock-tables=false",
@@ -152,18 +125,18 @@ async function createMysqlCli(options) {
152
125
  "-T",
153
126
  input.sharedPath,
154
127
  ...(input.items || []),
155
- ], null, {
156
- stderr: { toExitCode: true },
157
- onSpawn: input.onSpawn,
158
- log: {
128
+ ], {
129
+ $controller: input.controller,
130
+ $log: {
159
131
  exec: options.verbose,
160
132
  stderr: options.verbose,
161
133
  allToStderr: true,
162
134
  },
163
135
  });
136
+ await process.waitForClose();
164
137
  }
165
138
  async function importFile(input) {
166
- return await (0, process_1.exec)("mysql", [
139
+ const process = new async_process_1.AsyncProcess("mysql", [
167
140
  ...(await args()),
168
141
  `--init-command=SET ${[
169
142
  "autocommit=0",
@@ -171,30 +144,39 @@ async function createMysqlCli(options) {
171
144
  "foreign_key_checks=0",
172
145
  ].join(",")};`,
173
146
  input.database,
174
- ], null, {
175
- onSpawn: input.onSpawn,
176
- pipe: {
177
- stream: (0, fs_2.createReadStream)(input.path),
178
- onReadProgress: (data) => {
179
- if (options.verbose)
180
- (0, process_1.logExecStdout)({
181
- data: JSON.stringify(data),
182
- colorize: true,
183
- stderr: true,
184
- lineSalt: true,
185
- });
186
- },
187
- },
188
- stderr: { toExitCode: true },
189
- log: options.verbose,
147
+ ], {
148
+ $log: options.verbose,
149
+ $controller: input.controller,
190
150
  });
151
+ await process.stdin.pipe(input.path, options.verbose
152
+ ? (data) => (0, process_1.logStdout)({
153
+ data: JSON.stringify(data),
154
+ colorize: true,
155
+ stderr: true,
156
+ lineSalt: true,
157
+ })
158
+ : undefined);
191
159
  }
192
160
  async function importCsvFile(input) {
193
- return run(`
161
+ const query = `
194
162
  LOAD DATA LOCAL INFILE ${JSON.stringify(input.path.replaceAll("\\", "/"))}
195
163
  INTO TABLE ${input.table}
196
164
  FIELDS TERMINATED BY '\\t'
197
- LINES TERMINATED BY '\\n'`, input.database, ["--local-infile"], input.onSpawn);
165
+ LINES TERMINATED BY '\\n'
166
+ `;
167
+ const process = new async_process_1.AsyncProcess("mysql", [
168
+ ...(await args()),
169
+ input.database,
170
+ "--local-infile",
171
+ "-e",
172
+ flatQuery(query),
173
+ "-N",
174
+ "--silent",
175
+ ], {
176
+ $controller: input.controller,
177
+ $log: options.verbose,
178
+ });
179
+ await process.waitForClose();
198
180
  }
199
181
  async function isDatabaseEmpty(database) {
200
182
  const [row] = await fetchAll(`
@@ -278,7 +260,6 @@ async function createMysqlCli(options) {
278
260
  options,
279
261
  initSharedDir,
280
262
  args,
281
- run,
282
263
  execute,
283
264
  insert,
284
265
  changeDatabase,
@@ -1,85 +1,15 @@
1
1
  /// <reference types="node" />
2
- /// <reference types="node" />
3
- /// <reference types="node" />
4
- import { SpawnOptions, ChildProcess, ChildProcessByStdio } from "child_process";
5
- import { ReadStream, WriteStream } from "fs";
6
2
  import { Readable, Writable } from "stream";
7
3
  export type ProcessEnv = {
8
4
  [name: string]: string | undefined;
9
5
  };
10
- export type ExecLogSettings = {
11
- colorize?: boolean;
12
- exec?: boolean;
13
- stdout?: boolean;
14
- stderr?: boolean;
15
- allToStderr?: boolean;
16
- envNames?: string[];
17
- };
18
- export interface ExecSettingsInterface {
19
- exec?: boolean;
20
- pipe?: {
21
- stream: WriteStream;
22
- onWriteProgress?: (data: {
23
- totalBytes: number;
24
- }) => void;
25
- } | {
26
- stream: ReadStream;
27
- onReadProgress?: (data: {
28
- totalBytes: number;
29
- currentBytes: number;
30
- progress: number;
31
- }) => void;
32
- } | {
33
- stream: Readable;
34
- };
35
- log?: ExecLogSettings | boolean;
36
- onSpawn?: (p: ChildProcess) => void | undefined;
37
- stdout?: {
38
- save?: boolean;
39
- parseLines?: boolean | "skip-empty";
40
- onData?: (data: string) => void;
41
- };
42
- stderr?: {
43
- save?: boolean;
44
- parseLines?: boolean | "skip-empty";
45
- onData?: (data: string) => void;
46
- toExitCode?: boolean;
47
- };
48
- onExitCodeError?: (data: ExecResult, error: Error) => Error | false;
49
- }
50
- export declare function logExecStdout(input: {
6
+ export declare function logStdout(input: {
51
7
  data: string;
52
8
  colorize?: boolean;
53
9
  stderr?: boolean;
54
10
  lineSalt?: boolean;
55
11
  }): void;
56
- export declare function logExecStderr(data: string, colorize?: boolean): void;
57
- export type ExecResult = {
58
- stdout: string;
59
- stderr: string;
60
- exitCode: number;
61
- };
62
- export type ParseStreamDataOptions<S extends boolean = boolean> = {
63
- save?: S;
64
- parseLines?: boolean;
65
- log?: LogProcessOptions | boolean;
66
- onData?: (data: string) => void;
67
- };
68
- export declare function parseStreamData<S extends boolean>(stream: Readable, options?: ParseStreamDataOptions<S>): Promise<S extends true ? string : undefined>;
69
- type OnExitCode = OnExitCodeValue | ((code: number) => OnExitCodeValue | void | undefined);
70
- type OnExitCodeValue = Error | string | number | boolean;
71
- export declare function waitForClose<O extends boolean, E extends boolean>(p: ChildProcess, options?: {
72
- strict?: boolean;
73
- stdout?: O;
74
- stderr?: E;
75
- onExitCode?: OnExitCode;
76
- }): Promise<{
77
- exitCode: number;
78
- } & (O extends true ? {
79
- stdout: string;
80
- } : {}) & (E extends true ? {
81
- stderr: string;
82
- } : {})>;
12
+ export declare function logStderr(data: string, colorize?: boolean): void;
83
13
  export type LogProcessOptions = {
84
14
  envNames?: string[];
85
15
  env?: Record<string, any>;
@@ -87,23 +17,4 @@ export type LogProcessOptions = {
87
17
  toStderr?: boolean;
88
18
  colorize?: boolean;
89
19
  };
90
- export declare function logProcessExec(command: string, argv: any[], options: LogProcessOptions): Promise<void>;
91
- export type ProcessOptions<O1 extends boolean, O2 extends boolean> = {
92
- $stdout?: Omit<ParseStreamDataOptions<O1>, "log">;
93
- $stderr?: Omit<ParseStreamDataOptions<O2>, "log">;
94
- $onExitCode?: OnExitCode;
95
- $log?: boolean | {
96
- exec?: boolean | LogProcessOptions;
97
- stdout?: boolean | LogProcessOptions;
98
- stderr?: boolean | LogProcessOptions;
99
- };
100
- };
101
- export declare function createProcess<O1 extends boolean, O2 extends boolean>(command: string, argv?: (string | number)[], options?: SpawnOptions & ProcessOptions<O1, O2>): ChildProcessByStdio<Writable, Readable, Readable> & PromiseLike<{
102
- exitCode: number;
103
- } & (O1 extends true ? {
104
- stdout: string;
105
- } : {}) & (O2 extends true ? {
106
- stderr: string;
107
- } : {})>;
108
- export declare function exec(command: string, argv?: string[], options?: SpawnOptions | null, settings?: ExecSettingsInterface): Promise<ExecResult>;
109
- export {};
20
+ export declare function logProcess(command: string, argv: any[], options: LogProcessOptions): Promise<void>;