@wocker/mongodb-plugin 1.0.7 → 1.0.9-beta.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.
@@ -2,12 +2,14 @@ import { MongodbService } from "../services/MongodbService";
2
2
  export declare class MongodbController {
3
3
  protected readonly mongodbService: MongodbService;
4
4
  constructor(mongodbService: MongodbService);
5
- create(name?: string, username?: string, password?: string, imageName?: string, imageVersion?: string): Promise<void>;
6
- upgrade(name?: string, imageName?: string, imageVersion?: string, volume?: string, configVolume?: string): Promise<void>;
5
+ create(name?: string, username?: string, password?: string, imageName?: string, imageVersion?: string, containerPort?: number): Promise<void>;
6
+ upgrade(name?: string, imageName?: string, imageVersion?: string, volume?: string, configVolume?: string, containerPort?: number, enableAdmin?: boolean, disableAdmin?: boolean): Promise<void>;
7
7
  destroy(name: string, yes?: boolean, force?: boolean): Promise<void>;
8
8
  use(name: string): Promise<void>;
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
  }
@@ -28,26 +28,36 @@ let MongodbController = class MongodbController {
28
28
  constructor(mongodbService) {
29
29
  this.mongodbService = mongodbService;
30
30
  }
31
- create(name, username, password, imageName, imageVersion) {
31
+ create(name, username, password, imageName, imageVersion, containerPort) {
32
32
  return __awaiter(this, void 0, void 0, function* () {
33
33
  yield this.mongodbService.create({
34
34
  name,
35
35
  username,
36
36
  password,
37
37
  imageName,
38
- imageVersion
38
+ imageVersion,
39
+ containerPort
39
40
  });
40
41
  });
41
42
  }
42
- upgrade(name, imageName, imageVersion, volume, configVolume) {
43
+ upgrade(name, imageName, imageVersion, volume, configVolume, containerPort, enableAdmin, disableAdmin) {
43
44
  return __awaiter(this, void 0, void 0, function* () {
44
45
  yield this.mongodbService.upgrade({
45
46
  name,
46
47
  imageName,
47
48
  imageVersion,
48
49
  volume,
49
- configVolume
50
+ configVolume,
51
+ containerPort
50
52
  });
53
+ if (typeof enableAdmin !== "undefined") {
54
+ this.mongodbService.config.admin.enabled = true;
55
+ this.mongodbService.config.save();
56
+ }
57
+ if (typeof disableAdmin !== "undefined") {
58
+ this.mongodbService.config.admin.enabled = false;
59
+ this.mongodbService.config.save();
60
+ }
51
61
  });
52
62
  }
53
63
  destroy(name, yes, force) {
@@ -79,6 +89,20 @@ let MongodbController = class MongodbController {
79
89
  return this.mongodbService.list();
80
90
  });
81
91
  }
92
+ backup(service, database, file, del) {
93
+ return __awaiter(this, void 0, void 0, function* () {
94
+ if (del) {
95
+ yield this.mongodbService.deleteBackup(service, database, file);
96
+ return;
97
+ }
98
+ yield this.mongodbService.backup(service, database);
99
+ });
100
+ }
101
+ restore(service, database, file) {
102
+ return __awaiter(this, void 0, void 0, function* () {
103
+ yield this.mongodbService.restore(service, database, file);
104
+ });
105
+ }
82
106
  getNames() {
83
107
  return __awaiter(this, void 0, void 0, function* () {
84
108
  return this.mongodbService.config.databases.map((database) => {
@@ -112,8 +136,10 @@ __decorate([
112
136
  alias: "I",
113
137
  description: "The image version to start the service with"
114
138
  })),
139
+ __param(5, (0, core_1.Option)("container-port")),
140
+ __param(5, (0, core_1.Description)("Port on which the database container will be accessible on the host")),
115
141
  __metadata("design:type", Function),
116
- __metadata("design:paramtypes", [String, String, String, String, String]),
142
+ __metadata("design:paramtypes", [String, String, String, String, String, Number]),
117
143
  __metadata("design:returntype", Promise)
118
144
  ], MongodbController.prototype, "create", null);
119
145
  __decorate([
@@ -140,8 +166,12 @@ __decorate([
140
166
  alias: "V",
141
167
  description: "The config volume name to start the service with"
142
168
  })),
169
+ __param(5, (0, core_1.Option)("container-port")),
170
+ __param(5, (0, core_1.Description)("Port on which the database container will be accessible on the host")),
171
+ __param(6, (0, core_1.Option)("enable-admin")),
172
+ __param(7, (0, core_1.Option)("disable-admin")),
143
173
  __metadata("design:type", Function),
144
- __metadata("design:paramtypes", [String, String, String, String, String]),
174
+ __metadata("design:paramtypes", [String, String, String, String, String, Number, Boolean, Boolean]),
145
175
  __metadata("design:returntype", Promise)
146
176
  ], MongodbController.prototype, "upgrade", null);
147
177
  __decorate([
@@ -198,9 +228,34 @@ __decorate([
198
228
  __metadata("design:paramtypes", []),
199
229
  __metadata("design:returntype", Promise)
200
230
  ], MongodbController.prototype, "list", null);
231
+ __decorate([
232
+ (0, core_1.Command)("mongodb:backup [name]"),
233
+ __param(0, (0, core_1.Param)("name")),
234
+ __param(1, (0, core_1.Option)("database", "d")),
235
+ __param(1, (0, core_1.Description)("Database name to back up")),
236
+ __param(2, (0, core_1.Option)("filename", "f")),
237
+ __param(2, (0, core_1.Description)("Name of the backup file")),
238
+ __param(3, (0, core_1.Option)("delete", "D")),
239
+ __param(3, (0, core_1.Description)("Delete the specified backup file")),
240
+ __metadata("design:type", Function),
241
+ __metadata("design:paramtypes", [String, String, String, Boolean]),
242
+ __metadata("design:returntype", Promise)
243
+ ], MongodbController.prototype, "backup", null);
244
+ __decorate([
245
+ (0, core_1.Command)("mongodb:restore [name]"),
246
+ __param(0, (0, core_1.Param)("name")),
247
+ __param(1, (0, core_1.Option)("database", "d")),
248
+ __param(1, (0, core_1.Description)("Database name to restore")),
249
+ __param(2, (0, core_1.Option)("file-name", "f")),
250
+ __param(2, (0, core_1.Description)("File name")),
251
+ __metadata("design:type", Function),
252
+ __metadata("design:paramtypes", [String, String, String]),
253
+ __metadata("design:returntype", Promise)
254
+ ], MongodbController.prototype, "restore", null);
201
255
  __decorate([
202
256
  (0, core_1.Completion)("name", "mongodb:start [name]"),
203
257
  (0, core_1.Completion)("name", "mongodb:stop [name]"),
258
+ (0, core_1.Completion)("name", "mongodb:backup [name]"),
204
259
  __metadata("design:type", Function),
205
260
  __metadata("design:paramtypes", []),
206
261
  __metadata("design:returntype", Promise)
@@ -1,11 +1,16 @@
1
1
  import { Database, DatabaseProps } from "./Database";
2
+ export type AdminConfig = {
3
+ enabled: boolean;
4
+ };
2
5
  export type ConfigProps = {
3
6
  default?: string;
4
7
  databases?: DatabaseProps[];
8
+ admin?: AdminConfig;
5
9
  };
6
10
  export declare abstract class Config {
7
11
  default?: string;
8
12
  databases: Database[];
13
+ admin: AdminConfig;
9
14
  constructor(props: ConfigProps);
10
15
  setDatabase(database: Database): void;
11
16
  hasDatabase(name: string): boolean;
@@ -4,9 +4,12 @@ exports.Config = void 0;
4
4
  const Database_1 = require("./Database");
5
5
  class Config {
6
6
  constructor(props) {
7
- const { default: defaultDatabase, databases = [] } = props;
7
+ const { default: defaultDatabase, databases = [], admin: { enabled: enabledAdmin = true } = {} } = props;
8
8
  this.default = defaultDatabase;
9
9
  this.databases = databases.map(database => new Database_1.Database(database));
10
+ this.admin = {
11
+ enabled: enabledAdmin
12
+ };
10
13
  }
11
14
  setDatabase(database) {
12
15
  let exists = false;
@@ -61,7 +64,8 @@ class Config {
61
64
  default: this.default,
62
65
  databases: this.databases.length > 0
63
66
  ? this.databases.map((database) => database.toObject())
64
- : []
67
+ : [],
68
+ admin: this.admin
65
69
  };
66
70
  }
67
71
  }
@@ -8,6 +8,7 @@ export type DatabaseProps = {
8
8
  storage?: string;
9
9
  volume?: string;
10
10
  configVolume?: string;
11
+ containerPort?: number;
11
12
  };
12
13
  export declare class Database {
13
14
  name: string;
@@ -15,6 +16,7 @@ export declare class Database {
15
16
  imageVersion?: string;
16
17
  username: string;
17
18
  password: string;
19
+ containerPort?: number;
18
20
  protected _configVolume?: string;
19
21
  protected _volume?: string;
20
22
  constructor(props: DatabaseProps);
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Database = void 0;
4
4
  class Database {
5
5
  constructor(props) {
6
- const { name, imageName, imageVersion, username, password, configStorage, configVolume, storage, volume } = props;
6
+ const { name, imageName, imageVersion, username, password, configStorage, configVolume, storage, volume, containerPort } = props;
7
7
  this.name = name;
8
8
  this.imageName = imageName;
9
9
  this.imageVersion = imageVersion;
@@ -11,6 +11,7 @@ class Database {
11
11
  this.password = password;
12
12
  this._configVolume = configStorage || configVolume;
13
13
  this._volume = storage || volume;
14
+ this.containerPort = containerPort;
14
15
  }
15
16
  get containerName() {
16
17
  return `mongodb-${this.name}.ws`;
@@ -54,7 +55,8 @@ class Database {
54
55
  username: this.username,
55
56
  password: this.password,
56
57
  volume: this._volume,
57
- configVolume: this._configVolume
58
+ configVolume: this._configVolume,
59
+ containerPort: this.containerPort
58
60
  };
59
61
  }
60
62
  }
@@ -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)) {
@@ -97,6 +101,21 @@ let MongodbService = class MongodbService {
97
101
  throw new Error("Passwords do not match");
98
102
  }
99
103
  }
104
+ if (!props.containerPort) {
105
+ const needPort = yield (0, utils_1.promptConfirm)({
106
+ message: "Do you need to expose container port?",
107
+ default: false
108
+ });
109
+ if (needPort) {
110
+ props.containerPort = yield (0, utils_1.promptInput)({
111
+ required: true,
112
+ message: "Container port:",
113
+ type: "number",
114
+ min: 1,
115
+ default: 27017
116
+ });
117
+ }
118
+ }
100
119
  const database = new Database_1.Database({
101
120
  name: props.name,
102
121
  imageName: props.imageName,
@@ -128,6 +147,10 @@ let MongodbService = class MongodbService {
128
147
  service.configVolume = props.configVolume;
129
148
  changed = true;
130
149
  }
150
+ if (props.containerPort) {
151
+ service.containerPort = props.containerPort;
152
+ changed = true;
153
+ }
131
154
  if (changed) {
132
155
  this.config.setDatabase(service);
133
156
  this.config.save();
@@ -169,10 +192,10 @@ let MongodbService = class MongodbService {
169
192
  }
170
193
  start(name, restart) {
171
194
  return __awaiter(this, void 0, void 0, function* () {
172
- if (!this.pluginConfigService.isVersionGTE("1.0.19")) {
195
+ if (!this.pluginConfigService.isVersionGTE("1.0.22")) {
173
196
  throw new Error("Please update @wocker/ws");
174
197
  }
175
- if (!name || !this.config.default) {
198
+ if (!name && !this.config.default) {
176
199
  yield this.create();
177
200
  }
178
201
  const database = this.config.getDatabaseOrDefault(name);
@@ -201,7 +224,10 @@ let MongodbService = class MongodbService {
201
224
  volumes: [
202
225
  `${database.configVolume}:/data/configdb`,
203
226
  `${database.volume}:/data/db`
204
- ]
227
+ ],
228
+ ports: database.containerPort ? [
229
+ `${database.containerPort}:27017`
230
+ ] : undefined
205
231
  });
206
232
  }
207
233
  const { State: { Running } } = yield container.inspect();
@@ -230,7 +256,7 @@ let MongodbService = class MongodbService {
230
256
  catch (ignore) { }
231
257
  }
232
258
  yield this.dockerService.removeContainer(this.adminContainerName);
233
- if (connections.length === 0) {
259
+ if (!this.config.admin.enabled || connections.length === 0) {
234
260
  return;
235
261
  }
236
262
  let container = yield this.dockerService.getContainer(this.adminContainerName);
@@ -268,6 +294,171 @@ let MongodbService = class MongodbService {
268
294
  yield this.dockerService.removeContainer(database.containerName);
269
295
  });
270
296
  }
297
+ backup(name, database) {
298
+ return __awaiter(this, void 0, void 0, function* () {
299
+ const service = this.config.getDatabaseOrDefault(name);
300
+ if (!database) {
301
+ database = yield (0, utils_1.promptSelect)({
302
+ message: "Database",
303
+ required: true,
304
+ options: yield this.getDatabases(service)
305
+ });
306
+ }
307
+ if (!this.fs.exists(`dump/${service.name}/${database}`)) {
308
+ this.fs.mkdir(`dump/${service.name}/${database}`, {
309
+ recursive: true
310
+ });
311
+ }
312
+ let filename = (0, format_1.formatDate)(new Date(), "yyyy-MM-dd HH-mm") + ".sql";
313
+ const fileStream = this.fs.createWriteStream(`dump/${service.name}/${database}/${filename}`);
314
+ const stream = yield this.dockerService.exec(service.containerName, [
315
+ "mongodump",
316
+ "--authenticationDatabase", "admin",
317
+ "--host", `${service.containerName}:27017`,
318
+ "--username", "root",
319
+ "--password", "toor",
320
+ "--db", database,
321
+ "--archive",
322
+ "--gzip"
323
+ ], false);
324
+ stream.on("data", (chunk) => {
325
+ fileStream.write((0, utils_1.demuxOutput)(chunk));
326
+ });
327
+ try {
328
+ yield new Promise((resolve, reject) => {
329
+ stream.on("end", resolve);
330
+ stream.on("error", reject);
331
+ });
332
+ }
333
+ finally {
334
+ fileStream.close();
335
+ }
336
+ });
337
+ }
338
+ deleteBackup(name, database, filename, confirm) {
339
+ return __awaiter(this, void 0, void 0, function* () {
340
+ const service = this.config.getDatabaseOrDefault(name);
341
+ if (!database) {
342
+ const databases = this.fs.readdir(`dumps/${service.name}`);
343
+ if (databases.length === 0) {
344
+ throw new Error(`No backups were found for the "${service.name}" service`);
345
+ }
346
+ database = yield (0, utils_1.promptSelect)({
347
+ message: "Database",
348
+ required: true,
349
+ options: databases
350
+ });
351
+ }
352
+ if (!filename) {
353
+ const files = this.fs.readdir(`dumps/${service.name}/${database}`);
354
+ if (files.length === 0) {
355
+ throw new Error(`No backup files found for the "${database}" database`);
356
+ }
357
+ filename = yield (0, utils_1.promptSelect)({
358
+ message: "File",
359
+ required: true,
360
+ options: files
361
+ });
362
+ }
363
+ if (!confirm) {
364
+ confirm = yield (0, utils_1.promptConfirm)({
365
+ message: "Are you sure you want to delete?",
366
+ default: false
367
+ });
368
+ }
369
+ if (!confirm) {
370
+ throw new Error("Canceled");
371
+ }
372
+ this.fs.rm(`dumps/${service.name}/${database}/${filename}`);
373
+ console.info(`File "${filename}" deleted`);
374
+ const otherFiles = this.fs.readdir(`dump/${service.name}/${database}`);
375
+ if (otherFiles.length === 0) {
376
+ this.fs.rm(`dump/${service.name}/${database}`, {
377
+ force: true,
378
+ recursive: true
379
+ });
380
+ }
381
+ });
382
+ }
383
+ restore(name, database, filename) {
384
+ return __awaiter(this, void 0, void 0, function* () {
385
+ const service = this.config.getDatabaseOrDefault(name);
386
+ if (!database) {
387
+ const databases = this.fs.readdir(`dumps/${service.name}`);
388
+ if (databases.length === 0) {
389
+ throw new Error(`No backups were found for the "${service.name}" service`);
390
+ }
391
+ database = yield (0, utils_1.promptSelect)({
392
+ message: "Database",
393
+ required: true,
394
+ options: databases
395
+ });
396
+ }
397
+ if (!filename) {
398
+ const files = this.fs.readdir(`dumps/${service.name}/${database}`);
399
+ if (files.length === 0) {
400
+ throw new Error(`No backup files found for the "${database}" database`);
401
+ }
402
+ filename = yield (0, utils_1.promptSelect)({
403
+ message: "File",
404
+ required: true,
405
+ options: files
406
+ });
407
+ }
408
+ const file = this.fs.createReadStream(`dumps/${service.name}/${database}/${filename}`);
409
+ const stream = yield this.dockerService.exec(service.containerName, [
410
+ "mongorestore",
411
+ "--authenticationDatabase", "admin",
412
+ "--host", `${service.containerName}:27017`,
413
+ "--username", service.username,
414
+ "--password", service.password,
415
+ "--db", database,
416
+ "--drop",
417
+ "--gzip",
418
+ "--archive"
419
+ ], false);
420
+ yield new Promise((resolve, reject) => {
421
+ file.on("data", (data) => {
422
+ stream.write(data);
423
+ });
424
+ file.on("error", (err) => {
425
+ stream.destroy();
426
+ reject(err);
427
+ });
428
+ stream.on("finish", () => {
429
+ resolve();
430
+ });
431
+ stream.on("error", (err) => {
432
+ file.close();
433
+ reject(err);
434
+ });
435
+ });
436
+ });
437
+ }
438
+ getDatabases(service) {
439
+ return __awaiter(this, void 0, void 0, function* () {
440
+ const stream = yield this.dockerService.exec(service.containerName, [
441
+ "mongosh",
442
+ "--username", service.username,
443
+ "--password", service.password,
444
+ "--quiet",
445
+ "--eval", "db.getMongo().getDBNames().forEach(function(i){print(i)})"
446
+ ], false);
447
+ const res = yield new Promise((resolve, reject) => {
448
+ let res = "";
449
+ stream.on("data", (chunk) => {
450
+ res += (0, utils_1.demuxOutput)(chunk).toString();
451
+ });
452
+ stream.on("end", () => {
453
+ resolve(res);
454
+ });
455
+ stream.on("error", reject);
456
+ });
457
+ return res.split(/\r?\n/).filter((database) => {
458
+ return !!database;
459
+ });
460
+ });
461
+ }
271
462
  list() {
272
463
  return __awaiter(this, void 0, void 0, function* () {
273
464
  const table = new cli_table3_1.default({
@@ -283,7 +474,7 @@ let MongodbService = class MongodbService {
283
474
  table.push([
284
475
  database.name + (database.name === this.config.default ? " (default)" : ""),
285
476
  database.username,
286
- database.containerName,
477
+ database.containerName + (database.containerPort ? `:${database.containerPort}` : ""),
287
478
  database.image,
288
479
  `${database.configVolume}\n${database.volume}`
289
480
  ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wocker/mongodb-plugin",
3
- "version": "1.0.7",
3
+ "version": "1.0.9-beta.0",
4
4
  "author": "Kris Papercut <krispcut@gmail.com>",
5
5
  "description": "Mongodb plugin for wocker",
6
6
  "license": "MIT",
@@ -26,12 +26,13 @@
26
26
  "test": "echo \"Error: no test specified\" && exit 1"
27
27
  },
28
28
  "dependencies": {
29
- "@wocker/core": "^1.0.22",
29
+ "@wocker/core": "^1.0.24",
30
30
  "@wocker/utils": "^2.0.3",
31
- "cli-table3": "^0.6.5"
31
+ "cli-table3": "^0.6.5",
32
+ "date-fns": "^4.1.0"
32
33
  },
33
34
  "devDependencies": {
34
- "@types/node": "^22.14.1",
35
+ "@types/node": "^24.0.13",
35
36
  "typescript": "^5.8.3"
36
37
  }
37
38
  }