@datatruck/cli 0.10.0 → 0.11.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.
@@ -51,8 +51,9 @@ class BackupSessionsCommand extends CommandAbstract_1.CommandAbstract {
51
51
  }),
52
52
  verbose: verbose > 1,
53
53
  });
54
+ const items = await action.exec(manager);
54
55
  const dataFormat = new DataFormat_1.DataFormat({
55
- items: await action.exec(manager),
56
+ items,
56
57
  table: {
57
58
  labels: [
58
59
  " ",
@@ -77,7 +78,13 @@ class BackupSessionsCommand extends CommandAbstract_1.CommandAbstract {
77
78
  },
78
79
  });
79
80
  if (this.globalOptions.outputFormat)
80
- console.info(dataFormat.format(this.globalOptions.outputFormat));
81
+ console.info(dataFormat.format(this.globalOptions.outputFormat, {
82
+ tpl: {
83
+ sids: () => items.map((i) => i.snapshotId).join(),
84
+ ssids: () => items.map((i) => i.snapshotId.slice(0, 8)).join(),
85
+ pkgNames: () => items.map((i) => i.packageName).join(),
86
+ },
87
+ }));
81
88
  return 0;
82
89
  }
83
90
  }
@@ -8,7 +8,7 @@ export declare type ConfigCommandOptionsType<TResolved = false> = {
8
8
  repositoryType?: If<TResolved, RepositoryConfigType["type"][]>;
9
9
  };
10
10
  export declare type ConfigCommandLogType = {
11
- package: string;
11
+ packageName: string;
12
12
  repositoryNames: string[];
13
13
  taskName: string | undefined;
14
14
  }[];
@@ -40,7 +40,7 @@ class ConfigCommand extends CommandAbstract_1.CommandAbstract {
40
40
  repositoryTypes: this.options.repositoryType,
41
41
  });
42
42
  const summaryConfig = packages.flatMap((pkg) => ({
43
- package: pkg.name,
43
+ packageName: pkg.name,
44
44
  repositoryNames: pkg.repositoryNames ?? [],
45
45
  taskName: pkg.task?.name,
46
46
  }));
@@ -49,14 +49,18 @@ class ConfigCommand extends CommandAbstract_1.CommandAbstract {
49
49
  table: {
50
50
  labels: ["Package", "Repository", "Task"],
51
51
  handler: (item) => [
52
- item.package,
52
+ item.packageName,
53
53
  item.repositoryNames.join(", "),
54
54
  item.taskName ?? "",
55
55
  ],
56
56
  },
57
57
  });
58
58
  if (this.globalOptions.outputFormat)
59
- console.info(dataFormat.format(this.globalOptions.outputFormat));
59
+ console.info(dataFormat.format(this.globalOptions.outputFormat, {
60
+ tpl: {
61
+ pkgNames: () => summaryConfig.map((i) => i.packageName).join(),
62
+ },
63
+ }));
60
64
  return 0;
61
65
  }
62
66
  }
@@ -50,8 +50,9 @@ class RestoreSessionsCommand extends CommandAbstract_1.CommandAbstract {
50
50
  verbose: verbose > 1,
51
51
  }),
52
52
  });
53
+ const items = await action.exec(manager);
53
54
  const dataFormat = new DataFormat_1.DataFormat({
54
- items: await action.exec(manager),
55
+ items,
55
56
  table: {
56
57
  labels: [
57
58
  " ",
@@ -76,7 +77,13 @@ class RestoreSessionsCommand extends CommandAbstract_1.CommandAbstract {
76
77
  },
77
78
  });
78
79
  if (this.globalOptions.outputFormat)
79
- console.info(dataFormat.format(this.globalOptions.outputFormat));
80
+ console.info(dataFormat.format(this.globalOptions.outputFormat, {
81
+ tpl: {
82
+ sids: () => items.map((i) => i.snapshotId).join(),
83
+ ssids: () => items.map((i) => i.snapshotId.slice(0, 8)).join(),
84
+ pkgNames: () => items.map((i) => i.packageName).join(),
85
+ },
86
+ }));
80
87
  return 0;
81
88
  }
82
89
  }
@@ -106,8 +106,9 @@ class SnapshotsCommand extends CommandAbstract_1.CommandAbstract {
106
106
  verbose: verbose > 0,
107
107
  tags: this.options.tag,
108
108
  });
