@datatruck/cli 0.0.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 (154) hide show
  1. package/lib/Action/BackupAction.d.ts +32 -0
  2. package/lib/Action/BackupAction.js +201 -0
  3. package/lib/Action/BackupSessionsAction.d.ts +13 -0
  4. package/lib/Action/BackupSessionsAction.js +16 -0
  5. package/lib/Action/CleanCacheAction.d.ts +9 -0
  6. package/lib/Action/CleanCacheAction.js +18 -0
  7. package/lib/Action/ConfigAction.d.ts +14 -0
  8. package/lib/Action/ConfigAction.js +64 -0
  9. package/lib/Action/InitAction.d.ts +18 -0
  10. package/lib/Action/InitAction.js +39 -0
  11. package/lib/Action/PruneAction.d.ts +37 -0
  12. package/lib/Action/PruneAction.js +80 -0
  13. package/lib/Action/RestoreAction.d.ts +36 -0
  14. package/lib/Action/RestoreAction.js +246 -0
  15. package/lib/Action/RestoreSessionsAction.d.ts +13 -0
  16. package/lib/Action/RestoreSessionsAction.js +16 -0
  17. package/lib/Action/SnapshotsAction.d.ts +30 -0
  18. package/lib/Action/SnapshotsAction.js +35 -0
  19. package/lib/Command/BackupCommand.d.ts +15 -0
  20. package/lib/Command/BackupCommand.js +83 -0
  21. package/lib/Command/BackupSessionsCommand.d.ts +12 -0
  22. package/lib/Command/BackupSessionsCommand.js +88 -0
  23. package/lib/Command/CleanCacheCommand.d.ts +6 -0
  24. package/lib/Command/CleanCacheCommand.js +20 -0
  25. package/lib/Command/CommandAbstract.d.ts +19 -0
  26. package/lib/Command/CommandAbstract.js +14 -0
  27. package/lib/Command/ConfigCommand.d.ts +17 -0
  28. package/lib/Command/ConfigCommand.js +61 -0
  29. package/lib/Command/InitCommand.d.ts +13 -0
  30. package/lib/Command/InitCommand.js +67 -0
  31. package/lib/Command/PruneCommand.d.ts +27 -0
  32. package/lib/Command/PruneCommand.js +160 -0
  33. package/lib/Command/RestoreCommand.d.ts +14 -0
  34. package/lib/Command/RestoreCommand.js +71 -0
  35. package/lib/Command/RestoreSessionsCommand.d.ts +12 -0
  36. package/lib/Command/RestoreSessionsCommand.js +87 -0
  37. package/lib/Command/SnapshotsCommand.d.ts +25 -0
  38. package/lib/Command/SnapshotsCommand.js +128 -0
  39. package/lib/Config/Config.d.ts +8 -0
  40. package/lib/Config/Config.js +19 -0
  41. package/lib/Config/PackageConfig.d.ts +27 -0
  42. package/lib/Config/PackageConfig.js +69 -0
  43. package/lib/Config/PackageRepositoryConfig.d.ts +17 -0
  44. package/lib/Config/PackageRepositoryConfig.js +37 -0
  45. package/lib/Config/PrunePolicyConfig.d.ts +4 -0
  46. package/lib/Config/PrunePolicyConfig.js +28 -0
  47. package/lib/Config/RepositoryConfig.d.ts +18 -0
  48. package/lib/Config/RepositoryConfig.js +37 -0
  49. package/lib/Config/TaskConfig.d.ts +23 -0
  50. package/lib/Config/TaskConfig.js +39 -0
  51. package/lib/Decorator/EntityDecorator.d.ts +11 -0
  52. package/lib/Decorator/EntityDecorator.js +17 -0
  53. package/lib/Entity/BackupSessionEntity.d.ts +6 -0
  54. package/lib/Entity/BackupSessionEntity.js +22 -0
  55. package/lib/Entity/BackupSessionRepositoryEntity.d.ts +6 -0
  56. package/lib/Entity/BackupSessionRepositoryEntity.js +22 -0
  57. package/lib/Entity/BackupSessionTaskEntity.d.ts +5 -0
  58. package/lib/Entity/BackupSessionTaskEntity.js +22 -0
  59. package/lib/Entity/CrudEntityAbstract.d.ts +5 -0
  60. package/lib/Entity/CrudEntityAbstract.js +6 -0
  61. package/lib/Entity/RestoreSessionEntity.d.ts +5 -0
  62. package/lib/Entity/RestoreSessionEntity.js +22 -0
  63. package/lib/Entity/RestoreSessionRepositoryEntity.d.ts +6 -0
  64. package/lib/Entity/RestoreSessionRepositoryEntity.js +22 -0
  65. package/lib/Entity/RestoreSessionTaskEntity.d.ts +5 -0
  66. package/lib/Entity/RestoreSessionTaskEntity.js +22 -0
  67. package/lib/Entity/StateEntityAbstract.d.ts +12 -0
  68. package/lib/Entity/StateEntityAbstract.js +7 -0
  69. package/lib/Error/AppError.d.ts +2 -0
  70. package/lib/Error/AppError.js +6 -0
  71. package/lib/Factory/CommandFactory.d.ts +42 -0
  72. package/lib/Factory/CommandFactory.js +79 -0
  73. package/lib/Factory/EntityFactory.d.ts +6 -0
  74. package/lib/Factory/EntityFactory.js +40 -0
  75. package/lib/Factory/RepositoryFactory.d.ts +3 -0
  76. package/lib/Factory/RepositoryFactory.js +23 -0
  77. package/lib/Factory/TaskFactory.d.ts +3 -0
  78. package/lib/Factory/TaskFactory.js +30 -0
  79. package/lib/JsonSchema/DefinitionEnum.d.ts +25 -0
  80. package/lib/JsonSchema/DefinitionEnum.js +32 -0
  81. package/lib/JsonSchema/JsonSchema.d.ts +4 -0
  82. package/lib/JsonSchema/JsonSchema.js +50 -0
  83. package/lib/Repository/GitRepository.d.ts +29 -0
  84. package/lib/Repository/GitRepository.js +237 -0
  85. package/lib/Repository/LocalRepository.d.ts +51 -0
  86. package/lib/Repository/LocalRepository.js +358 -0
  87. package/lib/Repository/RepositoryAbstract.d.ts +77 -0
  88. package/lib/Repository/RepositoryAbstract.js +19 -0
  89. package/lib/Repository/ResticRepository.d.ts +36 -0
  90. package/lib/Repository/ResticRepository.js +230 -0
  91. package/lib/SessionDriver/ConsoleSessionDriver.d.ts +37 -0
  92. package/lib/SessionDriver/ConsoleSessionDriver.js +178 -0
  93. package/lib/SessionDriver/SessionDriverAbstract.d.ts +78 -0
  94. package/lib/SessionDriver/SessionDriverAbstract.js +27 -0
  95. package/lib/SessionDriver/SqliteSessionDriver.d.ts +20 -0
  96. package/lib/SessionDriver/SqliteSessionDriver.js +169 -0
  97. package/lib/SessionManager/BackupSessionManager.d.ts +44 -0
  98. package/lib/SessionManager/BackupSessionManager.js +206 -0
  99. package/lib/SessionManager/RestoreSessionManager.d.ts +44 -0
  100. package/lib/SessionManager/RestoreSessionManager.js +206 -0
  101. package/lib/Task/GitTask.d.ts +35 -0
  102. package/lib/Task/GitTask.js +248 -0
  103. package/lib/Task/MariadbTask.d.ts +25 -0
  104. package/lib/Task/MariadbTask.js +139 -0
  105. package/lib/Task/MssqlTask.d.ts +22 -0
  106. package/lib/Task/MssqlTask.js +109 -0
  107. package/lib/Task/MysqlDumpTask.d.ts +14 -0
  108. package/lib/Task/MysqlDumpTask.js +129 -0
  109. package/lib/Task/PostgresqlDumpTask.d.ts +14 -0
  110. package/lib/Task/PostgresqlDumpTask.js +101 -0
  111. package/lib/Task/SqlDumpTaskAbstract.d.ts +36 -0
  112. package/lib/Task/SqlDumpTaskAbstract.js +146 -0
  113. package/lib/Task/TaskAbstract.d.ts +37 -0
  114. package/lib/Task/TaskAbstract.js +17 -0
  115. package/lib/bin.d.ts +2 -0
  116. package/lib/bin.js +5 -0
  117. package/lib/cli.d.ts +4 -0
  118. package/lib/cli.js +110 -0
  119. package/lib/index.d.ts +0 -0
  120. package/lib/index.js +1 -0
  121. package/lib/util/DataFormat.d.ts +24 -0
  122. package/lib/util/DataFormat.js +50 -0
  123. package/lib/util/GitUtil.d.ts +38 -0
  124. package/lib/util/GitUtil.js +105 -0
  125. package/lib/util/ObjectVault.d.ts +13 -0
  126. package/lib/util/ObjectVault.js +31 -0
  127. package/lib/util/ResticUtil.d.ts +92 -0
  128. package/lib/util/ResticUtil.js +144 -0
  129. package/lib/util/cli-util.d.ts +27 -0
  130. package/lib/util/cli-util.js +118 -0
  131. package/lib/util/datatruck/config-util.d.ts +55 -0
  132. package/lib/util/datatruck/config-util.js +93 -0
  133. package/lib/util/datatruck/paths-util.d.ts +5 -0
  134. package/lib/util/datatruck/paths-util.js +22 -0
  135. package/lib/util/datatruck/snapshot-util.d.ts +4 -0
  136. package/lib/util/datatruck/snapshot-util.js +31 -0
  137. package/lib/util/date-util.d.ts +12 -0
  138. package/lib/util/date-util.js +74 -0
  139. package/lib/util/entity-util.d.ts +4 -0
  140. package/lib/util/entity-util.js +10 -0
  141. package/lib/util/fs-util.d.ts +43 -0
  142. package/lib/util/fs-util.js +278 -0
  143. package/lib/util/math-util.d.ts +1 -0
  144. package/lib/util/math-util.js +7 -0
  145. package/lib/util/object-util.d.ts +7 -0
  146. package/lib/util/object-util.js +58 -0
  147. package/lib/util/process-util.d.ts +50 -0
  148. package/lib/util/process-util.js +181 -0
  149. package/lib/util/string-util.d.ts +17 -0
  150. package/lib/util/string-util.js +77 -0
  151. package/lib/util/zip-util.d.ts +52 -0
  152. package/lib/util/zip-util.js +135 -0
  153. package/migrations/001-initial.sql +122 -0
  154. package/package.json +62 -0
