@datatruck/cli 0.21.0 → 0.21.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.
- package/Repository/DatatruckRepository.d.ts +3 -0
- package/Repository/DatatruckRepository.js +29 -11
- package/Task/MysqlDumpTask.d.ts +1 -1
- package/Task/MysqlDumpTask.js +5 -5
- package/Task/PostgresqlDumpTask.js +1 -1
- package/package.json +1 -1
- package/utils/fs.d.ts +3 -1
- package/utils/fs.js +9 -2
- package/utils/tar.js +38 -33
|
@@ -213,22 +213,26 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
213
213
|
});
|
|
214
214
|
await stream.end();
|
|
215
215
|
let packIndex = 0;
|
|
216
|
+
const tarStats = {};
|
|
216
217
|
for (const pack of packs) {
|
|
217
218
|
const packBasename = [`pack`, packIndex.toString(), pack.name]
|
|
218
219
|
.filter((v) => typeof v === "string")
|
|
219
220
|
.map((v) => encodeURIComponent(v.toString().replace(/[\\/]/g, "-")))
|
|
220
|
-
.join("-");
|
|
221
|
-
const ext = pack.compress ? `.tar.gz` : `.tar`;
|
|
221
|
+
.join("-") + (pack.compress ? `.tar.gz` : `.tar`);
|
|
222
222
|
const includeList = stream.path(packIndex);
|
|
223
|
-
if (includeList)
|
|
223
|
+
if (includeList) {
|
|
224
|
+
tarStats[packBasename] = {
|
|
225
|
+
files: stream.lines(packIndex),
|
|
226
|
+
};
|
|
224
227
|
await (0, tar_1.createTar)({
|
|
225
228
|
compress: pack.compress,
|
|
226
229
|
verbose: data.options.verbose,
|
|
227
230
|
includeList,
|
|
228
231
|
path: sourcePath,
|
|
229
|
-
output: (0, path_1.join)(outPath, packBasename)
|
|
232
|
+
output: (0, path_1.join)(outPath, packBasename),
|
|
230
233
|
onEntry: async (data) => await scanner.progress(pack.compress ? "Compressing" : "Packing", data.path),
|
|
231
234
|
});
|
|
235
|
+
}
|
|
232
236
|
packIndex++;
|
|
233
237
|
}
|
|
234
238
|
await scanner.end();
|
|
@@ -243,6 +247,7 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
243
247
|
task: data.package.task?.name,
|
|
244
248
|
version: nodePkg.version,
|
|
245
249
|
size: await (0, fs_1.fastFolderSizeAsync)(outPath),
|
|
250
|
+
tarStats,
|
|
246
251
|
};
|
|
247
252
|
if (data.options.verbose)
|
|
248
253
|
(0, cli_1.logExec)(`Writing metadata into ${metaPath}`);
|
|
@@ -298,6 +303,8 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
298
303
|
packageName: data.package.name,
|
|
299
304
|
});
|
|
300
305
|
const sourcePath = (0, path_1.join)(this.config.outPath, snapshotName);
|
|
306
|
+
const metaPath = (0, path_1.join)(sourcePath, "meta.json");
|
|
307
|
+
const meta = await DatatruckRepository.parseMetaData(metaPath);
|
|
301
308
|
const scanner = await (0, fs_1.createFileScanner)({
|
|
302
309
|
onProgress: data.onProgress,
|
|
303
310
|
glob: {
|
|
@@ -306,26 +313,37 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
306
313
|
},
|
|
307
314
|
});
|
|
308
315
|
const tarFiles = [];
|
|
316
|
+
const tarStats = meta?.tarStats || {};
|
|
309
317
|
await scanner.start(async (entry) => {
|
|
310
318
|
const path = (0, path_1.join)(sourcePath, entry.name);
|
|
311
319
|
const isTar = entry.name.endsWith(".tar");
|
|
312
320
|
const isTarGz = entry.name.endsWith(".tar.gz");
|
|
313
321
|
if (isTar || isTarGz) {
|
|
314
322
|
tarFiles.push(path);
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
}
|
|
321
|
-
|
|
323
|
+
if (typeof tarStats[entry.name]?.files === "number") {
|
|
324
|
+
scanner.total += tarStats[entry.name].files;
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
scanner.progress("Scanning", entry.name, false);
|
|
328
|
+
const selfTarStats = (tarStats[entry.name] = { files: 0 });
|
|
329
|
+
await (0, tar_1.listTar)({
|
|
330
|
+
input: path,
|
|
331
|
+
verbose: data.options.verbose,
|
|
332
|
+
onEntry: () => {
|
|
333
|
+
scanner.total++;
|
|
334
|
+
selfTarStats.files++;
|
|
335
|
+
},
|
|
336
|
+
});
|
|
337
|
+
}
|
|
322
338
|
}
|
|
323
339
|
return false;
|
|
324
340
|
});
|
|
325
341
|
if (data.options.verbose)
|
|
326
342
|
(0, cli_1.logExec)(`Unpacking files to ${restorePath}`);
|
|
327
343
|
for (const tarFile of tarFiles) {
|
|
344
|
+
const entryName = (0, path_1.basename)(tarFile);
|
|
328
345
|
await (0, tar_1.extractTar)({
|
|
346
|
+
total: tarStats[entryName].files,
|
|
329
347
|
input: tarFile,
|
|
330
348
|
output: restorePath,
|
|
331
349
|
decompress: tarFile.endsWith(".tar.gz"),
|
package/Task/MysqlDumpTask.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export declare const mysqlDumpTaskName = "mysql-dump";
|
|
|
4
4
|
export type MysqlDumpTaskConfigType = {} & SqlDumpTaskConfigType;
|
|
5
5
|
export declare const mysqlDumpTaskDefinition: JSONSchema7;
|
|
6
6
|
export declare class MysqlDumpTask extends SqlDumpTaskAbstract<MysqlDumpTaskConfigType> {
|
|
7
|
-
buildConnectionArgs(database?:
|
|
7
|
+
buildConnectionArgs(database?: string): Promise<string[]>;
|
|
8
8
|
onDatabaseIsEmpty(name: string): Promise<boolean>;
|
|
9
9
|
onCreateDatabase(database: TargetDatabaseType): Promise<void>;
|
|
10
10
|
onExecQuery(query: string): Promise<import("../utils/process").ExecResultType>;
|
package/Task/MysqlDumpTask.js
CHANGED
|
@@ -13,14 +13,14 @@ exports.mysqlDumpTaskDefinition = {
|
|
|
13
13
|
allOf: [(0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.sqlDumpTask)],
|
|
14
14
|
};
|
|
15
15
|
class MysqlDumpTask extends SqlDumpTaskAbstract_1.SqlDumpTaskAbstract {
|
|
16
|
-
async buildConnectionArgs(database
|
|
16
|
+
async buildConnectionArgs(database) {
|
|
17
17
|
const password = await this.fetchPassword();
|
|
18
18
|
return [
|
|
19
19
|
`--host=${this.config.hostname}`,
|
|
20
20
|
...(this.config.port ? [`--port=${this.config.port}`] : []),
|
|
21
21
|
`--user=${this.config.username}`,
|
|
22
22
|
`--password=${password ?? ""}`,
|
|
23
|
-
...(database
|
|
23
|
+
...(database ? [database] : []),
|
|
24
24
|
];
|
|
25
25
|
}
|
|
26
26
|
async onDatabaseIsEmpty(name) {
|
|
@@ -78,7 +78,7 @@ class MysqlDumpTask extends SqlDumpTaskAbstract_1.SqlDumpTaskAbstract {
|
|
|
78
78
|
stream.on("error", reject);
|
|
79
79
|
}),
|
|
80
80
|
await (0, process_1.exec)("mysqldump", [
|
|
81
|
-
...(await this.buildConnectionArgs()),
|
|
81
|
+
...(await this.buildConnectionArgs(this.config.database)),
|
|
82
82
|
"--lock-tables=false",
|
|
83
83
|
"--skip-add-drop-table=false",
|
|
84
84
|
...tableNames,
|
|
@@ -120,7 +120,7 @@ class MysqlDumpTask extends SqlDumpTaskAbstract_1.SqlDumpTaskAbstract {
|
|
|
120
120
|
stream.on("error", reject);
|
|
121
121
|
}),
|
|
122
122
|
await (0, process_1.exec)("mysqldump", [
|
|
123
|
-
...(await this.buildConnectionArgs()),
|
|
123
|
+
...(await this.buildConnectionArgs(this.config.database)),
|
|
124
124
|
"--lock-tables=false",
|
|
125
125
|
"--routines",
|
|
126
126
|
"--events",
|
|
@@ -143,7 +143,7 @@ class MysqlDumpTask extends SqlDumpTaskAbstract_1.SqlDumpTaskAbstract {
|
|
|
143
143
|
]);
|
|
144
144
|
}
|
|
145
145
|
async onImport(path, database) {
|
|
146
|
-
await (0, process_1.exec)("mysql",
|
|
146
|
+
await (0, process_1.exec)("mysql", await this.buildConnectionArgs(database), null, {
|
|
147
147
|
pipe: {
|
|
148
148
|
stream: (0, fs_3.createReadStream)(path),
|
|
149
149
|
onReadProgress: (data) => {
|
|
@@ -81,7 +81,7 @@ class PostgresqlDumpTask extends SqlDumpTaskAbstract_1.SqlDumpTaskAbstract {
|
|
|
81
81
|
stream.on("error", reject);
|
|
82
82
|
}),
|
|
83
83
|
(0, process_1.exec)("pg_dump", [
|
|
84
|
-
...(await this.buildConnectionArgs()),
|
|
84
|
+
...(await this.buildConnectionArgs(this.config.database)),
|
|
85
85
|
...(tableNames?.flatMap((v) => ["-t", v]) ?? []),
|
|
86
86
|
], null, {
|
|
87
87
|
pipe: { stream, onWriteProgress: onProgress },
|
package/package.json
CHANGED
package/utils/fs.d.ts
CHANGED
|
@@ -96,12 +96,13 @@ export declare function createFileScanner(options: {
|
|
|
96
96
|
disposed: boolean;
|
|
97
97
|
total: number;
|
|
98
98
|
current: number;
|
|
99
|
-
progress: (description: string, path?: string) => Promise<void>;
|
|
99
|
+
progress: (description: string, path?: string, increment?: boolean) => Promise<void>;
|
|
100
100
|
end: () => Promise<void>;
|
|
101
101
|
start: (cb?: ((entry: Required<Entry>) => any) | undefined) => Promise<void>;
|
|
102
102
|
}>;
|
|
103
103
|
type StreamItem = {
|
|
104
104
|
key: string;
|
|
105
|
+
lines: number;
|
|
105
106
|
stream: WriteStream;
|
|
106
107
|
finished: boolean;
|
|
107
108
|
error?: Error;
|
|
@@ -113,6 +114,7 @@ export declare function createWriteStreamPool(options: {
|
|
|
113
114
|
}): {
|
|
114
115
|
pool: Record<string, StreamItem>;
|
|
115
116
|
path(key: string | number): string | undefined;
|
|
117
|
+
lines(key: string | number): number;
|
|
116
118
|
writeLine(key: string | number, v: string): boolean;
|
|
117
119
|
end(): Promise<void>;
|
|
118
120
|
};
|
package/utils/fs.js
CHANGED
|
@@ -410,10 +410,10 @@ async function createFileScanner(options) {
|
|
|
410
410
|
disposed: false,
|
|
411
411
|
total: 0,
|
|
412
412
|
current: 0,
|
|
413
|
-
progress: async (description, path) => {
|
|
413
|
+
progress: async (description, path, increment = true) => {
|
|
414
414
|
if (object.disposed)
|
|
415
415
|
return;
|
|
416
|
-
if (path)
|
|
416
|
+
if (path && increment)
|
|
417
417
|
object.current++;
|
|
418
418
|
await options.onProgress({
|
|
419
419
|
relative: {
|
|
@@ -463,6 +463,7 @@ function createWriteStreamPool(options) {
|
|
|
463
463
|
const create = (key) => {
|
|
464
464
|
const item = {
|
|
465
465
|
key,
|
|
466
|
+
lines: 0,
|
|
466
467
|
stream: (0, fs_2.createWriteStream)((0, path_2.join)(options.path, options.onStreamPath ? options.onStreamPath(key) : key)),
|
|
467
468
|
finished: false,
|
|
468
469
|
};
|
|
@@ -484,16 +485,22 @@ function createWriteStreamPool(options) {
|
|
|
484
485
|
throw new Error(`Stream path is not defined: ${key}`);
|
|
485
486
|
return item.stream.path;
|
|
486
487
|
},
|
|
488
|
+
lines(key) {
|
|
489
|
+
const item = pool[key];
|
|
490
|
+
return item?.lines;
|
|
491
|
+
},
|
|
487
492
|
writeLine(key, v) {
|
|
488
493
|
const item = pool[key] || create(key.toString());
|
|
489
494
|
if (item.finished) {
|
|
490
495
|
return false;
|
|
491
496
|
}
|
|
492
497
|
else if (item.written) {
|
|
498
|
+
item.lines++;
|
|
493
499
|
return item.stream.write(`\n${v}`);
|
|
494
500
|
}
|
|
495
501
|
else {
|
|
496
502
|
item.written = true;
|
|
503
|
+
item.lines++;
|
|
497
504
|
return item.stream.write(`${v}`);
|
|
498
505
|
}
|
|
499
506
|
},
|
package/utils/tar.js
CHANGED
|
@@ -137,21 +137,23 @@ async function createTar(options) {
|
|
|
137
137
|
}, {
|
|
138
138
|
log: options.verbose ? { envNames: Object.keys(env) } : false,
|
|
139
139
|
stderr: { toExitCode: true },
|
|
140
|
-
stdout:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
140
|
+
stdout: options.onEntry
|
|
141
|
+
? {
|
|
142
|
+
parseLines: "skip-empty",
|
|
143
|
+
onData: (line) => {
|
|
144
|
+
current++;
|
|
145
|
+
const path = vendor === "bsdtar" ? line.slice(2) : line;
|
|
146
|
+
options.onEntry?.({
|
|
147
|
+
path,
|
|
148
|
+
progress: {
|
|
149
|
+
total,
|
|
150
|
+
current,
|
|
151
|
+
percent: (0, math_1.progressPercent)(total, current),
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
},
|
|
155
|
+
}
|
|
156
|
+
: undefined,
|
|
155
157
|
});
|
|
156
158
|
}
|
|
157
159
|
exports.createTar = createTar;
|
|
@@ -164,10 +166,11 @@ function toLocalPath(path) {
|
|
|
164
166
|
async function extractTar(options) {
|
|
165
167
|
let total = options.total ??
|
|
166
168
|
(await listTar({ input: options.input, verbose: options.verbose }));
|
|
167
|
-
if (options.
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
if (!(await (0, fs_1.existsDir)(options.output))) {
|
|
170
|
+
if (options.verbose)
|
|
171
|
+
(0, cli_1.logExec)("mkdir", ["-p", options.output]);
|
|
172
|
+
await (0, promises_1.mkdir)(options.output, { recursive: true });
|
|
173
|
+
}
|
|
171
174
|
const decompress = await ifX(options.decompress, async (decompress) => ({
|
|
172
175
|
...decompress,
|
|
173
176
|
cores: await resolveCores(decompress.cores),
|
|
@@ -192,20 +195,22 @@ async function extractTar(options) {
|
|
|
192
195
|
stderr: {
|
|
193
196
|
toExitCode: true,
|
|
194
197
|
},
|
|
195
|
-
stdout:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
198
|
+
stdout: options.onEntry
|
|
199
|
+
? {
|
|
200
|
+
parseLines: "skip-empty",
|
|
201
|
+
onData: (path) => {
|
|
202
|
+
current++;
|
|
203
|
+
options.onEntry?.({
|
|
204
|
+
path,
|
|
205
|
+
progress: {
|
|
206
|
+
total,
|
|
207
|
+
current,
|
|
208
|
+
percent: (0, math_1.progressPercent)(total, current),
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
},
|
|
212
|
+
}
|
|
213
|
+
: undefined,
|
|
209
214
|
});
|
|
210
215
|
}
|
|
211
216
|
exports.extractTar = extractTar;
|