109
+ const items = await snapshots.exec();
109
110
  const dataFormat = new DataFormat_1.DataFormat({
110
- items: await snapshots.exec(),
111
+ items,
111
112
  table: {
112
113
  labels: [
113
114
  "Id.",
@@ -128,7 +129,13 @@ class SnapshotsCommand extends CommandAbstract_1.CommandAbstract {
128
129
  },
129
130
  });
130
131
  if (this.globalOptions.outputFormat)
131
- console.info(dataFormat.format(this.globalOptions.outputFormat));
132
+ console.info(dataFormat.format(this.globalOptions.outputFormat, {
133
+ tpl: {
134
+ sids: () => items.map((i) => i.id).join(),
135
+ ssids: () => items.map((i) => i.shortId).join(),
136
+ pkgNames: () => items.map((i) => i.packageName).join(),
137
+ },
138
+ }));
132
139
  return 0;
133
140
  }
134
141
  }
package/cli.js CHANGED
@@ -78,9 +78,10 @@ const cwd = process.cwd();
78
78
  program.name(subname);
79
79
  program.version(version);
80
80
  program.description(description);
81
+ program.usage("dtt");
81
82
  program.option("-v,--verbose", "Verbose", (_, previous) => previous + 1, 0);
82
83
  program.option("-c,--config <path>", "Config path", process.env["DATATRUCK_CONFIG"] ?? (cwd.endsWith(path_1.sep) ? cwd : `${cwd}${path_1.sep}`));
83
- program.option("-o,--output-format <format>", "Output format (json, pjson, yaml, table, custom=$)", "table");
84
+ program.option("-o,--output-format <format>", "Output format (json, pjson, yaml, table, custom=$, tpl=name)", "table");
84
85
  makeCommand(CommandFactory_1.CommandEnum.config).alias("c");
85
86
  makeCommand(CommandFactory_1.CommandEnum.init).alias("i");
86
87
  makeCommand(CommandFactory_1.CommandEnum.snapshots).alias("s");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datatruck/cli",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "dependencies": {
5
5
  "ajv": "^8.11.0",
6
6
  "async": "^3.2.4",
