@wocker/mongodb-plugin 1.0.6 → 1.0.8

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.
@@ -9,5 +9,7 @@ export declare class MongodbController {
9
9
  start(name?: string, restart?: boolean): Promise<void>;
10
10
  stop(name?: string): Promise<void>;
11
11
  list(): Promise<string>;
12
+ backup(service?: string, database?: string, file?: string, del?: boolean): Promise<void>;
13
+ restore(service?: string, database?: string, file?: string): Promise<void>;
12
14
  getNames(): Promise<string[]>;
13
15
  }
@@ -79,6 +79,20 @@ let MongodbController = class MongodbController {
79
79
  return this.mongodbService.list();
80
80
  });
81
81
  }
82
+ backup(service, database, file, del) {
83
+ return __awaiter(this, void 0, void 0, function* () {
84
+ if (del) {
85
+ yield this.mongodbService.deleteBackup(service, database, file);
86
+ return;
87
+ }
88
+ yield this.mongodbService.backup(service, database);
89
+ });
90
+ }
91
+ restore(service, database, file) {
92
+ return __awaiter(this, void 0, void 0, function* () {
93
+ yield this.mongodbService.restore(service, database, file);
94
+ });
95
+ }
82
96
  getNames() {
83
97
  return __awaiter(this, void 0, void 0, function* () {
84
98
  return this.mongodbService.config.databases.map((database) => {
@@ -198,14 +212,40 @@ __decorate([
198
212
  __metadata("design:paramtypes", []),
199
213
  __metadata("design:returntype", Promise)
200
214
  ], MongodbController.prototype, "list", null);
215
+ __decorate([
216
+ (0, core_1.Command)("mongodb:backup [name]"),
217
+ __param(0, (0, core_1.Param)("name")),
218
+ __param(1, (0, core_1.Option)("database", "d")),
219
+ __param(1, (0, core_1.Description)("Database name to back up")),
220
+ __param(2, (0, core_1.Option)("filename", "f")),
221
+ __param(2, (0, core_1.Description)("Name of the backup file")),
222
+ __param(3, (0, core_1.Option)("delete", "D")),
223
+ __param(3, (0, core_1.Description)("Delete the specified backup file")),
224
+ __metadata("design:type", Function),
225
+ __metadata("design:paramtypes", [String, String, String, Boolean]),
226
+ __metadata("design:returntype", Promise)
227
+ ], MongodbController.prototype, "backup", null);
228
+ __decorate([
229
+ (0, core_1.Command)("mongodb:restore [name]"),
230
+ __param(0, (0, core_1.Param)("name")),
231
+ __param(1, (0, core_1.Option)("database", "d")),
232
+ __param(1, (0, core_1.Description)("Database name to restore")),
233
+ __param(2, (0, core_1.Option)("file-name", "f")),
234
+ __param(2, (0, core_1.Description)("File name")),
235
+ __metadata("design:type", Function),
236
+ __metadata("design:paramtypes", [String, String, String]),
237
+ __metadata("design:returntype", Promise)
238
+ ], MongodbController.prototype, "restore", null);
201
239
  __decorate([
202
240
  (0, core_1.Completion)("name", "mongodb:start [name]"),
203
241
  (0, core_1.Completion)("name", "mongodb:stop [name]"),
242
+ (0, core_1.Completion)("name", "mongodb:backup [name]"),
204
243
  __metadata("design:type", Function),
205
244
  __metadata("design:paramtypes", []),
206
245
  __metadata("design:returntype", Promise)
207
246
  ], MongodbController.prototype, "getNames", null);
208
247
  exports.MongodbController = MongodbController = __decorate([
209
248
  (0, core_1.Controller)(),
249
+ (0, core_1.Description)("MongoDB commands"),
210
250
  __metadata("design:paramtypes", [MongodbService_1.MongodbService])
211
251
  ], MongodbController);
@@ -1,5 +1,5 @@
1
- import { Config, ConfigProperties } from "@wocker/core";
2
- export type DatabaseProps = ConfigProperties & {
1
+ export type DatabaseProps = {
2
+ name: string;
3
3
  imageName?: string;
4
4
  imageVersion?: string;
5
5
  username: string;
@@ -9,7 +9,8 @@ export type DatabaseProps = ConfigProperties & {
9
9
  volume?: string;
10
10
  configVolume?: string;
11
11
  };
12
- export declare class Database extends Config<DatabaseProps> {
12
+ export declare class Database {
13
+ name: string;
13
14
  imageName?: string;
14
15
  imageVersion?: string;
15
16
  username: string;
@@ -1,10 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Database = void 0;
4
- const core_1 = require("@wocker/core");
5
- class Database extends core_1.Config {
4
+ class Database {
6
5
  constructor(props) {
7
- super(props);
8
6
  const { name, imageName, imageVersion, username, password, configStorage, configVolume, storage, volume } = props;
9
7
  this.name = name;
10
8
  this.imageName = imageName;
@@ -1,6 +1,6 @@
1
- import { AppConfigService, PluginConfigService, DockerService, ProxyService } from "@wocker/core";
1
+ import { AppConfigService, PluginConfigService, DockerService, ProxyService, FileSystem } from "@wocker/core";
2
2
  import { Config } from "../makes/Config";
3
- import { DatabaseProps } from "../makes/Database";
3
+ import { Database, DatabaseProps } from "../makes/Database";
4
4
  export declare class MongodbService {
5
5
  protected readonly appConfigService: AppConfigService;
6
6
  protected readonly pluginConfigService: PluginConfigService;
@@ -10,6 +10,7 @@ export declare class MongodbService {
10
10
  adminContainerName: string;
11
11
  constructor(appConfigService: AppConfigService, pluginConfigService: PluginConfigService, dockerService: DockerService, proxyService: ProxyService);
12
12
  get config(): Config;
13
+ get fs(): FileSystem;
13
14
  create(props?: Partial<DatabaseProps>): Promise<void>;
14
15
  upgrade(props: Partial<DatabaseProps>): Promise<void>;
15
16
  destroy(name: string, yes?: boolean, force?: boolean): Promise<void>;
@@ -17,5 +18,9 @@ export declare class MongodbService {
17
18
  start(name?: string, restart?: boolean): Promise<void>;
18
19
  admin(): Promise<void>;
19
20
  stop(name?: string): Promise<void>;
21
+ backup(name?: string, database?: string): Promise<void>;
22
+ deleteBackup(name?: string, database?: string, filename?: string, confirm?: boolean): Promise<void>;
23
+ restore(name?: string, database?: string, filename?: string): Promise<void>;
24
+ getDatabases(service: Database): Promise<string[]>;
20
25
  list(): Promise<string>;
21
26
  }
@@ -24,6 +24,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
24
24
  exports.MongodbService = void 0;
25
25
  const core_1 = require("@wocker/core");
26
26
  const utils_1 = require("@wocker/utils");
27
+ const format_1 = require("date-fns/format");
27
28
  const cli_table3_1 = __importDefault(require("cli-table3"));
28
29
  const Config_1 = require("../makes/Config");
29
30
  const Database_1 = require("../makes/Database");
@@ -54,6 +55,9 @@ let MongodbService = class MongodbService {
54
55
  }
55
56
  return this._config;
56
57
  }
58
+ get fs() {
59
+ return this.pluginConfigService.fs;
60
+ }
57
61
  create() {
58
62
  return __awaiter(this, arguments, void 0, function* (props = {}) {
59
63
  if (props.name && this.config.hasDatabase(props.name)) {
@@ -61,9 +65,9 @@ let MongodbService = class MongodbService {
61
65
  delete props.name;
62
66
  }
63
67
  if (!props.name) {
64
- props.name = (yield (0, utils_1.promptText)({
65
- message: "Mongodb name:",
66
- type: "string",
68
+ props.name = (yield (0, utils_1.promptInput)({
69
+ message: "Mongodb name",
70
+ type: "text",
67
71
  validate: (name) => {
68
72
  if (!name) {
69
73
  return "Name is required";
@@ -76,19 +80,19 @@ let MongodbService = class MongodbService {
76
80
  }));
77
81
  }
78
82
  if (!props.username) {
79
- props.username = yield (0, utils_1.promptText)({
83
+ props.username = yield (0, utils_1.promptInput)({
80
84
  message: "Username:",
81
- type: "string",
85
+ type: "text",
82
86
  required: true
83
87
  });
84
88
  }
85
89
  if (!props.password) {
86
- props.password = (yield (0, utils_1.promptText)({
90
+ props.password = (yield (0, utils_1.promptInput)({
87
91
  message: "Password:",
88
92
  type: "password",
89
93
  required: true
90
94
  }));
91
- const confirmPassword = yield (0, utils_1.promptText)({
95
+ const confirmPassword = yield (0, utils_1.promptInput)({
92
96
  message: "Confirm password:",
93
97
  type: "password",
94
98
  required: true
@@ -169,10 +173,10 @@ let MongodbService = class MongodbService {
169
173
  }
170
174
  start(name, restart) {
171
175
  return __awaiter(this, void 0, void 0, function* () {
172
- if (!this.pluginConfigService.isVersionGTE("1.0.19")) {
176
+ if (!this.pluginConfigService.isVersionGTE("1.0.22")) {
173
177
  throw new Error("Please update @wocker/ws");
174
178
  }
175
- if (!name || !this.config.default) {
179
+ if (!name && !this.config.default) {
176
180
  yield this.create();
177
181
  }
178
182
  const database = this.config.getDatabaseOrDefault(name);
@@ -223,7 +227,7 @@ let MongodbService = class MongodbService {
223
227
  const { State: { Running } } = yield container.inspect();
224
228
  if (Running) {
225
229
  connections.push(`mongodb://${database.username}:${database.password}@${database.containerName}:27017`);
226
- // Multiple servers are not supported by mongo-express
230
+ // Mongo-express does not support multiple servers
227
231
  break;
228
232
  }
229
233
  }
@@ -268,6 +272,171 @@ let MongodbService = class MongodbService {
268
272
  yield this.dockerService.removeContainer(database.containerName);
269
273
  });
270
274
  }
275
+ backup(name, database) {
276
+ return __awaiter(this, void 0, void 0, function* () {
277
+ const service = this.config.getDatabaseOrDefault(name);
278
+ if (!database) {
279
+ database = yield (0, utils_1.promptSelect)({
280
+ message: "Database",
281
+ required: true,
282
+ options: yield this.getDatabases(service)
283
+ });
284
+ }
285
+ if (!this.fs.exists(`dump/${service.name}/${database}`)) {
286
+ this.fs.mkdir(`dump/${service.name}/${database}`, {
287
+ recursive: true
288
+ });
289
+ }
290
+ let filename = (0, format_1.formatDate)(new Date(), "yyyy-MM-dd HH-mm") + ".sql";
291
+ const fileStream = this.fs.createWriteStream(`dump/${service.name}/${database}/${filename}`);
292
+ const stream = yield this.dockerService.exec(service.containerName, [
293
+ "mongodump",
294
+ "--authenticationDatabase", "admin",
295
+ "--host", `${service.containerName}:27017`,
296
+ "--username", "root",
297
+ "--password", "toor",
298
+ "--db", database,
299
+ "--archive",
300
+ "--gzip"
301
+ ], false);
302
+ stream.on("data", (chunk) => {
303
+ fileStream.write((0, utils_1.demuxOutput)(chunk));
304
+ });
305
+ try {
306
+ yield new Promise((resolve, reject) => {
307
+ stream.on("end", resolve);
308
+ stream.on("error", reject);
309
+ });
310
+ }
311
+ finally {
312
+ fileStream.close();
313
+ }
314
+ });
315
+ }
316
+ deleteBackup(name, database, filename, confirm) {
317
+ return __awaiter(this, void 0, void 0, function* () {
318
+ const service = this.config.getDatabaseOrDefault(name);
319
+ if (!database) {
320
+ const databases = this.fs.readdir(`dumps/${service.name}`);
321
+ if (databases.length === 0) {
322
+ throw new Error(`No backups were found for the "${service.name}" service`);
323
+ }
324
+ database = yield (0, utils_1.promptSelect)({
325
+ message: "Database",
326
+ required: true,
327
+ options: databases
328
+ });
329
+ }
330
+ if (!filename) {
331
+ const files = this.fs.readdir(`dumps/${service.name}/${database}`);
332
+ if (files.length === 0) {
333
+ throw new Error(`No backup files found for the "${database}" database`);
334
+ }
335
+ filename = yield (0, utils_1.promptSelect)({
336
+ message: "File",
337
+ required: true,
338
+ options: files
339
+ });
340
+ }
341
+ if (!confirm) {
342
+ confirm = yield (0, utils_1.promptConfirm)({
343
+ message: "Are you sure you want to delete?",
344
+ default: false
345
+ });
346
+ }
347
+ if (!confirm) {
348
+ throw new Error("Canceled");
349
+ }
350
+ this.fs.rm(`dumps/${service.name}/${database}/${filename}`);
351
+ console.info(`File "${filename}" deleted`);
352
+ const otherFiles = this.fs.readdir(`dump/${service.name}/${database}`);
353
+ if (otherFiles.length === 0) {
354
+ this.fs.rm(`dump/${service.name}/${database}`, {
355
+ force: true,
356
+ recursive: true
357
+ });
358
+ }
359
+ });
360
+ }
361
+ restore(name, database, filename) {
362
+ return __awaiter(this, void 0, void 0, function* () {
363
+ const service = this.config.getDatabaseOrDefault(name);
364
+ if (!database) {
365
+ const databases = this.fs.readdir(`dumps/${service.name}`);
366
+ if (databases.length === 0) {
367
+ throw new Error(`No backups were found for the "${service.name}" service`);
368
+ }
369
+ database = yield (0, utils_1.promptSelect)({
370
+ message: "Database",
371
+ required: true,
372
+ options: databases
373
+ });
374
+ }
375
+ if (!filename) {
376
+ const files = this.fs.readdir(`dumps/${service.name}/${database}`);
377
+ if (files.length === 0) {
378
+ throw new Error(`No backup files found for the "${database}" database`);
379
+ }
380
+ filename = yield (0, utils_1.promptSelect)({
381
+ message: "File",
382
+ required: true,
383
+ options: files
384
+ });
385
+ }
386
+ const file = this.fs.createReadStream(`dumps/${service.name}/${database}/${filename}`);
387
+ const stream = yield this.dockerService.exec(service.containerName, [
388
+ "mongorestore",
389
+ "--authenticationDatabase", "admin",
390
+ "--host", `${service.containerName}:27017`,
391
+ "--username", service.username,
392
+ "--password", service.password,
393
+ "--db", database,
394
+ "--drop",
395
+ "--gzip",
396
+ "--archive"
397
+ ], false);
398
+ yield new Promise((resolve, reject) => {
399
+ file.on("data", (data) => {
400
+ stream.write(data);
401
+ });
402
+ file.on("error", (err) => {
403
+ stream.destroy();
404
+ reject(err);
405
+ });
406
+ stream.on("finish", () => {
407
+ resolve();
408
+ });
409
+ stream.on("error", (err) => {
410
+ file.close();
411
+ reject(err);
412
+ });
413
+ });
414
+ });
415
+ }
416
+ getDatabases(service) {
417
+ return __awaiter(this, void 0, void 0, function* () {
418
+ const stream = yield this.dockerService.exec(service.containerName, [
419
+ "mongosh",
420
+ "--username", service.username,
421
+ "--password", service.password,
422
+ "--quiet",
423
+ "--eval", "db.getMongo().getDBNames().forEach(function(i){print(i)})"
424
+ ], false);
425
+ const res = yield new Promise((resolve, reject) => {
426
+ let res = "";
427
+ stream.on("data", (chunk) => {
428
+ res += (0, utils_1.demuxOutput)(chunk).toString();
429
+ });
430
+ stream.on("end", () => {
431
+ resolve(res);
432
+ });
433
+ stream.on("error", reject);
434
+ });
435
+ return res.split(/\r?\n/).filter((database) => {
436
+ return !!database;
437
+ });
438
+ });
439
+ }
271
440
  list() {
272
441
  return __awaiter(this, void 0, void 0, function* () {
273
442
  const table = new cli_table3_1.default({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wocker/mongodb-plugin",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "author": "Kris Papercut <krispcut@gmail.com>",
5
5
  "description": "Mongodb plugin for wocker",
6
6
  "license": "MIT",
@@ -26,9 +26,10 @@
26
26
  "test": "echo \"Error: no test specified\" && exit 1"
27
27
  },
28
28
  "dependencies": {
29
- "@wocker/core": "^1.0.21",
30
- "@wocker/utils": "^1.0.9",
31
- "cli-table3": "^0.6.5"
29
+ "@wocker/core": "^1.0.22",
30
+ "@wocker/utils": "^2.0.3",
31
+ "cli-table3": "^0.6.5",
32
+ "date-fns": "^4.1.0"
32
33
  },
33
34
  "devDependencies": {
34
35
  "@types/node": "^22.14.1",