@datatruck/cli 0.34.4 → 0.35.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.
@@ -399,6 +399,63 @@
399
399
  "name"
400
400
  ]
401
401
  },
402
+ {
403
+ "type": "object",
404
+ "properties": {
405
+ "name": {
406
+ "type": "string",
407
+ "const": "mongo-dump"
408
+ },
409
+ "config": {
410
+ "type": "object",
411
+ "properties": {
412
+ "command": {
413
+ "type": "string"
414
+ },
415
+ "hostname": {
416
+ "type": "string"
417
+ },
418
+ "port": {
419
+ "type": "number"
420
+ },
421
+ "username": {
422
+ "type": "string"
423
+ },
424
+ "password": {
425
+ "anyOf": [
426
+ {
427
+ "type": "object",
428
+ "properties": {
429
+ "path": {
430
+ "type": "string"
431
+ }
432
+ },
433
+ "additionalProperties": false,
434
+ "required": [
435
+ "path"
436
+ ]
437
+ },
438
+ {
439
+ "type": "string"
440
+ }
441
+ ]
442
+ },
443
+ "compress": {
444
+ "type": "boolean"
445
+ },
446
+ "concurrency": {
447
+ "type": "number"
448
+ }
449
+ },
450
+ "additionalProperties": false
451
+ }
452
+ },
453
+ "additionalProperties": false,
454
+ "required": [
455
+ "config",
456
+ "name"
457
+ ]
458
+ },
402
459
  {
403
460
  "type": "object",
404
461
  "properties": {
@@ -1,4 +1,49 @@
1
1
  "use strict";
2
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
3
+ if (value !== null && value !== void 0) {
4
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
5
+ var dispose;
6
+ if (async) {
7
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
8
+ dispose = value[Symbol.asyncDispose];
9
+ }
10
+ if (dispose === void 0) {
11
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
12
+ dispose = value[Symbol.dispose];
13
+ }
14
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
+ env.stack.push({ value: value, dispose: dispose, async: async });
16
+ }
17
+ else if (async) {
18
+ env.stack.push({ async: true });
19
+ }
20
+ return value;
21
+ };
22
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
23
+ return function (env) {
24
+ function fail(e) {
25
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
26
+ env.hasError = true;
27
+ }
28
+ function next() {
29
+ while (env.stack.length) {
30
+ var rec = env.stack.pop();
31
+ try {
32
+ var result = rec.dispose && rec.dispose.call(rec.value);
33
+ if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
34
+ }
35
+ catch (e) {
36
+ fail(e);
37
+ }
38
+ }
39
+ if (env.hasError) throw env.error;
40
+ }
41
+ return next();
42
+ };
43
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
44
+ var e = new Error(message);
45
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
46
+ });
2
47
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
48
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
49
  };
@@ -166,6 +211,7 @@ class BackupAction {
166
211
  }