@@ -1,4 +1,4 @@
1
- export declare type FormatType = "json" | "pjson" | "table" | "yaml" | "custom";
1
+ export declare type FormatType = "json" | "pjson" | "table" | "yaml" | "custom" | "tpl";
2
2
  export declare class DataFormat<TItem extends Record<string, unknown>> {
3
3
  readonly options: {
4
4
  items: TItem[];
@@ -20,5 +20,7 @@ export declare class DataFormat<TItem extends Record<string, unknown>> {
20
20
  protected formatToPrettyJson(): string;
21
21
  protected formatToYaml(): any;
22
22
  protected formatToTable(): string;
23
- format(format: FormatType): any;
23
+ format(format: FormatType, options?: {
24
+ tpl?: Record<string, () => string>;
25
+ }): any;
24
26
  }
@@ -8,6 +8,7 @@ const AppError_1 = require("../Error/AppError");
8
8
  const cli_table3_1 = __importDefault(require("cli-table3"));
9
9
  const util_1 = require("util");
10
10
  const customPrefix = "custom=";
11
+ const tplPrefix = "tpl=";
11
12
  class DataFormat {
12
13
  constructor(options) {
13
14
  this.options = options;
@@ -34,7 +35,7 @@ class DataFormat {
34
35
  table.push(this.options.table.handler(item));
35
36
  return table.toString();
36
37
  }
37
- format(format) {
38
+ format(format, options) {
38
39
  if (format === "table") {
39
40
  return this.formatToTable();
40
41
  }
@@ -51,6 +52,15 @@ class DataFormat {
51
52
  const code = format.slice(customPrefix.length);
52
53
  return runCustomCode(this.options.items, code);
53
54
  }
55
+ else if (format.startsWith(tplPrefix)) {
56
+ const name = format.slice(tplPrefix.length);
57
+ const tpl = options?.tpl || {};
58
+ if (!(name in tpl)) {
59
+ const tplNames = Object.keys(tpl).join(", ");
60
+ throw new AppError_1.AppError(`Template name not found: ${name} (valid names: ${tplNames})`);
61
+ }
62
+ return tpl[name]();
63
+ }
54
64
  else {
55
65
  throw new AppError_1.AppError(`Invalid output format: ${format}`);
56
66
  }
package/util/fs-util.d.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
+ /// <reference types="node" />
4
+ import { Stats } from "fs";
3
5
  import { Interface } from "readline";
6
+ export declare const isWSLSystem: boolean;
4
7
  export declare function isLocalDir(path: string): boolean;
5
8
  export declare function isDirEmpty(path: string): Promise<boolean>;
6
9
  export declare function mkdirIfNotExists(path: string): Promise<string>;
@@ -47,6 +50,8 @@ export declare function writePathLists(options: {
47
50
  multipleStats: Record<string, number>;
48
51
  };
49
52
  }>;
53
+ export declare function copyFileWithStreams(source: string, target: string): Promise<unknown>;
54
+ export declare function updateFileStats(path: string, fileInfo: Stats): Promise<void>;
50
55
  export declare function cpy(options: {
51
56
  input: {
52
57
  type: "glob";
package/util/fs-util.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.cpy = exports.writePathLists = exports.writeGitIgnoreList = exports.forEachFile = exports.readDir = exports.checkDir = exports.checkFile = exports.readPartialFile = exports.mkTmpDir = exports.tmpDir = exports.sessionTmpDir = exports.parentTmpDir = exports.existsFile = exports.findFile = exports.parsePackageFile = exports.parseFile = exports.parseFileExtensions = exports.readdirIfExists = exports.writeJSONFile = exports.existsDir = exports.ensureEmptyDir = exports.mkdirIfNotExists = exports.isDirEmpty = exports.isLocalDir = void 0;
6
+ exports.cpy = exports.updateFileStats = exports.copyFileWithStreams = exports.writePathLists = exports.writeGitIgnoreList = exports.forEachFile = exports.readDir = exports.checkDir = exports.checkFile = exports.readPartialFile = exports.mkTmpDir = exports.tmpDir = exports.sessionTmpDir = exports.parentTmpDir = exports.existsFile = exports.findFile = exports.parsePackageFile = exports.parseFile = exports.parseFileExtensions = exports.readdirIfExists = exports.writeJSONFile = exports.existsDir = exports.ensureEmptyDir = exports.mkdirIfNotExists = exports.isDirEmpty = exports.isLocalDir = exports.isWSLSystem = void 0;
7
7
  const globalData_1 = __importDefault(require("../globalData"));
8
8
  const path_util_1 = require("./path-util");
9
9
  const async_1 = require("async");
@@ -13,9 +13,11 @@ const fs_1 = require("fs");
13
13
  const fs_2 = require("fs");
14
14
  const promises_1 = require("fs/promises");
15
15
  const micromatch_1 = require("micromatch");
16
+ const os_1 = require("os");
16
17
  const path_1 = require("path");
17
18
  const path_2 = require("path");
18
19
  const readline_1 = require("readline");
20
+ exports.isWSLSystem = (0, os_1.release)().includes("microsoft-standard-WSL");
19
21
  function isLocalDir(path) {
20
22
  return /^[\/\.]|([A-Z]:)/i.test(path);
21
23
  }
@@ -332,6 +334,30 @@ async function writePathLists(options) {
332
334
  };
333
335
  }
334
336
  exports.writePathLists = writePathLists;
337
+ async function copyFileWithStreams(source, target) {
338
+ const r = (0, fs_1.createReadStream)(source);
339
+ const w = (0, fs_2.createWriteStream)(target);
340
+ try {
341
+ return await new Promise((resolve, reject) => {
342
+ r.on("error", reject);
343
+ w.on("error", reject);
344
+ w.on("finish", resolve);
345
+ r.pipe(w);
346
+ });
347
+ }
348
+ catch (error) {
349
+ r.destroy();
350
+ w.end();
351
+ throw error;
352
+ }
353
+ }
354
+ exports.copyFileWithStreams = copyFileWithStreams;
355
+ async function updateFileStats(path, fileInfo) {
356
+ await (0, promises_1.utimes)(path, fileInfo.atime, fileInfo.mtime);
357
+ await (0, promises_1.chmod)(path, fileInfo.mode);
358
+ await (0, promises_1.chown)(path, fileInfo.uid, fileInfo.gid);
359
+ }
360
+ exports.updateFileStats = updateFileStats;
335
361
  async function cpy(options) {
336
362
  const stats = { paths: 0, files: 0, dirs: 0 };
337
363
  const dirs = new Set();
@@ -367,7 +393,19 @@ async function cpy(options) {
367
393
  const dir = (0, path_1.dirname)(entryTargetPath);
368
394
  await makeRecursiveDir(dir);
369
395
  stats.files++;
370
- await (0, promises_1.cp)(entrySourcePath, entryTargetPath);
396
+ // https://github.com/nodejs/node/issues/44261
397
+ if (exports.isWSLSystem) {
398
+ const fileInfo = await (0, promises_1.stat)(entryTargetPath);
399
+ const isWritable = (fileInfo.mode & 0o200) === 0o200;
400
+ if (!isWritable) {
401
+ await copyFileWithStreams(entrySourcePath, entryTargetPath);
402
+ await updateFileStats(entryTargetPath, fileInfo);
403
+ return;
404
+ }
405
+ }
406
+ await (0, promises_1.cp)(entrySourcePath, entryTargetPath, {
407
+ preserveTimestamps: true,
408
+ });
371
409
  }
372
410
  };
373
411
  const { input } = options;