@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,230 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ResticRepository = exports.resticPackageRepositoryDefinition = exports.resticRepositoryDefinition = exports.resticRepositoryName = void 0;
4
+ const AppError_1 = require("../Error/AppError");
5
+ const ResticUtil_1 = require("../util/ResticUtil");
6
+ const paths_util_1 = require("../util/datatruck/paths-util");
7
+ const fs_util_1 = require("../util/fs-util");
8
+ const string_util_1 = require("../util/string-util");
9
+ const RepositoryAbstract_1 = require("./RepositoryAbstract");
10
+ const assert_1 = require("assert");
11
+ const micromatch_1 = require("micromatch");
12
+ const path_1 = require("path");
13
+ exports.resticRepositoryName = "restic";
14
+ exports.resticRepositoryDefinition = {
15
+ type: "object",
16
+ required: ["passwordFile", "repository"],
17
+ additionalProperties: false,
18
+ properties: {
19
+ passwordFile: { type: "string" },
20
+ repository: {
21
+ type: "object",
22
+ additionalProperties: false,
23
+ required: ["backend"],
24
+ properties: {
25
+ name: { type: "string" },
26
+ env: {
27
+ type: "object",
28
+ patternProperties: {
29
+ ".+": { type: "string" },
30
+ },
31
+ },
32
+ backend: {
33
+ enum: ["local", "rest", "sftp", "s3", "azure", "gs", "rclone"],
34
+ },
35
+ protocol: {
36
+ enum: ["http", "https"],
37
+ },
38
+ host: { type: "string" },
39
+ username: { type: "string" },
40
+ passwordFile: { type: "string" },
41
+ port: { type: "integer" },
42
+ path: { type: "string" },
43
+ },
44
+ },
45
+ },
46
+ };
47
+ exports.resticPackageRepositoryDefinition = {
48
+ type: "object",
49
+ additionalProperties: false,
50
+ properties: {},
51
+ };
52
+ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
53
+ async buildEnv() {
54
+ if (this.env)
55
+ return this.env;
56
+ return (this.env = {
57
+ RESTIC_PASSWORD_FILE: this.config.passwordFile,
58
+ RESTIC_REPOSITORY: await ResticUtil_1.ResticUtil.formatRepository(this.config.repository),
59
+ });
60
+ }
61
+ static buildSnapshotTag(name, value) {
62
+ return `${ResticRepository.refPrefix}${name}:${value}`;
63
+ }
64
+ static parseSnapshotTag(tag) {
65
+ for (const metaName in RepositoryAbstract_1.SnapshotTagEnum) {
66
+ const name = RepositoryAbstract_1.SnapshotTagEnum[metaName];
67
+ const prefix = `${ResticRepository.refPrefix}${name}:`;
68
+ if (tag.startsWith(prefix))
69
+ return {
70
+ name: name,
71
+ value: tag.slice(prefix.length),
72
+ };
73
+ }
74
+ return null;
75
+ }
76
+ static parseSnapshotTags(tags) {
77
+ const result = {
78
+ tags: [],
79
+ };
80
+ for (const tag of tags) {
81
+ const tagItem = ResticRepository.parseSnapshotTag(tag);
82
+ if (tagItem && tagItem.name !== "tags") {
83
+ result[tagItem.name] = tagItem.value;
84
+ }
85
+ else {
86
+ result.tags.push(tag);
87
+ }
88
+ }
89
+ return result;
90
+ }
91
+ onGetSource() {
92
+ return (0, string_util_1.formatUri)({ ...this.config.repository, password: undefined });
93
+ }
94
+ async onInit(data) {
95
+ const restic = new ResticUtil_1.ResticUtil({
96
+ env: await this.buildEnv(),
97
+ log: data.options.verbose,
98
+ });
99
+ if (this.config.repository.backend === "local")
100
+ await (0, fs_util_1.mkdirIfNotExists)(this.env.RESTIC_REPOSITORY);
101
+ if (!(await restic.checkRepository()))
102
+ await restic.exec(["init"]);
103
+ }
104
+ async onSnapshots(data) {
105
+ const restic = new ResticUtil_1.ResticUtil({
106
+ env: await this.buildEnv(),
107
+ log: data.options.verbose,
108
+ });
109
+ const packagePatterns = (0, string_util_1.makePathPatterns)(data.options.packageNames);
110
+ const result = await restic.snapshots({
111
+ json: true,
112
+ tags: [
113
+ ...(data.options.ids?.map((id) => ResticRepository.buildSnapshotTag(id.length === 8 ? RepositoryAbstract_1.SnapshotTagEnum.SHORT_ID : RepositoryAbstract_1.SnapshotTagEnum.ID, id)) ?? []),
114
+ ],
115
+ });
116
+ return result.reduce((items, item) => {
117
+ const tag = ResticRepository.parseSnapshotTags(item.tags ?? []);
118
+ if (!tag.id)
119
+ return items;
120
+ if (packagePatterns && !(0, micromatch_1.isMatch)(tag.package, packagePatterns))
121
+ return items;
122
+ const itemTags = tag.tags ?? [];
123
+ if (data.options.tags && !itemTags.some((t) => itemTags.includes(t)))
124
+ return items;
125
+ items.push({
126
+ originalId: item.id,
127
+ packageName: tag.package,
128
+ date: tag.date,
129
+ id: tag.id,
130
+ tags: itemTags,
131
+ });
132
+ return items;
133
+ }, []);
134
+ }
135
+ async onPrune(data) {
136
+ const restic = new ResticUtil_1.ResticUtil({
137
+ env: await this.buildEnv(),
138
+ log: data.options.verbose,
139
+ });
140
+ await restic.forget({
141
+ snapshotId: data.snapshot.originalId,
142
+ prune: true,
143
+ });
144
+ }
145
+ async onBackup(data) {
146
+ const restic = new ResticUtil_1.ResticUtil({
147
+ env: await this.buildEnv(),
148
+ log: data.options.verbose,
149
+ });
150
+ const pkg = data.package;
151
+ const sourcePath = data.targetPath ?? data.package.path;
152
+ (0, assert_1.ok)(sourcePath);
153
+ const include = (await (0, paths_util_1.parsePaths)(pkg.include ?? [], {
154
+ cwd: sourcePath,
155
+ verbose: data.options.verbose,
156
+ })).map(path_1.normalize);
157
+ // https://github.com/restic/restic/issues/233
158
+ // https://github.com/restic/restic/pull/2311
159
+ if (include.length)
160
+ throw new AppError_1.AppError(`Include is not supported`);
161
+ if (data.options.tags?.some((tag) => tag.startsWith(ResticRepository.refPrefix)))
162
+ throw new AppError_1.AppError(`Tag prefix is not allowed`);
163
+ const packageTag = ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.PACKAGE, data.package.name);
164
+ const [lastSnapshot] = await restic.snapshots({
165
+ json: true,
166
+ tags: [packageTag],
167
+ latest: 1,
168
+ });
169
+ const nodePkg = (0, fs_util_1.parsePackageFile)();
170
+ await restic.backup({
171
+ cwd: sourcePath,
172
+ paths: ["."],
173
+ parent: lastSnapshot?.id,
174
+ // https://github.com/restic/restic/pull/3200
175
+ ...((await restic.checkBackupSetPathSupport()) && {
176
+ setPaths: [`/datatruck/${data.package.name}`],
177
+ }),
178
+ exclude: (await (0, paths_util_1.parsePaths)(pkg.exclude ?? [], {
179
+ cwd: sourcePath,
180
+ verbose: data.options.verbose,
181
+ })).map(path_1.normalize),
182
+ tags: [
183
+ ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.ID, data.snapshot.id),
184
+ ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.SHORT_ID, data.snapshot.id.slice(0, 8)),
185
+ ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.DATE, data.snapshot.date),
186
+ ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.VERSION, nodePkg.version),
187
+ packageTag,
188
+ ...(data.options.tags ?? []),
189
+ ],
190
+ onStream: async (streamData) => {
191
+ if (streamData.message_type === "status") {
192
+ await data.onProgress({
193
+ total: streamData.total_bytes,
194
+ current: streamData.bytes_done ?? 0,
195
+ percent: Number((streamData.percent_done * 100).toFixed(2)),
196
+ step: streamData.current_files?.join(", ") ?? "-",
197
+ });
198
+ }
199
+ },
200
+ });
201
+ await data.onProgress({
202
+ current: 100,
203
+ percent: 100,
204
+ step: "",
205
+ total: 100,
206
+ });
207
+ }
208
+ async onRestore(data) {
209
+ const restorePath = data.targetPath ?? data.package.restorePath;
210
+ (0, assert_1.ok)(restorePath);
211
+ const restic = new ResticUtil_1.ResticUtil({
212
+ env: await this.buildEnv(),
213
+ log: data.options.verbose,
214
+ });
215
+ const [snapshot] = await this.onSnapshots({
216
+ options: {
217
+ ids: [data.snapshot.id],
218
+ packageNames: [data.package.name],
219
+ },
220
+ });
221
+ if (!snapshot)
222
+ throw new AppError_1.AppError(`Snapshot not found`);
223
+ await restic.restore({
224
+ id: snapshot.originalId,
225
+ target: restorePath,
226
+ });
227
+ }
228
+ }
229
+ exports.ResticRepository = ResticRepository;
230
+ ResticRepository.refPrefix = "dt-";
@@ -0,0 +1,37 @@
1
+ /// <reference types="node" />
2
+ import { WriteDataType, ReadResultType, SessionDriverAbstract } from "./SessionDriverAbstract";
3
+ declare type BadgeType = {
4
+ name: string;
5
+ value: string;
6
+ color: (input: string) => string;
7
+ };
8
+ declare type MessageType = {
9
+ sessionId: number;
10
+ level?: number;
11
+ textPrefix?: string;
12
+ text?: string;
13
+ badges: BadgeType[];
14
+ errorBadge?: BadgeType;
15
+ progressCurrent?: number | null;
16
+ progressTotal?: number | null;
17
+ progressPercent?: number | null;
18
+ progressStep?: string | null;
19
+ progressStepPercent?: number | null;
20
+ };
21
+ export declare class ConsoleSessionDriver extends SessionDriverAbstract {
22
+ protected lastMessage: MessageType | undefined;
23
+ protected lastMessageText: string | undefined;
24
+ protected prints: number;
25
+ protected renderInterval: NodeJS.Timeout;
26
+ protected rendering?: boolean;
27
+ protected lastColumns?: number;
28
+ protected startTime: number;
29
+ onInit(): Promise<void>;
30
+ onEnd(): Promise<void>;
31
+ onRead(): Promise<ReadResultType[]>;
32
+ protected printMessage(message: MessageType): void;
33
+ protected renderSpinner(text: string): string;
34
+ protected renderMessage(message: MessageType): string;
35
+ onWrite(data: WriteDataType): Promise<void>;
36
+ }
37
+ export {};
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConsoleSessionDriver = void 0;
4
+ const AppError_1 = require("../Error/AppError");
5
+ const cli_util_1 = require("../util/cli-util");
6
+ const SessionDriverAbstract_1 = require("./SessionDriverAbstract");
7
+ const chalk_1 = require("chalk");
8
+ const sep = (0, chalk_1.grey)(`|`);
9
+ const renderBadge = (badge) => `${badge.color(badge.name)}${(0, chalk_1.grey)(`:`)} ${(0, chalk_1.white)(badge.value)}`;
10
+ const renderBadges = (badges) => badges.map(renderBadge).join(` ${sep} `);
11
+ class ConsoleSessionDriver extends SessionDriverAbstract_1.SessionDriverAbstract {
12
+ constructor() {
13
+ super(...arguments);
14
+ this.prints = 0;
15
+ }
16
+ async onInit() {
17
+ this.startTime = Date.now();
18
+ this.renderInterval = setInterval(() => {
19
+ if (this.lastMessage)
20
+ this.printMessage(this.lastMessage);
21
+ }, 100);
22
+ }
23
+ async onEnd() {
24
+ clearInterval(this.renderInterval);
25
+ if (!this.options.verbose)
26
+ process.stdout.write(cli_util_1.showCursorCommand);
27
+ const ellapsed = (Date.now() - this.startTime) / 1000;
28
+ let ellapsedUnit;
29
+ let ellapsedValue;
30
+ if (ellapsed > 60 * 60) {
31
+ ellapsedValue = ellapsed / 60 / 60;
32
+ ellapsedUnit = `hour`;
33
+ }
34
+ else if (ellapsed > 60) {
35
+ ellapsedValue = ellapsed / 60;
36
+ ellapsedUnit = `minute`;
37
+ }
38
+ else {
39
+ ellapsedValue = ellapsed;
40
+ ellapsedUnit = `second`;
41
+ }
42
+ if (ellapsedValue !== 1)
43
+ ellapsedUnit += `s`;
44
+ const message = `Completed in ${ellapsedValue.toFixed(2)} ${ellapsedUnit}`;
45
+ console.info(`\n${(0, chalk_1.grey)(message)}`);
46
+ }
47
+ async onRead() {
48
+ throw new AppError_1.AppError("Method not implemented");
49
+ }
50
+ printMessage(message) {
51
+ const text = this.renderMessage(message);
52
+ if (this.options.verbose && this.lastMessageText === text) {
53
+ return;
54
+ }
55
+ if (this.options.verbose) {
56
+ process.stdout.write(`${this.renderSpinner(text)}\n`);
57
+ }
58
+ else {
59
+ const columns = process.stdout.columns;
60
+ const line = this.renderSpinner(text);
61
+ const [truncatedLine, truncted] = (0, cli_util_1.truncate)(line, columns);
62
+ if (this.lastColumns && columns !== this.lastColumns && truncted)
63
+ process.stdout.write(`${cli_util_1.clearCommand}\n`);
64
+ process.stdout.write(`${cli_util_1.clearCommand}${truncatedLine}${cli_util_1.hideCursorCommand}`);
65
+ this.lastColumns = columns;
66
+ }
67
+ this.prints++;
68
+ this.lastMessage = message;
69
+ this.lastMessageText = text;
70
+ }
71
+ renderSpinner(text) {
72
+ return text.replace("{spinner}", (0, chalk_1.grey)(this.options.verbose ? "?" : (0, cli_util_1.renderSpinner)(this.prints)));
73
+ }
74
+ renderMessage(message) {
75
+ const badges = renderBadges([
76
+ ...message.badges,
77
+ ...(message.errorBadge ? [message.errorBadge] : []),
78
+ ]);
79
+ const padding = " ".repeat(message.level ?? 0);
80
+ const haveProgressBar = typeof message.progressPercent === "number";
81
+ const sessionId = message.sessionId.toString().padStart(2, "0");
82
+ const parts = [
83
+ `${padding}${message.textPrefix} [${(0, chalk_1.grey)(sessionId)}] ${message.text}`,
84
+ badges,
85
+ ...(haveProgressBar
86
+ ? [
87
+ (0, chalk_1.cyan)((0, cli_util_1.renderProgressBar)(message.progressPercent ?? 0, 10)),
88
+ `${message.progressPercent?.toFixed(2)}%`,
89
+ `${message.progressCurrent}/${message.progressTotal}`,
90
+ message.progressStep,
91
+ `${message.progressStepPercent
92
+ ? (0, chalk_1.cyan)((0, cli_util_1.renderProgressBar)(message.progressStepPercent ?? 0, 10))
93
+ : ""}`,
94
+ ].filter((v) => !!v?.length)
95
+ : []),
96
+ ];
97
+ return parts.join(` ${sep} `);
98
+ }
99
+ async onWrite(data) {
100
+ if (data.action === SessionDriverAbstract_1.ActionEnum.Init)
101
+ return;
102
+ const message = {
103
+ sessionId: "sessionId" in data.data ? data.data.sessionId : data.data.id,
104
+ badges: [],
105
+ };
106
+ const isHeader = data.entity === SessionDriverAbstract_1.EntityEnum.BackupSession ||
107
+ data.entity === SessionDriverAbstract_1.EntityEnum.RestoreSession;
108
+ const hasProgress = isHeader ||
109
+ data.entity === SessionDriverAbstract_1.EntityEnum.BackupSessionTask ||
110
+ data.entity === SessionDriverAbstract_1.EntityEnum.BackupSessionRepository ||
111
+ data.entity === SessionDriverAbstract_1.EntityEnum.RestoreSessionTask ||
112
+ data.entity === SessionDriverAbstract_1.EntityEnum.RestoreSessionRepository;
113
+ if (data.action === SessionDriverAbstract_1.ActionEnum.Start) {
114
+ if (isHeader) {
115
+ message.textPrefix = data.data.error ? (0, chalk_1.red)("⨉") : (0, chalk_1.green)("✓");
116
+ }
117
+ else {
118
+ message.textPrefix = hasProgress ? "{spinner}" : (0, chalk_1.grey)("?");
119
+ }
120
+ }
121
+ else if (data.action === SessionDriverAbstract_1.ActionEnum.End) {
122
+ message.textPrefix = data.data.error ? (0, chalk_1.red)("⨉") : (0, chalk_1.green)("✓");
123
+ if (data.data.error)
124
+ message.errorBadge = {
125
+ name: "error",
126
+ value: this.options.verbose
127
+ ? data.data.error
128
+ : data.data.error.split("\n")[0],
129
+ color: chalk_1.red,
130
+ };
131
+ }
132
+ else if (data.action === SessionDriverAbstract_1.ActionEnum.Progress) {
133
+ message.textPrefix = "{spinner}";
134
+ }
135
+ if (hasProgress) {
136
+ message.progressPercent = data.data.progressPercent;
137
+ message.progressCurrent = data.data.progressCurrent;
138
+ message.progressTotal = data.data.progressTotal;
139
+ message.progressStep = data.data.progressStep;
140
+ message.progressStepPercent = data.data.progressStepPercent;
141
+ }
142
+ if (data.entity === SessionDriverAbstract_1.EntityEnum.BackupSession ||
143
+ data.entity === SessionDriverAbstract_1.EntityEnum.RestoreSession) {
144
+ message.text = data.data.packageName;
145
+ message.badges.push({
146
+ name: "snap",
147
+ value: data.data.snapshotId.slice(0, 8),
148
+ color: chalk_1.cyan,
149
+ });
150
+ }
151
+ else if (data.entity === SessionDriverAbstract_1.EntityEnum.BackupSessionTask ||
152
+ data.entity === SessionDriverAbstract_1.EntityEnum.RestoreSessionTask) {
153
+ message.text = data.sessionData.packageName;
154
+ message.badges.push({
155
+ name: "task",
156
+ value: data.data.taskName,
157
+ color: chalk_1.cyan,
158
+ });
159
+ }
160
+ else if (data.entity === SessionDriverAbstract_1.EntityEnum.BackupSessionRepository ||
161
+ data.entity === SessionDriverAbstract_1.EntityEnum.RestoreSessionRepository) {
162
+ message.text = data.sessionData.packageName;
163
+ message.badges.push({
164
+ name: "repo",
165
+ value: data.data.repositoryName,
166
+ color: chalk_1.cyan,
167
+ });
168
+ }
169
+ if (isHeader && data.action === SessionDriverAbstract_1.ActionEnum.End) {
170
+ return;
171
+ }
172
+ this.printMessage(message);
173
+ if (!this.options.verbose)
174
+ if (!hasProgress || data.action === SessionDriverAbstract_1.ActionEnum.End || isHeader)
175
+ process.stdout.write("\n");
176
+ }
177
+ }
178
+ exports.ConsoleSessionDriver = ConsoleSessionDriver;
@@ -0,0 +1,78 @@
1
+ import { BackupSessionEntity } from "../Entity/BackupSessionEntity";
2
+ import { BackupSessionRepositoryEntity } from "../Entity/BackupSessionRepositoryEntity";
3
+ import { BackupSessionTaskEntity } from "../Entity/BackupSessionTaskEntity";
4
+ import { RestoreSessionEntity } from "../Entity/RestoreSessionEntity";
5
+ import { RestoreSessionRepositoryEntity } from "../Entity/RestoreSessionRepositoryEntity";
6
+ import { RestoreSessionTaskEntity } from "../Entity/RestoreSessionTaskEntity";
7
+ export declare enum ActionEnum {
8
+ Init = 0,
9
+ Start = 1,
10
+ Progress = 2,
11
+ End = 3
12
+ }
13
+ export declare enum EntityEnum {
14
+ BackupSession = 0,
15
+ BackupSessionTask = 1,
16
+ BackupSessionRepository = 2,
17
+ RestoreSession = 3,
18
+ RestoreSessionTask = 4,
19
+ RestoreSessionRepository = 5
20
+ }
21
+ export declare type WriteDataType = {
22
+ action: ActionEnum;
23
+ entity: EntityEnum.BackupSession;
24
+ data: BackupSessionEntity;
25
+ } | {
26
+ action: ActionEnum;
27
+ entity: EntityEnum.BackupSessionRepository;
28
+ data: BackupSessionRepositoryEntity;
29
+ sessionData: BackupSessionEntity;
30
+ } | {
31
+ action: ActionEnum;
32
+ entity: EntityEnum.BackupSessionTask;
33
+ data: BackupSessionTaskEntity;
34
+ sessionData: BackupSessionEntity;
35
+ } | {
36
+ action: ActionEnum;
37
+ entity: EntityEnum.RestoreSession;
38
+ data: RestoreSessionEntity;
39
+ } | {
40
+ action: ActionEnum;
41
+ entity: EntityEnum.RestoreSessionTask;
42
+ data: RestoreSessionTaskEntity;
43
+ sessionData: RestoreSessionEntity;
44
+ } | {
45
+ action: ActionEnum;
46
+ entity: EntityEnum.RestoreSessionRepository;
47
+ data: RestoreSessionRepositoryEntity;
48
+ sessionData: RestoreSessionEntity;
49
+ };
50
+ export declare type ReadDataType = {
51
+ repositoryNames?: string[];
52
+ packageNames?: string[];
53
+ tags?: string[];
54
+ limit?: number | null;
55
+ verbose?: boolean;
56
+ };
57
+ export declare type ReadResultType = {
58
+ id: number;
59
+ snapshotId: string;
60
+ creationDate: string;
61
+ state: "started" | "ended";
62
+ packageName: string;
63
+ repositoryName: string;
64
+ repositoryType: string;
65
+ error: string | null;
66
+ };
67
+ export declare abstract class SessionDriverAbstract {
68
+ readonly options: {
69
+ verbose?: boolean;
70
+ };
71
+ constructor(options: {
72
+ verbose?: boolean;
73
+ });
74
+ onInit(): Promise<void>;
75
+ abstract onWrite(data: WriteDataType): Promise<void>;
76
+ onEnd(): Promise<void>;
77
+ abstract onRead(data: ReadDataType, entity: EntityEnum): Promise<ReadResultType[]>;
78
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SessionDriverAbstract = exports.EntityEnum = exports.ActionEnum = void 0;
4
+ var ActionEnum;
5
+ (function (ActionEnum) {
6
+ ActionEnum[ActionEnum["Init"] = 0] = "Init";
7
+ ActionEnum[ActionEnum["Start"] = 1] = "Start";
8
+ ActionEnum[ActionEnum["Progress"] = 2] = "Progress";
9
+ ActionEnum[ActionEnum["End"] = 3] = "End";
10
+ })(ActionEnum = exports.ActionEnum || (exports.ActionEnum = {}));
11
+ var EntityEnum;
12
+ (function (EntityEnum) {
13
+ EntityEnum[EntityEnum["BackupSession"] = 0] = "BackupSession";
14
+ EntityEnum[EntityEnum["BackupSessionTask"] = 1] = "BackupSessionTask";
15
+ EntityEnum[EntityEnum["BackupSessionRepository"] = 2] = "BackupSessionRepository";
16
+ EntityEnum[EntityEnum["RestoreSession"] = 3] = "RestoreSession";
17
+ EntityEnum[EntityEnum["RestoreSessionTask"] = 4] = "RestoreSessionTask";
18
+ EntityEnum[EntityEnum["RestoreSessionRepository"] = 5] = "RestoreSessionRepository";
19
+ })(EntityEnum = exports.EntityEnum || (exports.EntityEnum = {}));
20
+ class SessionDriverAbstract {
21
+ constructor(options) {
22
+ this.options = options;
23
+ }
24
+ async onInit() { }
25
+ async onEnd() { }
26
+ }
27
+ exports.SessionDriverAbstract = SessionDriverAbstract;
@@ -0,0 +1,20 @@
1
+ /// <reference types="./vendor-typings/sqlite3" />
2
+ import { WriteDataType, EntityEnum, ReadDataType, SessionDriverAbstract } from "./SessionDriverAbstract";
3
+ import { Database } from "sqlite";
4
+ import sqlite3 from "sqlite3";
5
+ export declare class SqliteSessionDriver extends SessionDriverAbstract {
6
+ protected idMap: {
7
+ [entity in EntityEnum]?: Record<number, number>;
8
+ };
9
+ protected db: Database<sqlite3.Database, sqlite3.Statement>;
10
+ onInit(): Promise<void>;
11
+ private buildInsertStm;
12
+ private buildUpdateStm;
13
+ private exec;
14
+ onRead(data: ReadDataType, type: EntityEnum): Promise<any[]>;
15
+ private setMapId;
16
+ private getMapId;
17
+ private static getEntityTable;
18
+ private static getParentEntity;
19
+ onWrite(data: WriteDataType): Promise<void>;
20
+ }