167
212
  async exec() {
168
213
  const { options } = this;
214
+ const gc = new temp_1.GargabeCollector();
169
215
  const pm = new progress_1.ProgressManager({
170
216
  verbose: options.verbose,
171
217
  tty: options.tty,
@@ -174,6 +220,7 @@ class BackupAction {
174
220
  const l = new list_1.Listr3({
175
221
  streams: this.options.streams,
176
222
  progressManager: pm,
223
+ gargabeCollector: gc,
177
224
  });
178
225
  return l
179
226
  .add([
@@ -197,11 +244,11 @@ class BackupAction {
197
244
  return [
198
245
  ...packages.flatMap((pkg) => {
199
246
  let taskResult = {};
200
- const gc = new temp_1.GargabeCollector();
201
247
  const repositories = this.getRepositoryNames(pkg.repositoryNames ?? []);
202
248
  const mirrorRepositories = repositories
203
249
  .filter((r) => r.mirrors.length)
204
250
  .flatMap(({ name, mirrors }) => mirrors.map((mirror) => ({ name, mirror })));
251
+ const taskGc = gc.create();
205
252
  return l.$tasks(!!pkg.task &&
206
253
  l.$task({
207
254
  key: "task",
@@ -214,13 +261,25 @@ class BackupAction {
214
261
  completed: `Task executed: ${pkg.name} (${pkg.task.name})`,
215
262
  },
216
263
  exitOnError: false,
217
- runWrapper: gc.cleanupIfFail.bind(gc),
218
264
  run: async (task) => {
219
- taskResult = await (0, task_1.createTask)(pkg.task).backup({
220
- options,
221
- package: pkg,
222
- snapshot,
223
- onProgress: (p) => pm.update(p, (t) => (task.output = t)),
265
+ await taskGc.disposeIfFail(async () => {
266
+ const env_1 = { stack: [], error: void 0, hasError: false };
267
+ try {
268
+ const progress = __addDisposableResource(env_1, pm.create(task), false);
269
+ taskResult = await (0, task_1.createTask)(pkg.task).backup({
270
+ options,
271
+ package: pkg,
272
+ snapshot,
273
+ onProgress: progress.update,
274
+ });
275
+ }
276
+ catch (e_1) {
277
+ env_1.error = e_1;
278
+ env_1.hasError = true;
279
+ }
280
+ finally {
281
+ __disposeResources(env_1);
282
+ }
224
283
  });
225
284
  },
226
285
  }), ...repositories.map(({ name: repositoryName }) => l.$task({
@@ -238,21 +297,34 @@ class BackupAction {
238
297
  failed: `Backup create failed: ${pkg.name} (${repositoryName})`,
239
298
  },
240
299
  exitOnError: false,
241
- runWrapper: gc.cleanupOnFinish.bind(gc),
242
300
  run: async (task, data) => {
243
- const taskSummary = pkg.task
244
- ? l.result("task", pkg.name)
245
- : undefined;
246
- if (taskSummary?.error)
247
- throw new error_1.AppError(`Task failed`);
248
- const backup = await this.backup({
249
- pkg,
250
- repositoryName,
251
- snapshot,
252
- snapshotPath: taskResult?.snapshotPath,
253
- onProgress: (p) => pm.update(p, (t) => (task.output = t)),
254
- });
255
- data.bytes = backup.bytes;
301
+ const env_2 = { stack: [], error: void 0, hasError: false };
302
+ try {
303
+ const _ = __addDisposableResource(env_2, gc.create().disposeOnFinish(), true);
304
+ const taskSummary = pkg.task
305
+ ? l.result("task", pkg.name)
306
+ : undefined;
307
+ if (taskSummary?.error)
308
+ throw new error_1.AppError(`Task failed`);
309
+ const progress = __addDisposableResource(env_2, pm.create(task), false);
310
+ const backup = await this.backup({
311
+ pkg,
312
+ repositoryName,
313
+ snapshot,
314
+ snapshotPath: taskResult?.snapshotPath,
315
+ onProgress: progress.update,
316
+ });
317
+ data.bytes = backup.bytes;
318
+ }
319
+ catch (e_2) {
320
+ env_2.error = e_2;
321
+ env_2.hasError = true;
322
+ }
323
+ finally {
324
+ const result_1 = __disposeResources(env_2);
325
+ if (result_1)
326
+ await result_1;
327
+ }
256
328
  },
257
329
  })), l.$task({
258
330
  key: "cleanup",
@@ -265,8 +337,8 @@ class BackupAction {
265
337
  failed: "Task files clean failed",
266
338
  },
267
339
  exitOnError: false,
268
- enabled: gc.pending,
269
- run: () => gc.cleanup(),
340
+ enabled: taskGc.pending(),
341
+ run: () => taskGc.dispose(),
270
342
  }), ...mirrorRepositories.map(({ name, mirror }) => l.$task({
271
343
  key: "copy",
272
344
  keyIndex: [pkg.name, mirror],
@@ -283,22 +355,35 @@ class BackupAction {
283
355
  failed: `Snapshot copy failed: ${pkg.name} (${mirror})`,
284
356
  },
285
357
  exitOnError: false,
286
- runWrapper: gc.cleanup.bind(gc),
287
358
  run: async (task, data) => {
288
- const backupSummary = l.result("backup", [
289
- pkg.name,
290
- name,
291
- ]);
292
- if (backupSummary.error)
293
- throw new error_1.AppError(`Backup failed`);
294
- const copy = await this.copy({
295
- repositoryName: name,
296
- mirrorRepositoryName: mirror,
297
- pkg,
298
- snapshot,
299
- onProgress: (p) => pm.update(p, (t) => (task.output = t)),
300
- });
301
- data.bytes = copy.bytes;
359
+ const env_3 = { stack: [], error: void 0, hasError: false };
360
+ try {
361
+ const _ = __addDisposableResource(env_3, gc.create().disposeOnFinish(), true);
362
+ const backupSummary = l.result("backup", [
363
+ pkg.name,
364
+ name,
365
+ ]);
366
+ if (backupSummary.error)
367
+ throw new error_1.AppError(`Backup failed`);
368
+ const progress = __addDisposableResource(env_3, pm.create(task), false);
369
+ const copy = await this.copy({
370
+ repositoryName: name,
371
+ mirrorRepositoryName: mirror,
372
+ pkg,
373
+ snapshot,
374
+ onProgress: progress.update,
375
+ });
376
+ data.bytes = copy.bytes;
377
+ }
378
+ catch (e_3) {
379
+ env_3.error = e_3;
380
+ env_3.hasError = true;
381
+ }
382
+ finally {
383
+ const result_2 = __disposeResources(env_3);
384
+ if (result_2)
385
+ await result_2;
386
+ }
302
387
  },
303
388
  })), !!this.options.prune &&
304
389
  l.$task({
@@ -269,26 +269,48 @@ class CopyAction {
269
269
  ? sourceRepo.get()
270
270
  : undefined;
271
271
  if ($sourceRepo) {
272
- const copy = await $sourceRepo.copy({
273
- mirrorRepositoryConfig: mirrorConfig.config,
274
- options: { verbose: this.options.verbose },
275
- package: { name: snapshot.packageName },
276
- snapshot,
277
- onProgress: (p) => pm.update(p, (d) => (task.output = d)),
278
- });
279
- data.bytes = copy.bytes;
272
+ const env_2 = { stack: [], error: void 0, hasError: false };
273
+ try {
274
+ const progress = __addDisposableResource(env_2, pm.create(task), false);
275
+ const copy = await $sourceRepo.copy({
276
+ mirrorRepositoryConfig: mirrorConfig.config,
277
+ options: { verbose: this.options.verbose },
278
+ package: { name: snapshot.packageName },
279
+ snapshot,
280
+ onProgress: progress.update,
281
+ });
282
+ data.bytes = copy.bytes;
283
+ }
284
+ catch (e_2) {
285
+ env_2.error = e_2;
286
+ env_2.hasError = true;
287
+ }
288
+ finally {
289
+ __disposeResources(env_2);
290
+ }
280
291
  }
281
292
  else {
282
- const copy = await this.copyCrossRepository({
283
- mirrorConfig,
284
- mirrorRepo,
285
- repo,
286
- repoConfig,
287
- snapshot,
288
- onProgress: (p) => pm.update(p, (d) => (task.output = d)),
289
- });
290
- data.bytes = copy.bytes;
291
- sourceRepo.set(mirrorRepo);
293
+ const env_3 = { stack: [], error: void 0, hasError: false };
294
+ try {
295
+ const progress = __addDisposableResource(env_3, pm.create(task), false);
296
+ const copy = await this.copyCrossRepository({
297
+ mirrorConfig,
298
+ mirrorRepo,
299
+ repo,
300
+ repoConfig,
301
+ snapshot,
302
+ onProgress: progress.update,
303
+ });
304
+ data.bytes = copy.bytes;
305
+ sourceRepo.set(mirrorRepo);
306
+ }
307
+ catch (e_3) {
308
+ env_3.error = e_3;
309
+ env_3.hasError = true;
310
+ }
311
+ finally {
312
+ __disposeResources(env_3);
313
+ }
292
314
  }
293
315
  },
294
316
  });
@@ -21,7 +21,7 @@ class InitAction {
21
21
  if (this.options.repositoryTypes &&
22
22
  !this.options.repositoryTypes.includes(repoConfig.type))
23
23
  continue;
24
- const repo = (0, repository_1.createRepo)(repoConfig);
24
+ const repo = (0, repository_1.createRepo)(repoConfig, this.options.verbose);
25
25
  let initError = null;
26
26
  try {
27
27
  await repo.init({
@@ -5,7 +5,6 @@ import type { Config, PackageConfig } from "../utils/datatruck/config-type";
5
5
  import { Listr3TaskResultEnd } from "../utils/list";
6
6
  import { Progress, ProgressMode } from "../utils/progress";
7
7
  import { StdStreams } from "../utils/stream";
8
- import { GargabeCollector } from "../utils/temp";
9
8
  import { IfRequireKeys } from "../utils/ts";
10
9
  export type RestoreActionOptions = {
11
10
  snapshotId: string;
@@ -47,7 +46,6 @@ export declare class RestoreAction<TRequired extends boolean = true> {
47
46
  pkg: PackageConfig;
48
47
  task: TaskAbstract | undefined;
49
48
  snapshot: RestoreSnapshot;
50
- gc: GargabeCollector;
51
49
  onProgress: (progress: Progress) => void;
52
50
  }): Promise<{
53
51
  snapshotPath: string | undefined;
@@ -1,4 +1,49 @@
1
1
  "use strict";
2
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
3
+ if (value !== null && value !== void 0) {
4
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
5
+ var dispose;
6
+ if (async) {
7
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
8
+ dispose = value[Symbol.asyncDispose];
9
+ }
10
+ if (dispose === void 0) {
11
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
12
+ dispose = value[Symbol.dispose];
13
+ }
14
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
+ env.stack.push({ value: value, dispose: dispose, async: async });
16
+ }
17
+ else if (async) {
18
+ env.stack.push({ async: true });
19
+ }
20
+ return value;
21
+ };
22
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
23
+ return function (env) {
24
+ function fail(e) {
25
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
26
+ env.hasError = true;
27
+ }
28
+ function next() {
29
+ while (env.stack.length) {
30
+ var rec = env.stack.pop();
31
+ try {
32
+ var result = rec.dispose && rec.dispose.call(rec.value);
33
+ if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
34
+ }
35
+ catch (e) {
36
+ fail(e);
37
+ }
38
+ }
39
+ if (env.hasError) throw env.error;
40
+ }
41
+ return next();
42
+ };
43
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
44
+ var e = new Error(message);
45
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
46
+ });
2
47
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
48
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
49
  };
@@ -71,27 +116,25 @@ class RestoreAction {
71
116
  const repoConfig = (0, config_1.findRepositoryOrFail)(this.config, snapshot.repositoryName);
72
117
  const repo = await (0, repository_1.createAndInitRepo)(repoConfig, this.options.verbose);
73
118
  let snapshotPath = pkg.restorePath ?? pkg.path;
74
- await data.gc.cleanupIfFail(async () => {
75
- if (task) {
76
- const taskResult = await task.prepareRestore({
77
- options: this.options,
78
- package: pkg,
79
- snapshot,
80
- });
81
- snapshotPath = taskResult?.snapshotPath;
82
- }
83
- await (0, fs_1.initEmptyDir)(snapshotPath);
84
- if (this.config.minFreeDiskSpace)
85
- await (0, fs_1.ensureFreeDiskSpace)([snapshotPath], this.config.minFreeDiskSpace);
86
- await repo.restore({
119
+ if (task) {
120
+ const taskResult = await task.prepareRestore({
87
121
  options: this.options,
88
- snapshot: data.snapshot,
89
122
  package: pkg,
90
- snapshotPath: snapshotPath,
91
- packageConfig: pkg.repositoryConfigs?.find((config) => config.type === repoConfig.type &&
92
- (!config.names || config.names.includes(repoConfig.name)))?.config,
93
- onProgress: data.onProgress,
123
+ snapshot,
94
124
  });
125
+ snapshotPath = taskResult?.snapshotPath;
126
+ }
127
+ await (0, fs_1.initEmptyDir)(snapshotPath);
128
+ if (this.config.minFreeDiskSpace)
129
+ await (0, fs_1.ensureFreeDiskSpace)([snapshotPath], this.config.minFreeDiskSpace);
130
+ await repo.restore({
131
+ options: this.options,
132
+ snapshot: data.snapshot,
133
+ package: pkg,
134
+ snapshotPath: snapshotPath,
135
+ packageConfig: pkg.repositoryConfigs?.find((config) => config.type === repoConfig.type &&
136
+ (!config.names || config.names.includes(repoConfig.name)))?.config,
137
+ onProgress: data.onProgress,
95
138
  });
96
139
  return { snapshotPath };
97
140
  }
@@ -139,6 +182,7 @@ class RestoreAction {
139
182
  }
140
183
  async exec() {
141
184
  const { options } = this;
185
+ const gc = new temp_1.GargabeCollector();
142
186
  const pm = new progress_1.ProgressManager({
143
187
  verbose: options.verbose,
144
188
  tty: options.tty,
@@ -147,6 +191,7 @@ class RestoreAction {
147
191
  const l = new list_1.Listr3({
148
192
  streams: options.streams,
149
193
  progressManager: pm,
194
+ gargabeCollector: gc,
150
195
  });
151
196
  return l
152
197
  .add(l.$task({
@@ -184,48 +229,71 @@ class RestoreAction {
184
229
  },
185
230
  exitOnError: false,
186
231
  run: async (listTask) => {
187
- let pkg = (0, config_1.resolvePackage)((0, config_1.findPackageOrFail)(this.config, snapshot.packageName), {
188
- snapshotId: options.snapshotId,
189
- snapshotDate: snapshot.date,
190
- action: "restore",
191
- });
192
- if (this.options.initial)
193
- pkg = { ...pkg, restorePath: pkg.path };
194
- const gc = new temp_1.GargabeCollector();
195
- const task = pkg.task ? (0, task_1.createTask)(pkg.task) : undefined;
196
- const restore = await this.restore({
197
- gc,
198
- pkg,
199
- task,
200
- snapshot: snapshot,
201
- onProgress: (p) => pm.update(p, (t) => (listTask.output = t)),
202
- });
203
- if (!task)
204
- return await gc.cleanup();
205
- return l.$tasks({
206
- key: "task",
207
- keyIndex: pkg.name,
208
- data: { taskName: pkg.task.name, packageName: pkg.name },
209
- title: {
210
- initial: `Execute task: ${pkg.name} (${pkg.task.name})`,
211
- started: `Executing task: ${pkg.name} (${pkg.task.name})`,
212
- completed: `Task executed: ${pkg.name} (${pkg.task.name})`,
213
- failed: `Task execute failed: ${pkg.name} (${pkg.task.name})`,
214
- },
215
- exitOnError: false,
216
- runWrapper: gc.cleanup.bind(gc),
217
- run: async (listTask) => {
218
- const { snapshotPath } = restore;
219
- (0, assert_1.ok)(snapshotPath);
220
- await task.restore({
221
- package: pkg,
222
- options,
223
- snapshot,
224
- snapshotPath,
225
- onProgress: (p) => pm.update(p, (t) => (listTask.output = t)),
226
- });
227
- },
228
- });
232
+ const env_1 = { stack: [], error: void 0, hasError: false };
233
+ try {
234
+ let pkg = (0, config_1.resolvePackage)((0, config_1.findPackageOrFail)(this.config, snapshot.packageName), {
235
+ snapshotId: options.snapshotId,
236
+ snapshotDate: snapshot.date,
237
+ action: "restore",
238
+ });
239
+ if (this.options.initial)
240
+ pkg = { ...pkg, restorePath: pkg.path };
241
+ const task = pkg.task ? (0, task_1.createTask)(pkg.task) : undefined;
242
+ const progress = __addDisposableResource(env_1, pm.create(listTask), false);
243
+ const restoreGc = gc.create();
244
+ const restore = await restoreGc.disposeIfFail(() => this.restore({
245
+ pkg,
246
+ task,
247
+ snapshot: snapshot,
248
+ onProgress: progress.update,
249
+ }));
250
+ if (!task)
251
+ return await restoreGc.dispose();
252
+ return l.$tasks({
253
+ key: "task",
254
+ keyIndex: pkg.name,
255
+ data: { taskName: pkg.task.name, packageName: pkg.name },
256
+ title: {
257
+ initial: `Execute task: ${pkg.name} (${pkg.task.name})`,
258
+ started: `Executing task: ${pkg.name} (${pkg.task.name})`,
259
+ completed: `Task executed: ${pkg.name} (${pkg.task.name})`,
260
+ failed: `Task execute failed: ${pkg.name} (${pkg.task.name})`,
261
+ },
262
+ exitOnError: false,
263
+ run: async (listTask) => {
264
+ const env_2 = { stack: [], error: void 0, hasError: false };
265
+ try {
266
+ const _ = __addDisposableResource(env_2, restoreGc.disposeOnFinish(), true);
267
+ const { snapshotPath } = restore;
268
+ (0, assert_1.ok)(snapshotPath);
269
+ const progress = __addDisposableResource(env_2, pm.create(listTask), false);
270
+ await task.restore({
271
+ package: pkg,
272
+ options,
273
+ snapshot,
274
+ snapshotPath,
275
+ onProgress: progress.update,
276
+ });
277
+ }
278
+ catch (e_2) {
279
+ env_2.error = e_2;
280
+ env_2.hasError = true;
281
+ }
282
+ finally {
283
+ const result_1 = __disposeResources(env_2);
284
+ if (result_1)
285
+ await result_1;
286
+ }
287
+ },
288
+ });
289
+ }
290
+ catch (e_1) {
291
+ env_1.error = e_1;
292
+ env_1.hasError = true;
293
+ }
294
+ finally {
295
+ __disposeResources(env_1);
296
+ }
229
297
  },
230
298
  }));
231
299
  },
@@ -12,7 +12,7 @@ export type MetaData = {
12
12
  files: number;
13
13
  size: number;
14
14
  checksum: string;
15
- }>;
15
+ } | undefined>;
16
16
  };
17
17
  export type DatatruckRepositoryConfig = {
18
18
  backend: string;