@datatruck/cli 0.30.0 → 0.31.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.
Files changed (50) hide show
  1. package/Action/BackupAction.d.ts +2 -4
  2. package/Action/BackupAction.js +2 -10
  3. package/Action/CopyAction.d.ts +2 -2
  4. package/Action/CopyAction.js +1 -2
  5. package/Action/RestoreAction.d.ts +2 -3
  6. package/Action/RestoreAction.js +1 -2
  7. package/CHANGELOG.md +16 -0
  8. package/Command/BackupCommand.d.ts +1 -1
  9. package/Command/BackupCommand.js +0 -1
  10. package/Command/CleanCacheCommand.d.ts +1 -1
  11. package/Command/CommandAbstract.d.ts +4 -3
  12. package/Command/CommandAbstract.js +3 -1
  13. package/Command/CopyCommand.d.ts +1 -1
  14. package/Command/CopyCommand.js +0 -1
  15. package/Command/RestoreCommand.d.ts +1 -1
  16. package/Command/RestoreCommand.js +0 -1
  17. package/Command/StartServerCommand.js +30 -8
  18. package/Config/Config.d.ts +7 -1
  19. package/Config/Config.js +79 -26
  20. package/Config/RepositoryConfig.d.ts +1 -0
  21. package/Config/RepositoryConfig.js +6 -1
  22. package/Factory/CommandFactory.d.ts +1 -1
  23. package/Factory/CommandFactory.js +2 -2
  24. package/JsonSchema/backup-def.d.ts +30 -0
  25. package/JsonSchema/backup-def.js +18 -0
  26. package/JsonSchema/copy-def.d.ts +24 -0
  27. package/JsonSchema/copy-def.js +15 -0
  28. package/Repository/DatatruckRepository.js +2 -0
  29. package/cli.js +5 -7
  30. package/config.schema.json +189 -39
  31. package/package.json +2 -1
  32. package/utils/cli.d.ts +3 -0
  33. package/utils/cli.js +21 -1
  34. package/utils/datatruck/client.js +3 -3
  35. package/utils/datatruck/cron-server.d.ts +23 -0
  36. package/utils/datatruck/cron-server.js +59 -0
  37. package/utils/datatruck/{server.d.ts → repository-server.d.ts} +12 -6
  38. package/utils/datatruck/{server.js → repository-server.js} +45 -28
  39. package/utils/http.d.ts +8 -2
  40. package/utils/http.js +16 -15
  41. package/utils/object.d.ts +1 -1
  42. package/utils/object.js +6 -6
  43. package/utils/progress.d.ts +17 -10
  44. package/utils/progress.js +20 -10
  45. package/utils/schema.d.ts +34 -0
  46. package/utils/schema.js +36 -0
  47. package/utils/string.d.ts +0 -3
  48. package/utils/string.js +1 -37
  49. package/utils/ObjectVault.d.ts +0 -13
  50. package/utils/ObjectVault.js +0 -29
package/utils/http.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.uploadFile = exports.downloadFile = exports.post = exports.fetchJson = exports.readRequestData = exports.closeServer = void 0;
3
+ exports.uploadFile = exports.downloadFile = exports.post = exports.fetchJson = exports.fetch = exports.readRequestData = exports.closeServer = void 0;
4
4
  const math_1 = require("./math");
5
5
  const fs_1 = require("fs");
6
6
  const promises_1 = require("fs/promises");
@@ -37,14 +37,15 @@ function readRequestData(req) {
37
37
  });
38
38
  }
39
39
  exports.readRequestData = readRequestData;