@@ -0,0 +1,35 @@
1
+ import { BackupDataType, RestoreDataType, TaskAbstract } from "./TaskAbstract";
2
+ import { JSONSchema7 } from "json-schema";
3
+ export declare type GitTaskConfigType = {
4
+ command?: string;
5
+ /**
6
+ * @default true
7
+ */
8
+ includeModified?: boolean | string[];
9
+ /**
10
+ * @default true
11
+ */
12
+ includeUntracked?: boolean | string[];
13
+ /**
14
+ * @default false
15
+ */
16
+ includeIgnored?: boolean | string[];
17
+ /**
18
+ * @default true
19
+ */
20
+ includeConfig?: boolean;
21
+ };
22
+ export declare const gitTaskName = "git";
23
+ export declare const gitTaskDefinition: JSONSchema7;
24
+ export declare class GitTask extends TaskAbstract<GitTaskConfigType> {
25
+ protected verbose?: boolean;
26
+ private get command();
27
+ onBeforeBackup(): Promise<{
28
+ targetPath: string;
29
+ }>;
30
+ onBackup(data: BackupDataType): Promise<void>;
31
+ onBeforeRestore(): Promise<{
32
+ targetPath: string;
33
+ }>;
34
+ onRestore(data: RestoreDataType): Promise<void>;
35
+ }
@@ -0,0 +1,248 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GitTask = exports.gitTaskDefinition = exports.gitTaskName = void 0;
4
+ const DefinitionEnum_1 = require("../JsonSchema/DefinitionEnum");
5
+ const cli_util_1 = require("../util/cli-util");
6
+ const fs_util_1 = require("../util/fs-util");
7
+ const math_util_1 = require("../util/math-util");
8
+ const process_util_1 = require("../util/process-util");
9
+ const TaskAbstract_1 = require("./TaskAbstract");
10
+ const assert_1 = require("assert");
11
+ const fs_1 = require("fs");
12
+ const fs_extra_1 = require("fs-extra");
13
+ const promises_1 = require("fs/promises");
14
+ const micromatch_1 = require("micromatch");
15
+ const path_1 = require("path");
16
+ const readline_1 = require("readline");
17
+ exports.gitTaskName = "git";
18
+ exports.gitTaskDefinition = {
19
+ type: "object",
20
+ additionalProperties: false,
21
+ properties: {
22
+ command: {
23
+ type: "string",
24
+ },
25
+ includeModified: {
26
+ anyOf: [
27
+ {
28
+ type: "boolean",
29
+ },
30
+ (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
31
+ ],
32
+ },
33
+ includeUntracked: {
34
+ anyOf: [
35
+ {
36
+ type: "boolean",
37
+ },
38
+ (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
39
+ ],
40
+ },
41
+ includeIgnored: {
42
+ anyOf: [
43
+ {
44
+ type: "boolean",
45
+ },
46
+ (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
47
+ ],
48
+ },
49
+ includeConfig: {
50
+ type: "boolean",
51
+ },
52
+ },
53
+ };
54
+ class GitTask extends TaskAbstract_1.TaskAbstract {
55
+ get command() {
56
+ return this.config.command ?? "git";
57
+ }
58
+ async onBeforeBackup() {
59
+ return {
60
+ targetPath: await (0, fs_util_1.mkTmpDir)(GitTask.name),
61
+ };
62
+ }
63
+ async onBackup(data) {
64
+ this.verbose = data.options.verbose;
65
+ const config = this.config;
66
+ const path = data.package.path;
67
+ const targetPath = data.targetPath;
68
+ (0, assert_1.ok)(typeof path === "string");
69
+ (0, assert_1.ok)(typeof targetPath === "string");
70
+ // Bundle
71
+ const bundlePath = (0, path_1.join)(targetPath, "repo.bundle");
72
+ await (0, process_util_1.exec)(this.command, ["bundle", "create", bundlePath, "--all"], {
73
+ cwd: path,
74
+ }, {
75
+ log: this.verbose,
76
+ });
77
+ // Config
78
+ if (this.config.includeConfig ?? true) {
79
+ const configPath = (0, path_1.join)(targetPath, "repo.config");
80
+ await (0, promises_1.copyFile)((0, path_1.join)(path, ".git", "config"), configPath);
81
+ }
82
+ // git ls-files
83
+ const lsFilesConfig = [
84
+ {
85
+ name: "untracked",
86
+ argv: ["--others"],
87
+ include: config.includeUntracked ?? true,
88
+ },
89
+ {
90
+ name: "modified",
91
+ argv: ["--modified"],
92
+ include: config.includeModified ?? true,
93
+ },
94
+ {
95
+ name: "ignored",
96
+ argv: ["--others", "--ignored"],
97
+ include: config.includeIgnored,
98
+ },
99
+ ];
100
+ // Paths list
101
+ let total = 0;
102
+ let currentFiles = 0;
103
+ for (const option of lsFilesConfig) {
104
+ if (!option.include)
105
+ continue;
106
+ option.pathsPath = (0, path_1.join)(targetPath, `repo.${option.name}-paths.txt`);
107
+ const stream = (0, fs_1.createWriteStream)(option.pathsPath);
108
+ let streamError;
109
+ stream.on("error", (e) => (streamError = e));
110
+ try {
111
+ await (0, process_util_1.exec)(this.command, [
112
+ "-c",
113
+ "core.quotepath=off",
114
+ "ls-files",
115
+ ...option.argv,
116
+ "--exclude-standard",
117
+ ], {
118
+ cwd: data.package.path,
119
+ }, {
120
+ log: {
121
+ exec: this.verbose,
122
+ },
123
+ onSpawn: (p) => {
124
+ const iface = (0, readline_1.createInterface)(p.stdout, stream);
125
+ iface.on("close", () => stream.end());
126
+ iface.on("line", (path) => {
127
+ path = path.trim();
128
+ if (!path.length)
129
+ return;
130
+ let found = false;
131
+ if (option.include === true) {
132
+ found = true;
133
+ }
134
+ else if (option.include) {
135
+ found = (0, micromatch_1.isMatch)(path, option.include);
136
+ }
137
+ if (found) {
138
+ total++;
139
+ stream.write(`${path}\n`);
140
+ }
141
+ });
142
+ },
143
+ });
144
+ }
145
+ finally {
146
+ await new Promise((resolve) => stream.end(resolve));
147
+ if (streamError)
148
+ throw streamError;
149
+ }
150
+ }
151
+ // Copy
152
+ for (const option of lsFilesConfig) {
153
+ if (!option.include)
154
+ continue;
155
+ const createdPaths = [];
156
+ const outPath = (0, path_1.join)(targetPath, `repo.${option.name}`);
157
+ await (0, fs_util_1.mkdirIfNotExists)(outPath);
158
+ if (data.options.verbose)
159
+ (0, cli_util_1.logExec)(`Copying ${option.name} files to ${outPath}`);
160
+ const reader = (0, readline_1.createInterface)({
161
+ input: (0, fs_1.createReadStream)(option.pathsPath),
162
+ });
163
+ for await (const entry of reader) {
164
+ const source = (0, path_1.join)(path, entry);
165
+ const target = (0, path_1.join)(outPath, entry);
166
+ if (entry.endsWith("/")) {
167
+ await (0, promises_1.mkdir)(target, {
168
+ recursive: true,
169
+ });
170
+ }
171
+ else {
172
+ currentFiles++;
173
+ await data.onProgress({
174
+ total,
175
+ current: currentFiles,
176
+ percent: (0, math_util_1.progressPercent)(total, currentFiles),
177
+ step: entry,
178
+ });
179
+ const dir = (0, path_1.dirname)(target);
180
+ if (!createdPaths.includes(dir)) {
181
+ await (0, promises_1.mkdir)(dir, {
182
+ recursive: true,
183
+ });
184
+ createdPaths.push(dir);
185
+ }
186
+ await (0, promises_1.copyFile)(source, target);
187
+ }
188
+ }
189
+ await (0, promises_1.rm)(option.pathsPath);
190
+ }
191
+ }
192
+ async onBeforeRestore() {
193
+ return {
194
+ targetPath: await (0, fs_util_1.mkTmpDir)(GitTask.name),
195
+ };
196
+ }
197
+ async onRestore(data) {
198
+ this.verbose = data.options.verbose;
199
+ const restorePath = data.package.restorePath;
200
+ const targetPath = data.targetPath;
201
+ (0, assert_1.ok)(typeof restorePath === "string");
202
+ (0, assert_1.ok)(typeof targetPath === "string");
203
+ await (0, fs_util_1.mkdirIfNotExists)(restorePath);
204
+ await (0, fs_util_1.ensureEmptyDir)(restorePath);
205
+ // Stats
206
+ let totalFiles = 0;
207
+ let currentFiles = 0;
208
+ await (0, fs_util_1.forEachFile)(targetPath, () => totalFiles++, true);
209
+ const incrementProgress = async (step = "") => {
210
+ await data.onProgress({
211
+ total: totalFiles,
212
+ current: Math.max(currentFiles, 0),
213
+ percent: (0, math_util_1.progressPercent)(totalFiles, Math.max(currentFiles, 0)),
214
+ step,
215
+ });
216
+ currentFiles++;
217
+ };
218
+ // Bundle
219
+ const bundlePath = (0, path_1.join)(targetPath, "repo.bundle");
220
+ await (0, process_util_1.exec)(this.command, ["clone", bundlePath, "."], {
221
+ cwd: restorePath,
222
+ }, {
223
+ log: this.verbose,
224
+ });
225
+ await incrementProgress();
226
+ // Config
227
+ const configPath = (0, path_1.join)(targetPath, "repo.config");
228
+ if (await (0, fs_util_1.checkFile)(configPath)) {
229
+ await (0, promises_1.copyFile)(configPath, (0, path_1.join)(restorePath, ".git", "config"));
230
+ await incrementProgress();
231
+ }
232
+ // ls-files
233
+ for (const name of ["untracked", "modified", "ignored"]) {
234
+ const sourcePath = (0, path_1.join)(targetPath, `repo.${name}`);
235
+ if (await (0, fs_util_1.checkDir)(sourcePath)) {
236
+ if (data.options.verbose)
237
+ (0, cli_util_1.logExec)(`Copying ${name} files to ${restorePath}`);
238
+ await (0, fs_extra_1.copy)(sourcePath, restorePath, {
239
+ filter: async (path) => {
240
+ await incrementProgress((0, path_1.relative)(sourcePath, path));
241
+ return true;
242
+ },
243
+ });
244
+ }
245
+ }
246
+ }
247
+ }
248
+ exports.GitTask = GitTask;
@@ -0,0 +1,25 @@
1
+ import { BackupDataType, RestoreDataType, TaskAbstract } from "./TaskAbstract";
2
+ import { JSONSchema7 } from "json-schema";
3
+ export declare type MariadbTaskConfigType = {
4
+ command?: string;
5
+ hostname: string;
6
+ username: string;
7
+ password: string | {
8
+ path: string;
9
+ };
10
+ includeTables?: string[];
11
+ excludeTables?: string[];
12
+ includeDatabases?: string[];
13
+ excludeDatabases?: string[];
14
+ };
15
+ export declare const mariadbTaskName = "mariadb";
16
+ export declare const mariadbTaskDefinition: JSONSchema7;
17
+ export declare class MariadbTask extends TaskAbstract<MariadbTaskConfigType> {
18
+ protected verbose?: boolean;
19
+ private get command();
20
+ onBeforeBackup(): Promise<{
21
+ targetPath: string;
22
+ }>;
23
+ onBackup(data: BackupDataType): Promise<void>;
24
+ onRestore(data: RestoreDataType): Promise<void>;
25
+ }
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MariadbTask = exports.mariadbTaskDefinition = exports.mariadbTaskName = void 0;
4
+ const DefinitionEnum_1 = require("../JsonSchema/DefinitionEnum");
5
+ const cli_util_1 = require("../util/cli-util");
6
+ const fs_util_1 = require("../util/fs-util");
7
+ const math_util_1 = require("../util/math-util");
8
+ const process_util_1 = require("../util/process-util");
9
+ const TaskAbstract_1 = require("./TaskAbstract");
10
+ const assert_1 = require("assert");
11
+ const promises_1 = require("fs/promises");
12
+ const path_1 = require("path");
13
+ const posix_1 = require("path/posix");
14
+ exports.mariadbTaskName = "mariadb";
15
+ exports.mariadbTaskDefinition = {
16
+ type: "object",
17
+ required: ["hostname", "username", "password"],
18
+ additionalProperties: false,
19
+ properties: {
20
+ command: { type: "string" },
21
+ hostname: { type: "string" },
22
+ username: { type: "string" },
23
+ password: {
24
+ anyOf: [
25
+ {
26
+ type: "string",
27
+ },
28
+ {
29
+ type: "object",
30
+ additionalProperties: false,
31
+ required: ["path"],
32
+ properties: {
33
+ path: { type: "string" },
34
+ },
35
+ },
36
+ ],
37
+ },
38
+ includeTables: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
39
+ excludeTables: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
40
+ includeDatabases: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
41
+ excludeDatabases: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
42
+ },
43
+ };
44
+ class MariadbTask extends TaskAbstract_1.TaskAbstract {
45
+ get command() {
46
+ return this.config.command ?? "mariabackup";
47
+ }
48
+ async onBeforeBackup() {
49
+ return {
50
+ targetPath: await (0, fs_util_1.mkTmpDir)(MariadbTask.name),
51
+ };
52
+ }
53
+ async onBackup(data) {
54
+ this.verbose = data.options.verbose;
55
+ const config = this.config;
56
+ const command = this.command;
57
+ const sourcePath = data.package.path;
58
+ const targetPath = data.targetPath;
59
+ (0, assert_1.ok)(typeof sourcePath === "string");
60
+ (0, assert_1.ok)(typeof targetPath === "string");
61
+ const args = [
62
+ `--backup`,
63
+ `--datadir=${sourcePath}`,
64
+ `--target-dir=${targetPath}`,
65
+ `--host=${config.hostname}`,
66
+ `--user=${config.username}`,
67
+ `--password=${typeof config.password === "string"
68
+ ? config.password
69
+ : config.password
70
+ ? (await (0, promises_1.readFile)(config.password.path)).toString()
71
+ : ""}`,
72
+ ];
73
+ if (config.includeDatabases)
74
+ args.push(`--databases=${config.includeDatabases.join(" ")}`);
75
+ if (config.excludeDatabases)
76
+ args.push(`--databases-exclude=${config.excludeDatabases.join(" ")}`);
77
+ if (config.includeTables)
78
+ args.push(`--tables=^(${config.includeTables.join("|")})$`);
79
+ if (config.excludeTables)
80
+ args.push(`--tables-exclude=^(${config.excludeTables.join("|")})$`);
81
+ let total = 0;
82
+ let current = 0;
83
+ await (0, fs_util_1.forEachFile)(sourcePath, () => {
84
+ total++;
85
+ });
86
+ const onData = async (lines) => {
87
+ const regex = /\[\d{1,}\] \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} Copying (.+) to/;
88
+ let path = lines
89
+ .split(/\r?\n/)
90
+ .reduce((result, line) => {
91
+ const matches = regex.exec(line);
92
+ if (matches) {
93
+ current++;
94
+ result.push(matches[1]);
95
+ }
96
+ return result;
97
+ }, [])
98
+ .pop();
99
+ if (path) {
100
+ path = (0, posix_1.normalize)(path);
101
+ await data.onProgress({
102
+ current,
103
+ percent: (0, math_util_1.progressPercent)(total, current),
104
+ total,
105
+ step: `Copying ${path}`,
106
+ });
107
+ }
108
+ };
109
+ await (0, process_util_1.exec)(command, args, undefined, {
110
+ log: this.verbose,
111
+ stdout: {
112
+ onData,
113
+ },
114
+ stderr: {
115
+ onData,
116
+ },
117
+ });
118
+ await (0, process_util_1.exec)(command, [`--prepare`, `--target-dir=${targetPath}`], undefined, {
119
+ log: this.verbose,
120
+ stderr: { onData: async () => { } },
121
+ });
122
+ }
123
+ async onRestore(data) {
124
+ this.verbose = data.options.verbose;
125
+ const restorePath = data.package.restorePath;
126
+ (0, assert_1.ok)(typeof restorePath === "string");
127
+ await (0, fs_util_1.mkdirIfNotExists)(restorePath);
128
+ const files = await (0, promises_1.readdir)(restorePath);
129
+ for (const file of files) {
130
+ if (file.startsWith("ib_logfile")) {
131
+ const filePath = (0, path_1.join)(restorePath, file);
132
+ if (this.verbose)
133
+ (0, cli_util_1.logExec)("rm", [filePath]);
134
+ await (0, promises_1.rm)(filePath);
135
+ }
136
+ }
137
+ }
138
+ }
139
+ exports.MariadbTask = MariadbTask;
@@ -0,0 +1,22 @@
1
+ import { BackupDataType, RestoreDataType, TaskAbstract } from "./TaskAbstract";
2
+ import { JSONSchema7 } from "json-schema";
3
+ export declare type MssqlTaskConfigType = {
4
+ command?: string;
5
+ hostname?: string;
6
+ username?: string;
7
+ passwordFile?: string;
8
+ targetDatabase?: string;
9
+ includeDatabases?: string[];
10
+ excludeDatabases?: string[];
11
+ };
12
+ export declare const mssqlTaskName = "mssql";
13
+ export declare const mssqlTaskDefinition: JSONSchema7;
14
+ export declare class MssqlTask extends TaskAbstract<MssqlTaskConfigType> {
15
+ static SUFFIX: string;
16
+ protected verbose?: boolean;
17
+ private get command();
18
+ exec(query: string): Promise<string[][]>;
19
+ fetchDatabaseNames(name?: string): Promise<string[]>;
20
+ onBackup(data: BackupDataType): Promise<void>;
21
+ onRestore(data: RestoreDataType): Promise<void>;
22
+ }
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MssqlTask = exports.mssqlTaskDefinition = exports.mssqlTaskName = void 0;
4
+ const AppError_1 = require("../Error/AppError");
5
+ const DefinitionEnum_1 = require("../JsonSchema/DefinitionEnum");
6
+ const config_util_1 = require("../util/datatruck/config-util");
7
+ const fs_util_1 = require("../util/fs-util");
8
+ const process_util_1 = require("../util/process-util");
9
+ const TaskAbstract_1 = require("./TaskAbstract");
10
+ const assert_1 = require("assert");
11
+ const fs_extra_1 = require("fs-extra");
12
+ const promises_1 = require("fs/promises");
13
+ const micromatch_1 = require("micromatch");
14
+ const path_1 = require("path");
15
+ exports.mssqlTaskName = "mssql";
16
+ exports.mssqlTaskDefinition = {
17
+ type: "object",
18
+ additionalProperties: false,
19
+ properties: {
20
+ command: { type: "string" },
21
+ hostname: { type: "string" },
22
+ username: { type: "string" },
23
+ passwordFile: { type: "string" },
24
+ includeDatabases: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
25
+ excludeDatabases: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
26
+ },
27
+ };
28
+ class MssqlTask extends TaskAbstract_1.TaskAbstract {
29
+ get command() {
30
+ return this.config.command ?? "sqlcmd";
31
+ }
32
+ async exec(query) {
33
+ const result = await (0, process_util_1.exec)(this.command, [
34
+ ...(this.config.hostname ? ["-S", this.config.hostname] : []),
35
+ ...(this.config.username ? ["-U", this.config.username] : []),
36
+ ...(this.config.passwordFile
37
+ ? ["-P", (await (0, promises_1.readFile)(this.config.passwordFile)).toString()]
38
+ : []),
39
+ "-E",
40
+ "-W",
41
+ "-s",
42
+ ",",
43
+ "-w",
44
+ "999",
45
+ "-Q",
46
+ `SET nocount ON; ${query.replace(/[\n\t]/g, " ")}`,
47
+ ], undefined, {
48
+ log: this.verbose,
49
+ stderr: {
50
+ toExitCode: true,
51
+ },
52
+ stdout: {
53
+ save: true,
54
+ },
55
+ });
56
+ return result.stdout
57
+ .split(/\n/g)
58
+ .map((row) => row.split(","))
59
+ .filter((row) => row.length);
60
+ }
61
+ async fetchDatabaseNames(name) {
62
+ const query = `SELECT name FROM master.dbo.sysdatabases ${name ? `WHERE name = '${name}'` : ""}`;
63
+ const rows = await this.exec(query);
64
+ const privateDatabases = ["master", "tempdb", "model", "msdb"];
65
+ return rows
66
+ .map(([database]) => database)
67
+ .filter((database) => !privateDatabases.includes(database));
68
+ }
69
+ async onBackup(data) {
70
+ this.verbose = data.options.verbose;
71
+ const targetPath = data.package.path;
72
+ (0, assert_1.ok)(typeof targetPath === "string");
73
+ const databaseNames = (await this.fetchDatabaseNames()).filter((databaseName) => (!this.config.includeDatabases ||
74
+ (0, micromatch_1.isMatch)(databaseName, this.config.includeDatabases)) &&
75
+ (!this.config.excludeDatabases ||
76
+ !(0, micromatch_1.isMatch)(databaseName, this.config.excludeDatabases)));
77
+ await (0, fs_util_1.mkdirIfNotExists)(targetPath);
78
+ for (const databaseName of databaseNames) {
79
+ const databasePath = (0, path_1.join)(targetPath, `${databaseName}${MssqlTask.SUFFIX}`);
80
+ await this.exec(`BACKUP DATABASE [${databaseName}] TO DISK='${databasePath}' WITH FORMAT`);
81
+ }
82
+ }
83
+ async onRestore(data) {
84
+ this.verbose = data.options.verbose;
85
+ const restorePath = data.package.restorePath;
86
+ (0, assert_1.ok)(typeof restorePath === "string");
87
+ await (0, fs_util_1.mkdirIfNotExists)(restorePath);
88
+ const files = await (0, fs_extra_1.readdir)(restorePath);
89
+ for (const file of files) {
90
+ if (!file.endsWith(MssqlTask.SUFFIX))
91
+ continue;
92
+ let databaseName = file.slice(0, MssqlTask.SUFFIX.length * -1);
93
+ if (this.config.targetDatabase)
94
+ databaseName = (0, config_util_1.resolveDatabaseName)(this.config.targetDatabase, {
95
+ action: "restore",
96
+ database: databaseName,
97
+ packageName: data.package.name,
98
+ snapshotId: data.options.snapshotId,
99
+ });
100
+ const databasePath = (0, path_1.join)(restorePath, file);
101
+ const exists = await this.fetchDatabaseNames(databaseName);
102
+ if (exists.length)
103
+ throw new AppError_1.AppError(`Target database already exists: ${databaseName}`);
104
+ await this.exec(`RESTORE DATABASE [${databaseName}] FROM disk='${databasePath}'`);
105
+ }
106
+ }
107
+ }
108
+ exports.MssqlTask = MssqlTask;
109
+ MssqlTask.SUFFIX = ".BAK";
@@ -0,0 +1,14 @@
1
+ import { SqlDumpTaskAbstract, SqlDumpTaskConfigType, TargetDatabaseType } from "./SqlDumpTaskAbstract";
2
+ import { JSONSchema7 } from "json-schema";
3
+ export declare const mysqlDumpTaskName = "mysql-dump";
4
+ export declare type MysqlDumpTaskConfigType = {} & SqlDumpTaskConfigType;
5
+ export declare const mysqlDumpTaskDefinition: JSONSchema7;
6
+ export declare class MysqlDumpTask extends SqlDumpTaskAbstract<MysqlDumpTaskConfigType> {
7
+ buildConnectionArgs(database?: boolean): Promise<string[]>;
8
+ onDatabaseIsEmpty(name: string): Promise<boolean>;
9
+ onCreateDatabase(database: TargetDatabaseType): Promise<void>;
10
+ onExecQuery(query: string): Promise<import("../util/process-util").ExecResultType>;
11
+ onFetchTableNames(): Promise<string[]>;
12
+ onExport(tableNames: string[], output: string): Promise<void>;
13
+ onImport(path: string, database: string): Promise<void>;
14
+ }