40
- async function fetchJson(url, options = {}) {
40
+ async function fetch(url, options = {}) {
41
+ const throwStatusCodeError = options.statusError ?? true;
41
42
  return new Promise((resolve, reject) => {
42
43
  let data;
43
44
  request(href(url, options.query), {
44
45
  method: "GET",
45
46
  headers: options.headers,
46
47
  }, (res) => {
47
- if (res.statusCode !== 200)
48
+ if (throwStatusCodeError && res.statusCode !== 200)
48
49
  return reject(new Error(`GET failed: ${res.statusCode} ${res.statusMessage}`));
49
50
  res
50
51
  .on("data", (chunk) => {
@@ -54,23 +55,20 @@ async function fetchJson(url, options = {}) {
54
55
  })
55
56
  .on("error", reject)
56
57
  .on("close", () => {
57
- if (data === undefined) {
58
- resolve(undefined);
59
- }
60
- else {
61
- try {
62
- resolve(JSON.parse(data));
63
- }
64
- catch (error) {
65
- reject(error);
66
- }
67
- }
58
+ resolve({ data, status: res.statusCode });
68
59
  });
69
60
  })
70
61
  .on("error", reject)
71
62
  .end();
72
63
  });
73
64
  }
65
+ exports.fetch = fetch;
66
+ async function fetchJson(url, options = {}) {
67
+ const res = await fetch(url, options);
68
+ if (res.data === undefined)
69
+ return;
70
+ return JSON.parse(res.data);
71
+ }
74
72
  exports.fetchJson = fetchJson;
75
73
  async function post(url, data, options = {}) {
76
74
  await new Promise((resolve, reject) => {
@@ -114,7 +112,10 @@ async function downloadFile(url, output, options = {}) {
114
112
  }
115
113
  res
116
114
  .on("error", async (error) => {
117
- file.destroy();
115
+ try {
116
+ file.destroy();
117
+ }
118
+ catch (_) { }
118
119
  try {
119
120
  await (0, promises_1.unlink)(output);
120
121
  }
package/utils/object.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export declare function merge<T extends Record<string, unknown>>(target: T, ...sources: Record<string, unknown>[]): T;
2
- export declare function push<T>(map: Record<string, T[]>, key: string, object: T): void;
2
+ export declare function omitProp<T extends Record<string, any>, N extends keyof T>(object: T, name: N): Omit<T, N>;
3
3
  export declare function getErrorProperties(error: Error): Record<string, string>;
4
4
  type GroupByKeyParamType<TItem> = ((item: TItem) => string[] | string) | (keyof TItem)[] | keyof TItem;
5
5
  export declare function groupBy<TItem>(items: TItem[], keyOrCb: GroupByKeyParamType<TItem>): Record<string, TItem[]>;
package/utils/object.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.groupBy = exports.getErrorProperties = exports.push = exports.merge = void 0;
3
+ exports.groupBy = exports.getErrorProperties = exports.omitProp = exports.merge = void 0;
4
4
  function merge(target, ...sources) {
5
5
  const isObject = (o) => typeof o === "object" && o !== null;
6
6
  for (const source of sources)
@@ -13,12 +13,12 @@ function merge(target, ...sources) {
13
13
  return target;
14
14
  }
15
15
  exports.merge = merge;
16
- function push(map, key, object) {
17
- if (!map[key])
18
- map[key] = [];
19
- map[key].push(object);
16
+ function omitProp(object, name) {
17
+ const result = { ...object };
18
+ delete result[name];
19
+ return result;
20
20
  }
21
- exports.push = push;
21
+ exports.omitProp = omitProp;
22
22
  function getErrorProperties(error) {
23
23
  const alt = {};
24
24
  for (const key of Object.getOwnPropertyNames(error)) {
@@ -17,29 +17,36 @@ export type Progress = {
17
17
  absolute?: ProgressStats;
18
18
  relative?: ProgressStats;
19
19
  };
20
+ export type ProgressTty = "auto" | boolean;
21
+ export type ProgressMode = "auto" | "interval" | `interval:${number}` | boolean;
20
22
  export declare class ProgressManager {
21
23
  readonly options: {
22
24
  verbose?: boolean;
23
25
  /**
24
- * @default true
26
+ * @default false
25
27
  */
26
- tty?: boolean | "auto";
27
- enabled?: boolean | "auto" | "interval";
28
- interval?: number;
28
+ tty?: ProgressTty;
29
+ /**
30
+ * @default "interval"
31
+ */
32
+ mode?: ProgressMode;
29
33
  };
30
34
  protected timer: Timer;
31
35
  protected interval: Timer | undefined;
36
+ protected intervalMs: number;
32
37
  protected keydownListener: ((data: Buffer | undefined) => void) | undefined;
33
- readonly tty: boolean;
34
- readonly enabled: boolean | "interval";
38
+ readonly tty: Exclude<ProgressTty, "auto">;
39
+ readonly mode: Exclude<ProgressMode, "auto" | `interval:${number}`>;
35
40
  constructor(options: {
36
41
  verbose?: boolean;
37
42
  /**
38
- * @default true
43
+ * @default false
44
+ */
45
+ tty?: ProgressTty;
46
+ /**
47
+ * @default "interval"
39
48
  */
40
- tty?: boolean | "auto";
41
- enabled?: boolean | "auto" | "interval";
42
- interval?: number;
49
+ mode?: ProgressMode;
43
50
  });
44
51
  elapsed(): number;
45
52
  start(): void;
package/utils/progress.js CHANGED
@@ -11,9 +11,10 @@ class ProgressManager {
11
11
  options;
12
12
  timer = (0, date_1.createTimer)();
13
13
  interval = (0, date_1.createTimer)();
14
+ intervalMs;
14
15
  keydownListener;
15
16
  tty;
16
- enabled;
17
+ mode;
17
18
  constructor(options) {
18
19
  this.options = options;
19
20
  this.tty =
@@ -22,12 +23,21 @@ class ProgressManager {
22
23
  ? false
23
24
  : process.stdout.isTTY
24
25
  : !!options.tty;
25
- this.enabled =
26
- options.enabled === "auto"
27
- ? this.tty
28
- ? true
29
- : "interval"
30
- : !!options.enabled;
26
+ const mode = options.mode === "auto"
27
+ ? this.tty
28
+ ? `interval:${300}`
29
+ : "interval"
30
+ : options.mode ?? "interval";
31
+ this.intervalMs = 1000;
32
+ if (typeof mode === "string" && mode.startsWith("interval:")) {
33
+ const [, ms] = mode.split(":");
34
+ this.mode = "interval";
35
+ if (/^\d+$/.test(ms))
36
+ this.intervalMs = Number(ms);
37
+ }
38
+ else {
39
+ this.mode = mode;
40
+ }
31
41
  }
32
42
  elapsed() {
33
43
  return this.timer.elapsed();
@@ -57,11 +67,11 @@ class ProgressManager {
57
67
  }
58
68
  }
59
69
  update(progress, cb) {
60
- if (!this.enabled)
70
+ if (!this.mode)
61
71
  return;
62
- if (this.enabled === "interval") {
72
+ if (this.mode === "interval") {
63
73
  if (this.interval) {
64
- if (!this.interval.reset(this.options.interval ?? 5000))
74
+ if (!this.interval.reset(this.intervalMs))
65
75
  return;
66
76
  }
67
77
  else {
@@ -0,0 +1,34 @@
1
+ import { JSONSchema7 } from "json-schema";
2
+ export declare function omitPropertySchema<T extends {
3
+ properties: Record<string, any>;
4
+ }, N extends keyof T["properties"]>(object: T, name: N): Omit<T, "properties"> & {
5
+ properties: Omit<T["properties"], N>;
6
+ };
7
+ type IfSchema<KType extends string, KValue extends string, T extends string, V extends JSONSchema7> = {
8
+ if: {
9
+ type: "object";
10
+ properties: {
11
+ [k in KType]: {
12
+ const: T;
13
+ };
14
+ };
15
+ };
16
+ then: {
17
+ type: "object";
18
+ properties: {
19
+ [k in KValue]: V;
20
+ };
21
+ };
22
+ else: false;
23
+ };
24
+ export declare function createCaseSchema<KType extends string, KValue extends string, V extends {
25
+ [K in KType]: JSONSchema7;
26
+ }>(keys: {
27
+ type: KType;
28
+ value: KValue;
29
+ }, value: V): IfSchema<KType, KValue, string, JSONSchema7>[];
30
+ export declare function createIfSchema<KType extends string, KValue extends string, T extends string, V extends JSONSchema7>(keys: {
31
+ type: KType;
32
+ value: KValue;
33
+ }, type: T, value: V): IfSchema<KType, KValue, T, V>;
34
+ export {};
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createIfSchema = exports.createCaseSchema = exports.omitPropertySchema = void 0;
4
+ const object_1 = require("./object");
5
+ function omitPropertySchema(object, name) {
6
+ return {
7
+ ...object,
8
+ properties: (0, object_1.omitProp)(object.properties, name),
9
+ };
10
+ }
11
+ exports.omitPropertySchema = omitPropertySchema;
12
+ function createCaseSchema(keys, value) {
13
+ return Object.entries(value).reduce((schemas, [type, value]) => {
14
+ schemas.push(createIfSchema(keys, type, value));
15
+ return schemas;
16
+ }, []);
17
+ }
18
+ exports.createCaseSchema = createCaseSchema;
19
+ function createIfSchema(keys, type, value) {
20
+ return {
21
+ if: {
22
+ type: "object",
23
+ properties: {
24
+ [keys.type]: { const: type },
25
+ },
26
+ },
27
+ then: {
28
+ type: "object",
29
+ properties: {
30
+ [keys.value]: value,
31
+ },
32
+ },
33
+ else: false,
34
+ };
35
+ }
36
+ exports.createIfSchema = createIfSchema;
package/utils/string.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- export declare function serialize(message: string, data?: Object): string;
2
1
  export declare function snakeCase(value: string, char?: string): string;
3
2
  export declare function render(subject: string, vars: Record<string, string | undefined>): string;
4
3
  type NoInfer<T> = [T][T extends any ? 0 : never];
@@ -12,12 +11,10 @@ export type UriType = {
12
11
  path?: string;
13
12
  };
14
13
  export declare function formatUri(input: UriType, hidePassword?: boolean): string;
15
- export declare function formatSeconds(seconds: number): string;
16
14
  export declare function makePathPatterns(values: string[] | undefined): string[] | undefined;
17
15
  export declare function match(path: string, include?: string[], exclude?: string[]): boolean;
18
16
  export declare function endsWith(input: string, patterns: string[]): boolean;
19
17
  export declare function createMatchFilter(include?: string[], exclude?: string[]): (input: string) => boolean;
20
18
  export declare function checkMatch(subject: string | undefined, patterns: string[]): boolean;
21
- export declare function formatDateTime(datetime: string): string;
22
19
  export declare function undefIfEmpty(input: string): string | undefined;
23
20
  export {};
package/utils/string.js CHANGED
@@ -1,14 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.undefIfEmpty = exports.formatDateTime = exports.checkMatch = exports.createMatchFilter = exports.endsWith = exports.match = exports.makePathPatterns = exports.formatSeconds = exports.formatUri = exports.parseStringList = exports.render = exports.snakeCase = exports.serialize = void 0;
3
+ exports.undefIfEmpty = exports.checkMatch = exports.createMatchFilter = exports.endsWith = exports.match = exports.makePathPatterns = exports.formatUri = exports.parseStringList = exports.render = exports.snakeCase = void 0;
4
4
  const AppError_1 = require("../Error/AppError");
5
5
  const micromatch_1 = require("micromatch");
6
- function serialize(message, data) {
7
- if (data)
8
- return `${message} (${JSON.stringify(data, null, 2)})`;
9
- return message;
10
- }
11
- exports.serialize = serialize;
12
6
  function snakeCase(value, char = "_") {
13
7
  return value.replace(/[A-Z]/g, (letter) => `${char}${letter.toLowerCase()}`);
14
8
  }
@@ -61,26 +55,6 @@ function formatUri(input, hidePassword) {
61
55
  return uri;
62
56
  }
63
57
  exports.formatUri = formatUri;
64
- function formatSeconds(seconds) {
65
- let unit;
66
- let value;
67
- if (seconds > 60 * 60) {
68
- value = seconds / 60 / 60;
69
- unit = `hour`;
70
- }
71
- else if (seconds > 60) {
72
- value = seconds / 60;
73
- unit = `minute`;
74
- }
75
- else {
76
- value = seconds;
77
- unit = `second`;
78
- }
79
- if (value !== 1)
80
- unit += `s`;
81
- return `${value.toFixed(2)} ${unit}`;
82
- }
83
- exports.formatSeconds = formatSeconds;
84
58
  function makePathPatterns(values) {
85
59
  return values?.flatMap((v) => {
86
60
  if (v === "*" || v === "**" || v === "<empty>" || v === "!<empty>") {
@@ -111,16 +85,6 @@ function checkMatch(subject, patterns) {
111
85
  return (0, micromatch_1.isMatch)(subject, patterns);
112
86
  }
113
87
  exports.checkMatch = checkMatch;
114
- function formatDateTime(datetime) {
115
- const date = new Date(datetime);
116
- const [result] = new Date(date.getTime() - date.getTimezoneOffset() * 60000)
117
- .toISOString()
118
- .replace("Z", "")
119
- .replace("T", " ")
120
- .split(".");
121
- return result;
122
- }
123
- exports.formatDateTime = formatDateTime;
124
88
  function undefIfEmpty(input) {
125
89
  return input.length ? input : undefined;
126
90
  }
@@ -1,13 +0,0 @@
1
- export type KeysType = (string | number)[];
2
- export declare class ObjectVault<TObject> {
3
- protected counter: number;
4
- protected readonly ids: Record<string, number>;
5
- protected readonly objects: Record<number, TObject>;
6
- static serializeKeys(keys: KeysType): string;
7
- get(id: number): TObject;
8
- getId(keys: KeysType): number;
9
- add(options: {
10
- keys: KeysType;
11
- handler: (id: number) => TObject;
12
- }): TObject;
13
- }
@@ -1,29 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ObjectVault = void 0;
4
- class ObjectVault {
5
- counter = 0;
6
- ids = {};
7
- objects = {};
8
- static serializeKeys(keys) {
9
- return JSON.stringify(keys);
10
- }
11
- get(id) {
12
- if (!(id in this.objects))
13
- throw new Error(`Object not found: ${id}`);
14
- return this.objects[id];
15
- }
16
- getId(keys) {
17
- const key = ObjectVault.serializeKeys(keys);
18
- const id = this.ids[key];
19
- if (!id)
20
- throw new Error(`Id not found: ${JSON.stringify(keys)}`);
21
- return id;
22
- }
23
- add(options) {
24
- const key = ObjectVault.serializeKeys(options.keys);
25
- const id = (this.ids[key] = ++this.counter);
26
- return (this.objects[id] = options.handler(id));
27
- }
28
- }
29
- exports.ObjectVault = ObjectVault;